[Bf-blender-cvs] [657204dfcef] functions: use auto load for registration
Jacques Lucke
noreply at git.blender.org
Sun Mar 10 16:28:30 CET 2019
Commit: 657204dfcefd78ae41111a4c2e52e232e341bc55
Author: Jacques Lucke
Date: Sun Mar 10 13:57:37 2019 +0100
Branches: functions
https://developer.blender.org/rB657204dfcefd78ae41111a4c2e52e232e341bc55
use auto load for registration
===================================================================
M release/scripts/startup/function_nodes/__init__.py
A release/scripts/startup/function_nodes/auto_load.py
M release/scripts/startup/function_nodes/menu.py
M release/scripts/startup/function_nodes/node_operators.py
M release/scripts/startup/function_nodes/nodes/__init__.py
M release/scripts/startup/function_nodes/nodes/clamp.py
M release/scripts/startup/function_nodes/nodes/combine_vector.py
M release/scripts/startup/function_nodes/nodes/float_math.py
M release/scripts/startup/function_nodes/nodes/function_input.py
M release/scripts/startup/function_nodes/nodes/function_output.py
M release/scripts/startup/function_nodes/nodes/map_range.py
M release/scripts/startup/function_nodes/nodes/object_transforms.py
M release/scripts/startup/function_nodes/nodes/random_number.py
M release/scripts/startup/function_nodes/nodes/separate_vector.py
M release/scripts/startup/function_nodes/nodes/vector_distance.py
M release/scripts/startup/function_nodes/sockets.py
===================================================================
diff --git a/release/scripts/startup/function_nodes/__init__.py b/release/scripts/startup/function_nodes/__init__.py
index 8877382c5fc..bc085e4ce94 100644
--- a/release/scripts/startup/function_nodes/__init__.py
+++ b/release/scripts/startup/function_nodes/__init__.py
@@ -1,7 +1,4 @@
+from . auto_load import init, register, unregister
-def register():
- from . import base
- from . import sockets
- from . import nodes
- from . import menu
- from . import node_operators
\ No newline at end of file
+init()
+print("INIT")
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/auto_load.py b/release/scripts/startup/function_nodes/auto_load.py
new file mode 100644
index 00000000000..6aef4a00924
--- /dev/null
+++ b/release/scripts/startup/function_nodes/auto_load.py
@@ -0,0 +1,139 @@
+import os
+import bpy
+import sys
+import typing
+import inspect
+import pkgutil
+import importlib
+from pathlib import Path
+
+__all__ = (
+ "init",
+ "register",
+ "unregister",
+)
+
+modules = None
+ordered_classes = None
+
+def init():
+ global modules
+ global ordered_classes
+
+ modules = get_all_submodules(Path(__file__).parent)
+ ordered_classes = get_ordered_classes_to_register(modules)
+
+def register():
+ print("REGISTER")
+ for cls in ordered_classes:
+ bpy.utils.register_class(cls)
+
+ for module in modules:
+ if module.__name__ == __name__:
+ continue
+ if hasattr(module, "register"):
+ module.register()
+
+def unregister():
+ for cls in reversed(ordered_classes):
+ bpy.utils.unregister_class(cls)
+
+ for module in modules:
+ if module.__name__ == __name__:
+ continue
+ if hasattr(module, "unregister"):
+ module.unregister()
+
+
+# Import modules
+#################################################
+
+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:
+ sub_path = path / module_name
+ sub_root = root + module_name + "."
+ yield from iter_submodule_names(sub_path, sub_root)
+ else:
+ yield root + module_name
+
+
+# Find classes to register
+#################################################
+
+def get_ordered_classes_to_register(modules):
+ return toposort(get_register_deps_dict(modules))
+
+def get_register_deps_dict(modules):
+ deps_dict = {}
+ classes_to_register = set(iter_classes_to_register(modules))
+ for cls in classes_to_register:
+ deps_dict[cls] = set(iter_own_register_deps(cls, classes_to_register))
+ return deps_dict
+
+def iter_own_register_deps(cls, own_classes):
+ yield from (dep for dep in iter_register_deps(cls) if dep in own_classes)
+
+def iter_register_deps(cls):
+ for value in typing.get_type_hints(cls, {}, {}).values():
+ dependency = get_dependency_from_annotation(value)
+ if dependency is not None:
+ yield dependency
+
+def get_dependency_from_annotation(value):
+ if isinstance(value, tuple) and len(value) == 2:
+ if value[0] in (bpy.props.PointerProperty, bpy.props.CollectionProperty):
+ return value[1]["type"]
+ return None
+
+def iter_classes_to_register(modules):
+ base_types = get_register_base_types()
+ for cls in get_classes_in_modules(modules):
+ if any(base in base_types for base in cls.__bases__):
+ if not getattr(cls, "is_registered", False):
+ yield cls
+
+def get_classes_in_modules(modules):
+ classes = set()
+ for module in modules:
+ for cls in iter_classes_in_module(module):
+ 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",
+ "AddonPreferences", "Header", "Menu",
+ "Node", "NodeSocket", "NodeTree",
+ "UIList", "RenderEngine"
+ ])
+
+
+# Find order to register to solve dependencies
+#################################################
+
+def toposort(deps_dict):
+ sorted_list = []
+ sorted_values = set()
+ while len(deps_dict) > 0:
+ unsorted = []
+ for value, deps in deps_dict.items():
+ if len(deps) == 0:
+ sorted_list.append(value)
+ sorted_values.add(value)
+ else:
+ unsorted.append(value)
+ deps_dict = {value : deps_dict[value] - sorted_values for value in unsorted}
+ return sorted_list
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/menu.py b/release/scripts/startup/function_nodes/menu.py
index 47fc6e8bdc6..da5a318f8e9 100644
--- a/release/scripts/startup/function_nodes/menu.py
+++ b/release/scripts/startup/function_nodes/menu.py
@@ -31,4 +31,6 @@ def insert_node(layout, type, text, settings = {}, icon = "NONE"):
item.value = value
return operator
-bpy.types.NODE_MT_add.append(draw_menu)
\ No newline at end of file
+
+def register():
+ bpy.types.NODE_MT_add.append(draw_menu)
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/node_operators.py b/release/scripts/startup/function_nodes/node_operators.py
index ea9919b3962..5c6aa24991e 100644
--- a/release/scripts/startup/function_nodes/node_operators.py
+++ b/release/scripts/startup/function_nodes/node_operators.py
@@ -24,6 +24,4 @@ class NodeOperator(bpy.types.Operator):
settings = eval(self.settings_repr)
function(*settings)
- return {"FINISHED"}
-
-bpy.utils.register_class(NodeOperator)
\ No newline at end of file
+ return {"FINISHED"}
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/__init__.py b/release/scripts/startup/function_nodes/nodes/__init__.py
index 56ead29f394..e69de29bb2d 100644
--- a/release/scripts/startup/function_nodes/nodes/__init__.py
+++ b/release/scripts/startup/function_nodes/nodes/__init__.py
@@ -1,13 +0,0 @@
-from . import (
- function_input,
- function_output,
-
- float_math,
- combine_vector,
- separate_vector,
- object_transforms,
- vector_distance,
- clamp,
- random_number,
- map_range,
-)
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/clamp.py b/release/scripts/startup/function_nodes/nodes/clamp.py
index 92f7a19046c..5f8cead91b2 100644
--- a/release/scripts/startup/function_nodes/nodes/clamp.py
+++ b/release/scripts/startup/function_nodes/nodes/clamp.py
@@ -12,6 +12,4 @@ class ClampNode(bpy.types.Node, FunctionNode):
("fn_FloatSocket", "Max"),
], [
("fn_FloatSocket", "Result"),
- ]
-
-bpy.utils.register_class(ClampNode)
\ No newline at end of file
+ ]
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/combine_vector.py b/release/scripts/startup/function_nodes/nodes/combine_vector.py
index cebd9f266f0..055491b9b86 100644
--- a/release/scripts/startup/function_nodes/nodes/combine_vector.py
+++ b/release/scripts/startup/function_nodes/nodes/combine_vector.py
@@ -12,6 +12,4 @@ class CombineVectorNode(bpy.types.Node, FunctionNode):
("fn_FloatSocket", "Z"),
], [
("fn_VectorSocket", "Result"),
- ]
-
-bpy.utils.register_class(CombineVectorNode)
\ No newline at end of file
+ ]
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/float_math.py b/release/scripts/startup/function_nodes/nodes/float_math.py
index f6b506529cb..7951925e496 100644
--- a/release/scripts/startup/function_nodes/nodes/float_math.py
+++ b/release/scripts/startup/function_nodes/nodes/float_math.py
@@ -27,6 +27,4 @@ class FloatMathNode(bpy.types.Node, FunctionNode):
]
def draw(self, layout):
- layout.prop(self, "operation", text="")
-
-bpy.utils.register_class(FloatMathNode)
\ No newline at end of file
+ layout.prop(self, "operation", text="")
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/function_input.py b/release/scripts/startup/function_nodes/nodes/function_input.py
index 4b57ad473b1..ea92fbf21e9 100644
--- a/release/scripts/startup/function_nodes/nodes/function_input.py
+++ b/release/scripts/startup/function_nodes/nodes/function_input.py
@@ -30,6 +30,3 @@ class FunctionInputNode(BaseNode, bpy.types.Node):
def remove_socket(self, index):
self.outputs.remove(self.outputs[index])
-
-
-bpy.utils.register_class(FunctionInputNode)
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/function_output.py b/release/scripts/startup/function_nodes/nodes/function_output.py
index 562fe636987..0fa485724d2 100644
--- a/release/scripts/startup/function_nodes/nodes/function_output.py
+++ b/release/scripts/startup/function_nodes/nodes/function_output.py
@@ -29,6 +29,4 @@ class FunctionOutputNode(BaseNode, bpy.types.Node):
self.inputs.new(idname, "Output")
def remove_socket(self, index):
- self.inputs.remove(self.inputs[index])
-
-bpy.utils.register_class(FunctionOutputNode)
\ No newline at end of file
+ self.inputs.remove(self.inputs[index])
\ No newline at end of file
diff --git a/release/scripts/startup/function_nodes/nodes/map_range.py b/release/scripts/startup/function_nodes/nodes/map_range.py
index f05a9fd9aa6..a8b971dfeeb 100644
--- a/release/scripts/startup/function_nodes/nodes/map_range.py
+++ b/release/scripts/startup/function_nodes/nodes/map_range.py
@@ -15,6 +15,4 @@ class MapRangeNode(bpy.types.Node, FunctionNode):
("fn_FloatSocket", "To Max"),
], [
("fn_FloatSocket", "Value"),
- ]
-
-bpy.utils.register_class(MapRangeNode)
\ No newline at end
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list