Skip to content

Commit

Permalink
a
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 committed Jan 7, 2024
1 parent 840d437 commit ac54378
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 204 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"last_check": "",
"backup_date": "",
"update_ready": false,
"ignore": false,
"just_restored": false,
"just_updated": false,
"version_text": {}
}
7 changes: 4 additions & 3 deletions fast64_internal/sm64/animation/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,11 @@ def toAction(self, action):

actionProps.customMaxFrame = max([1] + [len(x.values) for x in self.pairs])

for header in self.headers:
for i in range(len(self.headers) - 1):
actionProps.header_variants.add()
headerProps = actionProps.header_variants[-1]
header.toHeaderProps(action, headerProps)

for header, header_props in zip(self.headers, actionProps.get_headers()):
header.toHeaderProps(action, header_props)

updateHeaderVariantNumbers(actionProps.header_variants)

Expand Down
194 changes: 178 additions & 16 deletions fast64_internal/sm64/animation/importing.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import dataclasses
import math
from typing import Optional
import os
from typing import BinaryIO, Optional
import mathutils
import bpy
from bpy.types import Object

from ...utility import PluginError, decodeSegmentedAddr
from ...utility import PluginError, decodeSegmentedAddr, path_checks
from ...utility_anim import stashActionInArmature
from ..sm64_utility import import_rom_checks
from .utility import animationOperatorChecks, get_anim_pose_bones, sm64ToRadian

from .classes import SM64_Anim, SM64_AnimPair
from .reading import (
importBinaryDMAAnimation,
importBinaryHeader,
importBinaryTable,
importCAnimations,
)
from .utility import CArrayReader, RomReading, get_anim_pose_bones, sm64ToRadian

from .classes import SM64_Anim, SM64_AnimHeader, SM64_AnimPair

from ..sm64_level_parser import SM64_Level, parseLevelAtPointer
from ..sm64_constants import (
Expand Down Expand Up @@ -159,7 +155,6 @@ def importBinaryAnimations(
import_type: str,
read_entire_table: bool,
table_index: int,
dma_table_address: int,
ROMData,
dataDict,
tableList,
Expand All @@ -174,7 +169,7 @@ def importBinaryAnimations(
elif import_type == "DMA":
importBinaryDMAAnimation(
ROMData,
dma_table_address,
address,
table_index,
read_entire_table,
dataDict,
Expand All @@ -186,7 +181,176 @@ def importBinaryAnimations(
raise PluginError("Unimplemented binary import type.")


def importAnimationToBlender(
def importBinaryHeader(
ROMData: BinaryIO,
headerAddress: int,
isDMA: bool,
segmentData: dict[int, tuple[int, int]],
dataDict: dict[str, SM64_Anim],
):
header = SM64_AnimHeader()
header.readBinary(ROMData, headerAddress, segmentData, isDMA)

dataKey: str = f"{header.indices}-{header.values}"
if dataKey in dataDict:
data = dataDict[dataKey]
else:
data = SM64_Anim()
data.readBinary(ROMData, header)
dataDict[dataKey] = data

header.headerVariant = len(data.headers)
header.data = data
data.headers.append(header)
return header


@dataclasses.dataclass
class DMATableEntrie:
offsetFromTable: int
address: int
size: int


def readBinaryDMATableEntries(ROMData: BinaryIO, address: int) -> list[DMATableEntrie]:
entries: list[DMATableEntrie] = []
DMATableReader = RomReading(ROMData, address)

numEntries = DMATableReader.readValue(4)
addrPlaceholder = DMATableReader.readValue(4)

for i in range(numEntries):
offset = DMATableReader.readValue(4)
size = DMATableReader.readValue(4)
entries.append(DMATableEntrie(offset, address + offset, size))
return entries


def importBinaryDMAAnimation(
ROMData: BinaryIO,
address: int,
entrieNum: int,
read_entire_table: bool,
dataDict: dict[str, SM64_Anim],
tableList: list[SM64_Anim],
):
entries: list[DMATableEntrie] = readBinaryDMATableEntries(ROMData, address)
if read_entire_table:
for entrie in entries:
header = importBinaryHeader(ROMData, entrie.address, True, None, dataDict)
tableList.append(header)
else:
if not (0 <= entrieNum < len(entries)):
raise PluginError("Entrie outside of defined table.")

entrie: DMATableEntrie = entries[entrieNum]
header = importBinaryHeader(ROMData, entrie.address, True, None, dataDict)
tableList.append(header)
return header


def importBinaryTable(
ROMData: BinaryIO,
address: int,
read_entire_table: bool,
tableIndex: int,
segmentData: dict[int, tuple[int, int]],
dataDict: dict[str, SM64_Anim],
tableList: list[SM64_Anim],
):
for i in range(255):
ROMData.seek(address + (4 * i))
ptr = int.from_bytes(ROMData.read(4), "big", signed=False)
if ptr == 0:
if not read_entire_table:
raise PluginError("Table Index not in table.")
break

isCorrectIndex = not read_entire_table and i == tableIndex
if read_entire_table or isCorrectIndex:
ptrInBytes: bytes = ptr.to_bytes(4, "big")
if ptrInBytes[0] not in segmentData:
raise PluginError(
f"\
Header at table index {i} located at {ptr} does not belong to the current segment."
)
headerAddress = decodeSegmentedAddr(ptrInBytes, segmentData)

header = importBinaryHeader(ROMData, headerAddress, False, segmentData, dataDict)
tableList.append(header)

if isCorrectIndex:
break
else:
raise PluginError(
"\
Table address is invalid, iterated through 255 indices and no NULL was found."
)


def importAnimation(dataDict, array: "ReadArray", arrays: list["ReadArray"]):
print(f"Reading animation {array.name}")
header = SM64_AnimHeader()
header.readC(array)
print(header)

dataKey: str = f"{header.indices}-{header.values}"
if dataKey in dataDict:
data: SM64_Anim = dataDict[dataKey]
else:
data = SM64_Anim()
data.readC(header, arrays)
dataDict[dataKey] = data

header.headerVariant = len(data.headers)
header.data = data
data.headers.append(header)

return header


def importCAnimations(
path: str,
dataDict: dict[str, SM64_Anim],
tableList: list[SM64_Anim],
):
path_checks(path)

if os.path.isfile(path):
filePaths: list[str] = [path]
elif os.path.isdir(path):
fileNames = os.listdir(path)
filePaths: list[str] = [os.path.join(path, fileName) for fileName in fileNames]
else:
raise PluginError(f"Path ({path}) is not a file or a directory.")

filePaths.sort()

print("Reading arrays in path")

arrays: dict[ReadArray] = {}
for filePath in filePaths:
if not filePath.endswith(".c"):
continue

print(f"Reading file {filePath}")
with open(filePath, "r") as file:
arrayReader = CArrayReader()
arrays.update(arrayReader.findAllCArraysInFile(file.read(), filePath))

header = None
for array in arrays.values():
if "*const" in array.keywords or "Animation*" in array.keywords: # Table
continue
elif not "Animation" in array.keywords:
continue
header = importAnimation(dataDict, array, arrays)
tableList.append(header)

return header


def import_animation_to_blender(
armature_obj: Object,
import_type: str,
sm64_to_blender_scale: float,
Expand All @@ -199,7 +363,6 @@ def importAnimationToBlender(
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] = []
Expand All @@ -214,7 +377,6 @@ def importAnimationToBlender(
binary_import_type,
read_entire_table,
table_index,
dma_table_address,
ROMData,
dataDict,
tableList,
Expand Down
19 changes: 13 additions & 6 deletions fast64_internal/sm64/animation/operators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import cProfile
import math
import os
import bpy
Expand All @@ -10,8 +9,12 @@
IntProperty,
)

from .reading import importBinaryDMAAnimation
from .importing import animationDataToBlender, animation_table_to_blender, importAnimationToBlender
from .importing import (
importBinaryDMAAnimation,
animationDataToBlender,
animation_table_to_blender,
import_animation_to_blender,
)

from .exporting import (
exportAnimation,
Expand Down Expand Up @@ -347,20 +350,24 @@ def execute(self, context):
try:
sm64_props = context.scene.fast64.sm64
anim_import_props = sm64_props.anim_import
importAnimationToBlender(

animationOperatorChecks(context, False)

import_animation_to_blender(
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),
int(anim_import_props.DMATableAddress, 16)
if anim_import_props.binary_import_type == "DMA"
else 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"}
Expand Down
3 changes: 2 additions & 1 deletion fast64_internal/sm64/animation/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
StringProperty,
EnumProperty,
IntProperty,
FloatProperty,
CollectionProperty,
PointerProperty,
)
Expand Down Expand Up @@ -47,6 +46,7 @@
customExportWarning,
decompFolderMessage,
makeWriteInfoBox,
path_ui_warnings,
prop_split,
writeBoxExportType,
)
Expand Down Expand Up @@ -698,6 +698,7 @@ def drawBinary(self, layout: bpy.types.UILayout):
def drawC(self, layout: bpy.types.UILayout):
col = layout.column()
col.prop(self, "path")
path_ui_warnings(col, self.path)

def draw_props(self, layout: bpy.types.UILayout):
col = layout.column()
Expand Down
Loading

0 comments on commit ac54378

Please sign in to comment.