diff --git a/io_scene_psk_psa/psa/builder.py b/io_scene_psk_psa/psa/builder.py index f57361d..d2f50a5 100644 --- a/io_scene_psk_psa/psa/builder.py +++ b/io_scene_psk_psa/psa/builder.py @@ -1,6 +1,6 @@ from typing import Dict -from bpy.types import Action +from bpy.types import Action, Armature, Bone from .data import * from ..helpers import * @@ -19,6 +19,7 @@ class PsaBuildOptions(object): self.bone_group_indices = [] self.should_use_original_sequence_names = False self.should_trim_timeline_marker_sequences = True + self.should_ignore_bone_name_restrictions = False self.sequence_name_prefix = '' self.sequence_name_suffix = '' self.root_motion = False @@ -87,7 +88,7 @@ def get_timeline_marker_sequence_frame_ranges(animation_data, context, options: return sequence_frame_ranges -def build_psa(context, options: PsaBuildOptions) -> Psa: +def build_psa(context: bpy.types.Context, options: PsaBuildOptions) -> Psa: active_object = context.view_layer.objects.active if active_object.type != 'ARMATURE': @@ -112,7 +113,8 @@ def build_psa(context, options: PsaBuildOptions) -> Psa: psa = Psa() armature = active_object - bones = list(armature.data.bones) + armature_data = typing.cast(Armature, armature) + bones: List[Bone] = list(iter(armature_data.bones)) # The order of the armature bones and the pose bones is not guaranteed to be the same. # As a result, we need to reconstruct the list of pose bones in the same order as the @@ -135,7 +137,8 @@ def build_psa(context, options: PsaBuildOptions) -> Psa: raise RuntimeError('No bones available for export') # Check that all bone names are valid. - check_bone_names(map(lambda bone: bone.name, bones)) + if not options.should_ignore_bone_name_restrictions: + check_bone_names(map(lambda bone: bone.name, bones)) # Build list of PSA bones. for bone in bones: @@ -208,6 +211,7 @@ def build_psa(context, options: PsaBuildOptions) -> Psa: export_sequence.nla_state.action = None export_sequence.nla_state.frame_min = frame_min export_sequence.nla_state.frame_max = frame_max + nla_strips_actions = set( map(lambda x: x.action, get_nla_strips_in_timeframe(animation_data, frame_min, frame_max))) export_sequence.fps = get_sequence_fps(context, options, nla_strips_actions) diff --git a/io_scene_psk_psa/psa/exporter.py b/io_scene_psk_psa/psa/exporter.py index 59bd82d..ce2f085 100644 --- a/io_scene_psk_psa/psa/exporter.py +++ b/io_scene_psk_psa/psa/exporter.py @@ -136,6 +136,12 @@ class PsaExportPropertyGroup(PropertyGroup): description='Frames without NLA track information at the boundaries of timeline markers will be excluded from ' 'the exported sequences ' ) + should_ignore_bone_name_restrictions: BoolProperty( + default=False, + name='Ignore Bone Name Restrictions', + description='Bone names restrictions will be ignored. Note that bone names without properly formatted names ' + 'cannot be referenced in scripts.' + ) sequence_name_prefix: StringProperty(name='Prefix', options=empty_set) sequence_name_suffix: StringProperty(name='Suffix', options=empty_set) sequence_filter_name: StringProperty( @@ -262,6 +268,8 @@ class PsaExportOperator(Operator, ExportHelper): layout.template_list('PSX_UL_BoneGroupList', '', pg, 'bone_group_list', pg, 'bone_group_list_index', rows=rows) + layout.prop(pg, 'should_ignore_bone_name_restrictions') + layout.separator() # ROOT MOTION @@ -346,6 +354,7 @@ class PsaExportOperator(Operator, ExportHelper): options.bone_group_indices = [x.index for x in pg.bone_group_list if x.is_selected] options.should_use_original_sequence_names = pg.should_use_original_sequence_names options.should_trim_timeline_marker_sequences = pg.should_trim_timeline_marker_sequences + options.should_ignore_bone_name_restrictions = pg.should_ignore_bone_name_restrictions options.sequence_name_prefix = pg.sequence_name_prefix options.sequence_name_suffix = pg.sequence_name_suffix options.root_motion = pg.root_motion diff --git a/io_scene_psk_psa/psk/builder.py b/io_scene_psk_psa/psk/builder.py index 8a13f5c..1fef1ee 100644 --- a/io_scene_psk_psa/psk/builder.py +++ b/io_scene_psk_psa/psk/builder.py @@ -19,6 +19,7 @@ class PskBuildOptions(object): self.bone_group_indices: List[int] = [] self.use_raw_mesh_data = True self.material_names: List[str] = [] + self.should_ignore_bone_name_restrictions = False def get_psk_input_objects(context) -> PskInputObjects: @@ -81,7 +82,8 @@ def build_psk(context, options: PskBuildOptions) -> Psk: bones = [armature_object.data.bones[bone_name] for bone_name in bone_names] # Check that all bone names are valid. - check_bone_names(map(lambda x: x.name, bones)) + if not options.should_ignore_bone_name_restrictions: + check_bone_names(map(lambda x: x.name, bones)) for bone in bones: psk_bone = Psk.Bone() diff --git a/io_scene_psk_psa/psk/exporter.py b/io_scene_psk_psa/psk/exporter.py index 91c2566..7f55199 100644 --- a/io_scene_psk_psa/psk/exporter.py +++ b/io_scene_psk_psa/psk/exporter.py @@ -208,6 +208,10 @@ class PskExportOperator(Operator, ExportHelper): col.operator(PskMaterialListItemMoveUp.bl_idname, text='', icon='TRIA_UP') col.operator(PskMaterialListItemMoveDown.bl_idname, text='', icon='TRIA_DOWN') + layout.separator() + + layout.prop(pg, 'should_ignore_bone_name_restrictions') + def execute(self, context): pg = context.scene.psk_export options = PskBuildOptions() @@ -215,6 +219,7 @@ class PskExportOperator(Operator, ExportHelper): options.bone_group_indices = [x.index for x in pg.bone_group_list if x.is_selected] options.use_raw_mesh_data = pg.use_raw_mesh_data options.material_names = [m.material_name for m in pg.material_list] + options.should_ignore_bone_name_restrictions = pg.should_ignore_bone_name_restrictions try: psk = build_psk(context, options) @@ -242,6 +247,12 @@ class PskExportPropertyGroup(PropertyGroup): use_raw_mesh_data: BoolProperty(default=False, name='Raw Mesh Data', description='No modifiers will be evaluated as part of the exported mesh') material_list: CollectionProperty(type=MaterialListItem) material_list_index: IntProperty(default=0) + should_ignore_bone_name_restrictions: BoolProperty( + default=False, + name='Ignore Bone Name Restrictions', + description='Bone names restrictions will be ignored. Note that bone names without properly formatted names ' + 'cannot be referenced in scripts.' + ) classes = (