Skip to content

Commit

Permalink
Version 2.1.0
Browse files Browse the repository at this point in the history
- Additions
	- Support for weighted SA1 models
	- Texture coordinate precision level in mesh properties
	- Support for animated geometry in levels
	- "As weighted mesh" parameter for import and armature conversion
	- "Ensure positive Euler rotations" parameter for model and animation export
	- "Flip vertex color channels" parameter for SA2 model import and export
	- "Ensure land entry order" parameter for level importing

- Changes
	- Updated upgrade terminology of events
	- Land entries separated further; added "hybrid" and "neither" collections
	- Attempting to export models with armature parenting type now throws an error
	- Armatures of exported objects now gets included, even if not visible/selected
	- SA1 models now import with white ambient color

- Fixed issues
	- Various animation export fixes
	- Crash when exporting models without mesh data
	- Paths not Linux compatible
	- Scene lighting working again
	- Scene lighting color properties now using correct color mode
	- Corrected Documentation URL
	- Texture Archive saving is broken
  • Loading branch information
Justin113D authored Dec 9, 2023
1 parent 1ceb58c commit 825233c
Show file tree
Hide file tree
Showing 44 changed files with 1,148 additions and 292 deletions.
Binary file modified blender/SAIOTemplates.blend
Binary file not shown.
4 changes: 2 additions & 2 deletions blender/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"name": "Sonic Adventure I/O",
"author": "Justin113D, ItsEasyActually, X-Hax",
"description": "Import/Exporter for Sonic Adventure Model, Animation and other Formats.",
"version": (2, 0, 2),
"version": (2, 1, 0),
"blender": (4, 0, 0),
"location": "",
"warning": "",
"doc_url": "https://x-hax.github.io/SonicAdventureBlenderIODocs/",
"doc_url": "https://x-hax.github.io/SonicAdventureBlenderIO/",
"tracker_url": "https://github.com/X-Hax/SonicAdventureBlenderIO/issues/new",
"category": "Import-Export"
}
Expand Down
4 changes: 2 additions & 2 deletions blender/__initdev__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"name": "Sonic Adventure I/O TEST BUILD",
"author": "Justin113D, ItsEasyActually, X-Hax",
"description": "Import/Exporter for Sonic Adventure Model, Animation and other Formats.",
"version": (2, 0, 2),
"version": (2, 1, 0),
"blender": (4, 0, 0),
"location": "",
"warning": "",
"doc_url": "https://x-hax.github.io/SonicAdventureBlenderIODocs/",
"doc_url": "https://x-hax.github.io/SonicAdventureBlenderIO/",
"tracker_url": "https://github.com/X-Hax/SonicAdventureBlenderIO/issues/new",
"category": "Import-Export"
}
Expand Down
12 changes: 7 additions & 5 deletions blender/source/dotnet/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from .system import System
from .textcopy import TextCopy
from .sa3d_common import SA3D_Common
Expand Down Expand Up @@ -35,22 +36,23 @@ def load_dotnet():
"Could not install python.net, please try running blender with"
" admin rights")) from exc

path = get_path() + "\\DLL\\"
dll_paths = [
path = os.path.join(get_path(), "DLL")
dll_names = [
"SAIO.NET.dll",
"SA3D.Archival.dll",
"SA3D.SA2Event.dll",
"TextCopy.dll",
]

runtime_config = f"{path}SAIO.NET.runtimeconfig.json"
runtime_config = os.path.join(path, "SAIO.NET.runtimeconfig.json")

import pythonnet
pythonnet.load("coreclr", runtime_config=runtime_config)

import clr
for dll_path in dll_paths:
clr.AddReference(path + dll_path) # pylint: disable=no-member
for dll_name in dll_names:
dll_path = os.path.join(path, dll_name)
clr.AddReference(dll_path) # pylint: disable=no-member

for library in LIBRARIES:
library.load()
Expand Down
7 changes: 7 additions & 0 deletions blender/source/dotnet/sa3d_modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class SA3D_Modeling:
MOTION: any = None
'''Class SA3D.Modeling.Animation.Motion'''

LAND_ENTRY_MOTION: any = None
'''Class SA3D.Modeling.Animation.LandEntryMotion'''

KEYFRAMES: any = None
'''Class SA3D.Modeling.Animation.Keyframes'''

Expand Down Expand Up @@ -69,6 +72,7 @@ class SA3D_Modeling:
GEN_COMPLEMENTARY_MATRIX_DICT: any = None
'''Generic type: Dictionary<uint, Matrix4x4[]>'''


@classmethod
def load(cls):
from SA3D.Modeling.Structs import Color # pylint: disable=import-error
Expand Down Expand Up @@ -98,6 +102,7 @@ def load(cls):

from SA3D.Modeling.Animation import ( # pylint: disable=import-error
Motion,
LandEntryMotion,
Keyframes,
KeyframeAttributes,
)
Expand All @@ -124,6 +129,7 @@ def load(cls):
cls.WEIGHTED_VERTEX = WeightedVertex
cls.MODEL_FORMAT = ModelFormat
cls.MOTION = Motion
cls.LAND_ENTRY_MOTION = LandEntryMotion
cls.KEYFRAMES = Keyframes
cls.KEYFRAME_ATTRIBUTES = KeyframeAttributes
cls.KEYFRAME_ROTATION_UTILS = KeyframeRotationUtils
Expand All @@ -150,6 +156,7 @@ def unload(cls):
cls.BUFFER_CORNER = None
cls.WEIGHTED_VERTEX = None
cls.MOTION = None
cls.LAND_ENTRY_MOTION = None
cls.KEYFRAMES = None
cls.KEYFRAME_ATTRIBUTES = None
cls.KEYFRAME_ROTATION_UTILS = None
Expand Down
8 changes: 4 additions & 4 deletions blender/source/exporting/o_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ def get_evaluator(chunk: bool):
'SA2' if chunk else 'SA2B',
False,
self.optimize,
not chunk,
False,
True,
False,
auto_node_attributes,
False,
False
)

Expand Down Expand Up @@ -215,14 +215,14 @@ def _collect_objects(self):
def _get_children(
self,
obj: BObject,
output: list[BObject]):
output: set[BObject]):

output.append(obj)
output.add(obj)
for child in obj.children:
self._get_children(child, output)

def _convert_model(self, obj: bpy.types.Object):
objects = []
objects = set()
self._get_children(obj, objects)

event_props = obj.saio_event_entry
Expand Down
13 changes: 9 additions & 4 deletions blender/source/exporting/o_keyframes.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def _bake_keyframes(self, fcurves: list[FCurve], fallback: float = 0):
frames.update(self._eval_export_frames(curve))

result: dict[int, list[float]] = {}
for frame in frames:
for frame in sorted(frames):
result[frame - self._start] = [
(vc.evaluate(frame) if vc is not None else fallback)
for vc in fcurves]
Expand Down Expand Up @@ -155,7 +155,8 @@ def _evaluate_location(
def _get_complementary_matrices(
self,
euler: Euler,
previous_euler: Euler):
previous_euler: Euler,
base_rotation: Matrix):

if previous_euler is None:
return None
Expand Down Expand Up @@ -190,7 +191,7 @@ def _get_complementary_matrices(
previous_euler.order
)

mtx = self._rotation_matrix @ compl_euler.to_matrix().to_4x4()
mtx = base_rotation @ (self._rotation_matrix @ compl_euler.to_matrix().to_4x4())
net_mtx = o_matrix.bpy_to_net_matrix(mtx)

result.append(net_mtx)
Expand Down Expand Up @@ -225,7 +226,7 @@ def add_rotation(index: int, mtx: Matrix):
add_rotation(i, euler.to_matrix())

complementary = self._get_complementary_matrices(
euler, previous_euler)
euler, previous_euler, base_rotation)

if complementary is not None:
compl_matrices.Add(previous_frame, complementary)
Expand Down Expand Up @@ -345,6 +346,10 @@ def evaluate_node_keyframe_set(
self._evaluate_scale(scale_curves, base_matrix)

self._optimize_keyframes()

if self._anim_parameters.ensure_positive_euler_angles:
SA3D_Modeling.KEYFRAME_ROTATION_UTILS.EnsurePositiveEulerRotationAngles(self._output, True)

return self._output

def _get_camera_curves(self, camera_actions: camera_utils.CameraActionSet):
Expand Down
Loading

0 comments on commit 825233c

Please sign in to comment.