Jelajahi Sumber

UI: Autoload Components feature

Joseph Brandenburg 2 bulan lalu
induk
melakukan
a6833eaa6c
4 mengubah file dengan 75 tambahan dan 10 penghapusan
  1. 38 1
      __init__.py
  2. 27 4
      i_o.py
  3. 4 3
      preferences.py
  4. 6 2
      utilities.py

+ 38 - 1
__init__.py

@@ -318,7 +318,43 @@ def version_update_handler(filename):
                (node_tree.mantis_version[1] < MANTIS_VERSION_MINOR) or \
                (node_tree.mantis_version[2] < MANTIS_VERSION_SUB):
                 do_version_update(node_tree)
-                
+
+@persistent
+def autoload_components(filename):
+    # this should not be blocking or slow!
+    print("Auto-loading components")
+    from os import path as os_path
+    from .utilities import get_component_library_items, get_default_collection
+    from .i_o import do_import
+    from .preferences import get_bl_addon_object
+    import json
+    from bpy import context, data
+    bl_addon_object = get_bl_addon_object()
+    unlink_curves = True
+    unlink_armatures = True
+    if data.collections.get(bl_addon_object.preferences.CurveDefaultCollection):
+        unlink_curves=False
+    if data.collections.get(bl_addon_object.preferences.MetaArmatureDefaultCollection):
+        unlink_armatures=False
+    base_path = bl_addon_object.preferences.ComponentsAutoLoadFolder
+    components = get_component_library_items(path='AUTOLOAD')
+    for autoload_component in components:
+        path = os_path.join(base_path, autoload_component[0])
+        with open(path, 'r', encoding='utf-8') as f:
+            json_data = json.load(f)
+            do_import(json_data, context,
+                       search_multi_files=True, filepath=path,
+                       skip_existing=True)
+    # now we need to unlink the collections, and add fake users to them
+    curves_collection = get_default_collection(collection_type="CURVE")
+    armature_collection = get_default_collection(collection_type="ARMATURE")
+    if unlink_curves and (curves_collection := data.collections.get(
+            bl_addon_object.preferences.CurveDefaultCollection)):
+        context.scene.collection.children.unlink(curves_collection)
+    if unlink_armatures and (armature_collection := data.collections.get(
+            bl_addon_object.preferences.MetaArmatureDefaultCollection)):
+        context.scene.collection.children.unlink(armature_collection)
+
 
 # I'll need to do some fiddling here when it comes time to try
 #   and make rig definitions animatable.
@@ -370,6 +406,7 @@ def register():
     # add the handlers
     bpy.app.handlers.depsgraph_update_pre.insert(0, update_handler)
     bpy.app.handlers.depsgraph_update_post.insert(0, execute_handler)
+    bpy.app.handlers.load_post.insert(0, autoload_components)
     bpy.app.handlers.load_post.insert(0, version_update_handler)
     bpy.app.handlers.animation_playback_pre.insert(0, on_animation_playback_pre_handler)
     bpy.app.handlers.animation_playback_post.insert(0, on_animation_playback_post_handler)

+ 27 - 4
i_o.py

@@ -916,10 +916,10 @@ def get_graph_data_from_json(filepath) -> dict:
     return data
 
 
-def do_import(data, context, search_multi_files=False, filepath=''):
+def do_import(data, context, search_multi_files=False, filepath='', skip_existing=False):
     trees = []
     tree_sock_id_maps = {}
-
+    skip_trees = set()
     # First: init the interface of the node graph
     for tree_name, tree_data in data.items():
         tree_info = tree_data[0]
@@ -944,6 +944,9 @@ def do_import(data, context, search_multi_files=False, filepath=''):
 
         # need to make a new tree; first, try to get it:
         tree = bpy.data.node_groups.get(tree_info["name"])
+        if tree and skip_existing:
+            skip_trees.add(tree.name)
+            continue # already done here because the tree already exists.
         if tree is None:
             tree = bpy.data.node_groups.new(tree_info["name"], tree_info["bl_idname"])
         tree.nodes.clear(); tree.links.clear(); tree.interface.clear()
@@ -1002,6 +1005,8 @@ def do_import(data, context, search_multi_files=False, filepath=''):
         
     # Now go and do nodes and links
     for tree_name, tree_data in data.items():
+        if tree_name in skip_trees:
+            continue
         print ("Importing sub-graph: %s with %s nodes" % (wrapGreen(tree_name), wrapPurple(len(tree_data[2]))) )
 
         tree_info = tree_data[0]
@@ -1272,8 +1277,26 @@ class MantisImportNodeTree(Operator, ImportHelper):
     )
 
     def execute(self, context):
-        return do_import_from_file(self.filepath, context)
-
+        import cProfile
+        from os import environ
+        do_profile=False
+        if environ.get("DOPROFILE"):
+            do_profile=True
+        pass_error = True
+        if do_profile:
+            import pstats, io
+            from pstats import SortKey
+            with cProfile.Profile() as pr:
+                return_value = do_import_from_file(self.filepath, context)
+                s = io.StringIO()
+                sortby = SortKey.TIME
+                # sortby = SortKey.CUMULATIVE
+                ps = pstats.Stats(pr, stream=s).strip_dirs().sort_stats(sortby)
+                ps.print_stats(20) # print the top 20
+                print(s.getvalue())
+                return return_value
+        else:
+            return do_import_from_file(self.filepath, context)
 
 
 class MantisImportNodeTreeNoMenu(Operator):

+ 4 - 3
preferences.py

@@ -80,12 +80,12 @@ class MantisPreferences(bpy.types.AddonPreferences):
         name = "Component Library Folder",
         description = "Location of .rig files to place in the Add Armature menu.",
         subtype = 'FILE_PATH',
-        default = os.path.join(dir_path, 'widgets'),)
+        default = os.path.join(dir_path, 'component_packs'),)
     ComponentsAutoLoadFolder:bpy.props.StringProperty(
         name = "Component Autoload Folder",
         description = "Location of .rig files to load automatically.",
         subtype = 'FILE_PATH',
-        default = os.path.join(dir_path, 'widgets'),)
+        default = os.path.join(dir_path, 'auto_load_components'),)
     
     def draw(self, context):
         layout = self.layout
@@ -94,4 +94,5 @@ class MantisPreferences(bpy.types.AddonPreferences):
         layout.prop(self, "WidgetDefaultCollection")
         layout.prop(self, "ComponentsLibraryFolder", icon='FILE_FOLDER')
         layout.prop(self, "CurveDefaultCollection")
-        layout.prop(self, "MetaArmatureDefaultCollection")
+        layout.prop(self, "MetaArmatureDefaultCollection")
+        layout.prop(self, "ComponentsAutoLoadFolder", icon='FILE_FOLDER')

+ 6 - 2
utilities.py

@@ -520,13 +520,17 @@ def import_curve_data_to_object(curve_name, curve_data):
     collection.objects.link(curve_object)
     return curve_object
 
-def get_component_library_items():
+def get_component_library_items(path='ADD_ARMATURE'):
     from os import path as os_path
     from .preferences import get_bl_addon_object
     bl_mantis_addon = get_bl_addon_object()
     return_value=[]
     if bl_mantis_addon:
-        components_path = bl_mantis_addon.preferences.ComponentsLibraryFolder
+        match path:
+            case 'ADD_ARMATURE':
+                components_path = bl_mantis_addon.preferences.ComponentsLibraryFolder
+            case 'AUTOLOAD':
+                components_path = bl_mantis_addon.preferences.ComponentsAutoLoadFolder
         component_names = {}
         from os import walk as os_walk
         for path_root, dirs, files, in os_walk(components_path):