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

Shape Keys for Lattice now works

Joseph Brandenburg 4 hónapja
szülő
commit
743ad9d94b
1 módosított fájl, 93 hozzáadás és 8 törlés
  1. 93 8
      deformer_containers.py

+ 93 - 8
deformer_containers.py

@@ -538,7 +538,77 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
         evaluate_sockets(self, m, props_sockets)
         finish_drivers(self)
 
-    def gen_shape_key(self, xf, context): # TODO: make this a feature of the node definition that appears only when there are no prior deformers - and shows a warning!
+    def gen_shape_key_lattice(self, xf, context):
+        # first check if we need to do anything
+        targets = []
+        for k,v in self.inputs.items():
+            if "Target" in k:
+                targets.append(v)
+        if not targets:
+            return # nothing to do here
+        # TODO: deduplicate the code above here
+        from time import time
+        start_time = time()
+        from bpy import data
+        ob = xf.bGetObject()
+        dg = context.view_layer.depsgraph
+        dg.update()
+        if xf.has_shape_keys == False:
+            lat = ob.data.copy()
+            ob.data = lat
+            ob.add_rest_position_attribute = True
+            ob.shape_key_clear()
+            ob.shape_key_add(name='Basis', from_mix=False)
+        else:
+            lat = ob.data
+        xf.has_shape_keys = True
+        
+        # first make a basis shape key
+        keys, props_sockets, ={}, {}
+        for i, t in enumerate(targets):
+            mt_node = t.links[0].from_node; sk_ob = mt_node.GetxForm().bGetObject()
+            if sk_ob is None:
+                sk_ob = data.objects.new(mt_node.evaluate_input("Name"), data.meshes.new_from_object(ob))
+                context.collection.objects.link(sk_ob)
+                prOrange(f"WARN: no object found for f{mt_node}; creating duplicate of current object ")
+            sk_ob = dg.id_eval_get(sk_ob)
+            mt_name = sk_ob.name
+            vg = mt_node.parameters["Morph Target"]["vertex_group"]
+            if vg: mt_name = mt_name+"."+vg
+            
+            sk = ob.shape_key_add(name=mt_name, from_mix=False)
+            # the shapekey data is absolute point data for each vertex, in order, very simple
+
+            # SERIOUSLY IMPORTANT:
+               # use the current position of the vertex AFTER SHAPE KEYS AND DEFORMERS
+               # easiest way to do it is to eval the depsgraph
+               # TODO: try and get it without depsgraph update, since that may be (very) slow
+            sk_m = sk_ob.data#data.meshes.new_from_object(sk_ob, preserve_all_data_layers=True, depsgraph=dg)
+            for j in range(len(m.vertices)):
+                sk.data[j].co = sk_m.vertices[j].co # assume they match
+            # data.meshes.remove(sk_m)
+            sk.vertex_group = vg
+            sk.slider_min = -10
+            sk.slider_max = 10
+            keys[mt_name]=sk
+            props_sockets[mt_name]= ("Value."+str(i).zfill(3), 1.0)
+        for i, t in enumerate(targets):
+            mt_node = t.links[0].from_node; sk_ob = mt_node.GetxForm().bGetObject()
+            if sk_ob is None: continue
+            if rel := mt_node.parameters["Morph Target"]["relative_shape"]:
+                sk = keys.get(mt_name)
+                sk.relative_key = keys.get(rel)
+        
+        self.bObject.append(sk.id_data)
+        evaluate_sockets(self, sk.id_data, props_sockets)
+        finish_drivers(self)
+        prWhite(f"Initializing morph target took {time() -start_time} seconds")
+
+
+        
+
+    def gen_shape_key(self, xf, context):
+        # TODO: make this a feature of the node definition that appears only when there are no prior deformers - and shows a warning!
         # TODO: the below works well, but it is quite slow. It does not seem to have better performence. Its only advantage is export to FBX.
         # there are a number of things I need to fix here
         #   - reuse shape keys if possible
@@ -558,13 +628,17 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
         dg = context.view_layer.depsgraph
         dg.update()
         if xf.has_shape_keys == False:
-            m = data.meshes.new_from_object(ob, preserve_all_data_layers=True, depsgraph=dg)
-            ob.data = m
+            match ob.type:
+                case 'MESH':
+                    ob_data = data.meshes.new_from_object(ob, preserve_all_data_layers=True, depsgraph=dg)
+                case 'LATTICE':
+                    ob_data = ob.data.copy()
+            ob.data = ob_data
             ob.add_rest_position_attribute = True
             ob.shape_key_clear()
             ob.shape_key_add(name='Basis', from_mix=False)
         else:
-            m = ob.data
+            ob_data = ob.data
         xf.has_shape_keys = True
         
         # using the built-in shapekey feature is actually a lot harder in terms of programming because I need...
@@ -596,8 +670,13 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
                # easiest way to do it is to eval the depsgraph
                # TODO: try and get it without depsgraph update, since that may be (very) slow
             sk_m = sk_ob.data#data.meshes.new_from_object(sk_ob, preserve_all_data_layers=True, depsgraph=dg)
-            for j in range(len(m.vertices)):
-                sk.data[j].co = sk_m.vertices[j].co # assume they match
+            match ob.type:
+                case 'MESH':
+                    for j in range(len(ob_data.vertices)):
+                        sk.data[j].co = sk_m.vertices[j].co # assume they match
+                case 'LATTICE':
+                    for j in range(len(ob.data.points)):
+                        sk.data[j].co = sk_m.points[j].co_deform
             # data.meshes.remove(sk_m)
             sk.vertex_group = vg
             sk.slider_min = -10
@@ -615,7 +694,6 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
         evaluate_sockets(self, sk.id_data, props_sockets)
         finish_drivers(self)
         prWhite(f"Initializing morph target took {time() -start_time} seconds")
-        
 
     def bFinalize(self, bContext=None):
         prGreen(f"Executing Morph Deform node {self}")
@@ -631,7 +709,14 @@ class DeformerMorphTargetDeform(MantisDeformerNode):
                         use_shape_keys = False
         self.parameters["Use Shape Key"] = use_shape_keys
         for xf in self.GetxForm():
-            if use_shape_keys:
+            # Lattice objects do not support geometry nodes at this time.
+            ob = xf.bGetObject()
+            if ob and ob.type == 'LATTICE':
+                if not use_shape_keys:
+                    raise NotImplementedError("Blender does not support Geometry Nodes for Lattices. "
+                                              "Enable 'Shape Key' and execute again.")
+                self.gen_shape_key(xf, bContext)
+            elif use_shape_keys:
                 self.gen_shape_key(xf, bContext)
             else:
                 self.gen_morph_target_modifier(xf, bContext)