diff --git a/blender/__init__.py b/blender/__init__.py
index 56bc58c..9037248 100644
--- a/blender/__init__.py
+++ b/blender/__init__.py
@@ -6,7 +6,7 @@
"name": "Sonic Adventure I/O",
"author": "Justin113D, ItsEasyActually, X-Hax",
"description": "Import/Exporter for Sonic Adventure Model, Animation and other Formats.",
- "version": (2, 1, 0),
+ "version": (2, 1, 1),
"blender": (4, 0, 0),
"location": "",
"warning": "",
diff --git a/blender/__initdev__.py b/blender/__initdev__.py
index 36889d5..1d96418 100644
--- a/blender/__initdev__.py
+++ b/blender/__initdev__.py
@@ -6,7 +6,7 @@
"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, 1, 0),
+ "version": (2, 1, 1),
"blender": (4, 0, 0),
"location": "",
"warning": "",
diff --git a/blender/source/exporting/o_enum.py b/blender/source/exporting/o_enum.py
index 93aed32..9a0d7c1 100644
--- a/blender/source/exporting/o_enum.py
+++ b/blender/source/exporting/o_enum.py
@@ -7,9 +7,10 @@
GC_TEXCOORD_SOURCE,
GC_TEXCOORD_MATRIX,
ATTACH_FORMAT,
- MODEL_FORMAT
+ MODEL_FORMAT,
+ EVENT_TYPE
)
-from ..dotnet import SAIO_NET, SA3D_Modeling
+from ..dotnet import SAIO_NET, SA3D_Modeling, SA3D_SA2Event
def to_node_attributes(node_properties):
@@ -80,3 +81,6 @@ def to_attach_format(attach_format: str):
def to_model_format(model_format: str):
return getattr(SA3D_Modeling.MODEL_FORMAT, MODEL_FORMAT[model_format])
+
+def to_event_type(event_type: str):
+ return getattr(SA3D_SA2Event.EVENT_TYPE, EVENT_TYPE[event_type])
diff --git a/blender/source/exporting/o_event.py b/blender/source/exporting/o_event.py
index cea9a56..65eea17 100644
--- a/blender/source/exporting/o_event.py
+++ b/blender/source/exporting/o_event.py
@@ -1,6 +1,7 @@
import bpy
from bpy.types import Object as BObject
+from . import o_enum
from .o_event_cutinfo import CutInfo
from .o_shapemotion import ShapeMotionEvaluator
from .o_model import ModelEvaluator, ModelData
@@ -46,6 +47,7 @@ def get_base_scene(context: bpy.types.Context):
class EventExporter:
context: bpy.types.Context
+ event_type: str
optimize: bool
anim_parameters: AnimParameters
@@ -75,11 +77,13 @@ class EventExporter:
def __init__(
self,
context: bpy.types.Context,
+ event_type: str,
optimize: bool,
auto_node_attributes: bool,
anim_parameters: AnimParameters):
self.context = context
+ self.event_type = event_type
self.optimize = optimize
self.anim_parameters = anim_parameters
@@ -158,7 +162,7 @@ def _collect_objects(self):
self.entry_source_scene[obj] = self.base_scene
- self.shared_entries.sort(key=lambda x: x.name)
+ self.shared_entries.sort(key=lambda x: x.name.lower())
event_properties = self.base_scene.saio_scene.event
for name in OVERLAY_UPGRADE_LUT.values():
@@ -207,6 +211,9 @@ def _collect_objects(self):
if obj not in self.entry_source_scene:
self.entry_source_scene[obj] = cutinfo.scene
+ cutinfo.entries.sort(key=lambda x: x.name.lower())
+ cutinfo.particles.sort(key=lambda x: x.name.lower())
+
if len(self.blare) > 64:
raise UserException("Can't have more than 64 blare models!")
@@ -268,11 +275,10 @@ def _convert_model(self, obj: bpy.types.Object):
self.uv_animated_objects.extend(uv_meshes)
def _convert_models(self):
- base_entries = []
- base_entries.extend(self.shared_entries)
- base_entries.extend(self.shadows)
- base_entries.extend(self.upgrades)
- base_entries = set(base_entries)
+ base_entries = set()
+ base_entries.update(self.shared_entries)
+ base_entries.update(self.shadows)
+ base_entries.update(self.upgrades)
for entry in base_entries:
self._convert_model(entry)
@@ -623,12 +629,13 @@ def _setup_animated_scene(self, cutinfo: CutInfo):
motion = None
if obj in cutinfo.motions:
motion = cutinfo.motions[obj]
+ motion.EnsureKeyframes(posrot)
result.ParticleMotions.Add(motion)
return result
def _setup_eventdata(self):
- self.event_data = SA3D_SA2Event.MODEL_DATA(SA3D_SA2Event.EVENT_TYPE.gc)
+ self.event_data = SA3D_SA2Event.MODEL_DATA(o_enum.to_event_type(self.event_type))
self.event_data.EnableDropShadows = \
self.base_scene.saio_scene.event.drop_shadow_control
diff --git a/blender/source/exporting/o_event_cutinfo.py b/blender/source/exporting/o_event_cutinfo.py
index 1e882de..dfbf1e3 100644
--- a/blender/source/exporting/o_event_cutinfo.py
+++ b/blender/source/exporting/o_event_cutinfo.py
@@ -169,7 +169,7 @@ def _setup_temp_object_action(
self,
action: bpy.types.Action,
obj: BObject,
- only_location: bool = False):
+ no_scale: bool = False):
def create_curve(field, length):
for i in range(length):
@@ -181,16 +181,15 @@ def create_curve(field, length):
create_curve("location", 3)
- if only_location:
- return
-
- create_curve("scale", 3)
-
if obj.rotation_mode == 'QUATERNION':
create_curve("rotation_quaternion", 4)
else:
create_curve("rotation_euler", 3)
+ if not no_scale:
+ create_curve("scale", 3)
+
+
def _setup_temp_target_action(self, action: bpy.types.Action, obj):
def create_curve(field, index):
@@ -324,7 +323,7 @@ def _prepare_particle_actions(self):
action = self._setup_action(
particle.animation_data,
particle.name,
- lambda x: self._setup_temp_object_action(x, particle, True))
+ lambda x: self._setup_temp_object_action(x, particle))
if action is not None:
self.output_actions[particle] = action
diff --git a/blender/source/exporting/o_landtable.py b/blender/source/exporting/o_landtable.py
index e581a2e..adfb369 100644
--- a/blender/source/exporting/o_landtable.py
+++ b/blender/source/exporting/o_landtable.py
@@ -195,10 +195,10 @@ def _eval_animated(self, objects: set[bpy.types.Object]):
self._optimize,
self._write_specular,
self._apply_modifs,
- False, # apply posing
+ False, # Dont apply posing
self._automatic_node_attributes,
self._force_sort_bones,
- False) # flip vertex colors
+ False) # Dont flip vertex colors
modeldata = evaluator.evaluate(objects)
@@ -233,10 +233,10 @@ def evaluate(self, objects: set[bpy.types.Object]):
self._setup()
self._organize_objects(objects)
- for objects in self._anim_objects:
- self._eval_animated(objects)
+ for anim_tree in self._anim_objects:
+ self._eval_animated(anim_tree)
- for obj in self._le_objects:
+ for obj in sorted(self._le_objects, key=lambda x: x.name.lower()):
if obj.type == 'MESH' and len(obj.data.polygons) > 0:
self._eval_entry(obj)
diff --git a/blender/source/exporting/o_model.py b/blender/source/exporting/o_model.py
index bc7ac1a..23ba64d 100644
--- a/blender/source/exporting/o_model.py
+++ b/blender/source/exporting/o_model.py
@@ -92,7 +92,7 @@ def __init__(
apply_pose: bool = False,
automatic_node_attributes: bool = True,
force_sort_bones: bool = False,
- flip_vertex_color_channels: bool = False,):
+ flip_vertex_color_channels: bool = False):
self._context = context
self._attach_format = attach_format
diff --git a/blender/source/exporting/o_node.py b/blender/source/exporting/o_node.py
index 306c915..a1b6521 100644
--- a/blender/source/exporting/o_node.py
+++ b/blender/source/exporting/o_node.py
@@ -239,9 +239,9 @@ def _evaluate_object_tree(self, objects: set[BObject]):
self._hierarchy_dictionary[obj] = []
for hierarchy_objects in self._hierarchy_dictionary.values():
- hierarchy_objects.sort(key=lambda x: x.name)
+ hierarchy_objects.sort(key=lambda x: x.name.lower())
- self._parentless.sort(key=lambda x: x.name)
+ self._parentless.sort(key=lambda x: x.name.lower())
def _eval_object(self, obj: BObject, parent_index: int):
@@ -261,7 +261,7 @@ def _eval_bone(self, bone: PoseBone, parent_index: int):
children = list(bone.children)
if self._force_sort_bones:
- children.sort(key=lambda x: x.name)
+ children.sort(key=lambda x: x.name.lower())
for child in children:
self._eval_bone(child, index)
diff --git a/blender/source/importing/i_texture.py b/blender/source/importing/i_texture.py
index 132cba6..9b96b48 100644
--- a/blender/source/importing/i_texture.py
+++ b/blender/source/importing/i_texture.py
@@ -15,7 +15,7 @@ def process_texture_set(texture_set, texture_list):
img.pack()
tex = texture_list.new(name=texture.Name, image=img)
- tex.global_index = texture.GlobalIndex
+ tex.global_index = SAIO_NET.TEXTURE.ToSigned(texture.GlobalIndex)
tex.override_width = texture.OverrideWidth
tex.override_height = texture.OverrideHeight
diff --git a/blender/source/register/operators/export_operators.py b/blender/source/register/operators/export_operators.py
index a813742..c6fed7a 100644
--- a/blender/source/register/operators/export_operators.py
+++ b/blender/source/register/operators/export_operators.py
@@ -413,6 +413,19 @@ class SAIO_OT_Export_Event(NodeAnimExportOperator):
show_bone_localspace = False
+ event_type: EnumProperty(
+ name="Event Type",
+ description="Type of event to export",
+ items=(
+ ('DCBETA', "Dreamcast Beta", "Event targetting Dreamcast beta builds"),
+ ('DC', "Dreamcast", "Event targetting Dreamcast"),
+ ('DCGC', "Dreamcast-Gamecube",
+ "Event targetting Gamecube (and ports) but with Greamcast formatting"),
+ ('GC', "Gamecube", "Event targetting Gamecube and ports"),
+ ),
+ default='GC'
+ )
+
optimize: BoolProperty(
name="Optimize",
description="Optimize if possible",
@@ -445,6 +458,7 @@ class SAIO_OT_Export_Event(NodeAnimExportOperator):
)
def draw(self, context: bpy.types.Context):
+ self.layout.prop(self, "event_type")
self.layout.prop(self, "optimize")
self.layout.prop(self, "auto_node_attributes")
self.layout.prop(self, "export_textures")
@@ -459,6 +473,7 @@ def export(self, context: bpy.types.Context):
exporter = o_event.EventExporter(
context,
+ self.event_type,
self.optimize,
self.auto_node_attributes,
anim_parameters)
diff --git a/blender/source/register/operators/tool_operators.py b/blender/source/register/operators/tool_operators.py
index ab2c2f3..4b96f83 100644
--- a/blender/source/register/operators/tool_operators.py
+++ b/blender/source/register/operators/tool_operators.py
@@ -315,7 +315,7 @@ def add_children(
resultMeshes.append(parent)
children: list[bpy.types.Object] = [child for child in parent.children]
- children.sort(key=lambda x: x.name)
+ children.sort(key=lambda x: x.name.lower())
for child in children:
SAIO_OT_ArmatureFromObjects.add_children(
diff --git a/blender/source/register/property_groups/texture_properties.py b/blender/source/register/property_groups/texture_properties.py
index 86a4f2a..e52915e 100644
--- a/blender/source/register/property_groups/texture_properties.py
+++ b/blender/source/register/property_groups/texture_properties.py
@@ -28,8 +28,7 @@ class SAIO_Texture(bpy.types.PropertyGroup):
global_index: IntProperty(
name="Global Index",
description="The global texture id in the texture file",
- default=0,
- min=0
+ default=0
)
override_width: IntProperty(
diff --git a/blender/source/register/ui/material_panel.py b/blender/source/register/ui/material_panel.py
index 877730d..6f47c23 100644
--- a/blender/source/register/ui/material_panel.py
+++ b/blender/source/register/ui/material_panel.py
@@ -144,8 +144,8 @@ def rendering_prop(label, name):
rendering_menu.separator(factor=2)
rendering_prop("Double Sided:", "double_sided")
+ rendering_prop("Ignore Lighting:", "ignore_diffuse")
rendering_prop("Ignore Ambient Lighting:", "ignore_ambient")
- rendering_prop("Ignore Diffuse Lighting:", "ignore_diffuse")
rendering_prop("Ignore Specular Lighting:", "ignore_specular")
rendering_prop("Flat Shading:", "flat_shading")
diff --git a/blender/source/utility/bone_utils.py b/blender/source/utility/bone_utils.py
index e5de786..8c395aa 100644
--- a/blender/source/utility/bone_utils.py
+++ b/blender/source/utility/bone_utils.py
@@ -14,7 +14,7 @@ def _get_bone(
children = list(bone.children)
if force_sort:
- children.sort(key=lambda b: b.name)
+ children.sort(key=lambda b: b.name.lower())
for b in children:
_get_bone(b, force_sort, shape, result)
diff --git a/blender/source/utility/enum_lut.py b/blender/source/utility/enum_lut.py
index 026c0ac..d1d0760 100644
--- a/blender/source/utility/enum_lut.py
+++ b/blender/source/utility/enum_lut.py
@@ -377,3 +377,17 @@
'SA2': 'SA2',
'SA2B': 'SA2B'
}
+
+EVENT_TYPE = {
+ "dcbeta": "DCBETA",
+ "DCBETA" : "dcbeta",
+
+ "dc": "DC",
+ "DC" : "dc",
+
+ "dcgc": "DCGC",
+ "DCGC" : "dcgc",
+
+ "gc": "GC",
+ "GC" : "gc"
+}
diff --git a/blender/source/utility/material_setup.py b/blender/source/utility/material_setup.py
index 9866cff..f3053e3 100644
--- a/blender/source/utility/material_setup.py
+++ b/blender/source/utility/material_setup.py
@@ -444,7 +444,7 @@ def assemble_texture_list(
texlist = world.saio_texture_list
texs = list(texs)
- texs.sort(key=lambda x: x.name)
+ texs.sort(key=lambda x: x.name.lower())
index = global_index_offset
for tex in texs:
item = texlist.new(image=tex)
diff --git a/dotnet/Model.cs b/dotnet/Model.cs
index abc96f7..a6d92fe 100644
--- a/dotnet/Model.cs
+++ b/dotnet/Model.cs
@@ -143,16 +143,19 @@ public static Model Process(Node node, bool optimize, bool flipVertexColors = fa
meshes = WeightedMesh.MergeAtRoots(meshes);
}
- foreach(WeightedMesh mesh in meshes)
+ if(flipVertexColors)
{
- foreach(BufferCorner[] corners in mesh.TriangleSets)
+ foreach(WeightedMesh mesh in meshes)
{
- for(int i = 0; i < corners.Length; i++)
+ foreach(BufferCorner[] corners in mesh.TriangleSets)
{
- Color color = corners[i].Color;
- (color.Alpha, color.Blue) = (color.Blue, color.Alpha);
- (color.Red, color.Green) = (color.Green, color.Red);
- corners[i].Color = color;
+ for(int i = 0; i < corners.Length; i++)
+ {
+ Color color = corners[i].Color;
+ (color.Alpha, color.Blue) = (color.Blue, color.Alpha);
+ (color.Red, color.Green) = (color.Green, color.Red);
+ corners[i].Color = color;
+ }
}
}
}
diff --git a/dotnet/SAIO.NET.csproj b/dotnet/SAIO.NET.csproj
index b91bf21..e2e5bce 100644
--- a/dotnet/SAIO.NET.csproj
+++ b/dotnet/SAIO.NET.csproj
@@ -12,12 +12,12 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/dotnet/Texture.cs b/dotnet/Texture.cs
index e4e4f1c..f9c0b29 100644
--- a/dotnet/Texture.cs
+++ b/dotnet/Texture.cs
@@ -27,12 +27,14 @@ public static float[] GetData(Image texture)
return result;
}
- public static Image Create(string name, uint globalIndex, int width, int height, bool? index4, float[] colors)
+ public static Image Create(string name, int globalIndex, int width, int height, bool? index4, float[] colors)
{
ReadOnlySpan source = colors;
int destIndex = 0;
int pixRowSize = width * 4;
+ uint unsignedGlobalIndex = unchecked((uint)globalIndex);
+
if(index4 == null)
{
byte[] pixelData = new byte[width * height * 4];
@@ -47,7 +49,7 @@ public static Image Create(string name, uint globalIndex, int width, int height,
}
}
- return new ColorTexture(width, height, pixelData, name, globalIndex);
+ return new ColorTexture(width, height, pixelData, name, unsignedGlobalIndex);
}
else
{
@@ -67,11 +69,16 @@ public static Image Create(string name, uint globalIndex, int width, int height,
}
}
- return new IndexTexture(width, height, pixelData, name, globalIndex)
+ return new IndexTexture(width, height, pixelData, name, unsignedGlobalIndex)
{
IsIndex4 = index4.Value
};
}
}
+
+ public static int ToSigned(uint number)
+ {
+ return unchecked((int)number);
+ }
}
}