Skip to content

Instantly share code, notes, and snippets.

@Lateasusual
Created January 29, 2020 01:58
Show Gist options
  • Save Lateasusual/e463fc4947fe27c69ed6c9894629d3ef to your computer and use it in GitHub Desktop.
Save Lateasusual/e463fc4947fe27c69ed6c9894629d3ef to your computer and use it in GitHub Desktop.
import bpy
from bpy.types import Operator, DATA_PT_shape_keys
bl_info = {
"name": "Shape key mirror",
"description": "",
"author": "Lateasusual",
"version": (1, 0, 0),
"blender": (2, 81, 0),
"location": "Properties > Mesh > Shape Keys",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"support": "COMMUNITY",
"category": "Mesh"
}
def mirror(name: str):
if ".L" in name:
return name.replace(".L", ".R", 1)
if ".R" in name:
return name.replace(".R", ".L", 1)
return None
def is_mirror(name: str):
if ".L" in name:
return "L"
if ".R" in name:
return "R"
return None
class MESH_OT_MirrorShapeGroup(Operator):
bl_idname = 'mesh.mirror_shape_key_group'
bl_label = 'Make mirror from group'
bl_description = "Create a mirrored shape key with mirrored vertex group"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
obj = context.object
return obj and obj.type in {'MESH', 'LATTICE'}
def execute(self, context):
ob = context.object
keys = ob.data.shape_keys
kb = ob.active_shape_key
groups = ob.vertex_groups
vg1 = kb.vertex_group
# Unset everything
kb.vertex_group = ""
vals = [k.value for k in keys.key_blocks]
for k in keys.key_blocks:
k.value = 0.0
kb.value = kb.slider_max
vg2 = mirror(vg1)
if vg2 is None:
self.report({'ERROR'}, f"Vertex group {vg1} must be mirrorable (.L or .R)")
return {'CANCELLED'}
if vg2 not in groups:
self.report({'ERROR'}, f"No mirror group '{vg2}' found!")
return {'CANCELLED'}
mir = is_mirror(kb.name)
if mir is None:
kb.name += "." + is_mirror(vg1)
kb2 = ob.shape_key_add(name=mirror(kb.name), from_mix=True)
kb.vertex_group = vg1
kb2.vertex_group = vg2
for (i, v) in enumerate(vals):
keys.key_blocks[i].value = v
return {'FINISHED'}
def draw(self, context):
layout: bpy.types.UILayout = self.layout
ob = context.object
key = ob.data.shape_keys
kb = ob.active_shape_key
if kb:
if key.use_relative and ob.active_shape_key_index != 0:
if mirror(ob.active_shape_key.vertex_group) is not None:
layout.use_property_split = True
layout.operator('mesh.mirror_shape_key_group')
def register():
bpy.utils.register_class(MESH_OT_MirrorShapeGroup)
DATA_PT_shape_keys.append(draw)
def unregister():
bpy.utils.unregister_class(MESH_OT_MirrorShapeGroup)
DATA_PT_shape_keys.remove(draw)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment