From edafa1cfd7dbabb8876c3ccb4ccdaeac5d81b9ca Mon Sep 17 00:00:00 2001 From: Colin Basnett Date: Fri, 20 May 2022 17:13:12 -0700 Subject: [PATCH] Fix for bug #21. Bone names can now only contain alphanumeric, space and underscore characters. --- io_scene_psk_psa/helpers.py | 9 +++++++++ io_scene_psk_psa/psa/builder.py | 7 +++++-- io_scene_psk_psa/psk/builder.py | 5 ++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/io_scene_psk_psa/helpers.py b/io_scene_psk_psa/helpers.py index 937ea05..3057bf6 100644 --- a/io_scene_psk_psa/helpers.py +++ b/io_scene_psk_psa/helpers.py @@ -1,5 +1,6 @@ import datetime from collections import Counter +import re from typing import List, Iterable from bpy.types import NlaStrip, Object @@ -103,6 +104,14 @@ def get_psa_sequence_name(action, should_use_original_sequence_name): return action.name +def check_bone_names(bone_names: Iterable[str]): + pattern = re.compile(r'^[a-zA-Z0-9_ ]+$') + invalid_bone_names = [x for x in bone_names if pattern.match(x) is None] + if len(invalid_bone_names) > 0: + raise RuntimeError(f'The following bone names are invalid: {invalid_bone_names}.\n' + f'Bone names must only contain letters, numbers, spaces, and underscores.') + + def get_export_bone_names(armature_object, bone_filter_mode, bone_group_indices: List[int]) -> List[str]: """ Returns a sorted list of bone indices that should be exported for the given bone filter mode and bone groups. diff --git a/io_scene_psk_psa/psa/builder.py b/io_scene_psk_psa/psa/builder.py index 9a3cf79..15ba022 100644 --- a/io_scene_psk_psa/psa/builder.py +++ b/io_scene_psk_psa/psa/builder.py @@ -69,7 +69,7 @@ class PsaBuilder(object): bones = list(armature.data.bones) # The order of the armature bones and the pose bones is not guaranteed to be the same. - # As as a result, we need to reconstruct the list of pose bones in the same order as the + # As a result, we need to reconstruct the list of pose bones in the same order as the # armature bones. bone_names = [x.name for x in bones] pose_bones = [(bone_names.index(bone.name), bone) for bone in armature.pose.bones] @@ -88,10 +88,13 @@ class PsaBuilder(object): if len(bones) == 0: raise RuntimeError('No bones available for export') + # Check that all bone names are valid. + check_bone_names(map(lambda bone: bone.name, bones)) + # Build list of PSA bones. for bone in bones: psa_bone = Psa.Bone() - psa_bone.name = bytes(bone.name, encoding='utf-8') + psa_bone.name = bytes(bone.name, encoding='windows-1252') try: parent_index = bones.index(bone.parent) diff --git a/io_scene_psk_psa/psk/builder.py b/io_scene_psk_psa/psk/builder.py index a7ebc66..fc2d1d3 100644 --- a/io_scene_psk_psa/psk/builder.py +++ b/io_scene_psk_psa/psk/builder.py @@ -83,6 +83,9 @@ class PskBuilder(object): bone_names = get_export_bone_names(armature_object, options.bone_filter_mode, options.bone_group_indices) 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)) + for bone in bones: psk_bone = Psk.Bone() psk_bone.name = bytes(bone.name, encoding='windows-1252') @@ -134,7 +137,7 @@ class PskBuilder(object): else: # New material. psk_material = Psk.Material() - psk_material.name = bytes(material.name, encoding='utf-8') + psk_material.name = bytes(material.name, encoding='windows-1252') psk_material.texture_index = len(psk.materials) psk.materials.append(psk_material) materials[material.name] = material