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

Fix Schema fail when Group linked to In/Outgoing

The problem was that I was attempting to get the next node
but it hadn't been generated yet because it was in a node group
There was never a problem with outgoing connection after all
it was only handling the held link from the outgoing connection
that was messed up, and only then if the next node was a group!

oddly, it did work in some situations with the old code
because the node groups were generated.

this code maybe could be cleaned up by forcing the node group
to generate as soon as it is encountered
but I think this solution, though less elegant, is better
since I can then deal with the connection to the node group
which is already handled well elsewhere. So this doesn't add
complexity or modify the schema solve as a system.
Brandenburg 3 недель назад
Родитель
Сommit
a11e4be7da
1 измененных файлов с 50 добавлено и 39 удалено
  1. 50 39
      schema_solve.py

+ 50 - 39
schema_solve.py

@@ -51,7 +51,7 @@ class SchemaSolver:
         self.solve_length = self.node.evaluate_input("Schema Length")
         # I'm making this a property of the solver because the solver's data is modified as it solves each iteration
         self.index = 0
-        
+
         prWhite(f"\nExpanding schema {self.tree.name} in node {self.node.signature}"
                  f" with length {self.solve_length}.")
 
@@ -66,14 +66,14 @@ class SchemaSolver:
         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 
+            # 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, 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
                 # uuid/index attached.
-                get_sig = (*self.node.ui_signature, ui_node.bl_idname) 
+                get_sig = (*self.node.ui_signature, ui_node.bl_idname)
                 if not (mantis_node := self.all_nodes.get(get_sig)):
                     raise RuntimeError(wrapRed(f"Not found: {get_sig}"))
                 self.schema_nodes[signature] = mantis_node
@@ -89,14 +89,14 @@ class SchemaSolver:
                 mantis_node = SchemaConstOutput(signature=signature, base_tree=self.node.base_tree, parent_schema_node=self.node)
                 self.schema_nodes[signature] = mantis_node
                 mantis_node.fill_parameters(ui_node)
-    
+
     def set_index_strings(self):
         self.index_str = lambda : '.'+str(self.uuid)+'.'+str(self.index).zfill(4)
         self.prev_index_str = lambda : '.'+str(self.uuid)+'.'+str(self.index-1).zfill(4)
         if self.is_node_group:
             self.index_str=lambda : ''
             self.prev_index_str=lambda : ''
-    
+
     def init_schema_links(self,):
         """ Sort and store the links to/from the Schema group node."""
         for item in self.tree.interface.items_tree:
@@ -110,7 +110,7 @@ class SchemaSolver:
                         if incoming_links := self.node.inputs[item.identifier].links:
                             self.incoming_connections[item.name] = incoming_links[0]
                         else:
-                            self.incoming_connections[item.name] = None 
+                            self.incoming_connections[item.name] = None
                     else: # OUTPUT
                         if outgoing_links := self.node.outputs[item.identifier].links:
                             self.outgoing_connections[item.name] = outgoing_links.copy()
@@ -143,9 +143,11 @@ class SchemaSolver:
                             self.array_output_connections[item.identifier]=[]
                         if out_links := self.node.outputs[item.identifier].links:
                             self.array_output_connections[item.identifier] = out_links.copy()
-    
 
-    
+
+
+    def is_node_deeper_nested(self, queried_node, compare_node):
+        return len(compare_node.signature) < len(queried_node.signature)
 
     def gen_solve_iteration_mantis_nodes(self, frame_mantis_nodes, unprepared):
         for prototype_ui_node in self.tree.nodes:
@@ -213,17 +215,17 @@ class SchemaSolver:
             signature = ("MANTIS_AUTOGENERATED", *self.tree_path_names[1:-1], unique_name)
             from_node = self.all_nodes.get(signature)
             if not from_node:
-                from_node = autogen_node(self.node.base_tree, ui_link.from_socket, 
+                from_node = autogen_node(self.node.base_tree, ui_link.from_socket,
                                 signature=signature, mContext=self.node.mContext)
                 from_node.parameters = {ui_link.from_socket.name:index}
                 frame_mantis_nodes[signature]=from_node; self.solved_nodes[signature]=from_node
                 self.all_nodes[signature]=from_node
             _connection = from_node.outputs[ui_link.from_socket.name].connect(node=to_node, socket=ui_link.to_socket.identifier)
-            return 
+            return
         # Since the index is already determined, it is safe to remove the socket and just keep the value.
         to_node.parameters[ui_link.to_socket.name] = index
         del to_node.inputs[ui_link.to_socket.name]
-    
+
     def handle_link_from_schema_length_input(self, frame_mantis_nodes, ui_link):
         # see, here I can just use the schema node
         _from_name, to_name = get_link_in_out(ui_link)
@@ -256,14 +258,31 @@ class SchemaSolver:
     def handle_link_to_outgoing_connection_output(self, frame_mantis_nodes, ui_link,):
         mantis_incoming_node = self.schema_nodes[*self.tree_path_names,  'SchemaIncomingConnection']
         for mantis_link in mantis_incoming_node.outputs[ui_link.to_socket.name].links:
-            to_mantis_node, to_mantis_socket = mantis_link.to_node, mantis_link.to_socket
+            to_mantis_node, to_socket_name = mantis_link.to_node, mantis_link.to_socket
             from_name = get_link_in_out(ui_link)[0]
             from_mantis_node = self.solved_nodes[ (*self.autogen_path_names, from_name+self.prev_index_str()) ]
-            to_mantis_node = frame_mantis_nodes[ (*self.autogen_path_names, to_mantis_node.signature[-1]+self.index_str()) ]
+
+            to_mantis_node_signature = ( *self.autogen_path_names,
+                            to_mantis_node.signature[-1] + self.index_str() )
+
+            # we need to detect if the next node is in a group.
+            # REMEMBER: at this point, nested groups haven't been solved yet.
+            if to_mantis_node_signature not in frame_mantis_nodes.keys() and \
+                    self.is_node_deeper_nested(to_mantis_node, from_mantis_node):
+                to_mantis_node = frame_mantis_nodes[ (
+                    *self.autogen_path_names, # the SCHEMA_AUTOGENERATED string
+                    to_mantis_node.signature[-2]+ self.index_str() ) ]
+                # this connection was forbidden before, right? so this should be a safe assumption.
+                assert to_mantis_node.node_type == 'DUMMY_SCHEMA', "I expected this to be a group/schema"
+                # we need to get the identifier of the named socket now.
+                to_socket_name = to_mantis_node.prototype.inputs[to_socket_name].identifier
+            else:
+                to_mantis_node = frame_mantis_nodes[ to_mantis_node_signature ] # add the index string
+
             from_socket_name = ui_link.from_socket.name
             if from_mantis_node.node_type in ['DUMMY_SCHEMA']:
                 from_socket_name = ui_link.from_socket.identifier
-            connection = from_mantis_node.outputs[from_socket_name].connect(node=to_mantis_node, socket=to_mantis_socket)
+            connection = from_mantis_node.outputs[from_socket_name].connect(node=to_mantis_node, socket=to_socket_name)
             # We want to delete the links from the tree into the schema node.
             # TODO: this is not robust enough and I do not feel sure this is doing the right thing.
             if existing_link := self.incoming_connections[ui_link.to_socket.name]:
@@ -273,7 +292,7 @@ class SchemaSolver:
                         existing_link.die()
             # BUG may exist here.
             self.incoming_connections[ui_link.to_socket.name] = connection
-        
+
 
     def handle_link_from_constant_input(self, frame_mantis_nodes, ui_link, to_ui_node):
         incoming = self.constant_in[ui_link.from_socket.name]
@@ -288,7 +307,7 @@ class SchemaSolver:
             to_socket=ui_link.to_socket.identifier
         connection = from_node.outputs[incoming.from_socket].connect(node=to_node, socket=to_socket)
         init_connections(from_node)
-    
+
     def handle_link_from_array_input_get(self, frame_mantis_nodes, ui_link ):
         from_ui_node = ui_link.from_socket.node
         from_node = self.schema_nodes[(*self.node.ui_signature, from_ui_node.bl_idname)]
@@ -478,7 +497,7 @@ class SchemaSolver:
         # connected up correctly. between the output and the schema's generated nodes.
         # so seek BACK from the output node and grab the from-node that is connected to
         #  the link. then modify the ui_link to point to that node.
-        from .base_definitions import DummyLink 
+        from .base_definitions import DummyLink
         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)
@@ -591,7 +610,7 @@ class SchemaSolver:
             if isinstance(from_ui_node, (SchemaConstInput, NodeGroupInput)):
                 if ui_link.from_socket.name in self.constant_in.keys():
                     self.handle_link_from_constant_input( frame_mantis_nodes, ui_link, to_ui_node)
-                continue 
+                continue
             if isinstance(to_ui_node, SchemaArrayInputGet):
                 self.handle_link_to_array_input_get( frame_mantis_nodes, ui_link)
                 continue
@@ -604,16 +623,9 @@ class SchemaSolver:
             # HOLD these links to the next iteration:
             if isinstance(to_ui_node, SchemaOutgoingConnection):
                 if isinstance(from_ui_node, (MantisNodeGroup, SchemaGroup)):
-                    e = NotImplementedError(
-                        "You have connected a Node Group or Schema directly into an Outgoing Connection node"
-                        " inside another Schema. This is not currently supported. Try using a Constant Output" \
-                        f" instead. Affected node: {from_ui_node.name}"
-                        )
-                    e = execution_error_cleanup(self.node, e, show_error=self.error_popups)
-                    raise e # always raise this error because it is not implemented.
                     self.handle_link_from_subschema_to_output(frame_mantis_nodes, ui_link, to_ui_node)
-                self.held_links.append(ui_link)
-                continue 
+                self.held_links.append(ui_link) # is this wise? Why am I doing this?
+                continue
             # HOLD these links until prep is done a little later
             if isinstance(to_ui_node, (SchemaConstOutput, NodeGroupOutput)) or isinstance(to_ui_node, SchemaArrayOutput):
                 if isinstance(from_ui_node, (MantisNodeGroup, SchemaGroup)):
@@ -630,12 +642,12 @@ class SchemaSolver:
             if isinstance(from_ui_node, SchemaArrayInputGet):
                 array_input_get_link.append(ui_link)
                 continue
-            
+
             # for any of the special cases, we hit a 'continue' block. So this connection is not special, and is made here.
             connection = link_node_containers(self.autogen_path_names, ui_link,
                                 frame_mantis_nodes, from_suffix=self.index_str(),
                                 to_suffix=self.index_str())
-        
+
         for signature, node in frame_mantis_nodes.items():
             self.solved_nodes[signature]=node
             if node.node_type == "DUMMY_SCHEMA":
@@ -651,15 +663,15 @@ class SchemaSolver:
                 init_schema_dependencies(node, self.all_nodes)
             else:
                 init_dependencies(node) # it is hard to overstate how important this single line of code is
-    
+
         # We have to prepare the nodes leading to Schema Length
         unprepared=deque()
-        for node in frame_mantis_nodes.values(): 
+        for node in frame_mantis_nodes.values():
             if node.node_type == 'DUMMY_SCHEMA' and (schema_len_in := node.inputs.get("Schema Length")):
                 for l in schema_len_in.links:
                     unprepared.append(l.from_node)
             self.prepare_nodes(unprepared)
-        
+
         # We have to prepare the nodes leading to Array Input Get
         for ui_link in array_input_get_link:
             from_name = get_link_in_out(ui_link)[0]
@@ -706,7 +718,7 @@ class SchemaSolver:
                 else:
                     self.handle_link_to_array_output(frame_mantis_nodes, self.index, ui_link, to_ui_node, from_ui_node)
         return frame_mantis_nodes
-    
+
     def solve_nested_schema(self, schema_nc):
         """ Solves all schema node groups found in this Schema. This is a recursive function, which will
             solve all levels of nested schema - since this function is called by solver.solve().
@@ -748,7 +760,7 @@ class SchemaSolver:
                             # we need to kill the link between the Schema itself and the next node and update the deps. Otherwise:confusing bugs.
                             outgoing.die(); init_dependencies(to_node)
                     # else: # the node just isn't connected out this socket.
-        
+
 
         # # solve all unsolved nested schemas...
         for schema_sig, schema_nc in self.nested_schemas.items():
@@ -770,18 +782,18 @@ class SchemaSolver:
         for conn in self.array_output_connections.values():
             for outgoing in conn:
                 all_outgoing_links.append(outgoing)
-        
+
         for outgoing in all_outgoing_links:
             to_node = outgoing.to_node
             for l in to_node.inputs[outgoing.to_socket].links:
                 if self.node == l.from_node:
                     l.die()
-        
+
         for inp in self.node.inputs.values():
             for l in inp.links:
                 init_connections(l.from_node) # to force it to have hierarchy connections with the new nodes.
-                    
-        
+
+
     def solve(self):
         if self.solve_length < 1:
             from .base_definitions import GraphError
@@ -802,4 +814,3 @@ class SchemaSolver:
         self.node.prepared = True
         prGreen(f"Schema declared {len(self.solved_nodes)} nodes.\n")
         return self.solved_nodes
-