|
@@ -272,98 +272,112 @@ def solve_schema_to_tree(nc, all_nc, roots=[]):
|
|
|
# PARSE NODE TREE #
|
|
# PARSE NODE TREE #
|
|
|
# *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** #
|
|
# *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** # *** #
|
|
|
|
|
|
|
|
|
|
+schema_bl_idnames = [ "SchemaIndex",
|
|
|
|
|
+ "SchemaArrayInput",
|
|
|
|
|
+ "SchemaArrayInputGet",
|
|
|
|
|
+ "SchemaArrayOutput",
|
|
|
|
|
+ "SchemaConstInput",
|
|
|
|
|
+ "SchemaConstOutput",
|
|
|
|
|
+ "SchemaOutgoingConnection",
|
|
|
|
|
+ "SchemaIncomingConnection",
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
from .utilities import get_all_dependencies
|
|
from .utilities import get_all_dependencies
|
|
|
-def get_schema_length_dependencies(node):
|
|
|
|
|
- """ Find all of the nodes that the Schema Length input depends on. """
|
|
|
|
|
- # the deps recursively from the from_nodes connected to Schema Length
|
|
|
|
|
|
|
+def get_schema_length_dependencies(node, all_nodes={}):
|
|
|
|
|
+ """ Get a list of all dependencies for the given node's length or array properties.
|
|
|
|
|
+ This function will also recursively search for dependencies in its sub-trees.
|
|
|
|
|
+ """
|
|
|
deps = []
|
|
deps = []
|
|
|
- # return get_all_dependencies(node)
|
|
|
|
|
- inp = node.inputs.get("Schema Length")
|
|
|
|
|
- if not inp:
|
|
|
|
|
- inp = node.inputs.get("Array")
|
|
|
|
|
|
|
+ prepare_links_to = ['Schema Length','Array', 'Index']
|
|
|
|
|
+ def extend_dependencies_from_inputs(node):
|
|
|
|
|
+ for inp in node.inputs.values():
|
|
|
|
|
+ for l in inp.links:
|
|
|
|
|
+ if "MANTIS_AUTOGENERATED" in l.from_node.signature:
|
|
|
|
|
+ deps.extend([l.from_node]) # why we need this lol
|
|
|
|
|
+ if inp in prepare_links_to:
|
|
|
|
|
+ deps.extend(get_all_dependencies(l.from_node))
|
|
|
|
|
+ def deps_filter(dep): # remove any nodes inside the schema
|
|
|
|
|
+ if len(dep.signature) > len(node.signature):
|
|
|
|
|
+ for i in range(len(node.signature)):
|
|
|
|
|
+ dep_sig_elem, node_sig_elem = dep.signature[i], node.signature[i]
|
|
|
|
|
+ if dep_sig_elem != node_sig_elem: break # they don't match, it isn't an inner-node
|
|
|
|
|
+ else: # remove this, it didn't break, meaning it shares signature with outer node
|
|
|
|
|
+ return False # this is an inner-node
|
|
|
|
|
+ return True
|
|
|
|
|
+ pass
|
|
|
# this way we can handle Schema and Array Get nodes with one function
|
|
# this way we can handle Schema and Array Get nodes with one function
|
|
|
- # ... since I may add more in the future this is not a robust solution HACK
|
|
|
|
|
- for l in inp.links:
|
|
|
|
|
- deps.extend(get_all_dependencies(l.from_node))
|
|
|
|
|
- if inp := node.inputs.get("Index"):
|
|
|
|
|
- for l in inp.links:
|
|
|
|
|
- deps.extend(get_all_dependencies(l.from_node))
|
|
|
|
|
- # now get the auto-generated simple inputs. These should not really be there but I haven't figured out how to set things directly yet lol
|
|
|
|
|
- for inp in node.inputs.values():
|
|
|
|
|
- for l in inp.links:
|
|
|
|
|
- if "MANTIS_AUTOGENERATED" in l.from_node.signature:
|
|
|
|
|
- # l.from_node.bPrepare() # try this...
|
|
|
|
|
- # l.from_node.prepared = True; l.from_node.executed = True
|
|
|
|
|
- deps.extend([l.from_node]) # why we need this lol
|
|
|
|
|
-
|
|
|
|
|
- return deps
|
|
|
|
|
|
|
+ extend_dependencies_from_inputs(node)
|
|
|
|
|
+ if node.node_type == 'DUMMY_SCHEMA':
|
|
|
|
|
+ trees = [(node.prototype.node_tree, node.signature)] # this is UI data
|
|
|
|
|
+ while trees:
|
|
|
|
|
+ tree, tree_signature = trees.pop()
|
|
|
|
|
+ print(tree_signature)
|
|
|
|
|
+ for sub_ui_node in tree.nodes:
|
|
|
|
|
+ if sub_ui_node.bl_idname in ['NodeReroute', 'NodeFrame']:
|
|
|
|
|
+ continue
|
|
|
|
|
+ if sub_ui_node.bl_idname in schema_bl_idnames:
|
|
|
|
|
+ sub_node = all_nodes[(*tree_signature, sub_ui_node.bl_idname)]
|
|
|
|
|
+ else:
|
|
|
|
|
+ sub_node = all_nodes[(*tree_signature, sub_ui_node.name)]
|
|
|
|
|
+ if sub_node.node_type == 'DUMMY_SCHEMA':
|
|
|
|
|
+ extend_dependencies_from_inputs(sub_node)
|
|
|
|
|
+ trees.append((sub_node.prototype.node_tree, sub_node.signature))
|
|
|
|
|
+
|
|
|
|
|
+ filtered_deps = filter(deps_filter, deps)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ return list(filtered_deps)
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-def parse_tree(base_tree):
|
|
|
|
|
- from uuid import uuid4 # do this here?
|
|
|
|
|
- base_tree.execution_id = uuid4().__str__() # set this, it may be used by nodes during execution
|
|
|
|
|
|
|
|
|
|
|
|
+def parse_tree(base_tree):
|
|
|
|
|
+ from uuid import uuid4
|
|
|
|
|
+ base_tree.execution_id = uuid4().__str__() # set the unique id of this execution
|
|
|
|
|
+
|
|
|
|
|
+ import time
|
|
|
|
|
+ data_start_time = time.time()
|
|
|
# annoyingly I have to pass in values for all of the dicts because if I initialize them in the function call
|
|
# annoyingly I have to pass in values for all of the dicts because if I initialize them in the function call
|
|
|
# then they stick around because the function definition inits them once and keeps a reference
|
|
# then they stick around because the function definition inits them once and keeps a reference
|
|
|
# so instead I have to supply them to avoid ugly code or bugs elsewhere
|
|
# so instead I have to supply them to avoid ugly code or bugs elsewhere
|
|
|
- # it's REALLY confusing when you run into this sort of problem. So it warrants four entire lines of comments!
|
|
|
|
|
- import time
|
|
|
|
|
-
|
|
|
|
|
- data_start_time = time.time()
|
|
|
|
|
-
|
|
|
|
|
- dummy_nodes, all_nc, all_schema = data_from_tree(base_tree, tree_path = [None], dummy_nodes = {}, all_nc = {}, all_schema={})
|
|
|
|
|
-
|
|
|
|
|
- # return
|
|
|
|
|
-
|
|
|
|
|
- prGreen(f"Pulling data from tree took {time.time() - data_start_time} seconds")
|
|
|
|
|
-
|
|
|
|
|
- for sig, dummy in dummy_nodes.items():
|
|
|
|
|
|
|
+ # it's REALLY confusing when you run into this sort of problem. So it warrants four entire lines of comments!
|
|
|
|
|
+ dummy_nodes, all_mantis_nodes, all_schema = data_from_tree(base_tree, tree_path = [None], dummy_nodes = {}, all_nc = {}, all_schema={})
|
|
|
|
|
+ for dummy in dummy_nodes.values(): # reroute the links in the group nodes
|
|
|
if (hasattr(dummy, "reroute_links")):
|
|
if (hasattr(dummy, "reroute_links")):
|
|
|
- dummy.reroute_links(dummy, all_nc)
|
|
|
|
|
|
|
+ dummy.reroute_links(dummy, all_mantis_nodes)
|
|
|
|
|
+ prGreen(f"Pulling data from tree took {time.time() - data_start_time} seconds")
|
|
|
|
|
|
|
|
- # TODO
|
|
|
|
|
- # MODIFY BELOW to use hierarchy_dependencies instead
|
|
|
|
|
- # SCHEMA DUMMY nodes will need to gather the hierarchy and non-hierarchy dependencies
|
|
|
|
|
- # so SCHEMA DUMMY will not make their dependencies all hierarchy
|
|
|
|
|
- # since they will need to be able to send drivers and such
|
|
|
|
|
start_time = time.time()
|
|
start_time = time.time()
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- sig_check = (None, 'Node Group.001', 'switch_thigh')
|
|
|
|
|
- roots = []
|
|
|
|
|
- arrays = []
|
|
|
|
|
|
|
+ roots, array_nodes = [], []
|
|
|
from .misc_containers import UtilityArrayGet
|
|
from .misc_containers import UtilityArrayGet
|
|
|
- for nc in all_nc.values():
|
|
|
|
|
|
|
+ for mantis_node in all_mantis_nodes.values():
|
|
|
# clean up the groups
|
|
# clean up the groups
|
|
|
- if nc.node_type in ["DUMMY"]:
|
|
|
|
|
- if nc.prototype.bl_idname in ("MantisNodeGroup", "NodeGroupOutput"):
|
|
|
|
|
|
|
+ if mantis_node.node_type in ["DUMMY"]:
|
|
|
|
|
+ if mantis_node.prototype.bl_idname in ("MantisNodeGroup", "NodeGroupOutput"):
|
|
|
continue
|
|
continue
|
|
|
-
|
|
|
|
|
- from .base_definitions import from_name_filter, to_name_filter
|
|
|
|
|
-
|
|
|
|
|
- init_dependencies(nc)
|
|
|
|
|
- init_connections(nc)
|
|
|
|
|
- check_and_add_root(nc, roots, include_non_hierarchy=True)
|
|
|
|
|
- if isinstance(nc, UtilityArrayGet):
|
|
|
|
|
- arrays.append(nc)
|
|
|
|
|
|
|
+ # Initialize the dependencies and connections (from/to links) for each node.
|
|
|
|
|
+ # we record & store it because using a getter is much slower (according to profiling)
|
|
|
|
|
+ init_dependencies(mantis_node); init_connections(mantis_node)
|
|
|
|
|
+ check_and_add_root(mantis_node, roots, include_non_hierarchy=True)
|
|
|
|
|
+ # Array nodes need a little special treatment, they're quasi-schemas
|
|
|
|
|
+ if isinstance(mantis_node, UtilityArrayGet):
|
|
|
|
|
+ array_nodes.append(mantis_node)
|
|
|
|
|
|
|
|
from collections import deque
|
|
from collections import deque
|
|
|
unsolved_schema = deque()
|
|
unsolved_schema = deque()
|
|
|
solve_only_these = []; solve_only_these.extend(list(all_schema.values()))
|
|
solve_only_these = []; solve_only_these.extend(list(all_schema.values()))
|
|
|
for schema in all_schema.values():
|
|
for schema in all_schema.values():
|
|
|
- # so basically we need to check every parent node if it is a schema
|
|
|
|
|
- # this is a fairly slapdash solution but it works and I won't change it
|
|
|
|
|
|
|
+ # We can remove the schema that are inside another schema tree.
|
|
|
for i in range(len(schema.signature)-1): # -1, we don't want to check this node, obviously
|
|
for i in range(len(schema.signature)-1): # -1, we don't want to check this node, obviously
|
|
|
if parent := all_schema.get(schema.signature[:i+1]):
|
|
if parent := all_schema.get(schema.signature[:i+1]):
|
|
|
|
|
+ # This will be solved along with its parent schema.
|
|
|
solve_only_these.remove(schema)
|
|
solve_only_these.remove(schema)
|
|
|
break
|
|
break
|
|
|
else:
|
|
else:
|
|
|
- init_schema_dependencies(schema, all_nc)
|
|
|
|
|
- solve_only_these.extend(get_schema_length_dependencies(schema))
|
|
|
|
|
|
|
+ init_schema_dependencies(schema, all_mantis_nodes)
|
|
|
|
|
+ solve_only_these.extend(get_schema_length_dependencies(schema, all_mantis_nodes))
|
|
|
unsolved_schema.append(schema)
|
|
unsolved_schema.append(schema)
|
|
|
- for array in arrays:
|
|
|
|
|
|
|
+ for array in array_nodes:
|
|
|
solve_only_these.extend(get_schema_length_dependencies(array))
|
|
solve_only_these.extend(get_schema_length_dependencies(array))
|
|
|
- solve_only_these.extend(arrays)
|
|
|
|
|
|
|
+ solve_only_these.extend(array_nodes)
|
|
|
schema_solve_done = set()
|
|
schema_solve_done = set()
|
|
|
|
|
|
|
|
solve_only_these = set(solve_only_these)
|
|
solve_only_these = set(solve_only_these)
|
|
@@ -385,7 +399,7 @@ def parse_tree(base_tree):
|
|
|
solve_layer.appendleft(n)
|
|
solve_layer.appendleft(n)
|
|
|
break
|
|
break
|
|
|
else:
|
|
else:
|
|
|
- solved_nodes = solve_schema_to_tree(n, all_nc, roots)
|
|
|
|
|
|
|
+ solved_nodes = solve_schema_to_tree(n, all_mantis_nodes, roots)
|
|
|
unsolved_schema.remove(n)
|
|
unsolved_schema.remove(n)
|
|
|
schema_solve_done.add(n)
|
|
schema_solve_done.add(n)
|
|
|
for node in solved_nodes.values():
|
|
for node in solved_nodes.values():
|
|
@@ -411,11 +425,11 @@ def parse_tree(base_tree):
|
|
|
raise RuntimeError("Failed to resolve all schema declarations")
|
|
raise RuntimeError("Failed to resolve all schema declarations")
|
|
|
# I had a problem with this looping forever. I think it is resolved... but I don't know lol
|
|
# I had a problem with this looping forever. I think it is resolved... but I don't know lol
|
|
|
|
|
|
|
|
- all_nc = list(all_nc.values()).copy()
|
|
|
|
|
|
|
+ all_mantis_nodes = list(all_mantis_nodes.values()).copy()
|
|
|
kept_nc = {}
|
|
kept_nc = {}
|
|
|
- while (all_nc):
|
|
|
|
|
- nc = all_nc.pop()
|
|
|
|
|
- if nc in arrays:
|
|
|
|
|
|
|
+ while (all_mantis_nodes):
|
|
|
|
|
+ nc = all_mantis_nodes.pop()
|
|
|
|
|
+ if nc in array_nodes:
|
|
|
continue
|
|
continue
|
|
|
|
|
|
|
|
if nc.node_type in ["DUMMY"]:
|
|
if nc.node_type in ["DUMMY"]:
|