瀏覽代碼

Fix: Schema import fail in JSON I/O

This one was caused by the relink-socket stuff in the node-group
updating code, which is confusing and badly written
TODO: refactor this part of the code because it is TERRIBLE.
Joseph Brandenburg 6 月之前
父節點
當前提交
c6c264771f
共有 3 個文件被更改,包括 88 次插入75 次删除
  1. 16 5
      base_definitions.py
  2. 8 18
      i_o.py
  3. 64 52
      utilities.py

+ 16 - 5
base_definitions.py

@@ -250,6 +250,8 @@ def poll_node_tree(self, object):
 
 # TODO: try to check identifiers instead of name.
 def node_group_update(node, force = False):
+    if not node.is_updating:
+        raise RuntimeError("Cannot update node while it is not marked as updating.")
     if not force:
         if (node.id_data.do_live_update == False) or  \
            (node.id_data.is_executing == True) or \
@@ -314,11 +316,13 @@ def node_group_update(node, force = False):
         return
 
     if update_input or update_output:
+        socket_map_in, socket_map_out = None, None
         socket_maps = get_socket_maps(node)
-        if socket_maps is None:
+        if socket_maps is None and force == False:
             node.id_data.do_live_update = toggle_update
             return
-        socket_map_in, socket_map_out = socket_maps
+        if socket_maps:
+            socket_map_in, socket_map_out = socket_maps
 
         if update_input :
             if node.bl_idname == 'MantisSchemaGroup':
@@ -334,16 +338,23 @@ def node_group_update(node, force = False):
 
         if update_output: node.outputs.clear()
 
+        from .utilities import relink_socket_map_add_socket
 
         for item in node.node_tree.interface.items_tree:
             if item.item_type != "SOCKET": continue
             if (item.in_out == 'INPUT' and update_input):
-                relink_socket_map(node, node.inputs, socket_map_in, item)
+                socket = relink_socket_map_add_socket(node, node.inputs, item)
+                if socket_map_in:
+                    do_relink(node, socket, socket_map_in)
+
             if (item.in_out == 'OUTPUT' and update_output):
-                relink_socket_map(node, node.outputs, socket_map_out, item)
+                socket = relink_socket_map_add_socket(node, node.outputs, item)
+                if socket_map_out:
+                    do_relink(node, socket, socket_map_out)
+
         
         # at this point there is no wildcard socket
-        if '__extend__' in socket_map_in.keys():
+        if socket_map_in and '__extend__' in socket_map_in.keys():
             do_relink(node, None, socket_map_in, in_out='INPUT', parent_name='Constant' )
 
         node.id_data.do_live_update = toggle_update

+ 8 - 18
i_o.py

@@ -534,19 +534,12 @@ def do_import(data, context):
             
             if sub_tree := propslist.get("node_tree"):
                 n.node_tree = bpy.data.node_groups.get(sub_tree)
-                if n.bl_idname == "MantisNodeGroup":
-                    from .base_definitions import node_group_update
-                    n.is_updating = True
-                    try:
-                        node_group_update(n, force = True)
-                    finally:
-                        n.is_updating=False
-                else:
-                    n.is_updating = True
-                    try:
-                        n.inputs.clear()
-                    finally:
-                        n.is_updating=False
+                from .base_definitions import node_group_update
+                n.is_updating = True
+                try:
+                    node_group_update(n, force = True)
+                finally:
+                    n.is_updating=False
             
             sockets_removed = []
             for i, (s_id, s_val) in enumerate(propslist["sockets"].items()):
@@ -558,7 +551,6 @@ def do_import(data, context):
                         continue
                 try:
                     if s_val["is_output"]: # for some reason it thinks the index is a string?
-                        # try:
                         if n.bl_idname == "MantisSchemaGroup":
                             n.is_updating = True
                             try:
@@ -584,10 +576,8 @@ def do_import(data, context):
                             elif n.bl_idname in ["NodeGroupOutput"]:
                                 pass # this is dealt with separately
                             else:
-                                prWhite(n.name, s_val["name"], s_id)
-                                for k,v in propslist["sockets"].items():
-                                    print(k,v)
-                                prRed(s_val["index"], len(n.inputs))
+                                prWhite("Not found: ", n.name, s_val["name"], s_id)
+                                prRed("Index: ", s_val["index"], "Number of inputs", len(n.inputs))
                                 raise NotImplementedError(wrapRed(f"{n.bl_idname} needs to be handled in JSON load."))
                         else: # most of the time
                             socket = n.inputs[int(s_val["index"])]

+ 64 - 52
utilities.py

@@ -166,7 +166,8 @@ def update_interface(interface, name, in_out, sock_type, parent_name):
     else:
         raise RuntimeError(wrapRed("Cannot add interface item to tree without specifying type."))
 
-def relink_socket_map(node, socket_collection, map, item, in_out=None):
+#UGLY BAD REFACTOR
+def relink_socket_map_add_socket(node, socket_collection, item, in_out=None,):
     if not in_out: in_out=item.in_out
     if node.bl_idname in ['MantisSchemaGroup'] and item.parent and item.parent.name == 'Array':
         multi = True if in_out == 'INPUT' else False
@@ -174,6 +175,15 @@ def relink_socket_map(node, socket_collection, map, item, in_out=None):
     else:
         s = socket_collection.new(type=item.socket_type, name=item.name, identifier=item.identifier)
     if item.parent.name == 'Array': s.display_shape = 'SQUARE_DOT'
+    return s
+
+# TODO REFACTOR THIS
+# I did this awful thing because I needed the above code
+# but I have provided this interface to Mantis
+# I did not follow the Single Responsibility Principle
+# I am now suffering for it, as I rightly deserve.
+def relink_socket_map(node, socket_collection, map, item, in_out=None,):
+    s = relink_socket_map_add_socket(node, socket_collection, item, in_out=None,)
     do_relink(node, s, map)
 
 def unique_socket_name(node, other_socket, tree):
@@ -218,68 +228,70 @@ def init_dependencies(nc):
     nc.hierarchy_dependencies = hc
     nc.dependencies = c
 
-
-def init_schema_dependencies(schema, all_nc):
-    """ Initialize the dependencies for Schema, and mark them as hierarchy or non-hierarchy dependencies
-        Non-hierarchy dependencies are e.g. drivers and custom transforms.
-    """
+def schema_dependency_handle_item(schema, all_nc, item,):
+    hierarchy = True
     from .base_definitions import from_name_filter, to_name_filter
-    from .utilities import get_node_prototype
-    np = get_node_prototype(schema.signature, schema.base_tree)
-    tree = np.node_tree
-    schema.dependencies = []
-    schema.hierarchy_dependencies = []
-    for item in tree.interface.items_tree:
-        if item.item_type == 'PANEL':
-            continue
-        hierarchy = True
-        # hierarchy_reason=""
-        if item.in_out == 'INPUT':
-            c = schema.dependencies
-            hc = schema.hierarchy_dependencies
-            if item.parent and item.parent.name == 'Array':
-                for t in ['SchemaArrayInput', 'SchemaArrayInputGet']:
-                    if (nc := all_nc.get( (*schema.signature, t) )):
-                        for to_link in nc.outputs[item.name].links:
-                            if to_link.to_socket in to_name_filter:
-                                # hierarchy_reason='a'
-                                hierarchy = False
-                        for from_link in schema.inputs[item.identifier].links:
-                            if from_link.from_socket in from_name_filter:
-                                hierarchy = False
-                                # hierarchy_reason='b'
-                        if from_link.from_node not in c:
-                            if hierarchy:
-                                hc.append(from_link.from_node)
-                            c.append(from_link.from_node)
-            if item.parent and item.parent.name == 'Constant':
-                if nc := all_nc.get((*schema.signature, 'SchemaConstInput')):
-                    for to_link in nc.outputs[item.name].links:
-                        if to_link.to_socket in to_name_filter:
-                            # hierarchy_reason='c'
-                            hierarchy = False
-                    for from_link in schema.inputs[item.identifier].links:
-                        if from_link.from_socket in from_name_filter:
-                            # hierarchy_reason='d'
-                            hierarchy = False
-                    if from_link.from_node not in c:
-                        if hierarchy:
-                            hc.append(from_link.from_node)
-                        c.append(from_link.from_node)
-            if item.parent and item.parent.name == 'Connection':
-                if nc := all_nc.get((*schema.signature, 'SchemaIncomingConnection')):
+    if item.in_out == 'INPUT':
+        c = schema.dependencies
+        hc = schema.hierarchy_dependencies
+        if item.parent and item.parent.name == 'Array':
+            for t in ['SchemaArrayInput', 'SchemaArrayInputGet']:
+                if (nc := all_nc.get( (*schema.signature, t) )):
                     for to_link in nc.outputs[item.name].links:
                         if to_link.to_socket in to_name_filter:
-                            # hierarchy_reason='e'
+                            # hierarchy_reason='a'
                             hierarchy = False
                     for from_link in schema.inputs[item.identifier].links:
                         if from_link.from_socket in from_name_filter:
-                            # hierarchy_reason='f'
                             hierarchy = False
+                            # hierarchy_reason='b'
                     if from_link.from_node not in c:
                         if hierarchy:
                             hc.append(from_link.from_node)
                         c.append(from_link.from_node)
+        if item.parent and item.parent.name == 'Constant':
+            if nc := all_nc.get((*schema.signature, 'SchemaConstInput')):
+                for to_link in nc.outputs[item.name].links:
+                    if to_link.to_socket in to_name_filter:
+                        # hierarchy_reason='c'
+                        hierarchy = False
+                for from_link in schema.inputs[item.identifier].links:
+                    if from_link.from_socket in from_name_filter:
+                        # hierarchy_reason='d'
+                        hierarchy = False
+                if from_link.from_node not in c:
+                    if hierarchy:
+                        hc.append(from_link.from_node)
+                    c.append(from_link.from_node)
+        if item.parent and item.parent.name == 'Connection':
+            if nc := all_nc.get((*schema.signature, 'SchemaIncomingConnection')):
+                for to_link in nc.outputs[item.name].links:
+                    if to_link.to_socket in to_name_filter:
+                        # hierarchy_reason='e'
+                        hierarchy = False
+                for from_link in schema.inputs[item.identifier].links:
+                    if from_link.from_socket in from_name_filter:
+                        # hierarchy_reason='f'
+                        hierarchy = False
+                if from_link.from_node not in c:
+                    if hierarchy:
+                        hc.append(from_link.from_node)
+                    c.append(from_link.from_node)
+
+def init_schema_dependencies(schema, all_nc, raise_errors=False):
+    """ Initialize the dependencies for Schema, and mark them as hierarchy or non-hierarchy dependencies
+        Non-hierarchy dependencies are e.g. drivers and custom transforms.
+    """
+    from .utilities import get_node_prototype
+    np = get_node_prototype(schema.signature, schema.base_tree)
+    tree = np.node_tree
+    schema.dependencies = []
+    schema.hierarchy_dependencies = []
+    for item in tree.interface.items_tree:
+        if item.item_type == 'PANEL':
+            continue
+        schema_dependency_handle_item(schema, all_nc, item,)
+        
 
 
 def check_and_add_root(n, roots, include_non_hierarchy=False):