This commit is contained in:
2024-05-13 12:09:11 +08:00
parent 1990a16972
commit 5e8d12c564
5 changed files with 183 additions and 97 deletions

View File

@@ -16,6 +16,7 @@ blender_version = bpy.app.version
modules = None
ordered_classes = None
def init():
global modules
global ordered_classes
@@ -23,6 +24,7 @@ def init():
modules = get_all_submodules(Path(__file__).parent)
ordered_classes = get_ordered_classes_to_register(modules)
def register():
for cls in ordered_classes:
bpy.utils.register_class(cls)
@@ -33,15 +35,22 @@ def register():
if hasattr(module, "register"):
module.register()
def unregister():
for cls in reversed(ordered_classes):
bpy.utils.unregister_class(cls)
try:
bpy.utils.unregister_class(cls)
except Exception as e:
print(f"Fail to unregister {cls}, skiped")
for module in modules:
if module.__name__ == __name__:
continue
if hasattr(module, "unregister"):
module.unregister()
try:
if module.__name__ == __name__:
continue
if hasattr(module, "unregister"):
module.unregister()
except Exception as e:
print(f"Fail to unregister {module}, skiped")
# Import modules
@@ -50,10 +59,12 @@ def unregister():
def get_all_submodules(directory):
return list(iter_submodules(directory, directory.name))
def iter_submodules(path, package_name):
for name in sorted(iter_submodule_names(path)):
yield importlib.import_module("." + name, package_name)
def iter_submodule_names(path, root=""):
for _, module_name, is_package in pkgutil.iter_modules([str(path)]):
if is_package:
@@ -70,19 +81,24 @@ def iter_submodule_names(path, root=""):
def get_ordered_classes_to_register(modules):
return toposort(get_register_deps_dict(modules))
def get_register_deps_dict(modules):
my_classes = set(iter_my_classes(modules))
my_classes_by_idname = {cls.bl_idname : cls for cls in my_classes if hasattr(cls, "bl_idname")}
my_classes_by_idname = {
cls.bl_idname: cls for cls in my_classes if hasattr(cls, "bl_idname")}
deps_dict = {}
for cls in my_classes:
deps_dict[cls] = set(iter_my_register_deps(cls, my_classes, my_classes_by_idname))
deps_dict[cls] = set(iter_my_register_deps(
cls, my_classes, my_classes_by_idname))
return deps_dict
def iter_my_register_deps(cls, my_classes, my_classes_by_idname):
yield from iter_my_deps_from_annotations(cls, my_classes)
yield from iter_my_deps_from_parent_id(cls, my_classes_by_idname)
def iter_my_deps_from_annotations(cls, my_classes):
for value in typing.get_type_hints(cls, {}, {}).values():
dependency = get_dependency_from_annotation(value)
@@ -90,6 +106,7 @@ def iter_my_deps_from_annotations(cls, my_classes):
if dependency in my_classes:
yield dependency
def get_dependency_from_annotation(value):
if blender_version >= (2, 93):
if isinstance(value, bpy.props._PropertyDeferred):
@@ -100,6 +117,7 @@ def get_dependency_from_annotation(value):
return value[1]["type"]
return None
def iter_my_deps_from_parent_id(cls, my_classes_by_idname):
if bpy.types.Panel in cls.__bases__:
parent_idname = getattr(cls, "bl_parent_id", None)
@@ -108,6 +126,7 @@ def iter_my_deps_from_parent_id(cls, my_classes_by_idname):
if parent_cls is not None:
yield parent_cls
def iter_my_classes(modules):
base_types = get_register_base_types()
for cls in get_classes_in_modules(modules):
@@ -115,6 +134,7 @@ def iter_my_classes(modules):
if not getattr(cls, "is_registered", False):
yield cls
def get_classes_in_modules(modules):
classes = set()
for module in modules:
@@ -122,11 +142,13 @@ def get_classes_in_modules(modules):
classes.add(cls)
return classes
def iter_classes_in_module(module):
for value in module.__dict__.values():
if inspect.isclass(value):
yield value
def get_register_base_types():
return set(getattr(bpy.types, name) for name in [
"Panel", "Operator", "PropertyGroup", "FileHandler",
@@ -151,5 +173,6 @@ def toposort(deps_dict):
sorted_values.add(value)
else:
unsorted.append(value)
deps_dict = {value : deps_dict[value] - sorted_values for value in unsorted}
deps_dict = {value: deps_dict[value] -
sorted_values for value in unsorted}
return sorted_list