-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OoT/MM] Support ZAPD bone enums for skeleton import (#396)
* Ignore IntelliJ editor data * [OoT] Add skeleton import test scripts In preparation for fixing skeleton imports from the MM decomp, make a script for testing skeleton imports. Running `python3 scripts/make_all_skeletons.py <decomp path> <output folder>` will attempt to import all skeletons from every file in the decomp that appears to contain a skeleton, and report on how many files raised exceptions during the import. The generated .blend files are stored in the output folder. Including a third argument of ` will attempt to import all animations for files that contain a single skeleton as well. Running this on the mm decomp at commit 803ff1fb1593cdc0c62d14882973af04dc0f988e (from 2024-07-13) results in only 3/174 (1.7%) of files with skeletons importing them without exceptions. * [OoT] Strip comments in limb list The MM decomp specifies `EnumName` values for limbs in the asset XML, which generates an enum naming bone indicies. These enum values are also generated in comments in the limb list: void* gDekuButlerSkelLimbs[] = { &gDekuButlerRootLimb, /* DEKU_BUTLER_LIMB_ROOT */ Fast64's current limb list parsing does not expect comments here, which causes the limb list parse to fail. Add a function to strip comments of this style, and strip them before parsing limb list entires. * [OoT] Identify and parse enums when importing skeletnos The MM decomp defines EnumNames for limbs in asset XML, which causes ZAPD to generate limb definitions that use these enum values for the next child and next sibling (with an offset of 1). StandardLimb gDekuButlerRootLimb = { { 0, 2775, 0 }, DEKU_BUTLER_LIMB_PELVIS - 1, LIMB_DONE, ootGetLimb currently only supports int values, hex values, or LIMB_DONE here. In preparation for supporting limb enum values of this form, add the object's header file to skeletonData and parse all enums found during skeleton import. The next patch in this series will use the parsed enums to handle limb definitions of this form. * [OoT] Support limb enums for limb nextChild / nextSibling Use the parsed enums to support next child and next sibling definitions of the form `<limb enum value> - 1`. With this change and the others from this patch series, `make_all_skeletons.py` goes from just 3/174 (1.1%) of MM decomp files with successful skeleton imports to 169/174 (97.1%).
- Loading branch information
Showing
6 changed files
with
304 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ __pycache__/ | |
/.venv | ||
fast64_updater/ | ||
.python-version | ||
|
||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import re | ||
import subprocess | ||
import sys | ||
import shutil | ||
|
||
from pathlib import Path | ||
from typing import List | ||
|
||
""" | ||
A test script to try import skeletons (and optionally animations) in a decomp | ||
folder, generating .blend files for file, and report on successes & failures. | ||
WARNING: the specified output folder is unconditionally deleted before generating | ||
new output! | ||
Usage: | ||
python3 make_all_skeletons.py <path to decomp> <output folder> ["1" to import animations too] | ||
Example: | ||
python3 make_all_skeletons.py ~/git/mm blend-files 1 | ||
""" | ||
|
||
|
||
def main(): | ||
filePaths: List[Path] = [] | ||
failFiles: List[Path] = [] | ||
successFiles: List[Path] = [] | ||
|
||
print(f"args {sys.argv}") | ||
decompPath = Path(sys.argv[1]) | ||
outputPath = Path(sys.argv[2]) | ||
importAnimations = len(sys.argv) > 3 and sys.argv[3] == "1" | ||
|
||
# Delete the output folder if it already exists | ||
if outputPath.exists(): | ||
shutil.rmtree(outputPath) | ||
|
||
# populate filePaths with paths to all files in the decomp | ||
# that appear to contain a skeleton | ||
for inPath in (Path(decompPath) / "assets" / "objects").rglob("*.c"): | ||
with open(inPath, "r") as file: | ||
contents = file.read() | ||
if re.search(r"(Flex)?SkeletonHeader\s*(?P<name>[A-Za-z0-9\_]+)\s*=", contents) is not None: | ||
filePaths.append(inPath) | ||
|
||
for i, inPath in enumerate(filePaths): | ||
# Generate the output path as a subdir in the output folder with the same structure | ||
# as the file's location in the decomp | ||
outPath: Path = outputPath.joinpath(*inPath.parts[len(decompPath.parts) :]).with_suffix(".blend") | ||
objectName = inPath.parts[-2] | ||
|
||
# Make sure all the subdirs exist | ||
outPath.parent.mkdir(parents=True, exist_ok=True) | ||
|
||
# Run make_skeletons.py in blender to build the .blend file | ||
args = [ | ||
"blender", | ||
"--background", | ||
"--python-exit-code", # note: python-exit-code MUST come before python, or you'll always get 0! | ||
"1", | ||
"--python", | ||
"make_skeletons.py", | ||
"--", | ||
decompPath, | ||
inPath, | ||
outPath, | ||
objectName, | ||
] | ||
|
||
if importAnimations: | ||
args.append("1") | ||
|
||
res = subprocess.run(args) | ||
|
||
if res.returncode == 0: | ||
successFiles.append(inPath) | ||
else: | ||
failFiles.append(inPath) | ||
print("! Failed") | ||
|
||
# Report progress | ||
print(f"Progress: {i + 1}/{len(filePaths)} done") | ||
percentSuccessful = round(len(successFiles) / len(filePaths) * 100, 1) | ||
percentFailed = round(len(failFiles) / len(filePaths) * 100, 1) | ||
print(f"\tSuccessful: {len(successFiles)} {percentSuccessful:.1f}%") | ||
print(f"\tFailed: {len(failFiles)} {percentFailed:.1f}%", flush=True) | ||
|
||
# After all imports have been tried, list all the files with any failures | ||
print("Files with failures:") | ||
print("\n".join(str(f) for f in failFiles)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.