Skip to content

Commit

Permalink
s
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Jan 7, 2024
1 parent 1109f57 commit 840d437
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 81 deletions.
8 changes: 4 additions & 4 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

from ..sm64_constants import MAX_U16

from .utility import RomReading, updateHeaderVariantNumbers
from ...utility import PluginError, decodeSegmentedAddr, toAlnum
from .utility import RomReading, readArrayToStructDict, updateHeaderVariantNumbers
from ...utility import PluginError, decodeSegmentedAddr, is_bit_active, toAlnum


@dataclasses.dataclass
Expand Down Expand Up @@ -85,14 +85,14 @@ def toHeaderProps(self, action, header):

correctFrameRange = self.startFrame, self.loopStart, self.loopEnd
header.startFrame, header.loopStart, header.loopEnd = correctFrameRange
if correctFrameRange != header.getFrameRange(): # If auto frame range is wrong
if correctFrameRange != header.getFrameRange(action): # If auto frame range is wrong
header.manualFrameRange = True

header.yDivisor = self.yDivisor

if isinstance(self.flags, int):
header.customIntFlags = hex(self.flags)
cFlags = [flag for bit, flag in intFlagsToString.items() if isBitActive(self.flags, bit)]
cFlags = [flag for bit, flag in intFlagsToString.items() if is_bit_active(self.flags, bit)]
header.customFlags = " | ".join(cFlags)
for cFlag in cFlags:
if cFlag in intFlagsToProps:
Expand Down
7 changes: 3 additions & 4 deletions fast64_internal/sm64/animation/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
]

enumAnimBinaryImportTypes = [
("DMA", "DMA (Mario)", "Import a DMA animation from a ROM"),
("Table", "Table", "Import a DMA animation from a ROM"),
("Animation", "Animation", "Import a DMA animation from a ROM"),
("DMA", "DMA (Mario)", "Import a DMA animation from a DMA table from a ROM"),
("Table", "Table", "Import animations from an animation table from a ROM"),
("Animation", "Animation", "Import one animation from a ROM"),
]

enumAnimImportTypes = [
("C", "C", "Import a decomp folder or a specific animation"),
("Binary", "Binary", "Import from ROM"),
("glTF", "glTF", "Import from glTF"),
]

marioAnimationNames = [
Expand Down
109 changes: 65 additions & 44 deletions fast64_internal/sm64/animation/importing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import math
import bpy
from typing import Optional
import mathutils
import bpy
from bpy.types import Object

from ...utility import PluginError, decodeSegmentedAddr
from ...utility_anim import stashActionInArmature
Expand Down Expand Up @@ -93,18 +95,17 @@ def readRotation(self, pairs: list[SM64_AnimPair]):
self.rotation.append(e.to_quaternion())


def animationTableToBlender(context: bpy.types.Context, tableList: list["SM64_AnimHeader"]):
tableElements = context.scene.fast64.sm64.anim_export.table.elements
def animation_table_to_blender(table_elements, tableList: list["SM64_AnimHeader"]):
for header in tableList:
tableElements.add()
tableElements[-1].action = bpy.data.actions[header.data.actionName]
tableElements[-1].headerVariant = header.headerVariant
table_elements.add()
table_elements[-1].action = bpy.data.actions[header.data.actionName]
table_elements[-1].headerVariant = header.headerVariant


def animationDataToBlender(armatureObj: bpy.types.Object, blender_to_sm64_scale: float, anim_import: SM64_Anim):
animBonesInfo = get_anim_pose_bones(armatureObj)
for boneInfo in animBonesInfo:
boneInfo.poseBone.rotation_mode = "QUATERNION"
anim_bones = get_anim_pose_bones(armatureObj)
for pose_bone in anim_bones:
pose_bone.rotation_mode = "QUATERNION"

action = bpy.data.actions.new("")
anim_import.toAction(action)
Expand All @@ -128,81 +129,101 @@ def animationDataToBlender(armatureObj: bpy.types.Object, blender_to_sm64_scale:
boneAnimData.append(bone)

isRootTranslation = True
for boneInfo, boneData in zip(animBonesInfo, boneAnimData):
for pose_bone, boneData in zip(anim_bones, boneAnimData):
if isRootTranslation:
for propertyIndex in range(3):
fcurve = action.fcurves.new(
data_path='pose.bones["' + boneInfo.name + '"].location',
data_path='pose.bones["' + pose_bone.name + '"].location',
index=propertyIndex,
action_group=boneInfo.name,
action_group=pose_bone.name,
)
for frame in range(len(boneData.translation)):
fcurve.keyframe_points.insert(frame, boneData.translation[frame][propertyIndex])
isRootTranslation = False

for propertyIndex in range(4):
fcurve = action.fcurves.new(
data_path='pose.bones["' + boneInfo.name + '"].rotation_quaternion',
data_path='pose.bones["' + pose_bone.name + '"].rotation_quaternion',
index=propertyIndex,
action_group=boneInfo.name,
action_group=pose_bone.name,
)
for frame in range(len(boneData.rotation)):
fcurve.keyframe_points.insert(frame, boneData.rotation[frame][propertyIndex])
return action


def importBinaryAnimations(importProps, ROMData, dataDict, tableList):
address = int(importProps.address, 16)

levelParsed: SM64_Level = parseLevelAtPointer(ROMData, level_pointers[importProps.level])
def importBinaryAnimations(
address: int,
is_segmented_pointer: bool,
level: str,
import_type: str,
read_entire_table: bool,
table_index: int,
dma_table_address: int,
ROMData,
dataDict,
tableList,
):
levelParsed: SM64_Level = parseLevelAtPointer(ROMData, level_pointers[level])
segmentData: dict[int, tuple[int, int]] = levelParsed.segmentData
if importProps.isSegmentedPointer():
if is_segmented_pointer:
address = decodeSegmentedAddr(address.to_bytes(4, "big"), segmentData)

if importProps.binaryImportType == "Table":
importBinaryTable(
ROMData, address, importProps.readEntireTable, importProps.tableIndex, segmentData, dataDict, tableList
)
elif importProps.binaryImportType == "DMA":
if import_type == "Table":
importBinaryTable(ROMData, address, read_entire_table, table_index, segmentData, dataDict, tableList)
elif import_type == "DMA":
importBinaryDMAAnimation(
ROMData,
int(importProps.DMATableAddress, 16),
importProps.tableIndex if importProps.marioAnimation == -1 else importProps.marioAnimation,
importProps.readEntireTable,
dma_table_address,
table_index,
read_entire_table,
dataDict,
tableList,
)
elif importProps.binaryImportType == "Animation":
elif import_type == "Animation":
importBinaryHeader(ROMData, address, False, segmentData, dataDict)
else:
raise PluginError("Unimplemented binary import type.")


def importAnimationToBlender(context: bpy.types.Context):
sm64Props = context.scene.fast64.sm64
importProps = sm64Props.anim_import

armatureObj: bpy.types.Object = context.selected_objects[0]

def importAnimationToBlender(
armature_obj: Object,
import_type: str,
sm64_to_blender_scale: float,
table_elements,
c_path: Optional[str] = None,
import_rom_path: Optional[str] = None,
address: Optional[int] = None,
is_segmented_pointer: Optional[bool] = None,
level: Optional[str] = None,
binary_import_type: Optional[str] = None,
read_entire_table: Optional[bool] = None,
table_index: Optional[int] = None,
dma_table_address: Optional[int] = None,
):
dataDict: dict[str, SM64_Anim] = {}
tableList: list[str] = []

animationOperatorChecks(context, False)

if importProps.importType == "Binary":
import_rom_checks(sm64Props.import_rom)
with open(bpy.path.abspath(sm64Props.import_rom), "rb") as ROMData:
if import_type == "Binary":
import_rom_checks(import_rom_path)
with open(import_rom_path, "rb") as ROMData:
importBinaryAnimations(
importProps,
address,
is_segmented_pointer,
level,
binary_import_type,
read_entire_table,
table_index,
dma_table_address,
ROMData,
dataDict,
tableList,
)
elif importProps.importType == "C":
importCAnimations(importProps.path, dataDict, tableList)
elif import_type == "C":
importCAnimations(c_path, dataDict, tableList)
else:
raise PluginError("Unimplemented Import Type.")

for dataKey, data in dataDict.items():
animationDataToBlender(armatureObj, sm64Props.blender_to_sm64_scale, data)
animationTableToBlender(context, tableList)
animationDataToBlender(armature_obj, sm64_to_blender_scale, data)
animation_table_to_blender(table_elements, tableList)
29 changes: 22 additions & 7 deletions fast64_internal/sm64/animation/operators.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import cProfile
import math
import os
import bpy
from bpy.utils import register_class, unregister_class
from bpy.path import abspath
from bpy.props import (
EnumProperty,
FloatProperty,
StringProperty,
IntProperty,
)

from .reading import importBinaryDMAAnimation
from .importing import animationDataToBlender, animationTableToBlender, importAnimationToBlender
from .importing import animationDataToBlender, animation_table_to_blender, importAnimationToBlender

from .exporting import (
exportAnimation,
Expand Down Expand Up @@ -307,7 +308,7 @@ def execute_operator(self, context):
dataDict: dict[str, "SM64_Anim"] = {}
tableList: list["SM64_AnimHeader"] = []

if importProps.importType == "Binary":
if importProps.import_type == "Binary":
with open(bpy.path.abspath(sm64Props.import_rom), "rb") as ROMData:
for entrieStr, name, description in marioAnimationNames[1:]:
header = importBinaryDMAAnimation(
Expand All @@ -325,7 +326,7 @@ def execute_operator(self, context):

for dataKey, data in dataDict.items():
animationDataToBlender(armatureObj, sm64Props.blender_to_sm64_scale, data)
animationTableToBlender(context, tableList)
animation_table_to_blender(context, tableList)

return {"FINISHED"}

Expand All @@ -344,9 +345,23 @@ class SM64_ImportAnim(bpy.types.Operator):

def execute(self, context):
try:
animationOperatorChecks(context, False)
importAnimationToBlender(context)

sm64_props = context.scene.fast64.sm64
anim_import_props = sm64_props.anim_import
importAnimationToBlender(
context.selected_objects[0],
anim_import_props.import_type,
sm64_props.blender_to_sm64_scale,
sm64_props.anim_export.table.elements,
abspath(anim_import_props.path),
abspath(sm64_props.import_rom),
int(anim_import_props.address, 16),
anim_import_props.isSegmentedPointer(),
anim_import_props.level,
anim_import_props.binary_import_type,
anim_import_props.read_entire_table,
anim_import_props.tableIndex,
int(anim_import_props.DMATableAddress, 16)
)
self.report({"INFO"}, "Success!")
return {"FINISHED"}
except Exception as e:
Expand Down
2 changes: 1 addition & 1 deletion fast64_internal/sm64/animation/panels.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def draw(self, context: bpy.types.Context):
class SM64_ImportAnimPanel(SM64_Panel):
bl_idname = "SM64_PT_import_anim"
bl_label = "SM64 Animation Importing"
goal = "Export Object/Actor/Anim"
goal = "Import"
isImport = True

def draw(self, context: bpy.types.Context):
Expand Down
26 changes: 13 additions & 13 deletions fast64_internal/sm64/animation/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -640,16 +640,16 @@ def draw_props(self, context: bpy.types.Context, layout: bpy.types.UILayout):
class SM64_AnimImportProps(bpy.types.PropertyGroup):
"""Scene SM64 animation import properties found under scene.fast64.sm64.anim_import"""

importType: EnumProperty(items=enumAnimImportTypes, name="Import Type", default="C")
import_type: EnumProperty(items=enumAnimImportTypes, name="Import Type", default="C")

binaryImportType: EnumProperty(items=enumAnimBinaryImportTypes, name="Binary Import Type", default="Animation")
binary_import_type: EnumProperty(items=enumAnimBinaryImportTypes, name="Type", default="Animation")

address: StringProperty(name="Address", default="4EC690")
isSegPtr: BoolProperty(name="Is Segmented Address")
level: EnumProperty(items=level_enums, name="Level", default="IC")

# Table
readEntireTable: BoolProperty(name="Read All Animations", default=False)
read_entire_table: BoolProperty(name="Read All Animations", default=False)
tableIndex: IntProperty(name="Table Index", min=0)

# DMA
Expand All @@ -659,10 +659,10 @@ class SM64_AnimImportProps(bpy.types.PropertyGroup):
path: StringProperty(name="Path", subtype="FILE_PATH", default="U:/home/user/sm64/assets/anims/")

def isBinaryImport(self):
return self.importType == "Binary"
return self.import_type == "Binary"

def isSegmentedPointer(self):
return self.importType == "Binary" and self.binaryImportType != "DMA" and self.isSegPtr
return self.import_type == "Binary" and self.binary_import_type != "DMA" and self.isSegPtr

def drawBinaryAddress(self, layout: bpy.types.UILayout):
col = layout.column()
Expand All @@ -674,13 +674,13 @@ def drawBinary(self, layout: bpy.types.UILayout):

col.operator(SM64_ImportAllMarioAnims.bl_idname)

prop_split(col, self, "binaryImportType", "Binary Import Type")
prop_split(col, self, "binary_import_type", "Type")

if self.binaryImportType == "DMA":
if self.binary_import_type == "DMA":
prop_split(col, self, "DMATableAddress", "DMA Table Address")

col.prop(self, "readEntireTable")
if not self.readEntireTable:
col.prop(self, "read_entire_table")
if not self.read_entire_table:
col.operator(SM64_SearchMarioAnimEnum.bl_idname, icon="VIEWZOOM")
if self.marioAnimation == -1:
prop_split(col, self, "tableIndex", "Entry")
Expand All @@ -690,9 +690,9 @@ def drawBinary(self, layout: bpy.types.UILayout):
prop_split(col, self, "level", "Level")
self.drawBinaryAddress(col.box())

if self.binaryImportType == "Table":
col.prop(self, "readEntireTable")
if not self.readEntireTable:
if self.binary_import_type == "Table":
col.prop(self, "read_entire_table")
if not self.read_entire_table:
prop_split(col, self, "tableIndex", "List Index")

def drawC(self, layout: bpy.types.UILayout):
Expand All @@ -701,7 +701,7 @@ def drawC(self, layout: bpy.types.UILayout):

def draw_props(self, layout: bpy.types.UILayout):
col = layout.column()
col.prop(self, "importType")
col.prop(self, "import_type")

box = col.box().column()
if self.isBinaryImport():
Expand Down
Loading

0 comments on commit 840d437

Please sign in to comment.