nodeslicer/registry.py
2026-09-27 16:08:38 +03:00

102 lines
No EOL
2.9 KiB
Python

# registry.py
import bpy
from typing import Any, Callable
_bpy_class_registry: list[type] = []
_timer_registry: list[Callable[..., int | None]] = []
def setup_bpy_annotations(cls: type) -> type:
if not hasattr(cls, "__annotations__"):
cls.__annotations__ = {}
for name, val in list(cls.__dict__.items()):
val_type_name = type(val).__name__
if "PropertyDeferred" in val_type_name or val_type_name.startswith("_Property") or (isinstance(val, tuple) and len(val) > 0 and "Property" in type(val[0]).__name__):
cls.__annotations__[name] = val
try:
delattr(cls, name)
except (AttributeError, TypeError):
pass
return cls
# BPY CLASSES
def register_class(cls: type) -> type:
setup_bpy_annotations(cls)
if cls not in _bpy_class_registry:
_bpy_class_registry.append(cls)
return cls
def get() -> list[type]:
return list(_bpy_class_registry)
def get_label_by_name(name: str) -> str:
for cls in get():
if cls.__name__ == name:
return getattr(cls, "bl_label", "No Label")
return ''
def get_class_by_name(name: str) -> type | None:
for cls in get():
if cls.__name__ == name:
return cls
return None
def blender_register_classes():
for cls in _bpy_class_registry:
try:
setup_bpy_annotations(cls)
bpy.utils.register_class(cls)
except Exception as e:
print(f"Nodeslicer: Failed to register {cls}: {e}")
def blender_unregister_classes():
for cls in reversed(_bpy_class_registry):
try:
bpy.utils.unregister_class(cls)
except Exception:
pass
# TIMERS
def register_timer(clb: Callable[..., Any]):
_timer_registry.append(clb)
return clb
def get_timers() -> list[Callable[..., int | None]]:
return list(_timer_registry)
def blender_register_timers():
for timer in _timer_registry:
bpy.app.timers.register(timer, persistent=True)
def blender_unregister_timers():
for timer in _timer_registry:
bpy.app.timers.unregister(timer)
import os
try:
from bpy.utils.previews import ImagePreviewCollection
except ImportError:
ImagePreviewCollection = Any # type: ignore
_icons_pcoll: ImagePreviewCollection | None = None
def blender_register_icons():
global _icons_pcoll
_icons_pcoll = bpy.utils.previews.new()
my_icons_dir = os.path.join(os.path.dirname(__file__), "icons")
for filename in os.listdir(my_icons_dir):
_icons_pcoll.load(filename, os.path.join(my_icons_dir, filename), 'IMAGE')
def blender_unregister_icons():
global _icons_pcoll
if not _icons_pcoll: return
bpy.utils.previews.remove(_icons_pcoll)
del _icons_pcoll
def get_icon(icon_id: str) -> int:
global _icons_pcoll
if not _icons_pcoll: return -1
return _icons_pcoll[icon_id].icon_id