Просмотр исходного кода

io: Fix export missing some curve dependencies

Joseph Brandenburg 2 месяцев назад
Родитель
Сommit
db4e5bce7f
1 измененных файлов с 83 добавлено и 41 удалено
  1. 83 41
      i_o.py

+ 83 - 41
i_o.py

@@ -106,7 +106,8 @@ def TellClasses():
     return [ MantisExportNodeTreeSaveAs,
             MantisExportNodeTreeSave,
             MantisExportNodeTree,
-            MantisImportNodeTree, 
+            MantisImportNodeTree,
+            MantisImportNodeTreeNoMenu,
             MantisReloadNodeTree]
 
 # https://stackoverflow.com/questions/42033142/is-there-an-easy-way-to-check-if-an-object-is-json-serializable-in-python - thanks!
@@ -172,48 +173,78 @@ def fix_custom_parameter(n, property_definition, ):
 # to see if a dependency is created by node connections.
 # TODO it remains to be seen if that is even a desirable behaviour.
 def scan_tree_for_objects(base_tree, current_tree):
-    from bpy import data
+    # this should work 
     armatures, curves    = set(), set()
-    for node in current_tree.nodes:
-        match node.bl_idname:
+    if current_tree == base_tree:
+        scan_tree_dependencies(base_tree, curves, armatures,)
+    return (curves, armatures )
+
+def scan_tree_dependencies(base_tree, curves:set, armatures:set, ):
+    from .utilities import check_and_add_root
+    from collections import deque
+    from bpy import context, data
+    xForm_pass = deque()
+    if base_tree.tree_valid:
+        nodes = base_tree.parsed_tree
+    else:
+        base_tree.update_tree(context=context)
+        nodes = base_tree
+    for nc in nodes.values():
+        nc.reset_execution()
+        check_and_add_root(nc, xForm_pass)
+    from .readtree import sort_execution
+    from .utilities import get_node_prototype
+    sorted_nodes, execution_failed = sort_execution(nodes, xForm_pass)
+    if execution_failed:
+        prRed("Error reading dependencies from tree, skipping")
+        return curves, armatures
+    for n in sorted_nodes:
+        if n.ui_signature is None:
+            continue # doesn't matter
+        ui_node = get_node_prototype(n.ui_signature, n.base_tree)
+        if not ui_node:
+            continue
+        # we need to see if it is receiving a Curve
+        # so check the ui_node if it is a socket that takes an object
+        for s in ui_node.inputs:
+            if s.bl_idname in 'EnumCurveSocket':
+                curve_name = n.evaluate_input(s.name)
+                prRed(curve_name)
+                if curve := data.objects.get(curve_name):
+                    curves.add(curve)
+                else:
+                    raise NotImplementedError(curve_name)
+        match ui_node.bl_idname:
             case "UtilityMetaRig":
-                if node.inputs[0].is_linked:
-                    continue
-                if (armature := node.inputs[0].search_prop) is not None:
+                armature_name = n.evaluate_input("Meta-Armature")
+                prWhite(armature_name)
+                if armature := data.objects.get(armature_name):
                     armatures.add(armature)
             case "InputExistingGeometryObjectNode":
-                if node.inputs["Name"].is_linked:
-                    continue
-                ob_name = node.inputs["Name"].default_value
-                if ob := data.objects.get(ob_name):
-                    if ob.type == "ARMATURE":
-                        armatures.add(ob)
-                    elif ob.type == "CURVE":
-                        curves.add(ob)
-            case "xFormArmatureNode":
-                if node.inputs["Name"].is_linked:
-                    continue
-                armature_name = node.inputs["Name"].default_value
-                armature = data.objects.get(armature_name)
-                if armature:
-                    armatures.add(armature)
+                object_name = n.evaluate_input("Name")
+                prWhite(object_name)
+                if object := data.objects.get(object_name):
+                    if object.type == "ARMATURE":
+                        armatures.add(object)
+                    elif object.type == "CURVE":
+                        curves.add(object)
+            # Usually we don't want an object that is generated by the tree
+            # case "xFormArmatureNode":
+            #     armature_name = n.evaluate_input("Name")
+            #     prWhite(armature_name)
+            #     if armature := data.objects.get(armature_name):
+            #         armatures.add(armature)
             case "xFormGeometryObjectNode":
-                if node.inputs["Name"].is_linked:
-                    continue
-                ob_name = node.inputs["Name"].default_value
-                if ob := data.objects.get(ob_name):
-                    if ob.type == "ARMATURE":
-                        armatures.add(ob)
-                    elif ob.type == "CURVE":
-                        curves.add(ob)
-        for input in node.inputs:
-            if input.bl_idname in ["EnumCurveSocket"]:
-                if input.search_prop is not None:
-                    curves.add(input.search_prop)
-    # NOW check the parsed_tree and see if it is possible to find any other
-    # objects referred to/provided by the tree
+                object_name = n.evaluate_input("Name")
+                prWhite(object_name)
+                if object := data.objects.get(object_name):
+                    if object.type == "ARMATURE":
+                        armatures.add(object)
+                    elif object.type == "CURVE":
+                        curves.add(object)
     return (curves, armatures )
 
+# TODO move these dataclasses into a new file
 from dataclasses import dataclass, field, asdict
 # some basic classes to define curve point types
 @dataclass
@@ -1097,7 +1128,7 @@ def do_import(data, context, search_multi_files=False, filepath=''):
         tree.do_live_update = True
         
 
-def export_multi_file(trees : list, filepath : str, base_name :str) -> None:
+def export_multi_file(trees : list,  base_tree, filepath : str, base_name :str) -> None:
     for t in trees:
         # this should name them the name of the tree...
         from bpy.path import native_pathsep, clean_name
@@ -1105,7 +1136,7 @@ def export_multi_file(trees : list, filepath : str, base_name :str) -> None:
         from os import mkdir
         native_filepath = native_pathsep(filepath)
         directory = os_path.split(native_filepath)[0]
-        export_data = export_to_json([t], os_path.join(directory,
+        export_data = export_to_json([t], base_tree, os_path.join(directory,
                         clean_name(t.name)+'.rig'))
         write_json_data(export_data, os_path.join(directory,
                         clean_name(t.name)+'.rig'))
@@ -1158,7 +1189,7 @@ class MantisExportNodeTreeSaveAs(Operator, ExportHelper):
             export_data = export_to_json(trees, base_tree, self.filepath)
             write_json_data(export_data, self.filepath)
         else:
-            export_multi_file(trees, self.filepath, base_tree.name)
+            export_multi_file(trees, base_tree, self.filepath, base_tree.name)
         base_tree.is_exporting = False
         base_tree.prevent_next_exec = True
         # set the properties on the base tree for re-exporting with alt-s
@@ -1186,10 +1217,10 @@ class MantisExportNodeTreeSave(Operator):
             prGreen ("Node graph: \"%s\"" % (t.name))
         base_tree.is_exporting = True
         if base_tree.export_all_subtrees_together:
-            export_data = export_to_json(trees, filepath)
+            export_data = export_to_json(trees, base_tree, filepath)
             write_json_data(export_data, filepath)
         else:
-            export_multi_file(trees, filepath, base_tree.name)
+            export_multi_file(trees, base_tree,  filepath, base_tree.name)
         base_tree.is_exporting = False
         base_tree.prevent_next_exec = True
         return {'FINISHED'}
@@ -1244,6 +1275,17 @@ class MantisImportNodeTree(Operator, ImportHelper):
         return do_import_from_file(self.filepath, context)
 
 
+
+class MantisImportNodeTreeNoMenu(Operator):
+    """Import a Mantis Node Tree."""
+    bl_idname = "mantis.import_tree_no_menu"
+    bl_label = "Import Mantis Tree (.rig)"
+
+    filepath : StringProperty()
+
+    def execute(self, context):
+        return do_import_from_file(self.filepath, context)
+
 # this is useful:
 # https://blender.stackexchange.com/questions/73286/how-to-call-a-confirmation-dialog-box