Is it possible -- without using a previously defined vertex group -- to select those vertice, which are affected by a shape key? How?
2 Answers
I think a shape key stores the coordinates of any vertex of the mesh, regardless of whether the position has been changed or not. So it seems as if the only way to select vertices affected by the shape key is to individually compare whether the position of the vertices is the same for different shape keys.
import bpy
tolerance = 1e-5
obj = bpy.context.active_object
shape_keys = obj.data.shape_keys.key_blocks
sk1_data = shape_keys['Key 1'].data
skb_data = shape_keys['Basis'].data
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="DESELECT")
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.object.mode_set(mode="OBJECT")
for i, (x, y) in enumerate(zip(sk1_data, skb_data)):
if (x.co - y.co).length > tolerance:
obj.data.vertices[i].select = True
bpy.ops.object.mode_set(mode="EDIT")
EDIT: As per batFINGER's suggestion, replaced comparison based on equality with a tolerance based approach.
BMesh version
Using the same principle as @binweg's answer with an edit bmesh
- Shapekey vertex coordinate needs to be further than
TOL
(local) from vertex coordinate. Always suggest using a tolerance approach when looking at floats, rather than relying on10.0000000001 == 10
for example. - The two points of interest are vector coords. Test the length of the vector calcuated from their difference.
- Uses the active shapekey.
- Selected result is those verts further than tolerance from base mesh, IF the shapekey is the solo shape at full value
- For the script to "poll" needs to be run in edit mesh mode. The object must have an active shapekey.
script
import bpy
import bmesh
context = bpy.context
TOL = 1e-5 # tolerance
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
ask = ob.active_shape_key
for v in bm.verts:
bv = me.vertices[v.index]
v.select = (ask.data[v.index].co - bv.co).length > TOL
bmesh.update_edit_mesh(me)
-
$\begingroup$ I might have used this script wrong, but for me this script doesn't work. In edit mode
bm
's values always seem to be identical to the active shape key's values, so for me there is no selection. Only by replacingv.co
withme.vertices[v.index].co
orask.relative_key.data[v.index].co
I manage to run it. I appreciate your suggestion of using tolerances. I initially decided against it as I was under the assumption that, even if some coordinates are not exactly integers, when you create a new shape key the value gets copied just like it is. But I guess it's better to be safe than sorry. $\endgroup$– binwegCommented Aug 25, 2018 at 6:24 -
$\begingroup$ @binweg cheers... Have used the mesh coord as suggested. Forgot the nuances of different bmesh modes. from_edit_mesh vs from_mesh vs from_object. A second non live edit bmesh could be another way to go, but ultimately the mesh vert coord is the go. $\endgroup$ Commented Aug 25, 2018 at 6:54