Files
blender-portable-repo/scripts/addons/rokoko-studio-live-blender-master/operators/detector.py
T
2026-03-17 14:58:51 -06:00

228 lines
8.1 KiB
Python

import os
import bpy
import bpy_extras
from ..core import animation_lists
from ..core import detection_manager
from ..core import custom_schemes_manager
class DetectFaceShapes(bpy.types.Operator):
bl_idname = "rsl.detect_face_shapes"
bl_label = "Auto Detect"
bl_description = "Automatically detect face shape keys for supported naming schemes"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
def execute(self, context):
obj = context.object
if not hasattr(obj.data, 'shape_keys') or not hasattr(obj.data.shape_keys, 'key_blocks'):
self.report({'ERROR'}, 'This mesh has no shapekeys!')
return {'CANCELLED'}
for shape_name_key in animation_lists.face_shapes:
setattr(obj, 'rsl_face_' + shape_name_key, detection_manager.detect_shape(obj, shape_name_key))
return {'FINISHED'}
class DetectActorBones(bpy.types.Operator):
bl_idname = "rsl.detect_actor_bones"
bl_label = "Auto Detect"
bl_description = "Automatically detect actor bones for supported naming schemes"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
def execute(self, context):
obj = context.object
for bone_name_key in animation_lists.get_bones().keys():
setattr(obj, 'rsl_actor_' + bone_name_key, detection_manager.detect_bone(obj, bone_name_key))
return {'FINISHED'}
class SaveCustomShapes(bpy.types.Operator):
bl_idname = "rsl.save_custom_shapes"
bl_label = "Save Custom Shapes"
bl_description = "This saves the currently selected shapekeys and they will then get automatically detected"
bl_options = {'INTERNAL'}
def execute(self, context):
obj = context.object
# Go over all face shapekeys and see if the user changed the detected shapekey. If yes, save that new shapekey
for shape_name_key in animation_lists.face_shapes:
shape_name_selected = getattr(obj, 'rsl_face_' + shape_name_key)
if not shape_name_selected:
continue # TODO idea: maybe save these unselected choices as well
shape_name_detected = detection_manager.detect_shape(obj, shape_name_key)
if shape_name_detected == shape_name_selected: # This means that the user changed nothing, so don't save this
continue
custom_schemes_manager.save_live_data_shape_to_list(shape_name_key, shape_name_selected, shape_name_detected)
# At the end save all custom shapes to the file
custom_schemes_manager.save_to_file_and_update()
return {'FINISHED'}
class SaveCustomBones(bpy.types.Operator):
bl_idname = "rsl.save_custom_bones"
bl_label = "Save Custom Bones"
bl_description = "This saves the currently selected bones and they will then get automatically detected"
bl_options = {'INTERNAL'}
def execute(self, context):
obj = context.object
# Go over all actor bones and see if the user changed the detected bone. If yes, save that new bone
for bone_name_key in animation_lists.get_bones().keys():
bone_name_selected = getattr(obj, 'rsl_actor_' + bone_name_key)
if not bone_name_selected:
continue # TODO idea: maybe save these unselected choices as well
bone_name_detected = detection_manager.detect_bone(obj, bone_name_key)
if bone_name_detected == bone_name_selected: # This means that the user changed nothing, so don't save this
continue
custom_schemes_manager.save_live_data_bone_to_list(bone_name_key, bone_name_selected, bone_name_detected)
# At the end save all custom bones to the file
custom_schemes_manager.save_to_file_and_update()
return {'FINISHED'}
class SaveCustomBonesRetargeting(bpy.types.Operator):
bl_idname = "rsl.save_custom_bones_retargeting"
bl_label = "Save Custom Bones"
bl_description = "This saves the currently selected bones and they will then get automatically detected"
bl_options = {'INTERNAL'}
def execute(self, context):
# Save the bone list if the user changed anything
custom_schemes_manager.save_retargeting_to_list()
return {'FINISHED'}
class ImportCustomBones(bpy.types.Operator, bpy_extras.io_utils.ImportHelper):
bl_idname = "rsl.import_custom_schemes"
bl_label = "Import Custom Scheme"
bl_description = "Import a custom naming scheme"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'})
directory: bpy.props.StringProperty(maxlen=1024, subtype='FILE_PATH', options={'HIDDEN', 'SKIP_SAVE'})
filter_glob: bpy.props.StringProperty(default='*.json;', options={'HIDDEN'})
def execute(self, context):
import_count = 0
if self.directory:
for f in self.files:
file_name = f.name
if not file_name.endswith('.json'):
continue
custom_schemes_manager.import_custom_list(self.directory, file_name)
import_count += 1
# If this operator is called with no directory but a filepath argument, import that
elif self.filepath:
custom_schemes_manager.import_custom_list(os.path.dirname(self.filepath), os.path.basename(self.filepath))
import_count += 1
custom_schemes_manager.save_to_file_and_update()
if not import_count:
self.report({'ERROR'}, 'No files were imported.')
return {'FINISHED'}
self.report({'INFO'}, 'Successfully imported new naming schemes.')
return {'FINISHED'}
class ExportCustomBones(bpy.types.Operator, bpy_extras.io_utils.ExportHelper):
bl_idname = "rsl.export_custom_schemes"
bl_label = "Export Custom Scheme"
bl_description = "Export your custom naming schemes"
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
filename_ext = ".json"
filter_glob: bpy.props.StringProperty(default='*.json;', options={'HIDDEN'})
def execute(self, context):
file_name = custom_schemes_manager.export_custom_list(self.filepath)
if not file_name:
self.report({'ERROR'}, 'You don\'t have any custom naming schemes!')
return {'FINISHED'}
self.report({'INFO'}, 'Exported custom naming schemes as "' + file_name + '".')
return {'FINISHED'}
class ClearCustomBones(bpy.types.Operator):
bl_idname = "rsl.clear_custom_bones"
bl_label = "Clear Custom Bones"
bl_description = "Clear all custom bone naming schemes"
bl_options = {'INTERNAL'}
def draw(self, context):
layout = self.layout
layout.separator()
row = layout.row(align=True)
row.scale_y = 0.5
row.label(text='You are about to delete all stored custom bone naming schemes.', icon='ERROR')
row = layout.row(align=True)
row.scale_y = 0.5
row.label(text='Continue?', icon='BLANK1')
layout.separator()
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self, width=400)
def execute(self, context):
custom_schemes_manager.delete_custom_bone_list()
self.report({'INFO'}, 'Cleared all custom bone naming schemes!')
return {'FINISHED'}
class ClearCustomShapes(bpy.types.Operator):
bl_idname = "rsl.clear_custom_shapes"
bl_label = "Clear Custom Shapekeys"
bl_description = "Clear all custom shape naming schemes"
bl_options = {'INTERNAL'}
def draw(self, context):
layout = self.layout
layout.separator()
row = layout.row(align=True)
row.scale_y = 0.5
row.label(text='You are about to delete all stored custom shape naming schemes.', icon='ERROR')
row = layout.row(align=True)
row.scale_y = 0.5
row.label(text='Continue?', icon='BLANK1')
layout.separator()
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self, width=400)
def execute(self, context):
custom_schemes_manager.delete_custom_shape_list()
self.report({'INFO'}, 'Cleared all custom shape naming schemes!')
return {'FINISHED'}