Преглед на файлове

Fix: Deformers not binding most of the time

Joseph Brandenburg преди 4 месеца
родител
ревизия
3a118f2ef2
променени са 4 файла, в които са добавени 75 реда и са изтрити 25 реда
  1. 2 0
      base_definitions.py
  2. 17 15
      deformer_containers.py
  3. 11 10
      readtree.py
  4. 45 0
      utilities.py

+ 2 - 0
base_definitions.py

@@ -941,6 +941,8 @@ class MantisNode:
         return
     def bFinalize(self, bContext=None):
         return
+    def bModifierApply(self, bContext=None):
+        return
     
     if environ.get("DOERROR"):
         def __repr__(self): 

+ 17 - 15
deformer_containers.py

@@ -32,7 +32,6 @@ def trace_xForm_back(nc, socket):
                 return trace[ i ].bGetObject()
         raise GraphError(wrapRed(f"No other object found for {nc}."))
 
-
 class MantisDeformerNode(MantisNode):
     def __init__(self, signature : tuple,
                  base_tree : NodeTree,
@@ -64,6 +63,8 @@ class MantisDeformerNode(MantisNode):
             return_me.append(xf)
         return return_me
     
+
+    
     def reset_execution(self):
         super().reset_execution()
         self.bObject=[]; self.prepared=True
@@ -593,12 +594,12 @@ class DeformerSurfaceDeform(MantisDeformerNode):
             self.get_target_and_subtarget(d, input_name="Target")
             props_sockets = self.gen_property_socket_map()
             evaluate_sockets(self, d, props_sockets)
-            # now we have to bind it
 
-            import bpy
-            target = d.target
-            with bpy.context.temp_override(**{'active_object':ob, 'selected_objects':[ob, target]}):
-                bpy.ops.object.surfacedeform_bind(modifier=d.name)
+    def bModifierApply(self, bContext=None):
+        for d in self.bObject:
+            from bpy import ops
+            from .utilities import bind_modifier_operator
+            bind_modifier_operator(d, ops.object.surfacedeform_bind)
 
 
 class DeformerMeshDeform(MantisDeformerNode):
@@ -632,15 +633,16 @@ class DeformerMeshDeform(MantisDeformerNode):
             self.get_target_and_subtarget(d, input_name="Object")
             props_sockets = self.gen_property_socket_map()
             evaluate_sockets(self, d, props_sockets)
-            # now we have to bind it
-            import bpy
-            target = d.object
-            with bpy.context.temp_override(**{'active_object':ob, 'selected_objects':[ob, target]}):
-                bpy.ops.object.meshdeform_bind(modifier=d.name)
-            
-            # todo: add influence parameter and set it up with vertex group and geometry nodes
-            # todo: make cage object display as wireframe if it is not being used for something else
-            #          or add the option in the Geometry Object node
+
+    def bModifierApply(self, bContext=None):
+        for d in self.bObject:
+            from bpy import ops
+            from .utilities import bind_modifier_operator
+            bind_modifier_operator(d, ops.object.meshdeform_bind)
+
+    # todo: add influence parameter and set it up with vertex group and geometry nodes
+    # todo: make cage object display as wireframe if it is not being used for something else
+    #          or add the option in the Geometry Object node
 
 
 class DeformerLatticeDeform(MantisDeformerNode):

+ 11 - 10
readtree.py

@@ -445,16 +445,7 @@ def parse_tree(base_tree, error_popups=False):
     prWhite("Number of Nodes: %s" % (len(kept_nc)))
     return kept_nc
 
-def switch_mode(mode='OBJECT', objects = []):
-    active = None
-    if objects:
-        from bpy import context, ops
-        active = objects[-1]
-        context.view_layer.objects.active = active
-        if (active):
-            with context.temp_override(**{'active_object':active, 'selected_objects':objects}):
-                ops.object.mode_set(mode=mode)
-    return active
+from .utilities import switch_mode
 
 def execution_error_cleanup(node, exception, switch_objects = [], show_error=False ):
     from bpy import  context
@@ -618,6 +609,16 @@ def execute_tree(nodes, base_tree, context, error_popups = False):
                 if error_popups == False:
                     raise e
                 execution_failed = True; break
+            
+        # finally, apply modifiers and bind stuff
+        for n in executed:
+            try:
+                n.bModifierApply(context)
+            except Exception as e:
+                e = execution_error_cleanup(n, e, show_error=error_popups)
+                if error_popups == False:
+                    raise e
+                execution_failed = True; break
                 
         
         tot_time = (time() - start_execution_time)

+ 45 - 0
utilities.py

@@ -241,6 +241,51 @@ def unique_socket_name(node, other_socket, tree):
     name = name_stem + '.' + str(num).zfill(3)
     return name
 
+##############################
+# Dealing with Objects
+##############################
+
+# use this to ensure the active object is set back when changing it
+def preserve_active_object(func):
+    def wrapper(*args, **kwargs):
+        import bpy
+        original_active = bpy.context.active_object
+        func(*args, **kwargs)
+        bpy.context.view_layer.objects.active = original_active
+    return wrapper
+
+def switch_mode(mode='OBJECT', objects = []):
+    active = None
+    if objects:
+        from bpy import context, ops
+        active = objects[-1]
+        context.view_layer.objects.active = active
+        if (active):
+            with context.temp_override(**{'active_object':active, 'selected_objects':objects}):
+                ops.object.mode_set(mode=mode)
+    return active
+
+# run this in Object mode, during bFinalize
+@preserve_active_object
+def bind_modifier_operator(modifier, operator):
+        # now we have to bind it
+        ob = modifier.id_data; print (ob.name)
+        ob.modifiers.active = modifier
+        import bpy
+        bpy.context.view_layer.objects.active = ob
+        # Context override does not do anything here... it isn't handled in the C code
+        # I have verified this by building Blender with print statements to debug.
+
+        # let's just make sure the target object has its modifiers disabled and update the dg
+        targ_attr = "target"
+        if hasattr(modifier, "object"): targ_attr = "object"
+        target = getattr(modifier, targ_attr)
+        for m in target.modifiers:
+            m.show_viewport = False
+        bpy.context.view_layer.depsgraph.update()
+        for m in target.modifiers:
+            m.show_viewport = True
+        operator(modifier=modifier.name)
 
 ##############################
 #  READ TREE and also Schema Solve!