mirror of https://github.com/AxioDL/metaforce.git
212 lines
8.3 KiB
Python
212 lines
8.3 KiB
Python
|
from . import SACTEvent
|
||
|
import bpy
|
||
|
|
||
|
# Action update (if anything important changes)
|
||
|
def active_action_update(self, context):
|
||
|
if not bpy.app.background:
|
||
|
if context.scene.hecl_type == 'ACTOR' and context.scene.hecl_auto_select:
|
||
|
if SACTAction_load.poll(context):
|
||
|
bpy.ops.scene.SACTAction_load()
|
||
|
|
||
|
# Action type update
|
||
|
def action_type_update(self, context):
|
||
|
if not bpy.app.background:
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
active_action_update(self, context)
|
||
|
|
||
|
# Actor action class
|
||
|
class SACTAction(bpy.types.PropertyGroup):
|
||
|
name = bpy.props.StringProperty(name="Action Name")
|
||
|
action = bpy.props.StringProperty(name="Blender Action")
|
||
|
|
||
|
# Panel draw
|
||
|
def draw(layout, context):
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
|
||
|
row = layout.row(align=True)
|
||
|
row.alignment = 'LEFT'
|
||
|
row.prop(actor_data, 'show_actions', text="Actions", icon='ACTION', emboss=False)
|
||
|
if actor_data.show_actions:
|
||
|
|
||
|
row = layout.row()
|
||
|
row.template_list("UI_UL_list", "SCENE_UL_SACTActions",
|
||
|
actor_data, 'actions', actor_data, 'active_action')
|
||
|
col = row.column(align=True)
|
||
|
col.operator("scene.sactaction_add", icon="ZOOMIN", text="")
|
||
|
col.operator("scene.sactaction_remove", icon="ZOOMOUT", text="")
|
||
|
|
||
|
if len(actor_data.actions) and actor_data.active_action >= 0:
|
||
|
action = actor_data.actions[actor_data.active_action]
|
||
|
|
||
|
# Load action operator
|
||
|
if not bpy.context.scene.hecl_auto_select:
|
||
|
layout.operator("scene.sactaction_load", icon='FILE_TICK', text="Load Action")
|
||
|
|
||
|
# Name edit field
|
||
|
layout.prop(action, 'name', text="Name")
|
||
|
|
||
|
layout.prop_search(action, 'action', bpy.data, 'actions', text="Action")
|
||
|
linked_action = None
|
||
|
if bpy.data.actions.find(action.action) != -1:
|
||
|
linked_action = bpy.data.actions[action.action]
|
||
|
|
||
|
# Validate
|
||
|
if linked_action is None:
|
||
|
layout.label("Source action not set", icon='ERROR')
|
||
|
else:
|
||
|
layout.prop(linked_action, 'hecl_index', text="Index")
|
||
|
layout.prop(linked_action, 'hecl_anim_props', text="Props")
|
||
|
layout.prop(linked_action, 'hecl_fps', text="Frame Rate")
|
||
|
layout.prop(context.scene, 'hecl_auto_remap', text="60-fps Remap")
|
||
|
|
||
|
|
||
|
|
||
|
# Action 'add' operator
|
||
|
class SACTAction_add(bpy.types.Operator):
|
||
|
bl_idname = "scene.sactaction_add"
|
||
|
bl_label = "New HECL Actor Action"
|
||
|
bl_description = "Add New HECL Actor Action to active scene"
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
return (context.scene is not None and
|
||
|
not context.scene.library and
|
||
|
context.scene.hecl_type == 'ACTOR')
|
||
|
|
||
|
def execute(self, context):
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
action_name = 'ActorAction'
|
||
|
if action_name in actor_data.actions:
|
||
|
action_name = 'ActorAction.001'
|
||
|
action_idx = 1
|
||
|
while action_name in actor_data.actions:
|
||
|
action_idx += 1
|
||
|
action_name = 'ActorAction.{:0>3}'.format(action_idx)
|
||
|
action = actor_data.actions.add()
|
||
|
action.name = action_name
|
||
|
actor_data.active_action = len(actor_data.actions)-1
|
||
|
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
# Action 'remove' operator
|
||
|
class SACTAction_remove(bpy.types.Operator):
|
||
|
bl_idname = "scene.sactaction_remove"
|
||
|
bl_label = "Remove HECL Actor Action"
|
||
|
bl_description = "Remove HECL Actor Action from active scene"
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
return (context.scene is not None and
|
||
|
not context.scene.library and
|
||
|
context.scene.hecl_type == 'ACTOR' and
|
||
|
actor_data.active_action >= 0 and
|
||
|
len(actor_data.actions))
|
||
|
|
||
|
def execute(self, context):
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
actor_data.actions.remove(actor_data.active_action)
|
||
|
actor_data.active_action -= 1
|
||
|
if actor_data.active_action == -1:
|
||
|
actor_data.active_action = 0
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
|
||
|
# Action 'load' operator
|
||
|
class SACTAction_load(bpy.types.Operator):
|
||
|
bl_idname = "scene.sactaction_load"
|
||
|
bl_label = "Load HECL Actor Action"
|
||
|
bl_description = "Loads Action for playback in active scene"
|
||
|
|
||
|
@classmethod
|
||
|
def poll(cls, context):
|
||
|
return (context.scene is not None and
|
||
|
context.scene.hecl_type == 'ACTOR' and
|
||
|
len(context.scene.hecl_sact_data.actions) and
|
||
|
context.scene.hecl_sact_data.active_action >= 0)
|
||
|
|
||
|
def execute(self, context):
|
||
|
actor_data = context.scene.hecl_sact_data
|
||
|
|
||
|
if actor_data.active_action not in range(len(actor_data.actions)):
|
||
|
return {'CANCELLED'}
|
||
|
if actor_data.active_subtype not in range(len(actor_data.subtypes)):
|
||
|
return {'CANCELLED'}
|
||
|
|
||
|
action_data = actor_data.actions[actor_data.active_action]
|
||
|
subtype = actor_data.subtypes[actor_data.active_subtype]
|
||
|
|
||
|
# Refresh event markers
|
||
|
actor_event.clear_event_markers(actor_data, context)
|
||
|
actor_event.update_action_events(None)
|
||
|
actor_event.active_event_update(None, context)
|
||
|
|
||
|
# Clear animation data for all subtypes
|
||
|
for s in range(len(actor_data.subtypes)):
|
||
|
st = actor_data.subtypes[s]
|
||
|
if st.linked_armature in bpy.data.objects:
|
||
|
am = bpy.data.objects[st.linked_armature]
|
||
|
am.animation_data_clear()
|
||
|
|
||
|
# Set single action into armature
|
||
|
if subtype.linked_armature in bpy.data.objects:
|
||
|
armature_obj = bpy.data.objects[subtype.linked_armature]
|
||
|
if action_data.action in bpy.data.actions:
|
||
|
action_obj =\
|
||
|
bpy.data.actions[action_data.action]
|
||
|
armature_obj.animation_data_clear()
|
||
|
armature_obj.animation_data_create()
|
||
|
armature_obj.animation_data.action = action_obj
|
||
|
|
||
|
# Time remapping
|
||
|
if context.scene.hecl_auto_remap:
|
||
|
bpy.context.scene.render.fps = 60
|
||
|
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
|
||
|
bpy.context.scene.render.frame_map_new = 60
|
||
|
bpy.context.scene.frame_start = 2
|
||
|
bpy.context.scene.frame_end = action_obj.frame_range[1] * (60 / action_obj.hecl_fps)
|
||
|
else:
|
||
|
bpy.context.scene.render.fps = action_obj.hecl_fps
|
||
|
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
|
||
|
bpy.context.scene.render.frame_map_new = action_obj.hecl_fps
|
||
|
bpy.context.scene.frame_start = 1
|
||
|
bpy.context.scene.frame_end = action_obj.frame_range[1]
|
||
|
|
||
|
# Events
|
||
|
#actor_event.clear_action_events(self, context, actor_data)
|
||
|
#actor_event.load_action_events(self, context, action_obj, 0)
|
||
|
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
else:
|
||
|
armature_obj.animation_data_clear()
|
||
|
self.report({'WARNING'}, "Unable to load action; check HECL panel")
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
else:
|
||
|
self.report({'WARNING'}, "Unable to load armature; check HECL panel")
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
# Registration
|
||
|
def register():
|
||
|
bpy.types.Action.hecl_fps = bpy.props.IntProperty(name="HECL Actor Sub-action Frame-rate",
|
||
|
description="Frame-rate at which action is authored; to be interpolated at 60-fps by runtime",
|
||
|
min=1, max=60, default=30,
|
||
|
update=active_action_update)
|
||
|
bpy.types.Action.hecl_anim_props = bpy.props.StringProperty(name="Animation Metadata")
|
||
|
bpy.types.Action.hecl_index = bpy.props.IntProperty(name="HECL Actor Action Index")
|
||
|
bpy.utils.register_class(SACTAction)
|
||
|
bpy.utils.register_class(SACTAction_add)
|
||
|
bpy.utils.register_class(SACTAction_load)
|
||
|
bpy.utils.register_class(SACTAction_remove)
|
||
|
|
||
|
|
||
|
def unregister():
|
||
|
bpy.utils.unregister_class(SACTAction)
|
||
|
bpy.utils.unregister_class(SACTAction_add)
|
||
|
bpy.utils.unregister_class(SACTAction_load)
|
||
|
bpy.utils.unregister_class(SACTAction_remove)
|