Forráskód Böngészése

UI: Error Popups in Parse phase show only when manually executing tree

Joseph Brandenburg 6 hónapja
szülő
commit
10e5c76daf
4 módosított fájl, 53 hozzáadás és 49 törlés
  1. 2 2
      base_definitions.py
  2. 2 2
      ops_nodegroup.py
  3. 39 38
      readtree.py
  4. 10 7
      schema_solve.py

+ 2 - 2
base_definitions.py

@@ -108,7 +108,7 @@ class MantisTree(NodeTree):
         if (bpy.app.version >= (4,4,0)):
             fix_reroute_colors(self)
 
-    def update_tree(self, context = None, force=False):
+    def update_tree(self, context = None, force=False, error_popups=False):
         if self.is_exporting:
             return
         my_hash = str( hash_tree(self) )
@@ -122,7 +122,7 @@ class MantisTree(NodeTree):
                 # is used for display update... but I always want to do this
                 scene = bpy.context.scene
                 scene.render.use_lock_interface = True
-                self.parsed_tree = readtree.parse_tree(self)
+                self.parsed_tree = readtree.parse_tree(self, error_popups)
                 if context:
                     self.display_update(context)
                 self.tree_valid = True

+ 2 - 2
ops_nodegroup.py

@@ -262,7 +262,7 @@ class ExecuteNodeTree(Operator):
             import pstats, io
             from pstats import SortKey
             with cProfile.Profile() as pr:
-                tree.update_tree(context)
+                tree.update_tree(context, error_popups = pass_error)
                 tree.execute_tree(context, error_popups = pass_error)
                 # from the Python docs at https://docs.python.org/3/library/profile.html#module-cProfile
                 s = io.StringIO()
@@ -273,7 +273,7 @@ class ExecuteNodeTree(Operator):
                 print(s.getvalue())
 
         else:
-            tree.update_tree(context)
+            tree.update_tree(context, error_popups = pass_error)
             tree.execute_tree(context, error_popups = pass_error)
         prGreen("Finished executing tree in %f seconds" % (time() - start_time))
         return {"FINISHED"}

+ 39 - 38
readtree.py

@@ -197,7 +197,7 @@ def is_signature_in_other_signature(parent_signature, child_signature):
         return False
     return parent_signature[0:] == child_signature[:len(parent_signature)]
 
-def solve_schema_to_tree(nc, all_nc, roots=[]):
+def solve_schema_to_tree(nc, all_nc, roots=[], error_popups=False):
     from .utilities import get_node_prototype
     np = get_node_prototype(nc.signature, nc.base_tree)
     from .schema_solve import SchemaSolver
@@ -205,7 +205,7 @@ def solve_schema_to_tree(nc, all_nc, roots=[]):
     length = nc.evaluate_input("Schema Length")
     prOrange(f"Expanding schema {tree.name} in node {nc} with length {length}.")
 
-    solver = SchemaSolver(nc, all_nc, np)
+    solver = SchemaSolver(nc, all_nc, np, error_popups=error_popups)
     solved_nodes = solver.solve()
     prWhite(f"Schema declared {len(solved_nodes)} nodes.")
 
@@ -283,7 +283,7 @@ def get_schema_length_dependencies(node, all_nodes={}):
     return list(filter(deps_filter, deps))
 
 
-def parse_tree(base_tree):
+def parse_tree(base_tree, error_popups=False):
     from uuid import uuid4
     base_tree.execution_id = uuid4().__str__() # set the unique id of this execution
     
@@ -359,7 +359,7 @@ def parse_tree(base_tree):
                     solve_layer.appendleft(n)
                     break
             else:
-                solved_nodes = solve_schema_to_tree(n, all_mantis_nodes, roots)
+                solved_nodes = solve_schema_to_tree(n, all_mantis_nodes, roots, error_popups=error_popups)
                 unsolved_schema.remove(n)
                 schema_solve_done.add(n)
                 for node in solved_nodes.values():
@@ -380,7 +380,10 @@ def parse_tree(base_tree):
                 try:
                     n.bPrepare()
                 except Exception as e:
-                    raise execution_error_cleanup(n, e)
+                    e = execution_error_cleanup(n, e, show_error=error_popups)
+                    if error_popups == False:
+                        raise e
+                    
                 schema_solve_done.add(n)
                 for conn in n.hierarchy_connections:
                     if conn not in schema_solve_done and conn not in solve_layer:
@@ -431,31 +434,32 @@ def switch_mode(mode='OBJECT', objects = []):
                 ops.object.mode_set(mode=mode)
     return active
 
-def execution_error_cleanup(node, exception, switch_objects = [] ):
+def execution_error_cleanup(node, exception, switch_objects = [], show_error=False ):
     from bpy import  context
     ui_sig = None
-    if node:
-        ui_sig = node.ui_signature
-        # TODO: see about zooming-to-node.
-        base_tree = node.base_tree
-        tree = base_tree
-        try:
-            pass
-            space = context.space_data
-            for name in ui_sig[1:]:
-                for n in tree.nodes: n.select = False
-                n = tree.nodes[name]
-                n.select = True
-                tree.nodes.active = n
-                if hasattr(n, "node_tree"):
-                    tree = n.node_tree
-        except AttributeError: # not being run in node graph
-            pass
-        finally:
-            def error_popup_draw(self, context):
-                self.layout.label(text=f"Error: {exception}")
-                self.layout.label(text=f"see node: {ui_sig[1:]}.")
-            context.window_manager.popup_menu(error_popup_draw, title="Error", icon='ERROR')
+    if show_error: # show a popup and select the relevant nodes
+        if node:
+            ui_sig = node.ui_signature
+            # TODO: see about zooming-to-node.
+            base_tree = node.base_tree
+            tree = base_tree
+            try:
+                pass
+                space = context.space_data
+                for name in ui_sig[1:]:
+                    for n in tree.nodes: n.select = False
+                    n = tree.nodes[name]
+                    n.select = True
+                    tree.nodes.active = n
+                    if hasattr(n, "node_tree"):
+                        tree = n.node_tree
+            except AttributeError: # not being run in node graph
+                pass
+            finally:
+                def error_popup_draw(self, context):
+                    self.layout.label(text=f"Error: {exception}")
+                    self.layout.label(text=f"see node: {ui_sig[1:]}.")
+                context.window_manager.popup_menu(error_popup_draw, title="Error", icon='ERROR')
     switch_mode(mode='OBJECT', objects=switch_objects)
     for ob in switch_objects:
         ob.data.pose_position = 'POSE'
@@ -534,9 +538,8 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
                             if isinstance(ob, bpy.types.Object):
                                 select_me.append(ob)
                     except Exception as e:
-                        if error_popups:
-                            raise execution_error_cleanup(n, e,)
-                        else:
+                        e = execution_error_cleanup(n, e, show_error=error_popups)
+                        if error_popups == False:
                             raise e
                     n.execution_prepared=True
                     executed.append(n)
@@ -557,9 +560,8 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
                 if not n.executed:
                     n.bExecute(context)
             except Exception as e:
-                if error_popups:
-                    raise execution_error_cleanup(n, e,)
-                else:
+                e = execution_error_cleanup(n, e, show_error=error_popups)
+                if error_popups == False:
                     raise e
 
 
@@ -573,9 +575,8 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
             try:
                 n.bFinalize(context)
             except Exception as e:
-                if error_popups:
-                    raise execution_error_cleanup(n, e,)
-                else:
+                e = execution_error_cleanup(n, e, show_error=error_popups)
+                if error_popups == False:
                     raise e
         
         tot_time = (time() - start_execution_time)
@@ -584,7 +585,7 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
             context.view_layer.objects.active = original_active
             original_active.select_set(True)
     except Exception as e:
-        execution_error_cleanup(None, e, switch_me)
+        e = execution_error_cleanup(None, e, switch_me, show_error=error_popups)
         if error_popups == False:
             raise e
     finally:

+ 10 - 7
schema_solve.py

@@ -11,11 +11,12 @@ from bpy.types import NodeGroupInput, NodeGroupOutput
 from .readtree import execution_error_cleanup
 
 class SchemaSolver:
-    def __init__(self, schema_dummy, nodes, prototype, signature=None,):
+    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.tree = prototype.node_tree
         self.uuid = self.node.uuid
+        self.error_popups = error_popups
         if signature:
             self.signature = signature
         else:
@@ -465,14 +466,14 @@ class SchemaSolver:
         # and in fact, I could skip this in some cases, and should investigate if profiling reveals a slowdown here.
         forbidden=set()
         # forbid some nodes - they aren't necessary to solve the schema & cause problems.
-        from .readtree import execution_error_cleanup
         while unprepared:
             nc = unprepared.pop()
             if sum([dep.prepared for dep in nc.hierarchy_dependencies]) == len(nc.hierarchy_dependencies):
                 try:
                     nc.bPrepare()
                 except Exception as e:
-                    execution_error_cleanup(nc, e)
+                    e = execution_error_cleanup(nc, e, show_error = self.error_popups)
+                    raise e # always raise so that we don't enter an infinite loop.
                 if nc.node_type == 'DUMMY_SCHEMA':
                     self.solve_nested_schema(nc)
             elif nc.node_type == 'DUMMY_SCHEMA' and not self.test_is_sub_schema(nc):
@@ -568,7 +569,8 @@ class SchemaSolver:
                         " inside another Schema. This is not currently supported. Try using a Constant Output" \
                         f" instead. Affected node: {from_ui_node.name}"
                         )
-                    raise execution_error_cleanup(self.node, e)
+                    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 
@@ -580,10 +582,11 @@ class SchemaSolver:
                 awaiting_prep_stage.append(ui_link)
                 continue
             if isinstance(from_ui_node, SchemaArrayInputGet):
-                e = NotImplementedError("This node is deprecated. Use an Entire Array Input and Array Get node instead.")
+                e = DeprecationWarning("This node is deprecated. Use an Entire Array Input and Array Get node instead.")
                 from_name, to_name = get_link_in_out(ui_link)
                 from_nc = frame_mantis_nodes[(*self.autogen_path_names, from_name+self.index_str())]
-                raise execution_error_cleanup(from_nc, e)
+                # always raise this because it is deprecated.
+                raise execution_error_cleanup(from_nc, e, show_error=self.error_popups)
             
             # 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())
@@ -636,7 +639,7 @@ class SchemaSolver:
                 prOrange(f"Expanding Node Group {tree.name} in node {schema_nc}.")
             else:
                 prOrange(f"Expanding schema {tree.name} in node {schema_nc} with length {length}.")
-            solver = SchemaSolver(schema_nc, all_nodes, ui_node, schema_nc.ui_signature)
+            solver = SchemaSolver(schema_nc, all_nodes, ui_node, schema_nc.ui_signature, error_popups=self.error_popups)
             solved_nodes = solver.solve()
             schema_nc.prepared = True
             for k,v in solved_nodes.items():