Skip to content

Commit

Permalink
hold off cowboy
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Jan 18, 2024
1 parent 56f4272 commit 759c6bc
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 58 deletions.
70 changes: 37 additions & 33 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,22 @@

@dataclasses.dataclass
class SM64_AnimHeader:
data: "SM64_Anim" = None

name: str = None
address: int = None
origin_path: str = ""
header_variant: int = 0
flags: str | int = None

flags: int = 0
custom_flags: int = ""
trans_divisor: int = 0
start_frame: int = 0
loop_start: int = 0
loop_end: int = 1
bone_count: int = None
values: str = ""
indices: str = ""
data: "SM64_Anim" = None

def toC(self, designated: bool, asArray: bool) -> str:
headerData: list[tuple[str, object]] = [
Expand Down Expand Up @@ -189,17 +192,16 @@ def readC(self):

@dataclasses.dataclass
class SM64_AnimPair:
maxFrame: int = 1
values: list[int] = dataclasses.field(default_factory=list)

def appendFrame(self, value: int):
if len(self.values) >= 1:
lastValue = self.values[-1]
def clean_frames(self):
last_value = self.values[-1]

if abs(value - lastValue) > 1:
self.maxFrame = len(self.values) + 1

self.values.append(value)
i = 1
for i, value in enumerate(reversed(self.values)):
if value != last_value:
break
self.values = self.values[:-i]

def getFrame(self, frame: int):
if frame < len(self.values):
Expand All @@ -214,7 +216,7 @@ def read_binary(self, indicesReader: RomReading, data: bytes, valuesAdress: int)
valueReader = RomReading(data, valuesAdress + valueOffset)
for _ in range(maxFrame):
value = valueReader.read_value(2, signed=True)
self.appendFrame(value)
self.values.append(value)

def readC(self, maxFrame, offset, values: list[int]):
for frame in range(maxFrame):
Expand All @@ -234,52 +236,52 @@ class SM64_Anim:
indicesReference: str = ""
valuesReference: str = ""
reference: bool = False
isDmaStructure: bool = False
headers: list[SM64_AnimHeader] = dataclasses.field(default_factory=list)
pairs: list[SM64_AnimPair] = dataclasses.field(default_factory=list)
actionName: str = None
fileName: str = None

def createTables(self, merge: bool) -> tuple[list[int], list[int]]:
def findOffset(addedIndexes: list, pairValues) -> int | None:
def create_tables(self, pairs: list[SM64_AnimPair]):
def find_offset(added_indices: list, pairValues) -> int | None:
offset: int | None = None
for addedIndex in addedIndexes:
for i, j in zip(pairValues[0 : len(addedIndex.values)], addedIndex.values[0 : len(pairValues)]):
offset = addedIndex.offset
for added_index in added_indices:
for i, j in zip(pairValues[0 : len(added_index.values)], added_index.values[0 : len(pairValues)]):
offset = added_index.offset
if abs(i - j) > 1:
offset = None
break
if len(addedIndex.values) < len(pairValues):
addedIndex.extend(pairValues[len(pairValues) - 1 :])
if len(added_index.values) < len(pairValues):
added_index.values.extend(pairValues[len(pairValues) - 1 :])
return offset

print("Merging values and creating tables.")

valueTable, indicesTable, addedIndexes = [], [], []
value_table, indices_table, added_indices = [], [], []

for pair in pairs:
max_frame: int = len(pair.values)
if max_frame > MAX_U16:
raise PluginError("Index pair´s max frame is too high. Too many frames.")

for pair in self.pairs:
maxFrame: int = pair.maxFrame
pairValues: list[int] = pair.values[0:maxFrame]
pairValues: list[int] = pair.values[0:max_frame]

existingOffset: int | None = None
if merge:
existingOffset = findOffset(addedIndexes, pairValues)
existing_offset = find_offset(added_indices, pairValues)

if existingOffset is None:
offset: int = len(valueTable)
if existing_offset is None:
offset: int = len(value_table)
pair.offset = offset
valueTable.extend(pairValues)
value_table.extend(pairValues)

addedIndexes.append(pair)
added_indices.append(pair)
else:
offset: int = existingOffset
offset: int = existing_offset

if offset > MAX_U16:
raise PluginError("Index pair´s value offset is too high. Value table might be too long.")

indicesTable.extend([maxFrame, offset])
indices_table.extend([max_frame, offset])

return valueTable, indicesTable
return value_table, indices_table

def headersToC(self, designated: bool, asArray: bool) -> str:
cData = StringIO()
Expand Down Expand Up @@ -389,6 +391,7 @@ def read_binary(self, data: bytes, header: SM64_AnimHeader):
for _ in range((header.bone_count + 1) * 3):
pair = SM64_AnimPair()
pair.read_binary(indicesReader, data, header.values)
pair.clean_frames()
self.pairs.append(pair)

def readC(self, header: SM64_AnimHeader, c_parser: CParser):
Expand All @@ -410,4 +413,5 @@ def readC(self, header: SM64_AnimHeader, c_parser: CParser):
maxFrame, offset = indices[i].value, indices[i + 1].value
pair = SM64_AnimPair()
pair.readC(maxFrame, offset, values)
pair.clean_frames()
self.pairs.append(pair)
23 changes: 14 additions & 9 deletions fast64_internal/sm64/animation/exporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def get_animation_pairs(
transXPair, transYPair, transZPair = pairs

rotationPairs: list[tuple[SM64_AnimPair]] = []
for boneInfo in animBonesInfo:
for _ in animBonesInfo:
xyzPairs = (
SM64_AnimPair(),
SM64_AnimPair(),
Expand All @@ -58,12 +58,15 @@ def get_animation_pairs(
for boneIndex, poseBone in enumerate(animBonesInfo):
if boneIndex == 0: # Only first bone has translation.
translation: mathutils.Vector = poseBone.location * scale
transXPair.appendFrame(int(translation.x))
transYPair.appendFrame(int(translation.y))
transZPair.appendFrame(int(translation.z))
transXPair.values.append(int(translation.x))
transYPair.values.append(int(translation.y))
transZPair.values.append(int(translation.z))

for angle, pair in zip(poseBone.matrix_basis.to_euler(), rotationPairs[boneIndex]):
pair.appendFrame(radian_to_sm64_degree(angle))
pair.values.append(radian_to_sm64_degree(angle))

for pair in pairs:
pair.clean_frames()

armature_obj.animation_data.action = pre_export_action
bpy.context.scene.frame_current = pre_export_frame
Expand Down Expand Up @@ -340,7 +343,11 @@ def getAnimationPaths(anim_export_props):


def get_animation_data(
armature_obj: Object, action: Action, blender_to_sm64_scale: float, is_dma_structure: bool, headers
armature_obj: Object,
action: Action,
blender_to_sm64_scale: float,
headers,
actor_name: str = "",
):
action_props = action.fast64.sm64

Expand All @@ -358,10 +365,8 @@ def get_animation_data(
else:
animation.pairs = get_animation_pairs(blender_to_sm64_scale, action, armature_obj, anim_bones)

animation.isDmaStructure = is_dma_structure

for header_props in headers:
animation.headers.append(header_props.to_header_class())
animation.headers.append(header_props.to_header_class(animation, action, actor_name))
return animation


Expand Down
13 changes: 11 additions & 2 deletions fast64_internal/sm64/animation/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .exporting import (
exportAnimation,
exportAnimationTable,
get_animation_data,
)
from .utility import (
animation_operator_checks,
Expand Down Expand Up @@ -272,9 +273,17 @@ def execute_operator(self, context):

armature_obj: Object = context.selected_objects[0]

exportAnimation(armature_obj, anim_export_props.selected_action, sm64_props.blender_to_sm64_scale)
action = anim_export_props.selected_action
sm64Anim = get_animation_data(
armature_obj,
action,
sm64_props.blender_to_sm64_scale,
action.fast64.sm64.get_headers(),
anim_export_props.actor_name,
)

self.report({"INFO"}, "Animation exported successfully")
return {"FINISHED"}

def execute(self, context: Context):
starting_context_mode = context.mode
Expand All @@ -292,7 +301,7 @@ def execute(self, context: Context):
applyRotation([armatureObj], math.radians(90), "X")

try:
self.execute_operator(context)
return self.execute_operator(context)
except Exception as e:
raisePluginError(self, e)
return {"CANCELLED"}
Expand Down
48 changes: 34 additions & 14 deletions fast64_internal/sm64/animation/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class SM64_AnimHeaderProps(PropertyGroup):
description="ANIM_FLAG_NO_TRANS\nSkips animation translation",
)
set_custom_flags: BoolProperty(name="Set Custom Flags")
custom_flags: StringProperty(name="Flags", default="ANIM_FLAG_UNUSED")
custom_flags: StringProperty(name="Flags", default="")

# Binary
dma_entry: IntProperty(name="DMA Entrie")
Expand Down Expand Up @@ -144,24 +144,45 @@ def copyHeader(self, actor_name, action, header: "SM64_AnimHeaderProps"):

self.custom_name = f"{header.get_anim_name(actor_name, action)}_variant{self.header_variant}"

def to_header_class(self, animation: SM64_Anim, actor_name: str, action: Action) -> SM64_AnimHeader:
def get_int_flags(header):
flags: int = 0
if header.no_loop:
flags |= 1 << 0
if header.backwards:
flags |= 1 << 1
if header.no_acceleration:
flags |= 1 << 2
if header.only_horizontal_trans:
flags |= 1 << 3
if header.only_vertical_trans:
flags |= 1 << 4
if header.disabled:
flags |= 1 << 5
if header.no_trans:
flags |= 1 << 6

return flags

def to_header_class(self, animation: SM64_Anim, action: Action, actor_name: str = "") -> SM64_AnimHeader:
header = SM64_AnimHeader()
header.data = animation
animation.headers.append(header)

header.name = self.get_anim_name(actor_name, action)
if animation.isDmaStructure or sm64Props.is_binary_export():
header.flags = getIntFlags(header_props)

if self.set_custom_flags:
header.custom_flags = self.custom_flags
else:
header.flags = getCFlags(header_props)
header.flags = self.get_int_flags()

startFrame, loopStart, loop_end = header_props.get_frame_range(action)
startFrame, loopStart, loop_end = self.get_frame_range(action)

header.trans_divisor = header_props.trans_divisor
header.trans_divisor = self.trans_divisor
header.startFrame = startFrame
header.loopStart = loopStart
header.loop_end = loop_end
header.bone_count = len(anim_bones)
header.bone_count = 0 # TODO: Pass bone count here

return header

def draw_binary(self, layout: UILayout, is_binary_dma: bool):
col = layout.column()
Expand All @@ -183,12 +204,11 @@ def draw_binary(self, layout: UILayout, is_binary_dma: bool):
def draw_flag_props(self, layout: UILayout, export_type: str):
col = layout.column()

if export_type == "C":
col.prop(self, "set_custom_flags")
col.prop(self, "set_custom_flags")

if self.set_custom_flags:
col.prop(self, "custom_flags")
return
if self.set_custom_flags:
col.prop(self, "custom_flags")
return

row = col.row()
row.prop(self, "no_acceleration")
Expand Down

0 comments on commit 759c6bc

Please sign in to comment.