mirror of
https://github.com/DarklightGames/io_scene_psk_psa.git
synced 2025-02-22 11:59:55 +01:00
Added an export list to the PSA export dialog for active actions
This commit is contained in:
parent
491e042cec
commit
ef559d9475
@ -1,6 +1,6 @@
|
||||
import re
|
||||
from collections import Counter
|
||||
from typing import List, Iterable, Dict, Tuple, Optional
|
||||
from typing import List, Iterable, Dict, Tuple, cast, Optional
|
||||
|
||||
import bpy
|
||||
from bpy.props import StringProperty
|
||||
@ -16,6 +16,20 @@ from ...shared.helpers import populate_bone_collection_list, get_nla_strips_in_f
|
||||
from ...shared.ui import draw_bone_filter_mode
|
||||
|
||||
|
||||
def get_sequences_propnames_from_source(sequence_source: str) -> Optional[Tuple[str, str]]:
|
||||
match sequence_source:
|
||||
case 'ACTIONS':
|
||||
return 'action_list', 'action_list_index'
|
||||
case 'TIMELINE_MARKERS':
|
||||
return 'marker_list', 'marker_list_index'
|
||||
case 'NLA_TRACK_STRIPS':
|
||||
return 'nla_strip_list', 'nla_strip_list_index'
|
||||
case 'ACTIVE_ACTION':
|
||||
return 'active_action_list', 'active_action_list_index'
|
||||
case _:
|
||||
raise ValueError(f'Unhandled sequence source: {sequence_source}')
|
||||
|
||||
|
||||
def is_action_for_armature(armature: Armature, action: Action):
|
||||
if len(action.fcurves) == 0:
|
||||
return False
|
||||
@ -30,12 +44,13 @@ def is_action_for_armature(armature: Armature, action: Action):
|
||||
return False
|
||||
|
||||
|
||||
def update_actions_and_timeline_markers(context: Context, armature: Armature):
|
||||
def update_actions_and_timeline_markers(context: Context):
|
||||
pg = getattr(context.scene, 'psa_export')
|
||||
|
||||
# Clear actions and markers.
|
||||
pg.action_list.clear()
|
||||
pg.marker_list.clear()
|
||||
pg.active_action_list.clear()
|
||||
|
||||
# Get animation data.
|
||||
animation_data_object = get_animation_data_object(context)
|
||||
@ -44,9 +59,11 @@ def update_actions_and_timeline_markers(context: Context, armature: Armature):
|
||||
if animation_data is None:
|
||||
return
|
||||
|
||||
active_armature = cast(Armature, context.active_object.data)
|
||||
|
||||
# Populate actions list.
|
||||
for action in bpy.data.actions:
|
||||
if not is_action_for_armature(armature, action):
|
||||
if not is_action_for_armature(active_armature, action):
|
||||
continue
|
||||
|
||||
if action.name != '' and not action.name.startswith('#'):
|
||||
@ -91,6 +108,19 @@ def update_actions_and_timeline_markers(context: Context, armature: Armature):
|
||||
item.frame_start = frame_start
|
||||
item.frame_end = frame_end
|
||||
|
||||
# Populate the active action list.
|
||||
for armature_object in context.selected_objects:
|
||||
if armature_object.type != 'ARMATURE':
|
||||
continue
|
||||
action = armature_object.animation_data.action
|
||||
item = pg.active_action_list.add()
|
||||
item.name = action.name
|
||||
item.armature_object = armature_object
|
||||
item.action = action
|
||||
item.frame_start = int(item.action.frame_range[0])
|
||||
item.frame_end = int(item.action.frame_range[1])
|
||||
item.is_selected = True
|
||||
|
||||
|
||||
def get_sequence_fps(context: Context, fps_source: str, fps_custom: float, actions: Iterable[Action]) -> float:
|
||||
match fps_source:
|
||||
@ -229,41 +259,29 @@ class PSA_OT_export(Operator, ExportHelper):
|
||||
flow.use_property_decorate = False
|
||||
flow.prop(pg, 'sequence_source', text='Source')
|
||||
|
||||
if pg.sequence_source != 'ACTIVE_ACTION':
|
||||
if pg.sequence_source in {'TIMELINE_MARKERS', 'NLA_TRACK_STRIPS'}:
|
||||
# ANIMDATA SOURCE
|
||||
flow.prop(pg, 'should_override_animation_data')
|
||||
if pg.should_override_animation_data:
|
||||
flow.prop(pg, 'animation_data_override', text=' ')
|
||||
if pg.sequence_source in {'TIMELINE_MARKERS', 'NLA_TRACK_STRIPS'}:
|
||||
# ANIMDATA SOURCE
|
||||
flow.prop(pg, 'should_override_animation_data')
|
||||
if pg.should_override_animation_data:
|
||||
flow.prop(pg, 'animation_data_override', text=' ')
|
||||
|
||||
if pg.sequence_source == 'NLA_TRACK_STRIPS':
|
||||
flow = sequences_panel.grid_flow()
|
||||
flow.use_property_split = True
|
||||
flow.use_property_decorate = False
|
||||
flow.prop(pg, 'nla_track')
|
||||
if pg.sequence_source == 'NLA_TRACK_STRIPS':
|
||||
flow = sequences_panel.grid_flow()
|
||||
flow.use_property_split = True
|
||||
flow.use_property_decorate = False
|
||||
flow.prop(pg, 'nla_track')
|
||||
|
||||
# SELECT ALL/NONE
|
||||
row = sequences_panel.row(align=True)
|
||||
row.label(text='Select')
|
||||
row.operator(PSA_OT_export_actions_select_all.bl_idname, text='All', icon='CHECKBOX_HLT')
|
||||
row.operator(PSA_OT_export_actions_deselect_all.bl_idname, text='None', icon='CHECKBOX_DEHLT')
|
||||
# SELECT ALL/NONE
|
||||
row = sequences_panel.row(align=True)
|
||||
row.label(text='Select')
|
||||
row.operator(PSA_OT_export_actions_select_all.bl_idname, text='All', icon='CHECKBOX_HLT')
|
||||
row.operator(PSA_OT_export_actions_deselect_all.bl_idname, text='None', icon='CHECKBOX_DEHLT')
|
||||
|
||||
from .ui import PSA_UL_export_sequences
|
||||
from .ui import PSA_UL_export_sequences
|
||||
|
||||
def get_sequences_propnames_from_source(sequence_source: str) -> Optional[Tuple[str, str]]:
|
||||
match sequence_source:
|
||||
case 'ACTIONS':
|
||||
return 'action_list', 'action_list_index'
|
||||
case 'TIMELINE_MARKERS':
|
||||
return 'marker_list', 'marker_list_index'
|
||||
case 'NLA_TRACK_STRIPS':
|
||||
return 'nla_strip_list', 'nla_strip_list_index'
|
||||
case _:
|
||||
raise ValueError(f'Unhandled sequence source: {sequence_source}')
|
||||
|
||||
propname, active_propname = get_sequences_propnames_from_source(pg.sequence_source)
|
||||
sequences_panel.template_list(PSA_UL_export_sequences.bl_idname, '', pg, propname, pg, active_propname,
|
||||
rows=max(3, min(len(getattr(pg, propname)), 10)))
|
||||
propname, active_propname = get_sequences_propnames_from_source(pg.sequence_source)
|
||||
sequences_panel.template_list(PSA_UL_export_sequences.bl_idname, '', pg, propname, pg, active_propname,
|
||||
rows=max(3, min(len(getattr(pg, propname)), 10)))
|
||||
|
||||
flow = sequences_panel.grid_flow()
|
||||
flow.use_property_split = True
|
||||
@ -345,7 +363,7 @@ class PSA_OT_export(Operator, ExportHelper):
|
||||
# data created before (i.e. if no action was ever assigned to it).
|
||||
self.armature_object.animation_data_create()
|
||||
|
||||
update_actions_and_timeline_markers(context, self.armature_object.data)
|
||||
update_actions_and_timeline_markers(context)
|
||||
|
||||
populate_bone_collection_list(self.armature_object, pg.bone_collection_list)
|
||||
|
||||
@ -410,11 +428,9 @@ class PSA_OT_export(Operator, ExportHelper):
|
||||
export_sequence.key_quota = nla_strip_item.action.psa_export.key_quota
|
||||
export_sequences.append(export_sequence)
|
||||
case 'ACTIVE_ACTION':
|
||||
for obj in selected_armature_objects:
|
||||
if obj.animation_data is None or obj.animation_data.action is None:
|
||||
continue
|
||||
action = obj.animation_data.action
|
||||
export_sequence = PsaBuildSequence(obj, obj.animation_data)
|
||||
for active_action_item in filter(lambda x: x.is_selected, pg.active_action_list):
|
||||
export_sequence = PsaBuildSequence(active_action_item.armature_object, active_action_item.armature_object.animation_data)
|
||||
action = active_action_item.action
|
||||
export_sequence.name = action.name
|
||||
export_sequence.nla_state.action = action
|
||||
export_sequence.nla_state.frame_start = int(action.frame_range[0])
|
||||
@ -464,6 +480,8 @@ class PSA_OT_export_actions_select_all(Operator):
|
||||
return pg.marker_list
|
||||
case 'NLA_TRACK_STRIPS':
|
||||
return pg.nla_strip_list
|
||||
case 'ACTIVE_ACTION':
|
||||
return pg.active_action_list
|
||||
case _:
|
||||
return None
|
||||
|
||||
@ -471,6 +489,7 @@ class PSA_OT_export_actions_select_all(Operator):
|
||||
def poll(cls, context):
|
||||
pg = getattr(context.scene, 'psa_export')
|
||||
item_list = cls.get_item_list(context)
|
||||
print(item_list)
|
||||
visible_sequences = get_visible_sequences(pg, item_list)
|
||||
has_unselected_sequences = any(map(lambda item: not item.is_selected, visible_sequences))
|
||||
return has_unselected_sequences
|
||||
@ -499,6 +518,8 @@ class PSA_OT_export_actions_deselect_all(Operator):
|
||||
return pg.marker_list
|
||||
case 'NLA_TRACK_STRIPS':
|
||||
return pg.nla_strip_list
|
||||
case 'ACTIVE_ACTION':
|
||||
return pg.active_action_list
|
||||
case _:
|
||||
return None
|
||||
|
||||
|
@ -27,6 +27,15 @@ class PSA_PG_export_action_list_item(PropertyGroup):
|
||||
is_pose_marker: BoolProperty(options={'HIDDEN'})
|
||||
|
||||
|
||||
class PSA_PG_export_active_action_list_item(PropertyGroup):
|
||||
action: PointerProperty(type=Action)
|
||||
name: StringProperty()
|
||||
armature_object: PointerProperty(type=Object)
|
||||
is_selected: BoolProperty(default=True)
|
||||
frame_start: IntProperty(options={'HIDDEN'})
|
||||
frame_end: IntProperty(options={'HIDDEN'})
|
||||
|
||||
|
||||
class PSA_PG_export_timeline_markers(PropertyGroup): # TODO: rename this to singular
|
||||
marker_index: IntProperty()
|
||||
name: StringProperty()
|
||||
@ -153,6 +162,8 @@ class PSA_PG_export(PropertyGroup):
|
||||
marker_list_index: IntProperty(default=0)
|
||||
nla_strip_list: CollectionProperty(type=PSA_PG_export_nla_strip_list_item)
|
||||
nla_strip_list_index: IntProperty(default=0)
|
||||
active_action_list: CollectionProperty(type=PSA_PG_export_active_action_list_item)
|
||||
active_action_list_index: IntProperty(default=0)
|
||||
bone_filter_mode: EnumProperty(
|
||||
name='Bone Filter',
|
||||
options=empty_set,
|
||||
@ -235,5 +246,6 @@ classes = (
|
||||
PSA_PG_export_action_list_item,
|
||||
PSA_PG_export_timeline_markers,
|
||||
PSA_PG_export_nla_strip_list_item,
|
||||
PSA_PG_export_active_action_list_item,
|
||||
PSA_PG_export,
|
||||
)
|
||||
|
@ -15,6 +15,7 @@ class PSA_UL_export_sequences(UIList):
|
||||
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
item = typing.cast(PSA_PG_export_action_list_item, item)
|
||||
|
||||
is_pose_marker = hasattr(item, 'is_pose_marker') and item.is_pose_marker
|
||||
layout.prop(item, 'is_selected', icon_only=True, text=item.name)
|
||||
if hasattr(item, 'action') and item.action is not None and item.action.asset_data is not None:
|
||||
@ -27,6 +28,9 @@ class PSA_UL_export_sequences(UIList):
|
||||
if is_pose_marker:
|
||||
row.label(text=item.action.name, icon='PMARKER')
|
||||
|
||||
if hasattr(item, 'armature_object') and item.armature_object is not None:
|
||||
row.label(text=item.armature_object.name, icon='ARMATURE_DATA')
|
||||
|
||||
def draw_filter(self, context, layout):
|
||||
pg = getattr(context.scene, 'psa_export')
|
||||
row = layout.row()
|
||||
|
Loading…
x
Reference in New Issue
Block a user