浏览代码

fix: subschema cannot link into parent schema

this happened because the subschema requested a node in
the parent schema which was not in the all_nodes collection yet
because it was a member of the same frame as the
sub-schema. the solution is simple: just keep all_nodes
up-to-date

looking back at the code... were the schema nodes ever added
to all_nodes? it looks like the all_nodes was just all the
nodes that existed before the schema was generated?

this commit also does a little cleanup that is not intended to
change behaviour, but might in some rare cases. If it does, I
expect the changes only to be positive.
Joseph Brandenburg 5 月之前
父节点
当前提交
cf2953f480
共有 2 个文件被更改,包括 18 次插入20 次删除
  1. 1 0
      internal_containers.py
  2. 17 20
      schema_solve.py

+ 1 - 0
internal_containers.py

@@ -10,6 +10,7 @@ class DummyNode(MantisNode):
         self.node_type = 'DUMMY'
         self.prepared = True
         self.uuid = uuid4()
+        self.solver = None
         if prototype:
             if prototype.bl_idname in ["MantisSchemaGroup"]:
                 self.node_type = 'DUMMY_SCHEMA'

+ 17 - 20
schema_solve.py

@@ -15,6 +15,8 @@ class SchemaSolver:
     def __init__(self, schema_dummy, nodes, prototype, signature=None, error_popups=False):
         self.all_nodes = nodes # this is the parsed tree from Mantis
         self.node = schema_dummy
+        self.node.solver = self
+        self.solved = False
         self.tree = prototype.node_tree
         self.uuid = self.node.uuid
         self.error_popups = error_popups
@@ -50,7 +52,7 @@ class SchemaSolver:
         # I'm making this a property of the solver because the solver's data is modified as it solves each iteration
         self.index = 0
         
-        prOrange(f"\nExpanding schema {self.tree.name} in node {self.node.signature}"
+        prWhite(f"\nExpanding schema {self.tree.name} in node {self.node.signature}"
                  f" with length {self.solve_length}.")
 
         self.init_schema_links()
@@ -61,11 +63,12 @@ class SchemaSolver:
         for inp in self.node.inputs.values():
             inp.links.sort(key=lambda a : -a.multi_input_sort_id)
 
+        from bpy.types import NodeGroupInput, NodeGroupOutput
         for ui_node in self.tree.nodes:
             # first we need to fill the parameters of the schema nodes.
             # we use the bl_idname because all schema nodes should be single-instance 
             signature = (*self.tree_path_names, ui_node.bl_idname)
-            if isinstance(ui_node, SchemaUINode):
+            if isinstance(ui_node, (SchemaUINode, NodeGroupInput, NodeGroupOutput)):
                 # We use the schema node's "natural signature" here because it represents
                 # the "original" signature of the schema UI group node since this schema
                 # solver may be in a nested schema, and its node's signature may have
@@ -185,6 +188,7 @@ class SchemaSolver:
             else:
                 mantis_node = prototype_mantis_node.__class__(signature, prototype_mantis_node.base_tree)
             frame_mantis_nodes[mantis_node.signature] = mantis_node
+            self.all_nodes[mantis_node.signature] = mantis_node
             mantis_node.ui_signature=ui_signature # set the natural signature to ensure we can access from the UI
             if mantis_node.prepared == False:
                 unprepared.append(mantis_node)
@@ -452,29 +456,22 @@ class SchemaSolver:
                 else:
                     from_socket_name = ui_link.from_socket.name
 
-            # I have a feeling that something bad will happen if both of these conditions (above and below) are true
             if to_node.node_type == 'DUMMY_SCHEMA' and to_node.prepared:
                 other_stem = ('SCHEMA_AUTOGENERATED', *to_node.signature[1:])
-                from .utilities import get_node_prototype
-                other_schema_np = get_node_prototype(to_node.signature, to_node.base_tree)
+                other_schema_np = to_node.prototype
                 other_schema_tree = other_schema_np.node_tree
                 for n in other_schema_tree.nodes:
-                    if n.bl_idname not in ["SchemaArrayInput", "SchemaArrayInputGet"]:
+                    if n.bl_idname not in ["SchemaArrayInput", "SchemaArrayInputGet", "SchemaArrayInputAll"]:
                         continue
                     out = n.outputs[outgoing.to_socket]
                     for l in out.links:
                         other_index_str = lambda : '.'+str(to_node.uuid)+'.'+str(index).zfill(4)
-                        # get it by [], we want a KeyError if this fails
-                        try:
-                            out_node = self.all_nodes[(*other_stem, l.to_node.name+other_index_str())]
-                        except KeyError as e:
-                            for n in self.all_nodes:
-                                if len(n) > len(other_stem)+1: break
-                                for elem in other_stem:
-                                    if elem not in n: break
-                                else:
-                                    print(n)
-                            raise e
+                        other_sig = (*other_stem, l.to_node.name+other_index_str())
+                        out_node = self.all_nodes.get(other_sig)
+                        if not out_node: # if it is a sub-schema, the other node is in the parent
+                            out_node = to_node.solver.all_nodes.get(other_sig)
+                        if not out_node:
+                            raise KeyError(f"Cannot find node:  {other_sig}")
                         connection = from_node.outputs[from_socket_name].connect(node=out_node, socket=l.to_socket.name)
             else:
                 connection = from_node.outputs[from_socket_name].connect(node=to_node, socket=outgoing.to_socket)
@@ -490,7 +487,7 @@ class SchemaSolver:
         if not isinstance(ui_link, DummyLink): # make it a Dummy so i can modify it
             ui_link = DummyLink(ui_link.from_socket, ui_link.to_socket,
                                 multi_input_sort_id=ui_link.multi_input_sort_id)
-        to_node = self.schema_nodes[(*self.node.ui_signature, to_ui_node.bl_idname)]
+        to_node = self.schema_nodes[(*self.tree_path_names, to_ui_node.bl_idname)]
         for inp in to_node.inputs:
             if inp.name == ui_link.to_socket.name: # the most recent one is from
                 l = inp.links[-1]; break # <----  this index of the outer schema
@@ -791,8 +788,8 @@ class SchemaSolver:
                 if nc.node_type == 'DUMMY_SCHEMA':
                     self.nested_schemas[sig] = nc
         self.finalize(frame_mantis_nodes)
-        self.node.solver = self
+        self.solved = True
         self.node.prepared = True
-        prWhite(f"Schema declared {len(self.solved_nodes)} nodes.\n")
+        prGreen(f"Schema declared {len(self.solved_nodes)} nodes.\n")
         return self.solved_nodes