rig_picker/operators/shape.py

223 lines
6.7 KiB
Python
Raw Normal View History

2022-04-06 10:12:32 +02:00
2024-02-19 11:53:15 +01:00
import json
from pathlib import Path
from mathutils import Matrix
2022-04-06 10:12:32 +02:00
import bpy
2024-02-19 11:53:15 +01:00
from bpy.types import Operator
from ..core.shape import get_picker_data
2023-11-09 10:29:56 +01:00
from ..core.addon_utils import is_shape
2024-02-19 11:53:15 +01:00
from ..core.bl_utils import link_mat_to_object, flip_name
2022-04-06 10:12:32 +02:00
2024-02-19 11:53:15 +01:00
class RP_OT_create_shape(Operator):
2022-04-06 10:12:32 +02:00
bl_label = 'Create UI shape'
bl_idname = 'rigpicker.create_shape'
#bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return (context.object and context.object.mode == 'POSE')
def execute(self,context):
scn = context.scene
vl = context.view_layer
offset = 0
for bone in context.selected_pose_bones:
name = bone.name
mesh = bpy.data.meshes.new(name)
ob = bpy.data.objects.new(name, mesh)
ob.rig_picker.name = name
verts=[(0,0,0)]
edges = []
faces =[]
mesh.from_pydata(verts, edges, faces)
for c in scn.rig_picker.canvas.users_collection:
c.objects.link(ob)
ob.location.z = 0.05
ob.location.x = offset
for obj in scn.objects:
obj.select_set(False)
vl.objects.active = ob
ob.select_set(True)
offset += 0.05
return {'FINISHED'}
2024-02-19 11:53:15 +01:00
class RP_OT_name_from_bone(Operator):
2022-04-06 10:12:32 +02:00
bl_label = 'Name Shape from selected bones'
bl_idname = 'rigpicker.name_from_bone'
#bl_options = {'REGISTER', 'UNDO'}
def execute(self,context):
scene = context.scene
rig = scene.rig_picker.rig
bone = rig.data.bones.active
if bone:
context.object.name = bone.name
context.object.rig_picker.name = bone.name
return {'FINISHED'}
2024-02-19 11:53:15 +01:00
class RP_OT_mirror_shape(Operator):
2022-04-06 10:12:32 +02:00
bl_label = 'Mirror UI shape'
bl_idname = 'rigpicker.mirror_shape'
#bl_options = {'REGISTER', 'UNDO'}
2024-02-19 11:53:15 +01:00
@classmethod
def poll(cls, context):
return (context.object and context.object.type in ('MESH', 'CURVE', 'TEXT'))
2022-04-06 10:12:32 +02:00
def execute(self,context):
scn = context.scene
2024-02-19 11:53:15 +01:00
ob = context.object
collection = next((c for c in ob.users_collection if c.rig_picker.enabled), None)
objects = context.selected_objects
# Remove mirror object:
for ob in list(collection.all_objects):
if ob in objects:
continue
for mod in ob.modifiers:
if (mod.type == 'NODES' and mod.node_group.name == 'Symmetrize' and
mod.get('Socket_2') in objects):
bpy.data.objects.remove(ob)
if collection.rig_picker.symmetry:
x_axis = collection.rig_picker.symmetry.matrix_world.to_translation()[0]
else:
x_axis = 0
for ob in objects:
flipped_name = flip_name(ob.name)
if flipped_name == ob.name:
suffix = '.L'
flipped_suffix = '.R'
# Determine side of the object
if ob.matrix_world.to_translation()[0] < x_axis:
suffix, flipped_suffix = flipped_suffix, suffix
flipped_name = f'{ob.name}{flipped_suffix}'
ob.name = f'{ob.name}{suffix}'
flipped_object = ob.copy()
flipped_object.name = flipped_name
flipped_object.parent = None
flipped_object.matrix_world = Matrix()
for mod in list(flipped_object.modifiers):
flipped_object.modifiers.remove(mod)
# Add symmetrize modifier
mod = flipped_object.modifiers.new(name='Symmetrize', type='NODES')
mod.node_group = bpy.data.node_groups['Symmetrize']
mod['Socket_2'] = ob
mod['Socket_3'] = collection.rig_picker.symmetry
for col in ob.users_collection:
col.objects.link(flipped_object)
2022-04-06 10:12:32 +02:00
if ob.rig_picker.shape_type == 'BONE':
2024-02-19 11:53:15 +01:00
flipped_object.rig_picker.name = flip_name(ob.rig_picker.name)
2022-04-06 10:12:32 +02:00
elif ob.rig_picker.shape_type == 'FUNCTION':
args = {}
for key,value in eval(ob.rig_picker.arguments).items():
if type(value) == list:
mirrored_value = []
for item in value:
2024-02-19 11:53:15 +01:00
mirrored_value.append(flip_name(item))
2022-04-06 10:12:32 +02:00
elif type(value) == str:
2024-02-19 11:53:15 +01:00
mirrored_value = flip_name(value)
2022-04-06 10:12:32 +02:00
args[key] = mirrored_value
2024-02-19 11:53:15 +01:00
flipped_object.rig_picker.arguments = str(args)
2022-04-06 10:12:32 +02:00
return {'FINISHED'}
2024-02-19 11:53:15 +01:00
class RP_OT_select_shape_type(Operator):
2022-04-06 10:12:32 +02:00
bl_label = 'Select Shape by Type'
bl_idname = 'rigpicker.select_shape_type'
#bl_options = {'REGISTER', 'UNDO'}
shape_type = bpy.props.EnumProperty(items =[(i.upper(), i, '') for i in ('Bone', 'Display', 'Function')])
def draw(self,context):
layout = self.layout
col = layout.column()
col.prop(self,'shape_type', expand=True)
def execute(self,context):
scene = context.scene
#print(self.shape_type)
canvas = context.scene.rig_picker.canvas
if canvas:
for ob in [o for o in bpy.data.objects if o.layers==canvas.layers]:
if ob.type in ['MESH', 'CURVE', 'FONT'] and ob.rig_picker.shape_type == self.shape_type:
ob.select = True
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self, width=150)
2024-02-19 11:53:15 +01:00
class RP_OT_save_picker(Operator):
2022-04-06 10:12:32 +02:00
bl_label = 'Store UI Data'
bl_idname = 'rigpicker.save_picker'
def execute(self, context):
scn = context.scene
2024-02-19 11:53:15 +01:00
ob = context.object
collection = next((c for c in ob.users_collection if c.rig_picker.enabled), None)
canvas = collection.rig_picker.canvas
rig = collection.rig_picker.rig
shapes = [o for o in collection.all_objects if o != canvas and o.type in ('MESH', 'CURVE', 'FONT')]
2022-04-06 10:12:32 +02:00
if not rig:
self.report({'ERROR'}, 'Choose a Rig')
return {'CANCELLED'}
if not canvas:
self.report({'ERROR'}, 'Choose a Canvas')
return {'CANCELLED'}
2024-02-19 11:53:15 +01:00
data = get_picker_data(shapes, canvas, rig)
2022-04-06 10:12:32 +02:00
2024-02-19 11:53:15 +01:00
picker_path = Path(bpy.path.abspath(collection.rig_picker.destination))
2022-04-06 10:12:32 +02:00
picker_path.write_text(json.dumps(data))
bpy.ops.rigpicker.reload_picker()
return {'FINISHED'}
classes = (
RP_OT_create_shape,
RP_OT_name_from_bone,
RP_OT_mirror_shape,
RP_OT_select_shape_type,
RP_OT_save_picker
)
register, unregister = bpy.utils.register_classes_factory(classes)