Compare commits
6 Commits
ut-poly-fl
...
blender-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d996f59cae | ||
|
|
bd667d4833 | ||
|
|
d81477673b | ||
|
|
4d41f1af83 | ||
|
|
15e2c6ccdd | ||
|
|
14116963bb |
@@ -10,7 +10,7 @@ This Blender addon allows you to import and export meshes and animations to and
|
|||||||
| Blender Version | Addon Version | Long Term Support |
|
| Blender Version | Addon Version | Long Term Support |
|
||||||
|--------------------------------------------------------------|--------------------------------------------------------------------------------|-------------------|
|
|--------------------------------------------------------------|--------------------------------------------------------------------------------|-------------------|
|
||||||
| 4.0+ | [latest](https://github.com/DarklightGames/io_scene_psk_psa/releases/latest) | TBD |
|
| 4.0+ | [latest](https://github.com/DarklightGames/io_scene_psk_psa/releases/latest) | TBD |
|
||||||
| [3.4 - 3.6](https://www.blender.org/download/lts/3-6/) | [5.0.5](https://github.com/DarklightGames/io_scene_psk_psa/releases/tag/5.0.5) | ✅️ June 2025 |
|
| [3.4 - 3.6](https://www.blender.org/download/lts/3-6/) | [5.0.6](https://github.com/DarklightGames/io_scene_psk_psa/releases/tag/5.0.6) | ✅️ June 2025 |
|
||||||
| [2.93 - 3.3](https://www.blender.org/download/releases/3-3/) | [4.3.0](https://github.com/DarklightGames/io_scene_psk_psa/releases/tag/4.3.0) | ✅️ September 2024 |
|
| [2.93 - 3.3](https://www.blender.org/download/releases/3-3/) | [4.3.0](https://github.com/DarklightGames/io_scene_psk_psa/releases/tag/4.3.0) | ✅️ September 2024 |
|
||||||
|
|
||||||
Bug fixes will be issued for legacy addon versions that are under [Blender's LTS maintenance period](https://www.blender.org/download/lts/). Once the LTS period has ended, legacy addon versions will no longer be supported by the maintainers of this repository, although we will accept pull requests for bug fixes.
|
Bug fixes will be issued for legacy addon versions that are under [Blender's LTS maintenance period](https://www.blender.org/download/lts/). Once the LTS period has ended, legacy addon versions will no longer be supported by the maintainers of this repository, although we will accept pull requests for bug fixes.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from bpy.app.handlers import persistent
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
'name': 'PSK/PSA Importer/Exporter',
|
'name': 'PSK/PSA Importer/Exporter',
|
||||||
'author': 'Colin Basnett, Yurii Ti',
|
'author': 'Colin Basnett, Yurii Ti',
|
||||||
'version': (6, 1, 2),
|
'version': (6, 2, 0),
|
||||||
'blender': (4, 0, 0),
|
'blender': (4, 0, 0),
|
||||||
'description': 'PSK/PSA Import/Export (.psk/.psa)',
|
'description': 'PSK/PSA Import/Export (.psk/.psa)',
|
||||||
'warning': '',
|
'warning': '',
|
||||||
@@ -36,6 +36,7 @@ if 'bpy' in locals():
|
|||||||
importlib.reload(psa_reader)
|
importlib.reload(psa_reader)
|
||||||
importlib.reload(psa_writer)
|
importlib.reload(psa_writer)
|
||||||
importlib.reload(psa_builder)
|
importlib.reload(psa_builder)
|
||||||
|
importlib.reload(psa_importer)
|
||||||
importlib.reload(psa_export_properties)
|
importlib.reload(psa_export_properties)
|
||||||
importlib.reload(psa_export_operators)
|
importlib.reload(psa_export_operators)
|
||||||
importlib.reload(psa_export_ui)
|
importlib.reload(psa_export_ui)
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ def import_psa(context: Context, psa_reader: PsaReader, armature_object: Object,
|
|||||||
import_bone.original_rotation.conjugate()
|
import_bone.original_rotation.conjugate()
|
||||||
else:
|
else:
|
||||||
import_bone.original_location = armature_bone.matrix_local.translation.copy()
|
import_bone.original_location = armature_bone.matrix_local.translation.copy()
|
||||||
import_bone.original_rotation = armature_bone.matrix_local.to_quaternion()
|
import_bone.original_rotation = armature_bone.matrix_local.to_quaternion().conjugated()
|
||||||
|
|
||||||
import_bone.post_rotation = import_bone.original_rotation.conjugated()
|
import_bone.post_rotation = import_bone.original_rotation.conjugated()
|
||||||
|
|
||||||
context.window_manager.progress_begin(0, len(sequences))
|
context.window_manager.progress_begin(0, len(sequences))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import numpy as np
|
|||||||
from bpy.types import Armature, Material
|
from bpy.types import Armature, Material
|
||||||
|
|
||||||
from .data import *
|
from .data import *
|
||||||
from .properties import get_poly_flags
|
from .properties import triangle_type_and_bit_flags_to_poly_flags
|
||||||
from ..helpers import *
|
from ..helpers import *
|
||||||
|
|
||||||
|
|
||||||
@@ -76,9 +76,9 @@ def build_psk(context, options: PskBuildOptions) -> PskBuildResult:
|
|||||||
psk = Psk()
|
psk = Psk()
|
||||||
bones = []
|
bones = []
|
||||||
|
|
||||||
if armature_object is None:
|
if armature_object is None or len(armature_object.data.bones) == 0:
|
||||||
# If the mesh has no armature object, simply assign it a dummy bone at the root to satisfy the requirement
|
# If the mesh has no armature object or no bones, simply assign it a dummy bone at the root to satisfy the
|
||||||
# that a PSK file must have at least one bone.
|
# requirement that a PSK file must have at least one bone.
|
||||||
psk_bone = Psk.Bone()
|
psk_bone = Psk.Bone()
|
||||||
psk_bone.name = bytes('root', encoding='windows-1252')
|
psk_bone.name = bytes('root', encoding='windows-1252')
|
||||||
psk_bone.flags = 0
|
psk_bone.flags = 0
|
||||||
@@ -146,8 +146,8 @@ def build_psk(context, options: PskBuildOptions) -> PskBuildResult:
|
|||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
raise RuntimeError(f'Material name "{material.name}" contains characters that cannot be encoded in the Windows-1252 codepage')
|
raise RuntimeError(f'Material name "{material.name}" contains characters that cannot be encoded in the Windows-1252 codepage')
|
||||||
psk_material.texture_index = len(psk.materials)
|
psk_material.texture_index = len(psk.materials)
|
||||||
psk_material.poly_flags = get_poly_flags(material.psk)
|
psk_material.poly_flags = triangle_type_and_bit_flags_to_poly_flags(material.psk.mesh_triangle_type,
|
||||||
print(psk_material.name, psk_material.poly_flags)
|
material.psk.mesh_triangle_bit_flags)
|
||||||
psk.materials.append(psk_material)
|
psk.materials.append(psk_material)
|
||||||
|
|
||||||
context.window_manager.progress_begin(0, len(input_objects.mesh_objects))
|
context.window_manager.progress_begin(0, len(input_objects.mesh_objects))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from bpy.types import VertexGroup
|
|||||||
from mathutils import Quaternion, Vector, Matrix
|
from mathutils import Quaternion, Vector, Matrix
|
||||||
|
|
||||||
from .data import Psk
|
from .data import Psk
|
||||||
|
from .properties import poly_flags_to_triangle_type_and_bit_flags
|
||||||
from ..helpers import rgb_to_srgb, is_bdk_addon_loaded
|
from ..helpers import rgb_to_srgb, is_bdk_addon_loaded
|
||||||
|
|
||||||
|
|
||||||
@@ -134,6 +135,9 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:
|
|||||||
else:
|
else:
|
||||||
# Just create a blank material.
|
# Just create a blank material.
|
||||||
material = bpy.data.materials.new(material_name)
|
material = bpy.data.materials.new(material_name)
|
||||||
|
mesh_triangle_type, mesh_triangle_bit_flags = poly_flags_to_triangle_type_and_bit_flags(psk_material.poly_flags)
|
||||||
|
material.psk.mesh_triangle_type = mesh_triangle_type
|
||||||
|
material.psk.mesh_triangle_bit_flags = mesh_triangle_bit_flags
|
||||||
material.use_nodes = True
|
material.use_nodes = True
|
||||||
mesh_data.materials.append(material)
|
mesh_data.materials.append(material)
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ from bpy.props import EnumProperty
|
|||||||
from bpy.types import PropertyGroup
|
from bpy.types import PropertyGroup
|
||||||
|
|
||||||
mesh_triangle_types_items = (
|
mesh_triangle_types_items = (
|
||||||
('MTT_Normal', 'Normal', 'Normal one-sided', 0),
|
('NORMAL', 'Normal', 'Normal one-sided', 0),
|
||||||
('MTT_NormalTwoSided', 'Normal Two-Sided', 'Normal but two-sided', 1),
|
('NORMAL_TWO_SIDED', 'Normal Two-Sided', 'Normal but two-sided', 1),
|
||||||
('MTT_Translucent', 'Translucent', 'Translucent two-sided', 2),
|
('TRANSLUCENT', 'Translucent', 'Translucent two-sided', 2),
|
||||||
('MTT_Masked', 'Masked', 'Masked two-sided', 3),
|
('MASKED', 'Masked', 'Masked two-sided', 3),
|
||||||
('MTT_Modulate', 'Modulate', 'Modulation blended two-sided', 4),
|
('MODULATE', 'Modulate', 'Modulation blended two-sided', 4),
|
||||||
('MTT_Placeholder', 'Placeholder', 'Placeholder triangle for positioning weapon. Invisible', 8),
|
('PLACEHOLDER', 'Placeholder', 'Placeholder triangle for positioning weapon. Invisible', 8),
|
||||||
)
|
)
|
||||||
|
|
||||||
mesh_triangle_bit_flags_items = (
|
mesh_triangle_bit_flags_items = (
|
||||||
('MTT_Unlit', 'Unlit', 'Full brightness, no lighting', 16),
|
('UNLIT', 'Unlit', 'Full brightness, no lighting', 16),
|
||||||
('MTT_Flat', 'Flat', 'Flat surface, don\'t do bMeshCurvy thing', 32),
|
('FLAT', 'Flat', 'Flat surface, don\'t do bMeshCurvy thing', 32),
|
||||||
('MTT_Environment', 'Environment', 'Environment mapped', 64),
|
('ENVIRONMENT', 'Environment', 'Environment mapped', 64),
|
||||||
('MTT_NoSmooth', 'No Smooth', 'No bilinear filtering on this poly\'s texture', 128),
|
('NO_SMOOTH', 'No Smooth', 'No bilinear filtering on this poly\'s texture', 128),
|
||||||
)
|
)
|
||||||
|
|
||||||
class PSX_PG_material(PropertyGroup):
|
class PSX_PG_material(PropertyGroup):
|
||||||
@@ -26,13 +26,23 @@ mesh_triangle_types_items_dict = {item[0]: item[3] for item in mesh_triangle_typ
|
|||||||
mesh_triangle_bit_flags_items_dict = {item[0]: item[3] for item in mesh_triangle_bit_flags_items}
|
mesh_triangle_bit_flags_items_dict = {item[0]: item[3] for item in mesh_triangle_bit_flags_items}
|
||||||
|
|
||||||
|
|
||||||
def get_poly_flags(material: PSX_PG_material) -> int:
|
def triangle_type_and_bit_flags_to_poly_flags(mesh_triangle_type: str, mesh_triangle_bit_flags: set[str]) -> int:
|
||||||
poly_flags = 0
|
poly_flags = 0
|
||||||
poly_flags |= mesh_triangle_types_items_dict[material.mesh_triangle_type]
|
poly_flags |= mesh_triangle_types_items_dict.get(mesh_triangle_type, 0)
|
||||||
for flag in material.mesh_triangle_bit_flags:
|
for flag in mesh_triangle_bit_flags:
|
||||||
poly_flags |= mesh_triangle_bit_flags_items_dict[flag]
|
poly_flags |= mesh_triangle_bit_flags_items_dict.get(flag, 0)
|
||||||
return poly_flags
|
return poly_flags
|
||||||
|
|
||||||
|
|
||||||
|
def poly_flags_to_triangle_type_and_bit_flags(poly_flags: int) -> (str, set[str]):
|
||||||
|
try:
|
||||||
|
triangle_type = next(item[0] for item in mesh_triangle_types_items if item[3] == (poly_flags & 15))
|
||||||
|
except StopIteration:
|
||||||
|
triangle_type = 'NORMAL'
|
||||||
|
triangle_bit_flags = {item[0] for item in mesh_triangle_bit_flags_items if item[3] & poly_flags}
|
||||||
|
return triangle_type, triangle_bit_flags
|
||||||
|
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
PSX_PG_material,
|
PSX_PG_material,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user