Эх сурвалжийг харах

Fix: Tree will not re-validate if topology has not changed

note: I think this commit might mess up some rare cases in updating the tree with socket
changes. whatever, if it is causing problems I need to re-write it. lol
I didn't find any problems when I tested updating/executing the tree from a socket change
Joseph Brandenburg 6 сар өмнө
parent
commit
fd999e4c25
2 өөрчлөгдсөн 46 нэмэгдсэн , 30 устгасан
  1. 4 11
      __init__.py
  2. 42 19
      base_definitions.py

+ 4 - 11
__init__.py

@@ -211,8 +211,10 @@ addon_keymaps = []
 
 # handlers! these have to be persistent
 from bpy.app.handlers import persistent
+from .base_definitions import hash_tree
 @persistent
 def update_handler(scene):
+    # return
     context=bpy.context
     if context.space_data:
         if not hasattr(context.space_data, "path"):
@@ -224,16 +226,7 @@ def update_handler(scene):
                 return 
             if node_tree.prevent_next_exec : pass
             elif node_tree.do_live_update and not (node_tree.is_executing):
-                prev_links = node_tree.num_links
-                node_tree.num_links = len(node_tree.links)
-                if (prev_links == -1):
-                    return
-                if prev_links != node_tree.num_links:
-                    node_tree.tree_valid = False
-                if node_tree.tree_valid == False:
-                        scene.render.use_lock_interface = True
-                        node_tree.update_tree(context)
-                        scene.render.use_lock_interface = False
+                node_tree.update_tree(context)
 
 @persistent
 def execute_handler(scene):
@@ -245,7 +238,7 @@ def execute_handler(scene):
         if not trees: return
         if (node_tree := trees[0]).bl_idname in ['MantisTree']:
             if node_tree.is_exporting:
-                return 
+                return
             if node_tree.prevent_next_exec : node_tree.prevent_next_exec = False
             elif node_tree.tree_valid and node_tree.do_live_update and not (node_tree.is_executing):
                 scene.render.use_lock_interface = True

+ 42 - 19
base_definitions.py

@@ -54,13 +54,29 @@ def fix_reroute_colors(tree):
             rr = reroutes_without_color.pop()
             if rr.inputs[0].is_linked:
                 link = rr.inputs[0].links[0]
-                from_node = link.from_node
                 socket = socket_seek(link, tree.links)
                 if isinstance(socket, MantisSocket):
                     rr.socket_idname = socket.bl_idname
     except Exception as e:
         print(wrapOrange("WARN: Updating reroute color failed with exception: ")+wrapWhite(f"{e.__class__.__name__}"))
 
+#functions to identify the state of the system using hashes
+# this function runs a lot so it should be optimized as well as possible.
+def hash_tree(tree):
+    trees=set(); links=[]; hash_data=""
+    for node in tree.nodes:
+        hash_data+=str(node.name)
+        if hasattr(node, 'node_tree'):
+            trees.add(node.node_tree)
+    for other_tree in trees:
+        hash_data+=str(hash_tree(other_tree))
+    for link in tree.links:
+        links.append( link.from_node.name+link.from_socket.name+
+                      link.to_node.name+link.to_socket.name+
+                      str(link.multi_input_sort_id) )
+    links.sort(); hash_data+=''.join(links)
+    return hash(hash_data)
+
 class MantisTree(NodeTree):
     '''A custom node tree type that will show up in the editor type list'''
     bl_idname = 'MantisTree'
@@ -68,12 +84,14 @@ class MantisTree(NodeTree):
     bl_icon = 'OUTLINER_OB_ARMATURE'
     
     tree_valid:BoolProperty(default=False)
+    hash:StringProperty(default='')
     do_live_update:BoolProperty(default=True) # use this to disable updates for e.g. scripts
     num_links:IntProperty(default=-1)
     filepath:StringProperty(default="", subtype='FILE_PATH')
     is_executing:BoolProperty(default=False)
     is_exporting:BoolProperty(default=False)
     execution_id:StringProperty(default='')
+    # prev_execution_id:StringProperty(default='')
     mantis_version:IntVectorProperty(default=[0,9,2])
     # this prevents the node group from executing on the next depsgraph update
     # because I don't always have control over when the dg update happens.
@@ -93,26 +111,31 @@ class MantisTree(NodeTree):
     def update_tree(self, context = None):
         if self.is_exporting:
             return
-        # return
-        self.is_executing = True
-        from . import readtree
-        prGreen("Validating Tree: %s" % self.name)
-        try:
-            self.parsed_tree = readtree.parse_tree(self)
-            if context:
-                self.display_update(context)
-            self.is_executing = False
-            self.tree_valid = True
-        except GraphError as e:
-            prRed("Failed to update node tree due to error.")
-            self.tree_valid = False
-            self.is_executing = False
-            raise e
-        finally:
-            self.is_executing = False
+        my_hash = str( hash_tree(self) )
+        if my_hash != self.hash:
+            self.hash = my_hash
+            self.is_executing = True
+            from . import readtree
+            prGreen("Validating Tree: %s" % self.name)
+            try:
+                scene = context.scene
+                scene.render.use_lock_interface = True
+                self.parsed_tree = readtree.parse_tree(self)
+                if context:
+                    self.display_update(context)
+                self.tree_valid = True
+            except GraphError as e:
+                prRed("Failed to update node tree due to error.")
+                self.tree_valid = False
+                raise e
+            finally:
+                scene.render.use_lock_interface = False
+                self.is_executing = False
 
-    
     def display_update(self, context):
+        my_hash = str( hash_tree(self) )
+        if my_hash != self.hash:
+            return
         if self.is_exporting:
             return
         self.is_executing = True