From 0d06236babdc8c9d9f18f6079d18b9d207f291c2 Mon Sep 17 00:00:00 2001 From: Colin Basnett Date: Mon, 24 Jan 2022 14:14:35 -0800 Subject: [PATCH] Added the ability to export actions with the original sequence names that they were imported from. This will be very helpful in resolving naming conflicts when working with actions that share the same name on export (e.g. players and weapons often share the same animation name (e.g., `prone_reload_mg42` but have to exist in the same file). Still kind of broken though because it allows duplicate names which will possibly break downstream programs. --- io_scene_psk_psa/psa/builder.py | 9 ++++++++- io_scene_psk_psa/psa/exporter.py | 21 ++++++++++++++++++++- io_scene_psk_psa/psa/importer.py | 8 +++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/io_scene_psk_psa/psa/builder.py b/io_scene_psk_psa/psa/builder.py index 825676a..cddc250 100644 --- a/io_scene_psk_psa/psa/builder.py +++ b/io_scene_psk_psa/psa/builder.py @@ -7,6 +7,7 @@ class PsaBuilderOptions(object): self.actions = [] self.bone_filter_mode = 'ALL' self.bone_group_indices = [] + self.should_use_original_sequence_names = False class PsaBuilder(object): @@ -106,7 +107,13 @@ class PsaBuilder(object): frame_min, frame_max = [int(x) for x in action.frame_range] sequence = Psa.Sequence() - sequence.name = bytes(action.name, encoding='utf-8') + + if options.should_use_original_sequence_names and 'original_sequence_name' in action: + sequence_name = action['original_sequence_name'] + else: + sequence_name = action.name + + sequence.name = bytes(sequence_name, encoding='windows-1252') sequence.frame_count = frame_max - frame_min + 1 sequence.frame_start_index = frame_start_index sequence.fps = context.scene.render.fps diff --git a/io_scene_psk_psa/psa/exporter.py b/io_scene_psk_psa/psa/exporter.py index 6349d2e..d53cfb2 100644 --- a/io_scene_psk_psa/psa/exporter.py +++ b/io_scene_psk_psa/psa/exporter.py @@ -45,6 +45,19 @@ class PsaExportActionListItem(PropertyGroup): return self.action.name +def update_action_names(context): + property_group = context.scene.psa_export + for item in property_group.action_list: + action = item.action + if property_group.should_use_original_sequence_names and 'original_sequence_name' in action: + item.action_name = action['original_sequence_name'] + else: + item.action_name = action.name + + +def should_use_original_sequence_names_updated(property, context): + update_action_names(context) + class PsaExportPropertyGroup(PropertyGroup): action_list: CollectionProperty(type=PsaExportActionListItem) action_list_index: IntProperty(default=0) @@ -58,6 +71,7 @@ class PsaExportPropertyGroup(PropertyGroup): ) bone_group_list: CollectionProperty(type=BoneGroupListItem) bone_group_list_index: IntProperty(default=0) + should_use_original_sequence_names: BoolProperty(default=False, description='If the action was imported from the PSA Import panel, the original name of the action will be used instead of the action name assigned in Blender', update=should_use_original_sequence_names_updated) def is_bone_filter_mode_item_available(context, identifier): @@ -97,6 +111,8 @@ class PsaExportOperator(Operator, ExportHelper): row.operator('psa_export.actions_select_all', text='All') row.operator('psa_export.actions_deselect_all', text='None') + layout.prop(property_group, 'should_use_original_sequence_names', text='Original Sequence Names') + # BONES box = layout.box() box.label(text='Bones', icon='BONE_DATA') @@ -115,7 +131,6 @@ class PsaExportOperator(Operator, ExportHelper): rows = max(3, min(len(property_group.bone_group_list), 10)) row.template_list('PSX_UL_BoneGroupList', '', property_group, 'bone_group_list', property_group, 'bone_group_list_index', rows=rows) - def is_action_for_armature(self, action): if len(action.fcurves) == 0: return False @@ -148,9 +163,12 @@ class PsaExportOperator(Operator, ExportHelper): item = property_group.action_list.add() item.action = action item.action_name = action.name + if self.is_action_for_armature(action): item.is_selected = True + update_action_names(context) + if len(property_group.action_list) == 0: # If there are no actions at all, we have nothing to export, so just cancel the operation. self.report({'ERROR_INVALID_CONTEXT'}, 'There are no actions to export.') @@ -175,6 +193,7 @@ class PsaExportOperator(Operator, ExportHelper): options.actions = actions options.bone_filter_mode = property_group.bone_filter_mode options.bone_group_indices = [x.index for x in property_group.bone_group_list if x.is_selected] + options.should_use_original_sequence_names = property_group.should_use_original_sequence_names builder = PsaBuilder() try: psa = builder.build(context, options) diff --git a/io_scene_psk_psa/psa/importer.py b/io_scene_psk_psa/psa/importer.py index 29febd7..fa177c0 100644 --- a/io_scene_psk_psa/psa/importer.py +++ b/io_scene_psk_psa/psa/importer.py @@ -116,7 +116,8 @@ class PsaImporter(object): actions = [] for sequence in sequences: # Add the action. - action_name = options.action_name_prefix + sequence.name.decode('windows-1252') + sequence_name = sequence.name.decode('windows-1252') + action_name = options.action_name_prefix + sequence_name action = bpy.data.actions.new(name=action_name) action.use_fake_user = options.should_use_fake_user @@ -136,8 +137,6 @@ class PsaImporter(object): action.fcurves.new(location_data_path, index=2), # Lz ] - sequence_name = sequence.name.decode('windows-1252') - # Read the sequence data matrix from the PSA. sequence_data_matrix = psa_reader.read_sequence_data_matrix(sequence_name) keyframe_write_matrix = np.ones(sequence_data_matrix.shape, dtype=np.int8) @@ -183,6 +182,9 @@ class PsaImporter(object): if should_write: fcurve.keyframe_points.insert(frame_index, datum, options={'FAST'}) + # Store the original sequence name for use when exporting this same action using the PSA exporter. + action['original_sequence_name'] = sequence_name + actions.append(action) # If the user specifies, store the new animations as strips on a non-contributing NLA stack.