228 lines
8.1 KiB
Python
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'}
|