Refactor of disparate export sequences types to use a unified type
This commit is contained in:
@@ -10,10 +10,8 @@ from bpy_extras.io_utils import ExportHelper
|
|||||||
|
|
||||||
from .properties import (
|
from .properties import (
|
||||||
PSA_PG_export,
|
PSA_PG_export,
|
||||||
PSA_PG_export_action_list_item,
|
|
||||||
PsaExportMixin,
|
PsaExportMixin,
|
||||||
PsaExportSequenceMixin,
|
PsaExportSequenceMixin,
|
||||||
PsaExportSequenceWithActionMixin,
|
|
||||||
filter_sequences,
|
filter_sequences,
|
||||||
get_sequences_from_name_and_frame_range,
|
get_sequences_from_name_and_frame_range,
|
||||||
)
|
)
|
||||||
@@ -261,7 +259,7 @@ def get_sequences_from_action_pose_markers(
|
|||||||
yield from get_sequences_from_name_and_frame_range(sequence_name, frame_start, frame_end)
|
yield from get_sequences_from_name_and_frame_range(sequence_name, frame_start, frame_end)
|
||||||
|
|
||||||
|
|
||||||
def get_visible_sequences(pg: PsaExportMixin, sequences) -> List[PSA_PG_export_action_list_item]:
|
def get_visible_sequences(pg: PsaExportMixin, sequences) -> List[PsaExportSequenceMixin]:
|
||||||
visible_sequences = []
|
visible_sequences = []
|
||||||
for i, flag in enumerate(filter_sequences(pg, sequences)):
|
for i, flag in enumerate(filter_sequences(pg, sequences)):
|
||||||
if bool(flag & (1 << 30)):
|
if bool(flag & (1 << 30)):
|
||||||
|
|||||||
@@ -21,43 +21,38 @@ from ...shared.types import TransformMixin, ExportSpaceMixin, PsxBoneExportMixin
|
|||||||
def psa_export_property_group_animation_data_override_poll(_context, obj):
|
def psa_export_property_group_animation_data_override_poll(_context, obj):
|
||||||
return obj.animation_data is not None
|
return obj.animation_data is not None
|
||||||
|
|
||||||
|
|
||||||
class PsaExportSequenceMixin(PropertyGroup):
|
class PsaExportSequenceMixin(PropertyGroup):
|
||||||
name: StringProperty(name='Name')
|
name: StringProperty(name='Name')
|
||||||
is_selected: BoolProperty(name='Selected', default=True)
|
is_selected: BoolProperty(name='Selected', default=True)
|
||||||
frame_start: IntProperty(name='Start Frame', options={'HIDDEN'})
|
frame_start: IntProperty(name='Start Frame', options={'HIDDEN'})
|
||||||
frame_end: IntProperty(name='End Frame', options={'HIDDEN'})
|
frame_end: IntProperty(name='End Frame', options={'HIDDEN'})
|
||||||
group: StringProperty(name='Group')
|
group: StringProperty(name='Group')
|
||||||
|
action_name: StringProperty(name='Action Name',default='', options={'HIDDEN'})
|
||||||
|
armature_object_name: StringProperty(name='Armature Object Name',default='', options={'HIDDEN'})
|
||||||
|
marker_index: IntProperty(name='Marker Index',default=-1, options={'HIDDEN'})
|
||||||
|
is_pose_marker: BoolProperty(name='Is Pose Marker',default=False, options={'HIDDEN'})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action(self) -> Action | None:
|
||||||
|
"""Get the action associated with this sequence (if any)."""
|
||||||
|
return bpy.data.actions.get(self.action_name) if self.action_name else None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def armature_object(self) -> Object | None:
|
||||||
|
"""Get the armature object associated with this sequence (if any)."""
|
||||||
|
return bpy.data.objects.get(self.armature_object_name) if self.armature_object_name else None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_reversed(self) -> bool:
|
||||||
|
"""Check if the sequence is reversed (end frame before start frame)."""
|
||||||
|
return self.frame_end < self.frame_start
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(self.name)
|
return hash(self.name)
|
||||||
|
|
||||||
class PsaExportSequenceWithActionMixin(PsaExportSequenceMixin):
|
|
||||||
action_name: StringProperty()
|
|
||||||
|
|
||||||
@property
|
class PSA_PG_export_sequence(PsaExportSequenceMixin):
|
||||||
def action(self) -> Optional[Action]:
|
|
||||||
return bpy.data.actions.get(self.action_name)
|
|
||||||
|
|
||||||
class PSA_PG_export_action_list_item(PsaExportSequenceWithActionMixin):
|
|
||||||
is_pose_marker: BoolProperty(options={'HIDDEN'})
|
|
||||||
|
|
||||||
|
|
||||||
class PSA_PG_export_active_action_list_item(PsaExportSequenceWithActionMixin):
|
|
||||||
armature_object_name: StringProperty()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def armature_object(self) -> Optional[Object]:
|
|
||||||
return bpy.data.objects.get(self.armature_object_name)
|
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
|
||||||
return super().__hash__()
|
|
||||||
|
|
||||||
|
|
||||||
class PSA_PG_export_timeline_marker(PsaExportSequenceMixin):
|
|
||||||
marker_index: IntProperty()
|
|
||||||
|
|
||||||
|
|
||||||
class PSA_PG_export_nla_strip_list_item(PsaExportSequenceWithActionMixin):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +100,7 @@ def nla_track_update_cb(self: 'PSA_PG_export', context: Context) -> None:
|
|||||||
nla_track = animation_data.nla_tracks[self.nla_track_index]
|
nla_track = animation_data.nla_tracks[self.nla_track_index]
|
||||||
for nla_strip in nla_track.strips:
|
for nla_strip in nla_track.strips:
|
||||||
for sequence_name, frame_start, frame_end in get_sequences_from_name_and_frame_range(nla_strip.name, nla_strip.frame_start, nla_strip.frame_end):
|
for sequence_name, frame_start, frame_end in get_sequences_from_name_and_frame_range(nla_strip.name, nla_strip.frame_start, nla_strip.frame_end):
|
||||||
strip: PSA_PG_export_nla_strip_list_item = self.nla_strip_list.add()
|
strip: PSA_PG_export_sequence = self.nla_strip_list.add()
|
||||||
strip.action_name = nla_strip.action
|
strip.action_name = nla_strip.action
|
||||||
strip.name = sequence_name
|
strip.name = sequence_name
|
||||||
strip.frame_start = frame_start
|
strip.frame_start = frame_start
|
||||||
@@ -203,13 +198,13 @@ class PsaExportMixin(PropertyGroup, TransformMixin, ExportSpaceMixin, PsxBoneExp
|
|||||||
)
|
)
|
||||||
compression_ratio_custom: FloatProperty(default=1.0, min=0.0, max=1.0, subtype='FACTOR', description='The key sampling ratio of the exported sequence.\n\nA compression ratio of 1.0 will export all frames, while a compression ratio of 0.5 will export half of the frames')
|
compression_ratio_custom: FloatProperty(default=1.0, min=0.0, max=1.0, subtype='FACTOR', description='The key sampling ratio of the exported sequence.\n\nA compression ratio of 1.0 will export all frames, while a compression ratio of 0.5 will export half of the frames')
|
||||||
|
|
||||||
action_list: CollectionProperty(type=PSA_PG_export_action_list_item)
|
action_list: CollectionProperty(type=PSA_PG_export_sequence)
|
||||||
action_list_index: IntProperty(default=0)
|
action_list_index: IntProperty(default=0)
|
||||||
marker_list: CollectionProperty(type=PSA_PG_export_timeline_marker)
|
marker_list: CollectionProperty(type=PSA_PG_export_sequence)
|
||||||
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_sequence)
|
||||||
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: CollectionProperty(type=PSA_PG_export_sequence)
|
||||||
active_action_list_index: IntProperty(default=0)
|
active_action_list_index: IntProperty(default=0)
|
||||||
|
|
||||||
sequence_name_prefix: StringProperty(name='Prefix', options=set())
|
sequence_name_prefix: StringProperty(name='Prefix', options=set())
|
||||||
@@ -264,7 +259,7 @@ class PSA_PG_export(PsaExportMixin):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def filter_sequences(pg: PsaExportMixin, sequences: Sequence[PsaExportSequenceMixin]) -> List[int]:
|
def filter_sequences(pg: PsaExportMixin, sequences: Sequence[PsaExportSequenceMixin]) -> list[int]:
|
||||||
bitflag_filter_item = 1 << 30
|
bitflag_filter_item = 1 << 30
|
||||||
flt_flags = [bitflag_filter_item] * len(sequences)
|
flt_flags = [bitflag_filter_item] * len(sequences)
|
||||||
|
|
||||||
@@ -279,31 +274,26 @@ def filter_sequences(pg: PsaExportMixin, sequences: Sequence[PsaExportSequenceMi
|
|||||||
for i, sequence in enumerate(sequences):
|
for i, sequence in enumerate(sequences):
|
||||||
flt_flags[i] ^= bitflag_filter_item
|
flt_flags[i] ^= bitflag_filter_item
|
||||||
|
|
||||||
# TODO: perhaps just make one type that has all of the possible data types? hasattr is very flakey.
|
|
||||||
# we could just add the "type" as a variable and switch on that for different behaviors.
|
|
||||||
if not pg.sequence_filter_asset:
|
if not pg.sequence_filter_asset:
|
||||||
for i, sequence in enumerate(sequences):
|
for i, sequence in enumerate(sequences):
|
||||||
if hasattr(sequence, 'action') and sequence.action is not None and sequence.action.asset_data is not None:
|
if sequence.action is not None and sequence.action.asset_data is not None:
|
||||||
flt_flags[i] &= ~bitflag_filter_item
|
flt_flags[i] &= ~bitflag_filter_item
|
||||||
|
|
||||||
if not pg.sequence_filter_pose_marker:
|
if not pg.sequence_filter_pose_marker:
|
||||||
for i, sequence in enumerate(sequences):
|
for i, sequence in enumerate(sequences):
|
||||||
if hasattr(sequence, 'is_pose_marker') and sequence.is_pose_marker:
|
if sequence.is_pose_marker:
|
||||||
flt_flags[i] &= ~bitflag_filter_item
|
flt_flags[i] &= ~bitflag_filter_item
|
||||||
|
|
||||||
if not pg.sequence_filter_reversed:
|
if not pg.sequence_filter_reversed:
|
||||||
for i, sequence in enumerate(sequences):
|
for i, sequence in enumerate(sequences):
|
||||||
if sequence.frame_start > sequence.frame_end:
|
if sequence.is_reversed:
|
||||||
flt_flags[i] &= ~bitflag_filter_item
|
flt_flags[i] &= ~bitflag_filter_item
|
||||||
|
|
||||||
return flt_flags
|
return flt_flags
|
||||||
|
|
||||||
|
|
||||||
_classes = (
|
_classes = (
|
||||||
PSA_PG_export_action_list_item,
|
PSA_PG_export_sequence,
|
||||||
PSA_PG_export_timeline_marker,
|
|
||||||
PSA_PG_export_nla_strip_list_item,
|
|
||||||
PSA_PG_export_active_action_list_item,
|
|
||||||
PSA_PG_export,
|
PSA_PG_export,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -8,30 +8,23 @@ class PsaExportSequenceMixin(PropertyGroup):
|
|||||||
frame_start: int
|
frame_start: int
|
||||||
frame_end: int
|
frame_end: int
|
||||||
group: str
|
group: str
|
||||||
|
|
||||||
class PsaExportSequenceWithActionMixin(PsaExportSequenceMixin):
|
|
||||||
action_name: str
|
action_name: str
|
||||||
|
armature_object_name: str
|
||||||
@property
|
marker_index: int
|
||||||
def action(self) -> Action | None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class PSA_PG_export_action_list_item(PsaExportSequenceWithActionMixin):
|
|
||||||
is_pose_marker: bool
|
is_pose_marker: bool
|
||||||
|
|
||||||
|
@property
|
||||||
class PSA_PG_export_active_action_list_item(PsaExportSequenceWithActionMixin):
|
def action(self) -> Action | None: ...
|
||||||
armature_object_name: str
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def armature_object(self) -> Object | None:
|
def armature_object(self) -> Object | None: ...
|
||||||
pass
|
|
||||||
|
@property
|
||||||
|
def is_reversed(self) -> bool: ...
|
||||||
|
|
||||||
|
|
||||||
class PSA_PG_export_timeline_marker(PsaExportSequenceMixin):
|
class PSA_PG_export_sequence(PsaExportSequenceMixin):
|
||||||
marker_index: int
|
"""Concrete type for PSA export sequences."""
|
||||||
|
|
||||||
class PSA_PG_export_nla_strip_list_item(PsaExportSequenceWithActionMixin):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -43,13 +36,13 @@ class PsaExportMixin(PropertyGroup, TransformMixin, ExportSpaceMixin, PsxBoneExp
|
|||||||
fps_custom: float
|
fps_custom: float
|
||||||
compression_ratio_source: str
|
compression_ratio_source: str
|
||||||
compression_ratio_custom: float
|
compression_ratio_custom: float
|
||||||
action_list: BpyCollectionProperty[PSA_PG_export_action_list_item]
|
action_list: BpyCollectionProperty[PSA_PG_export_sequence]
|
||||||
action_list_index: int
|
action_list_index: int
|
||||||
marker_list: BpyCollectionProperty[PSA_PG_export_timeline_marker]
|
marker_list: BpyCollectionProperty[PSA_PG_export_sequence]
|
||||||
marker_list_index: int
|
marker_list_index: int
|
||||||
nla_strip_list: BpyCollectionProperty[PSA_PG_export_nla_strip_list_item]
|
nla_strip_list: BpyCollectionProperty[PSA_PG_export_sequence]
|
||||||
nla_strip_list_index: int
|
nla_strip_list_index: int
|
||||||
active_action_list: BpyCollectionProperty[PSA_PG_export_active_action_list_item]
|
active_action_list: BpyCollectionProperty[PSA_PG_export_sequence]
|
||||||
active_action_list_index: int
|
active_action_list_index: int
|
||||||
sequence_name_prefix: str
|
sequence_name_prefix: str
|
||||||
sequence_name_suffix: str
|
sequence_name_suffix: str
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import cast as typing_cast
|
|||||||
|
|
||||||
from bpy.types import UIList
|
from bpy.types import UIList
|
||||||
|
|
||||||
from .properties import PSA_PG_export_action_list_item, filter_sequences
|
from .properties import PsaExportSequenceMixin, filter_sequences
|
||||||
|
|
||||||
|
|
||||||
class PSA_UL_export_sequences(UIList):
|
class PSA_UL_export_sequences(UIList):
|
||||||
@@ -14,7 +14,7 @@ class PSA_UL_export_sequences(UIList):
|
|||||||
self.use_filter_show = True
|
self.use_filter_show = True
|
||||||
|
|
||||||
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(PsaExportSequenceMixin, 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)
|
||||||
@@ -24,9 +24,9 @@ class PSA_UL_export_sequences(UIList):
|
|||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
row.alignment = 'RIGHT'
|
row.alignment = 'RIGHT'
|
||||||
|
|
||||||
row.label(text=str(abs(item.frame_end - item.frame_start) + 1), icon='FRAME_PREV' if item.frame_end < item.frame_start else 'KEYFRAME')
|
row.label(text=str(abs(item.frame_end - item.frame_start) + 1), icon='FRAME_PREV' if item.is_reversed else 'KEYFRAME')
|
||||||
|
|
||||||
if hasattr(item, 'armature_object') and item.armature_object is not None:
|
if item.armature_object is not None:
|
||||||
row.label(text=item.armature_object.name, icon='ARMATURE_DATA')
|
row.label(text=item.armature_object.name, icon='ARMATURE_DATA')
|
||||||
|
|
||||||
# row.label(text=item.action.name, icon='PMARKER' if is_pose_marker else 'ACTION_DATA')
|
# row.label(text=item.action.name, icon='PMARKER' if is_pose_marker else 'ACTION_DATA')
|
||||||
|
|||||||
Reference in New Issue
Block a user