167 lines
5.9 KiB
Python
167 lines
5.9 KiB
Python
import bpy
|
|
|
|
from ..core import animations, animation_lists
|
|
from ..operators.actor import InitTPose, ResetTPose
|
|
from ..operators import detector
|
|
|
|
|
|
# Create a panel in the Object category of all objects
|
|
class ObjectsPanel(bpy.types.Panel):
|
|
bl_label = "Rokoko Studio Live Setup"
|
|
bl_idname = "OBJECT_PT_rsl_objects_v2"
|
|
bl_space_type = 'PROPERTIES'
|
|
bl_region_type = 'WINDOW'
|
|
bl_context = "object"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
obj = context.object
|
|
|
|
self.draw_tracker(context, layout)
|
|
|
|
if obj.type == 'MESH':
|
|
self.draw_face(context, layout)
|
|
|
|
elif obj.type == 'ARMATURE':
|
|
self.draw_actor(context, layout)
|
|
|
|
@staticmethod
|
|
def draw_tracker(context, layout):
|
|
obj = context.object
|
|
|
|
props_string = 'Prop or Tracker' if animations.live_data.version <= 2 else 'prop'
|
|
|
|
row = layout.row(align=True)
|
|
row.label(text=f'Attach to {props_string}:')
|
|
|
|
if not animations.live_data.trackers and not animations.live_data.props:
|
|
row = layout.row(align=True)
|
|
row.label(text=f'No {props_string.lower()} data available.', icon='INFO')
|
|
return
|
|
|
|
row = layout.row(align=True)
|
|
row.prop(context.object, 'rsl_animations_props_trackers')
|
|
|
|
if obj.rsl_animations_props_trackers and obj.rsl_animations_props_trackers != 'None':
|
|
row = layout.row(align=True)
|
|
row.prop(context.object, 'rsl_use_custom_scale')
|
|
if obj.rsl_use_custom_scale:
|
|
row.prop(context.object, 'rsl_custom_scene_scale', text='')
|
|
|
|
@staticmethod
|
|
def draw_face(context, layout):
|
|
obj = context.object
|
|
|
|
layout.separator()
|
|
|
|
row = layout.row(align=True)
|
|
row.label(text='Attach to Face:')
|
|
|
|
if not animations.live_data.faces:
|
|
row = layout.row(align=True)
|
|
row.label(text='No face data available.', icon='INFO')
|
|
row = layout.row(align=True)
|
|
row.scale_y = 0.1
|
|
return
|
|
|
|
row = layout.row(align=True)
|
|
row.prop(obj, 'rsl_animations_faces')
|
|
|
|
if obj.rsl_animations_faces and obj.rsl_animations_faces != 'None':
|
|
layout.separator()
|
|
row = layout.row(align=True)
|
|
row.label(text='Select Shapekeys:')
|
|
row.operator(detector.DetectFaceShapes.bl_idname)
|
|
|
|
if not hasattr(obj.data, 'shape_keys') or not hasattr(obj.data.shape_keys, 'key_blocks'):
|
|
row = layout.row(align=True)
|
|
row.label(text='This mesh has no shapekeys!', icon='INFO')
|
|
return
|
|
|
|
draw_import_export(layout, shapes=True)
|
|
|
|
for shape in animation_lists.face_shapes:
|
|
row = layout.row(align=True)
|
|
row.prop_search(obj, 'rsl_face_' + shape, obj.data.shape_keys, "key_blocks", text=shape)
|
|
|
|
@staticmethod
|
|
def draw_actor(context, layout):
|
|
obj = context.object
|
|
|
|
layout.separator()
|
|
|
|
row = layout.row(align=True)
|
|
row.label(text='Attach to Actor:')
|
|
|
|
if not animations.live_data.actors:
|
|
row = layout.row(align=True)
|
|
row.label(text='No actor data available.', icon='INFO')
|
|
else:
|
|
row = layout.row(align=True)
|
|
row.prop(context.object, 'rsl_animations_actors')
|
|
|
|
if obj.rsl_animations_actors and obj.rsl_animations_actors != 'None':
|
|
layout.separator()
|
|
|
|
split = layout.row(align=True)
|
|
row = split.split(factor=0.16, align=True)
|
|
row.label(text='Bones:')
|
|
row.operator(detector.DetectActorBones.bl_idname)
|
|
row.operator(InitTPose.bl_idname)
|
|
row.operator(ResetTPose.bl_idname)
|
|
|
|
# if obj.rsl_animations_actors and obj.rsl_animations_actors != 'None':
|
|
if not obj.get('CUSTOM') or not obj.get('CUSTOM').get('rsl_tpose_bones'):
|
|
row = layout.row(align=True)
|
|
row.label(text='T-Pose is not set yet!', icon='ERROR')
|
|
|
|
draw_import_export(layout)
|
|
|
|
col = layout.column()
|
|
show_gloves = True
|
|
for actor_bone in animation_lists.get_bones().keys():
|
|
if not show_gloves:
|
|
continue
|
|
|
|
split = col.row(align=True)
|
|
row = split.split(factor=0.32, align=True)
|
|
row.label(text=actor_bone + ':')
|
|
row.prop_search(obj, 'rsl_actor_' + actor_bone, obj.pose, "bones", text='')
|
|
|
|
# Make a split after right toe to separate hands
|
|
if actor_bone == 'rightToe':
|
|
if not animations.live_data.has_gloves(animations.live_data.get_actor_by_obj(obj)): # Stop showing glove bones if they are not supported by the JSON version
|
|
show_gloves = False
|
|
continue
|
|
col.separator()
|
|
row = col.row(align=True)
|
|
row.label(text='Gloves:', icon='VIEW_PAN')
|
|
|
|
if actor_bone == 'leftLittleDistal':
|
|
col.separator()
|
|
|
|
|
|
def draw_import_export(layout, shapes=False):
|
|
layout.separator()
|
|
|
|
row = layout.row(align=True)
|
|
row.label(text='Custom Naming Schemes:')
|
|
if shapes:
|
|
row.operator(detector.SaveCustomShapes.bl_idname, text='Save Current Naming Scheme')
|
|
else:
|
|
row.operator(detector.SaveCustomBones.bl_idname, text='Save Current Naming Scheme')
|
|
|
|
subrow = layout.row(align=True)
|
|
row = subrow.row(align=True)
|
|
row.scale_y = 0.9
|
|
row.operator(detector.ImportCustomBones.bl_idname, text='Import')
|
|
row.operator(detector.ExportCustomBones.bl_idname, text='Export')
|
|
row = subrow.row(align=True)
|
|
row.scale_y = 0.9
|
|
row.alignment = 'RIGHT'
|
|
if shapes:
|
|
row.operator(detector.ClearCustomShapes.bl_idname, text='', icon='X')
|
|
else:
|
|
row.operator(detector.ClearCustomBones.bl_idname, text='', icon='X')
|
|
|
|
layout.separator() |