mirror of
https://github.com/DarklightGames/io_scene_psk_psa.git
synced 2025-02-23 04:18:59 +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
|
import re
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List, Iterable, Dict, Tuple, Optional
|
from typing import List, Iterable, Dict, Tuple, cast, Optional
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.props import StringProperty
|
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
|
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):
|
def is_action_for_armature(armature: Armature, action: Action):
|
||||||
if len(action.fcurves) == 0:
|
if len(action.fcurves) == 0:
|
||||||
return False
|
return False
|
||||||
@ -30,12 +44,13 @@ def is_action_for_armature(armature: Armature, action: Action):
|
|||||||
return False
|
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')
|
pg = getattr(context.scene, 'psa_export')
|
||||||
|
|
||||||
# Clear actions and markers.
|
# Clear actions and markers.
|
||||||
pg.action_list.clear()
|
pg.action_list.clear()
|
||||||
pg.marker_list.clear()
|
pg.marker_list.clear()
|
||||||
|
pg.active_action_list.clear()
|
||||||
|
|
||||||
# Get animation data.
|
# Get animation data.
|
||||||
animation_data_object = get_animation_data_object(context)
|
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:
|
if animation_data is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
active_armature = cast(Armature, context.active_object.data)
|
||||||
|
|
||||||
# Populate actions list.
|
# Populate actions list.
|
||||||
for action in bpy.data.actions:
|
for action in bpy.data.actions:
|
||||||
if not is_action_for_armature(armature, action):
|
if not is_action_for_armature(active_armature, action):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if action.name != '' and not action.name.startswith('#'):
|
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_start = frame_start
|
||||||
item.frame_end = frame_end
|
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:
|
def get_sequence_fps(context: Context, fps_source: str, fps_custom: float, actions: Iterable[Action]) -> float:
|
||||||
match fps_source:
|
match fps_source:
|
||||||
@ -229,7 +259,6 @@ class PSA_OT_export(Operator, ExportHelper):
|
|||||||
flow.use_property_decorate = False
|
flow.use_property_decorate = False
|
||||||
flow.prop(pg, 'sequence_source', text='Source')
|
flow.prop(pg, 'sequence_source', text='Source')
|
||||||
|
|
||||||
if pg.sequence_source != 'ACTIVE_ACTION':
|
|
||||||
if pg.sequence_source in {'TIMELINE_MARKERS', 'NLA_TRACK_STRIPS'}:
|
if pg.sequence_source in {'TIMELINE_MARKERS', 'NLA_TRACK_STRIPS'}:
|
||||||
# ANIMDATA SOURCE
|
# ANIMDATA SOURCE
|
||||||
flow.prop(pg, 'should_override_animation_data')
|
flow.prop(pg, 'should_override_animation_data')
|
||||||
@ -250,17 +279,6 @@ class PSA_OT_export(Operator, ExportHelper):
|
|||||||
|
|
||||||
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)
|
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,
|
sequences_panel.template_list(PSA_UL_export_sequences.bl_idname, '', pg, propname, pg, active_propname,
|
||||||
rows=max(3, min(len(getattr(pg, propname)), 10)))
|
rows=max(3, min(len(getattr(pg, propname)), 10)))
|
||||||
@ -345,7 +363,7 @@ class PSA_OT_export(Operator, ExportHelper):
|
|||||||
# data created before (i.e. if no action was ever assigned to it).
|
# data created before (i.e. if no action was ever assigned to it).
|
||||||
self.armature_object.animation_data_create()
|
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)
|
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_sequence.key_quota = nla_strip_item.action.psa_export.key_quota
|
||||||
export_sequences.append(export_sequence)
|
export_sequences.append(export_sequence)
|
||||||
case 'ACTIVE_ACTION':
|
case 'ACTIVE_ACTION':
|
||||||
for obj in selected_armature_objects:
|
for active_action_item in filter(lambda x: x.is_selected, pg.active_action_list):
|
||||||
if obj.animation_data is None or obj.animation_data.action is None:
|
export_sequence = PsaBuildSequence(active_action_item.armature_object, active_action_item.armature_object.animation_data)
|
||||||
continue
|
action = active_action_item.action
|
||||||
action = obj.animation_data.action
|
|
||||||
export_sequence = PsaBuildSequence(obj, obj.animation_data)
|
|
||||||
export_sequence.name = action.name
|
export_sequence.name = action.name
|
||||||
export_sequence.nla_state.action = action
|
export_sequence.nla_state.action = action
|
||||||
export_sequence.nla_state.frame_start = int(action.frame_range[0])
|
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
|
return pg.marker_list
|
||||||
case 'NLA_TRACK_STRIPS':
|
case 'NLA_TRACK_STRIPS':
|
||||||
return pg.nla_strip_list
|
return pg.nla_strip_list
|
||||||
|
case 'ACTIVE_ACTION':
|
||||||
|
return pg.active_action_list
|
||||||
case _:
|
case _:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -471,6 +489,7 @@ class PSA_OT_export_actions_select_all(Operator):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
pg = getattr(context.scene, 'psa_export')
|
pg = getattr(context.scene, 'psa_export')
|
||||||
item_list = cls.get_item_list(context)
|
item_list = cls.get_item_list(context)
|
||||||
|
print(item_list)
|
||||||
visible_sequences = get_visible_sequences(pg, item_list)
|
visible_sequences = get_visible_sequences(pg, item_list)
|
||||||
has_unselected_sequences = any(map(lambda item: not item.is_selected, visible_sequences))
|
has_unselected_sequences = any(map(lambda item: not item.is_selected, visible_sequences))
|
||||||
return has_unselected_sequences
|
return has_unselected_sequences
|
||||||
@ -499,6 +518,8 @@ class PSA_OT_export_actions_deselect_all(Operator):
|
|||||||
return pg.marker_list
|
return pg.marker_list
|
||||||
case 'NLA_TRACK_STRIPS':
|
case 'NLA_TRACK_STRIPS':
|
||||||
return pg.nla_strip_list
|
return pg.nla_strip_list
|
||||||
|
case 'ACTIVE_ACTION':
|
||||||
|
return pg.active_action_list
|
||||||
case _:
|
case _:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -27,6 +27,15 @@ class PSA_PG_export_action_list_item(PropertyGroup):
|
|||||||
is_pose_marker: BoolProperty(options={'HIDDEN'})
|
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
|
class PSA_PG_export_timeline_markers(PropertyGroup): # TODO: rename this to singular
|
||||||
marker_index: IntProperty()
|
marker_index: IntProperty()
|
||||||
name: StringProperty()
|
name: StringProperty()
|
||||||
@ -153,6 +162,8 @@ class PSA_PG_export(PropertyGroup):
|
|||||||
marker_list_index: IntProperty(default=0)
|
marker_list_index: IntProperty(default=0)
|
||||||
nla_strip_list: CollectionProperty(type=PSA_PG_export_nla_strip_list_item)
|
nla_strip_list: CollectionProperty(type=PSA_PG_export_nla_strip_list_item)
|
||||||
nla_strip_list_index: IntProperty(default=0)
|
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(
|
bone_filter_mode: EnumProperty(
|
||||||
name='Bone Filter',
|
name='Bone Filter',
|
||||||
options=empty_set,
|
options=empty_set,
|
||||||
@ -235,5 +246,6 @@ classes = (
|
|||||||
PSA_PG_export_action_list_item,
|
PSA_PG_export_action_list_item,
|
||||||
PSA_PG_export_timeline_markers,
|
PSA_PG_export_timeline_markers,
|
||||||
PSA_PG_export_nla_strip_list_item,
|
PSA_PG_export_nla_strip_list_item,
|
||||||
|
PSA_PG_export_active_action_list_item,
|
||||||
PSA_PG_export,
|
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):
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||||
item = typing.cast(PSA_PG_export_action_list_item, item)
|
item = typing.cast(PSA_PG_export_action_list_item, item)
|
||||||
|
|
||||||
is_pose_marker = hasattr(item, 'is_pose_marker') and item.is_pose_marker
|
is_pose_marker = hasattr(item, 'is_pose_marker') and item.is_pose_marker
|
||||||
layout.prop(item, 'is_selected', icon_only=True, text=item.name)
|
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:
|
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:
|
if is_pose_marker:
|
||||||
row.label(text=item.action.name, icon='PMARKER')
|
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):
|
def draw_filter(self, context, layout):
|
||||||
pg = getattr(context.scene, 'psa_export')
|
pg = getattr(context.scene, 'psa_export')
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user