Repository navigation
Blender extension on mhp-formats and mhfu-port - #48
Merged
Merged
Conversation
… tests apps/blender is a Blender 4.2+ extension (mhfu_blender, GPL-3.0-or-later) with an empty class list for the operators to come. build.py stages the source with the dependency closure as pure wheels at uv.lock's pins (numpy, psutil and rabbitizer left out), writes version and wheels into the staged manifest and runs Blender's extension build and validate; `build.py test` installs the zip into a throwaway profile and runs apps/blender/tests inside Blender with a cached pytest. Outside Blender those tests skip. mypy reads fake-bpy-module's 4.2 stubs through its native parser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The inverse of fk.rig_clip. Both, and motion.split (which replaces the private _split in motion.build), deal tracks to parts through one fk.part_joints. A part keeps its own clip object, loop and extra tracks where the clip leaves them, so a read-and-write round trip is byte-identical: every slot of all 101 MHFU model PACs with an in-game anim. motion.frames and motion.filled replace slots.frames and verify.Port.slots' own copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ender The bpy- and Qt-free assembly of the studio's monster scene (groups, textures, clips, from_bytes, from_path) moves to mhfu_port.model, which imports nothing of mhfu, so a Blender extension can bundle it; a subprocess test blocks mhfu's live chain and imports what the extension uses. The studio's Scene subclasses Model and keeps the manifest, build id and pose. What it needed from the mhfu chain moves to mhfu-free homes: the record map to records.for_moveset, the donor file offsets GEO/ANIM to records, the PAC entry numbers to model (diff.py drops its copy), clip_key to model. A donor's moveset is an input, the emNNN file; from_path defaults it to the file two after the model PAC. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Between two keys the engine evaluates a cubic with the left key's ease_out and the right key's ease_in as slopes in raw units per frame; fk drew a straight line. Built ports are byte-identical; verify/stretch numbers and the studio's posed goldens between keys move (rewritten in the container). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…read with So a caller holding only the bytes (a .blend) can read the same model again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File > Import > MHFU Model (and the sidebar's MHFU tab) reads an MHFU model PAC, a built port or an MHP3rd model through mhfu_port.model: an armature whose bones rest unrotated so pose channels are the engine's, one mesh per PMO group with its skin, UVs, normals and textured materials, and an Action per clip whose Bezier keys draw the engine's spline. Action -> Clip reads an untouched Action back to its clip exactly; the armature keeps the source bytes so the .blend alone reads the model again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So an editor can rebuild a single group of an existing PMO. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An empty track collapses its joint's geometry; a track the part keyed comes back as rest(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… game A group with its vertex count and faces unchanged is written in place, weights over its own palette included; any other is rebuilt and the palette repatched for the groups after it. Edit Mode bone moves ship, a changed armature is refused, every slot's Action goes back through motion.put. An MHP3rd model exports as an MHFU PAC without clips. Push writes into the memory stick's inject folder: same size in place, larger for the relocate path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
quantize_weights rounds the largest remainders up, so a vertex whose weights sum to 1.0 sums to the unit exactly, as the games' own vertices do. quantize_vertices and the Blender extension's in-place weight write both go through it. The brute_tigrex and zinogre builds and every port digest are unchanged: their weights are already whole raw units. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Geometry carries each corner's UV; a vertex whose faces give it several keeps the first and is copied for each other, which rebuilds its group instead of dropping the edit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blender 4.2 shows about half the Tigrex's custom normals 3 to 8 degrees off the file's, so the import records each normal as shown, and a group written in place keeps every stored normal that has not moved from it. Byte-identical on 4.2, 4.5 and 5.2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The research Blender addon becomes a Blender 4.2+ extension in
apps/blender(GPL-3.0-or-later), onmhp-formatsandmhfu-port. For sp00ktober/MHFU-ModKit#70.mhfu_blender):emNNNmoveset.motion.put; unedited ones stay byte for byte.uv run apps/blender/build.pystages the version and the wheels fromuv.lock, then runsextension buildandvalidate.build.py testinstalls the zip into a throwaway profile and runsapps/blender/testsinside Blender. CI has no Blender, so those tests skip there.numpy>=1.24(Blender 4.2 to 5.0 bundle 1.24 or 1.26).mhfu_port.modelis the studio's loader, now shared. It stays free ofmhfu, and a test enforces that.motion.putis the inverse offk.rig_clip.fk.Curvesnow uses the engine's cubic spline with the key eases (EU0x088630D0) instead of linear interpolation. Between keys, linear was off by up to ~430 units.verify's tear and stretch figures move a little.quantize_weightsmakes a vertex's weights sum to 128, as native data does. Built ports are unchanged.native_parser = true, because thebpystubs use 3.12 generics. mypy calls this option experimental.The issue's bugs:
Pmo.to_bytes.2, 4, 6, 7. Geometry, skeletons, textures and vertex scale are fixed by the shared loader.
Pmo.materialis confirmed by render. The 284 unexplained groups were the old walker's 0x20 stride reading Khezu and Red Khezu group records as a fifth mesh.Tested:
brute_tigrexandzinogrebuilds byte for byte on all three Blenders.🤖 Generated with Claude Code