Lots of typing fixes and simplifications (using list and dict instead of the typing.List etc.)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from bpy.types import Action, AnimData, Context, Object, PoseBone
|
from bpy.types import Action, AnimData, Context, Object, PoseBone
|
||||||
|
|
||||||
from psk_psa_py.psa.data import Psa
|
from psk_psa_py.psa.data import Psa
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Tuple
|
||||||
from mathutils import Matrix, Quaternion, Vector
|
from mathutils import Matrix, Quaternion, Vector
|
||||||
|
|
||||||
from ..shared.helpers import PsxBoneCollection, convert_bpy_quaternion_to_psx_quaternion, convert_vector_to_vector3, create_psx_bones, get_coordinate_system_transform
|
from ..shared.helpers import PsxBoneCollection, convert_bpy_quaternion_to_psx_quaternion, convert_vector_to_vector3, create_psx_bones, get_coordinate_system_transform
|
||||||
@@ -10,7 +10,7 @@ from ..shared.helpers import PsxBoneCollection, convert_bpy_quaternion_to_psx_qu
|
|||||||
class PsaBuildSequence:
|
class PsaBuildSequence:
|
||||||
class NlaState:
|
class NlaState:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.action: Optional[Action] = None
|
self.action: Action | None = None
|
||||||
self.frame_start: int = 0
|
self.frame_start: int = 0
|
||||||
self.frame_end: int = 0
|
self.frame_end: int = 0
|
||||||
|
|
||||||
@@ -22,16 +22,16 @@ class PsaBuildSequence:
|
|||||||
self.compression_ratio: float = 1.0
|
self.compression_ratio: float = 1.0
|
||||||
self.key_quota: int = 0
|
self.key_quota: int = 0
|
||||||
self.fps: float = 30.0
|
self.fps: float = 30.0
|
||||||
self.group: Optional[str] = None
|
self.group: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class PsaBuildOptions:
|
class PsaBuildOptions:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.armature_objects: List[Object] = []
|
self.armature_objects: list[Object] = []
|
||||||
self.animation_data: Optional[AnimData] = None
|
self.animation_data: AnimData | None = None
|
||||||
self.sequences: List[PsaBuildSequence] = []
|
self.sequences: list[PsaBuildSequence] = []
|
||||||
self.bone_filter_mode: str = 'ALL'
|
self.bone_filter_mode: str = 'ALL'
|
||||||
self.bone_collection_indices: List[PsxBoneCollection] = []
|
self.bone_collection_indices: list[PsxBoneCollection] = []
|
||||||
self.sequence_name_prefix: str = ''
|
self.sequence_name_prefix: str = ''
|
||||||
self.sequence_name_suffix: str = ''
|
self.sequence_name_suffix: str = ''
|
||||||
self.scale = 1.0
|
self.scale = 1.0
|
||||||
@@ -307,7 +307,6 @@ def build_psa(context: Context, options: PsaBuildOptions) -> Psa:
|
|||||||
options.export_space,
|
options.export_space,
|
||||||
export_bone.scale,
|
export_bone.scale,
|
||||||
coordinate_system_transform=coordinate_system_transform
|
coordinate_system_transform=coordinate_system_transform
|
||||||
# has_false_root_bone=psx_bone_create_result.has_false_root_bone,
|
|
||||||
)
|
)
|
||||||
last_frame_bone_poses.append((location, rotation))
|
last_frame_bone_poses.append((location, rotation))
|
||||||
|
|
||||||
@@ -331,7 +330,6 @@ def build_psa(context: Context, options: PsaBuildOptions) -> Psa:
|
|||||||
export_space=options.export_space,
|
export_space=options.export_space,
|
||||||
scale=export_bone.scale,
|
scale=export_bone.scale,
|
||||||
coordinate_system_transform=coordinate_system_transform,
|
coordinate_system_transform=coordinate_system_transform,
|
||||||
# has_false_root_bone=psx_bone_create_result.has_false_root_bone,
|
|
||||||
)
|
)
|
||||||
next_frame_bone_poses.append((location, rotation))
|
next_frame_bone_poses.append((location, rotation))
|
||||||
|
|
||||||
@@ -359,7 +357,6 @@ def build_psa(context: Context, options: PsaBuildOptions) -> Psa:
|
|||||||
export_space=options.export_space,
|
export_space=options.export_space,
|
||||||
scale=export_bone.scale,
|
scale=export_bone.scale,
|
||||||
coordinate_system_transform=coordinate_system_transform,
|
coordinate_system_transform=coordinate_system_transform,
|
||||||
# has_false_root_bone=psx_bone_create_result.has_false_root_bone,
|
|
||||||
)
|
)
|
||||||
add_key(location, rotation)
|
add_key(location, rotation)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from typing import Dict, List
|
|
||||||
|
|
||||||
REMOVE_TRACK_LOCATION = (1 << 0)
|
REMOVE_TRACK_LOCATION = (1 << 0)
|
||||||
REMOVE_TRACK_ROTATION = (1 << 1)
|
REMOVE_TRACK_ROTATION = (1 << 1)
|
||||||
@@ -8,7 +7,7 @@ REMOVE_TRACK_ROTATION = (1 << 1)
|
|||||||
|
|
||||||
class PsaConfig:
|
class PsaConfig:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.sequence_bone_flags: Dict[str, Dict[int, int]] = dict()
|
self.sequence_bone_flags: dict[str, dict[int, int]] = dict()
|
||||||
|
|
||||||
|
|
||||||
def _load_config_file(file_path: str) -> ConfigParser:
|
def _load_config_file(file_path: str) -> ConfigParser:
|
||||||
@@ -48,7 +47,7 @@ def _get_bone_flags_from_value(value: str) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def read_psa_config(psa_sequence_names: List[str], file_path: str) -> PsaConfig:
|
def read_psa_config(psa_sequence_names: list[str], file_path: str) -> PsaConfig:
|
||||||
psa_config = PsaConfig()
|
psa_config = PsaConfig()
|
||||||
|
|
||||||
config = _load_config_file(file_path)
|
config = _load_config_file(file_path)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List, Iterable, Dict, Protocol, Sequence, Tuple, cast as typing_cast
|
from typing import Iterable, Sequence, Tuple, cast as typing_cast
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import re
|
import re
|
||||||
@@ -19,7 +19,7 @@ from .ui import PSA_UL_export_sequences
|
|||||||
from ..builder import build_psa, PsaBuildSequence, PsaBuildOptions
|
from ..builder import build_psa, PsaBuildSequence, PsaBuildOptions
|
||||||
from psk_psa_py.psa.writer import write_psa_to_file
|
from psk_psa_py.psa.writer import write_psa_to_file
|
||||||
from ...shared.helpers import get_collection_export_operator_from_context, get_collection_from_context, get_psk_input_objects_for_collection, populate_bone_collection_list, get_nla_strips_in_frame_range, PsxBoneCollection
|
from ...shared.helpers import get_collection_export_operator_from_context, get_collection_from_context, get_psk_input_objects_for_collection, populate_bone_collection_list, get_nla_strips_in_frame_range, PsxBoneCollection
|
||||||
from ...shared.types import BpyCollectionProperty, PSX_PG_action_export
|
from ...shared.types import PSX_PG_action_export
|
||||||
from ...shared.ui import draw_bone_filter_mode
|
from ...shared.ui import draw_bone_filter_mode
|
||||||
from ...shared.operators import PSK_OT_bone_collection_list_populate, PSK_OT_bone_collection_list_select_all
|
from ...shared.operators import PSK_OT_bone_collection_list_populate, PSK_OT_bone_collection_list_select_all
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ def get_sequence_compression_ratio(
|
|||||||
def get_timeline_marker_sequence_frame_ranges(
|
def get_timeline_marker_sequence_frame_ranges(
|
||||||
animation_data: AnimData,
|
animation_data: AnimData,
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
marker_names: List[str],
|
marker_names: list[str],
|
||||||
) -> dict[str, tuple[int, int]]:
|
) -> dict[str, tuple[int, int]]:
|
||||||
# Timeline markers need to be sorted so that we can determine the sequence start and end positions.
|
# Timeline markers need to be sorted so that we can determine the sequence start and end positions.
|
||||||
sequence_frame_ranges: dict[str, tuple[int, int]] = dict()
|
sequence_frame_ranges: dict[str, tuple[int, int]] = dict()
|
||||||
@@ -240,7 +240,7 @@ def get_sequences_from_action(action: Action):
|
|||||||
|
|
||||||
def get_sequences_from_action_pose_markers(
|
def get_sequences_from_action_pose_markers(
|
||||||
action: Action,
|
action: Action,
|
||||||
pose_markers: List[TimelineMarker],
|
pose_markers: list[TimelineMarker],
|
||||||
pose_marker: TimelineMarker,
|
pose_marker: TimelineMarker,
|
||||||
pose_marker_index: int,
|
pose_marker_index: int,
|
||||||
):
|
):
|
||||||
@@ -259,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[PsaExportSequenceMixin]:
|
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)):
|
||||||
@@ -471,7 +471,7 @@ def create_psa_export_options(context: Context, armature_objects: Sequence[Objec
|
|||||||
raise RuntimeError(f'No armatures')
|
raise RuntimeError(f'No armatures')
|
||||||
|
|
||||||
animation_data = armature_objects[0].animation_data
|
animation_data = armature_objects[0].animation_data
|
||||||
export_sequences: List[PsaBuildSequence] = []
|
export_sequences: list[PsaBuildSequence] = []
|
||||||
|
|
||||||
# TODO: this needs to be changed so that we iterate over all of the armature objects?
|
# TODO: this needs to be changed so that we iterate over all of the armature objects?
|
||||||
# do we need to check for primary key? (data vs. object?)
|
# do we need to check for primary key? (data vs. object?)
|
||||||
@@ -507,7 +507,7 @@ def create_psa_export_options(context: Context, armature_objects: Sequence[Objec
|
|||||||
export_sequences.append(export_sequence)
|
export_sequences.append(export_sequence)
|
||||||
case 'TIMELINE_MARKERS':
|
case 'TIMELINE_MARKERS':
|
||||||
for marker_item in filter(lambda x: x.is_selected, pg.marker_list):
|
for marker_item in filter(lambda x: x.is_selected, pg.marker_list):
|
||||||
nla_strips_actions: List[Action] = []
|
nla_strips_actions: list[Action] = []
|
||||||
for nla_strip in get_nla_strips_in_frame_range(animation_data, marker_item.frame_start, marker_item.frame_end):
|
for nla_strip in get_nla_strips_in_frame_range(animation_data, marker_item.frame_start, marker_item.frame_end):
|
||||||
if nla_strip.action:
|
if nla_strip.action:
|
||||||
nla_strips_actions.append(nla_strip.action)
|
nla_strips_actions.append(nla_strip.action)
|
||||||
@@ -584,7 +584,7 @@ class PSA_OT_export(Operator, ExportHelper):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.armature_objects: List[Object] = []
|
self.armature_objects: list[Object] = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from typing import List, Optional, Sequence
|
from typing import Sequence
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
@@ -58,7 +58,7 @@ class PSA_PG_export_sequence(PsaExportSequenceMixin):
|
|||||||
|
|
||||||
def get_sequences_from_name_and_frame_range(name: str, frame_start: int, frame_end: int):
|
def get_sequences_from_name_and_frame_range(name: str, frame_start: int, frame_end: int):
|
||||||
# Check for loop
|
# Check for loop
|
||||||
anims: List[tuple[str, int, int]] = []
|
anims: list[tuple[str, int, int]] = []
|
||||||
loop_pattern = r'\@(\d+)\:(.+)'
|
loop_pattern = r'\@(\d+)\:(.+)'
|
||||||
loop_match = re.match(loop_pattern, name)
|
loop_match = re.match(loop_pattern, name)
|
||||||
if loop_match:
|
if loop_match:
|
||||||
@@ -107,7 +107,7 @@ def nla_track_update_cb(self: 'PSA_PG_export', context: Context) -> None:
|
|||||||
strip.frame_end = frame_end
|
strip.frame_end = frame_end
|
||||||
|
|
||||||
|
|
||||||
def get_animation_data(pg: 'PSA_PG_export', context: Context) -> Optional[AnimData]:
|
def get_animation_data(pg: 'PSA_PG_export', context: Context) -> AnimData | None:
|
||||||
animation_data_object = context.object
|
animation_data_object = context.object
|
||||||
return animation_data_object.animation_data if animation_data_object else None
|
return animation_data_object.animation_data if animation_data_object else None
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from pathlib import Path
|
|||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from bpy.props import CollectionProperty, StringProperty
|
from bpy.props import CollectionProperty, StringProperty
|
||||||
from bpy.types import Context, Event, FileHandler, Object, Operator, OperatorFileListElement
|
from bpy.types import Context, Event, Object, Operator, OperatorFileListElement
|
||||||
from bpy_extras.io_utils import ImportHelper
|
from bpy_extras.io_utils import ImportHelper
|
||||||
|
|
||||||
from .properties import PsaImportMixin, get_visible_sequences
|
from .properties import PsaImportMixin, get_visible_sequences
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from bpy.props import (
|
from bpy.props import (
|
||||||
BoolProperty,
|
BoolProperty,
|
||||||
@@ -133,7 +132,7 @@ class PSA_PG_import(PropertyGroup):
|
|||||||
select_text: PointerProperty(type=Text)
|
select_text: PointerProperty(type=Text)
|
||||||
|
|
||||||
|
|
||||||
def filter_sequences(pg: PSA_PG_import, sequences) -> List[int]:
|
def filter_sequences(pg: PSA_PG_import, sequences) -> 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)
|
||||||
|
|
||||||
@@ -167,7 +166,7 @@ def filter_sequences(pg: PSA_PG_import, sequences) -> List[int]:
|
|||||||
return flt_flags
|
return flt_flags
|
||||||
|
|
||||||
|
|
||||||
def get_visible_sequences(pg: PSA_PG_import, sequences) -> List[PSA_PG_import_action_list_item]:
|
def get_visible_sequences(pg: PSA_PG_import, sequences) -> list[PSA_PG_import_action_list_item]:
|
||||||
bitflag_filter_item = 1 << 30
|
bitflag_filter_item = 1 << 30
|
||||||
visible_sequences = []
|
visible_sequences = []
|
||||||
for i, flag in enumerate(filter_sequences(pg, sequences)):
|
for i, flag in enumerate(filter_sequences(pg, sequences)):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Sequence, Iterable, List, Optional, cast as typing_cast
|
from typing import Sequence, Iterable, cast as typing_cast
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -32,7 +32,7 @@ class PsaImportOptions(object):
|
|||||||
fps_custom: float = 30.0,
|
fps_custom: float = 30.0,
|
||||||
fps_source: str = 'SEQUENCE',
|
fps_source: str = 'SEQUENCE',
|
||||||
psa_config: PsaConfig = PsaConfig(),
|
psa_config: PsaConfig = PsaConfig(),
|
||||||
sequence_names: Optional[List[str]] = None,
|
sequence_names: list[str] | None = None,
|
||||||
should_convert_to_samples: bool = False,
|
should_convert_to_samples: bool = False,
|
||||||
should_overwrite: bool = False,
|
should_overwrite: bool = False,
|
||||||
should_stash: bool = False,
|
should_stash: bool = False,
|
||||||
@@ -61,13 +61,13 @@ class PsaImportOptions(object):
|
|||||||
class ImportBone(object):
|
class ImportBone(object):
|
||||||
def __init__(self, psa_bone: PsxBone):
|
def __init__(self, psa_bone: PsxBone):
|
||||||
self.psa_bone: PsxBone = psa_bone
|
self.psa_bone: PsxBone = psa_bone
|
||||||
self.parent: Optional[ImportBone] = None
|
self.parent: ImportBone | None = None
|
||||||
self.armature_bone: Optional[Bone] = None
|
self.armature_bone: Bone | None = None
|
||||||
self.pose_bone: Optional[PoseBone] = None
|
self.pose_bone: PoseBone | None = None
|
||||||
self.original_location: Vector = Vector()
|
self.original_location: Vector = Vector()
|
||||||
self.original_rotation: Quaternion = Quaternion()
|
self.original_rotation: Quaternion = Quaternion()
|
||||||
self.post_rotation: Quaternion = Quaternion()
|
self.post_rotation: Quaternion = Quaternion()
|
||||||
self.fcurves: List[FCurve] = []
|
self.fcurves: list[FCurve] = []
|
||||||
|
|
||||||
|
|
||||||
def _calculate_fcurve_data(import_bone: ImportBone, key_data: Sequence[float]):
|
def _calculate_fcurve_data(import_bone: ImportBone, key_data: Sequence[float]):
|
||||||
@@ -90,10 +90,10 @@ def _calculate_fcurve_data(import_bone: ImportBone, key_data: Sequence[float]):
|
|||||||
|
|
||||||
class PsaImportResult:
|
class PsaImportResult:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.warnings: List[str] = []
|
self.warnings: list[str] = []
|
||||||
|
|
||||||
|
|
||||||
def _get_armature_bone_index_for_psa_bone(psa_bone_name: str, armature_bone_names: List[str], bone_mapping: BoneMapping) -> Optional[int]:
|
def _get_armature_bone_index_for_psa_bone(psa_bone_name: str, armature_bone_names: list[str], bone_mapping: BoneMapping) -> int | None:
|
||||||
"""
|
"""
|
||||||
@param psa_bone_name: The name of the PSA bone.
|
@param psa_bone_name: The name of the PSA bone.
|
||||||
@param armature_bone_names: The names of the bones in the armature.
|
@param armature_bone_names: The names of the bones in the armature.
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import bmesh
|
import bmesh
|
||||||
import bpy
|
import bpy
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from bpy.types import Armature, Context, Object, Mesh
|
from bpy.types import Armature, Context, Object, Mesh, Material
|
||||||
from mathutils import Matrix
|
from mathutils import Matrix
|
||||||
from typing import Dict, Iterable, List, Optional, cast as typing_cast
|
from typing import Iterable, Sequence, cast as typing_cast
|
||||||
from psk_psa_py.shared.data import Vector3
|
from psk_psa_py.shared.data import Vector3
|
||||||
from psk_psa_py.psk.data import Psk
|
from psk_psa_py.psk.data import Psk
|
||||||
from .properties import triangle_type_and_bit_flags_to_poly_flags
|
from .properties import triangle_type_and_bit_flags_to_poly_flags
|
||||||
@@ -23,10 +23,10 @@ from ..shared.helpers import (
|
|||||||
class PskBuildOptions(object):
|
class PskBuildOptions(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.bone_filter_mode = 'ALL'
|
self.bone_filter_mode = 'ALL'
|
||||||
self.bone_collection_indices: List[PsxBoneCollection] = []
|
self.bone_collection_indices: list[PsxBoneCollection] = []
|
||||||
self.object_eval_state = 'EVALUATED'
|
self.object_eval_state = 'EVALUATED'
|
||||||
self.material_order_mode = 'AUTOMATIC'
|
self.material_order_mode = 'AUTOMATIC'
|
||||||
self.material_name_list: List[str] = []
|
self.material_name_list: list[str] = []
|
||||||
self.scale = 1.0
|
self.scale = 1.0
|
||||||
self.export_space = 'WORLD'
|
self.export_space = 'WORLD'
|
||||||
self.forward_axis = 'X'
|
self.forward_axis = 'X'
|
||||||
@@ -37,7 +37,7 @@ class PskBuildOptions(object):
|
|||||||
class PskBuildResult(object):
|
class PskBuildResult(object):
|
||||||
def __init__(self, psk: Psk, warnings: list[str]):
|
def __init__(self, psk: Psk, warnings: list[str]):
|
||||||
self.psk: Psk = psk
|
self.psk: Psk = psk
|
||||||
self.warnings: List[str] = warnings
|
self.warnings: list[str] = warnings
|
||||||
|
|
||||||
|
|
||||||
def _get_mesh_export_space_matrix(node: ObjectNode | None, export_space: str) -> Matrix:
|
def _get_mesh_export_space_matrix(node: ObjectNode | None, export_space: str) -> Matrix:
|
||||||
@@ -70,7 +70,7 @@ def _get_mesh_export_space_matrix(node: ObjectNode | None, export_space: str) ->
|
|||||||
assert False, f'Invalid export space: {export_space}'
|
assert False, f'Invalid export space: {export_space}'
|
||||||
|
|
||||||
|
|
||||||
def _get_material_name_indices(obj: Object, material_names: List[str]) -> Iterable[int]:
|
def _get_material_name_indices(obj: Object, material_names: list[str]) -> Iterable[int]:
|
||||||
"""
|
"""
|
||||||
Returns the index of the material in the list of material names.
|
Returns the index of the material in the list of material names.
|
||||||
If the material is not found, the index 0 is returned.
|
If the material is not found, the index 0 is returned.
|
||||||
@@ -271,6 +271,7 @@ def build_psk(context: Context, input_objects: PskInputObjects, options: PskBuil
|
|||||||
for loop_index, loop in enumerate(mesh_data.loops):
|
for loop_index, loop in enumerate(mesh_data.loops):
|
||||||
wedges.append(Psk.Wedge(point_index=loop.vertex_index + vertex_offset, u=0.0, v=0.0))
|
wedges.append(Psk.Wedge(point_index=loop.vertex_index + vertex_offset, u=0.0, v=0.0))
|
||||||
|
|
||||||
|
|
||||||
# Assign material indices to the wedges.
|
# Assign material indices to the wedges.
|
||||||
for triangle in mesh_data.loop_triangles:
|
for triangle in mesh_data.loop_triangles:
|
||||||
for loop_index in triangle.loops:
|
for loop_index in triangle.loops:
|
||||||
@@ -315,7 +316,7 @@ def build_psk(context: Context, input_objects: PskInputObjects, options: PskBuil
|
|||||||
|
|
||||||
bone_names = psx_bone_create_result.armature_object_bone_names[armature_object]
|
bone_names = psx_bone_create_result.armature_object_bone_names[armature_object]
|
||||||
vertex_group_names = [x.name for x in mesh_object.vertex_groups]
|
vertex_group_names = [x.name for x in mesh_object.vertex_groups]
|
||||||
vertex_group_bone_indices: Dict[int, int] = dict()
|
vertex_group_bone_indices: dict[int, int] = dict()
|
||||||
for vertex_group_index, vertex_group_name in enumerate(vertex_group_names):
|
for vertex_group_index, vertex_group_name in enumerate(vertex_group_names):
|
||||||
try:
|
try:
|
||||||
vertex_group_bone_indices[vertex_group_index] = bone_names.index(vertex_group_name) + bone_index_offset
|
vertex_group_bone_indices[vertex_group_index] = bone_names.index(vertex_group_name) + bone_index_offset
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, List, cast as typing_cast
|
from typing import Iterable, cast as typing_cast
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.props import StringProperty
|
from bpy.props import StringProperty
|
||||||
@@ -173,7 +173,7 @@ class PSK_OT_material_list_name_move_down(Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
def get_sorted_materials_by_names(materials: Iterable[Material], material_names: List[str]) -> List[Material]:
|
def get_sorted_materials_by_names(materials: Iterable[Material], material_names: list[str]) -> list[Material]:
|
||||||
"""
|
"""
|
||||||
Sorts the materials by the order of the material names list. Any materials not in the list will be appended to the
|
Sorts the materials by the order of the material names list. Any materials not in the list will be appended to the
|
||||||
end of the list in the order they are found.
|
end of the list in the order they are found.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import numpy as np
|
|||||||
|
|
||||||
from bpy.types import Context, Object, VertexGroup, ArmatureModifier, FloatColorAttribute
|
from bpy.types import Context, Object, VertexGroup, ArmatureModifier, FloatColorAttribute
|
||||||
from mathutils import Matrix, Quaternion, Vector
|
from mathutils import Matrix, Quaternion, Vector
|
||||||
from typing import List, Optional, cast as typing_cast
|
from typing import cast as typing_cast
|
||||||
|
|
||||||
from psk_psa_py.psk.data import Psk
|
from psk_psa_py.psk.data import Psk
|
||||||
from psk_psa_py.shared.data import PsxBone
|
from psk_psa_py.shared.data import PsxBone
|
||||||
@@ -35,12 +35,11 @@ class ImportBone:
|
|||||||
def __init__(self, index: int, psk_bone: PsxBone):
|
def __init__(self, index: int, psk_bone: PsxBone):
|
||||||
self.index: int = index
|
self.index: int = index
|
||||||
self.psk_bone: PsxBone = psk_bone
|
self.psk_bone: PsxBone = psk_bone
|
||||||
self.parent: Optional[ImportBone] = None
|
self.parent: ImportBone | None = None
|
||||||
self.local_rotation: Quaternion = Quaternion()
|
self.local_rotation: Quaternion = Quaternion()
|
||||||
self.local_translation: Vector = Vector()
|
self.local_translation: Vector = Vector()
|
||||||
self.world_rotation_matrix: Matrix = Matrix()
|
self.world_rotation_matrix: Matrix = Matrix()
|
||||||
self.world_matrix: Matrix = Matrix()
|
self.world_matrix: Matrix = Matrix()
|
||||||
self.vertex_group = None
|
|
||||||
self.original_rotation: Quaternion = Quaternion()
|
self.original_rotation: Quaternion = Quaternion()
|
||||||
self.original_location: Vector = Vector()
|
self.original_location: Vector = Vector()
|
||||||
self.post_rotation: Quaternion = Quaternion()
|
self.post_rotation: Quaternion = Quaternion()
|
||||||
@@ -48,9 +47,9 @@ class ImportBone:
|
|||||||
|
|
||||||
class PskImportResult:
|
class PskImportResult:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.warnings: List[str] = []
|
self.warnings: list[str] = []
|
||||||
self.armature_object: Optional[Object] = None
|
self.armature_object: Object | None = None
|
||||||
self.mesh_object: Optional[Object] = None
|
self.mesh_object: Object | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_object(self) -> Object:
|
def root_object(self) -> Object:
|
||||||
@@ -83,7 +82,7 @@ def import_psk(psk: Psk, context: Context, name: str, options: PskImportOptions)
|
|||||||
|
|
||||||
bpy.ops.object.mode_set(mode='EDIT')
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
|
||||||
import_bones: List[ImportBone] = []
|
import_bones: list[ImportBone] = []
|
||||||
|
|
||||||
for bone_index, psk_bone in enumerate(psk.bones):
|
for bone_index, psk_bone in enumerate(psk.bones):
|
||||||
import_bone = ImportBone(bone_index, psk_bone)
|
import_bone = ImportBone(bone_index, psk_bone)
|
||||||
@@ -263,7 +262,7 @@ def import_psk(psk: Psk, context: Context, name: str, options: PskImportOptions)
|
|||||||
# Weights
|
# Weights
|
||||||
# Get a list of all bones that have weights associated with them.
|
# Get a list of all bones that have weights associated with them.
|
||||||
vertex_group_bone_indices = set(map(lambda weight: weight.bone_index, psk.weights))
|
vertex_group_bone_indices = set(map(lambda weight: weight.bone_index, psk.weights))
|
||||||
vertex_groups: List[Optional[VertexGroup]] = [None] * len(psk.bones)
|
vertex_groups: list[VertexGroup | None] = [None] * len(psk.bones)
|
||||||
for bone_index, psk_bone in map(lambda x: (x, psk.bones[x]), vertex_group_bone_indices):
|
for bone_index, psk_bone in map(lambda x: (x, psk.bones[x]), vertex_group_bone_indices):
|
||||||
vertex_groups[bone_index] = mesh_object.vertex_groups.new(name=psk_bone.name.decode('windows-1252'))
|
vertex_groups[bone_index] = mesh_object.vertex_groups.new(name=psk_bone.name.decode('windows-1252'))
|
||||||
|
|
||||||
|
|||||||
@@ -16,3 +16,8 @@ class PskImportMixin:
|
|||||||
should_import_shape_keys: bool
|
should_import_shape_keys: bool
|
||||||
scale: float
|
scale: float
|
||||||
bdk_repository_id: str
|
bdk_repository_id: str
|
||||||
|
|
||||||
|
|
||||||
|
def triangle_type_and_bit_flags_to_poly_flags(mesh_triangle_type: str, mesh_triangle_bit_flags: set[str]) -> int: ...
|
||||||
|
|
||||||
|
def poly_flags_to_triangle_type_and_bit_flags(poly_flags: int) -> tuple[str, set[str]]: ...
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ These functions are used to iterate over objects in a collection or view layer i
|
|||||||
instances. This is useful for exporters that need to traverse the object hierarchy in a predictable order.
|
instances. This is useful for exporters that need to traverse the object hierarchy in a predictable order.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional, Set, Iterable, List
|
from typing import Iterable
|
||||||
|
|
||||||
from bpy.types import Collection, Object, ViewLayer, LayerCollection
|
from bpy.types import Collection, Object, ViewLayer, LayerCollection
|
||||||
from mathutils import Matrix
|
from mathutils import Matrix
|
||||||
@@ -15,7 +15,7 @@ class DfsObject:
|
|||||||
"""
|
"""
|
||||||
Represents an object in a depth-first search.
|
Represents an object in a depth-first search.
|
||||||
"""
|
"""
|
||||||
def __init__(self, obj: Object, instance_objects: List[Object], matrix_world: Matrix):
|
def __init__(self, obj: Object, instance_objects: list[Object], matrix_world: Matrix):
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
self.instance_objects = instance_objects
|
self.instance_objects = instance_objects
|
||||||
self.matrix_world = matrix_world
|
self.matrix_world = matrix_world
|
||||||
@@ -85,9 +85,9 @@ def dfs_collection_objects(collection: Collection, visible_only: bool = False) -
|
|||||||
|
|
||||||
def _dfs_collection_objects_recursive(
|
def _dfs_collection_objects_recursive(
|
||||||
collection: Collection,
|
collection: Collection,
|
||||||
instance_objects: Optional[List[Object]] = None,
|
instance_objects: list[Object] | None = None,
|
||||||
matrix_world: Matrix = Matrix.Identity(4),
|
matrix_world: Matrix = Matrix.Identity(4),
|
||||||
visited: Optional[Set[Object]]=None
|
visited: set[Object] | None = None
|
||||||
) -> Iterable[DfsObject]:
|
) -> Iterable[DfsObject]:
|
||||||
"""
|
"""
|
||||||
Depth-first search of objects in a collection, including recursing into instances.
|
Depth-first search of objects in a collection, including recursing into instances.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List, Iterable, Optional, Dict, Tuple, cast as typing_cast
|
from typing import Iterable, cast as typing_cast
|
||||||
from bpy.types import Armature, AnimData, Collection, Context, Object, ArmatureModifier, SpaceProperties, PropertyGroup
|
from bpy.types import Armature, AnimData, Collection, Context, Object, ArmatureModifier, SpaceProperties, PropertyGroup
|
||||||
from mathutils import Matrix, Vector, Quaternion as BpyQuaternion
|
from mathutils import Matrix, Vector, Quaternion as BpyQuaternion
|
||||||
from psk_psa_py.shared.data import PsxBone, Quaternion, Vector3
|
from psk_psa_py.shared.data import PsxBone, Quaternion, Vector3
|
||||||
@@ -102,7 +102,7 @@ def populate_bone_collection_list(
|
|||||||
item.is_selected = bone_collection.name in selected_assigned_collection_names if has_selected_collections else True
|
item.is_selected = bone_collection.name in selected_assigned_collection_names if has_selected_collections else True
|
||||||
|
|
||||||
|
|
||||||
def get_export_bone_names(armature_object: Object, bone_filter_mode: str, bone_collection_indices: Iterable[int]) -> List[str]:
|
def get_export_bone_names(armature_object: Object, bone_filter_mode: str, bone_collection_indices: Iterable[int]) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Returns a sorted list of bone indices that should be exported for the given bone filter mode and bone collections.
|
Returns a sorted list of bone indices that should be exported for the given bone filter mode and bone collections.
|
||||||
|
|
||||||
@@ -172,9 +172,9 @@ def convert_string_to_cp1252_bytes(string: str) -> bytes:
|
|||||||
|
|
||||||
|
|
||||||
def create_psx_bones_from_blender_bones(
|
def create_psx_bones_from_blender_bones(
|
||||||
bones: List[bpy.types.Bone],
|
bones: list[bpy.types.Bone],
|
||||||
armature_object_matrix_world: Matrix,
|
armature_object_matrix_world: Matrix,
|
||||||
) -> List[PsxBone]:
|
) -> list[PsxBone]:
|
||||||
"""
|
"""
|
||||||
Creates PSX bones from the given Blender bones.
|
Creates PSX bones from the given Blender bones.
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ def create_psx_bones_from_blender_bones(
|
|||||||
# Apply the scale of the armature object to the bone location.
|
# Apply the scale of the armature object to the bone location.
|
||||||
_, _, armature_object_scale = armature_object_matrix_world.decompose()
|
_, _, armature_object_scale = armature_object_matrix_world.decompose()
|
||||||
|
|
||||||
psx_bones: List[PsxBone] = []
|
psx_bones: list[PsxBone] = []
|
||||||
for bone in bones:
|
for bone in bones:
|
||||||
psx_bone = PsxBone()
|
psx_bone = PsxBone()
|
||||||
psx_bone.name = convert_string_to_cp1252_bytes(bone.name)
|
psx_bone.name = convert_string_to_cp1252_bytes(bone.name)
|
||||||
@@ -238,10 +238,6 @@ class PsxBoneCreateResult:
|
|||||||
self.armature_object_root_bone_indices = armature_object_root_bone_indices
|
self.armature_object_root_bone_indices = armature_object_root_bone_indices
|
||||||
self.armature_object_bone_names = armature_object_bone_names
|
self.armature_object_bone_names = armature_object_bone_names
|
||||||
|
|
||||||
@property
|
|
||||||
def has_false_root_bone(self) -> bool:
|
|
||||||
return len(self.bones) > 0 and self.bones[0].armature_object is None
|
|
||||||
|
|
||||||
|
|
||||||
def convert_vector_to_vector3(vector: Vector) -> Vector3:
|
def convert_vector_to_vector3(vector: Vector) -> Vector3:
|
||||||
"""
|
"""
|
||||||
@@ -280,7 +276,7 @@ class ObjectNode:
|
|||||||
def __init__(self, obj: Object):
|
def __init__(self, obj: Object):
|
||||||
self.object = obj
|
self.object = obj
|
||||||
self.parent: ObjectNode | None = None
|
self.parent: ObjectNode | None = None
|
||||||
self.children: List[ObjectNode] = []
|
self.children: list[ObjectNode] = []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root(self):
|
def root(self):
|
||||||
@@ -298,8 +294,8 @@ class ObjectTree:
|
|||||||
A tree of the armature objects based on their hierarchy.
|
A tree of the armature objects based on their hierarchy.
|
||||||
'''
|
'''
|
||||||
def __init__(self, objects: Iterable[Object]):
|
def __init__(self, objects: Iterable[Object]):
|
||||||
self.root_nodes: List[ObjectNode] = []
|
self.root_nodes: list[ObjectNode] = []
|
||||||
object_node_map: Dict[Object, ObjectNode] = {x: ObjectNode(x) for x in objects}
|
object_node_map: dict[Object, ObjectNode] = {x: ObjectNode(x) for x in objects}
|
||||||
|
|
||||||
for obj, object_node in object_node_map.items():
|
for obj, object_node in object_node_map.items():
|
||||||
if obj.parent in object_node_map:
|
if obj.parent in object_node_map:
|
||||||
@@ -334,14 +330,14 @@ class ObjectTree:
|
|||||||
|
|
||||||
|
|
||||||
def create_psx_bones(
|
def create_psx_bones(
|
||||||
armature_objects: List[Object],
|
armature_objects: list[Object],
|
||||||
export_space: str = 'WORLD',
|
export_space: str = 'WORLD',
|
||||||
root_bone_name: str = 'ROOT',
|
root_bone_name: str = 'ROOT',
|
||||||
forward_axis: str = 'X',
|
forward_axis: str = 'X',
|
||||||
up_axis: str = 'Z',
|
up_axis: str = 'Z',
|
||||||
scale: float = 1.0,
|
scale: float = 1.0,
|
||||||
bone_filter_mode: str = 'ALL',
|
bone_filter_mode: str = 'ALL',
|
||||||
bone_collection_indices: Optional[List[PsxBoneCollection]] = None,
|
bone_collection_indices: list[PsxBoneCollection] | None = None,
|
||||||
bone_collection_primary_key: str = 'OBJECT',
|
bone_collection_primary_key: str = 'OBJECT',
|
||||||
) -> PsxBoneCreateResult:
|
) -> PsxBoneCreateResult:
|
||||||
"""
|
"""
|
||||||
@@ -366,9 +362,9 @@ def create_psx_bones(
|
|||||||
total_bone_count += len(armature_data.bones)
|
total_bone_count += len(armature_data.bones)
|
||||||
|
|
||||||
# Store the bone names to be exported for each armature object.
|
# Store the bone names to be exported for each armature object.
|
||||||
armature_object_bone_names: Dict[Object, List[str]] = dict()
|
armature_object_bone_names: dict[Object, list[str]] = dict()
|
||||||
for armature_object in armature_objects:
|
for armature_object in armature_objects:
|
||||||
armature_bone_collection_indices: List[int] = []
|
armature_bone_collection_indices: list[int] = []
|
||||||
match bone_collection_primary_key:
|
match bone_collection_primary_key:
|
||||||
case 'OBJECT':
|
case 'OBJECT':
|
||||||
armature_bone_collection_indices.extend([x.index for x in bone_collection_indices if x.armature_object_name == armature_object.name])
|
armature_bone_collection_indices.extend([x.index for x in bone_collection_indices if x.armature_object_name == armature_object.name])
|
||||||
@@ -390,6 +386,13 @@ def create_psx_bones(
|
|||||||
armature_data = typing_cast(Armature, armature_object.data)
|
armature_data = typing_cast(Armature, armature_object.data)
|
||||||
armature_bones = [armature_data.bones[bone_name] for bone_name in bone_names]
|
armature_bones = [armature_data.bones[bone_name] for bone_name in bone_names]
|
||||||
|
|
||||||
|
# Ensure that we don't have multiple root bones in this armature.
|
||||||
|
root_bone_count = sum(1 for bone in armature_bones if bone.parent is None)
|
||||||
|
if root_bone_count > 1:
|
||||||
|
raise RuntimeError(f'Armature object \'{armature_object.name}\' has multiple root bones. '
|
||||||
|
f'Only one root bone is allowed per armature.'
|
||||||
|
)
|
||||||
|
|
||||||
armature_psx_bones = create_psx_bones_from_blender_bones(
|
armature_psx_bones = create_psx_bones_from_blender_bones(
|
||||||
bones=armature_bones,
|
bones=armature_bones,
|
||||||
armature_object_matrix_world=armature_object.matrix_world,
|
armature_object_matrix_world=armature_object.matrix_world,
|
||||||
@@ -611,8 +614,8 @@ from bpy.types import Depsgraph
|
|||||||
|
|
||||||
class PskInputObjects(object):
|
class PskInputObjects(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.mesh_dfs_objects: List[DfsObject] = []
|
self.mesh_dfs_objects: list[DfsObject] = []
|
||||||
self.armature_objects: List[Object] = []
|
self.armature_objects: list[Object] = []
|
||||||
|
|
||||||
|
|
||||||
def get_materials_for_mesh_objects(depsgraph: Depsgraph, mesh_objects: Iterable[Object]):
|
def get_materials_for_mesh_objects(depsgraph: Depsgraph, mesh_objects: Iterable[Object]):
|
||||||
@@ -640,7 +643,7 @@ def get_mesh_objects_for_context(context: Context) -> Iterable[DfsObject]:
|
|||||||
yield dfs_object
|
yield dfs_object
|
||||||
|
|
||||||
|
|
||||||
def get_armature_for_mesh_object(mesh_object: Object) -> Optional[Object]:
|
def get_armature_for_mesh_object(mesh_object: Object) -> Object | None:
|
||||||
if mesh_object.type != 'MESH':
|
if mesh_object.type != 'MESH':
|
||||||
return None
|
return None
|
||||||
# Get the first armature modifier with a non-empty armature object.
|
# Get the first armature modifier with a non-empty armature object.
|
||||||
|
|||||||
@@ -59,3 +59,5 @@ class PsxBoneExportMixin:
|
|||||||
|
|
||||||
class PSX_PG_scene_export(TransformSourceMixin):
|
class PSX_PG_scene_export(TransformSourceMixin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
bone_filter_mode_items: tuple[tuple[str, str, str]]
|
||||||
|
|||||||
Reference in New Issue
Block a user