Skip to content

Fix skeleton bone deletion reordering all bones - #383

Merged
donkeyProgramming merged 2 commits into
donkeyProgramming:masterfrom
robert-d-schultz:fix-skeleton-bone-delete-reorder
Aug 9, 2026
Merged

Fix skeleton bone deletion reordering all bones#383
donkeyProgramming merged 2 commits into
donkeyProgramming:masterfrom
robert-d-schultz:fix-skeleton-bone-delete-reorder

Conversation

@robert-d-schultz

Copy link
Copy Markdown
Contributor

GameSkeleton.DeleteBone renumbered every bone via a depth-first tree traversal, which doesn't necessarily match the skeleton's original bone order — deleting one bone could silently reorder every other bone's index. Now only the deleted bone (and its descendants) are removed; the rest keep their original relative order.

Added a regression test reproducing the reordering with an unrelated bone deletion.

robert-d-schultz and others added 2 commits August 3, 2026 19:00
The BMD editor was read-only: it parsed a .bmd and rendered a text dump of
every field. There was no writer at all, so nothing could be saved.

Format layer:
- Add BmdWriter, mirroring BmdParser section-for-section over the whole file
  (not just the editable categories), with a self-check that re-parses its own
  output before returning. Legacy/undocumented branches that the parser itself
  discards throw NotSupportedException rather than silently corrupting data.
- Capture data the parser previously read purely to advance the stream and then
  dropped, which a writer cannot reproduce otherwise: BmdFile.SectionVersions,
  PropInfo.PropIndex (prop string tables contain duplicate paths, so re-deriving
  an index can silently repoint a prop), and CultureMask.RawBytes (several bit
  positions map to no named field and would be zeroed on reconstruction).
- Fix BmdParser never populating BmdFile.Props (the shared prop string table was
  read and thrown away).
- Fix unreachable spotlight branch: `if (Version > 3) ... else if (Version > 4)`
  meant v>4 spotlights read a UInt32 PdlcMask instead of a UInt64, misaligning
  the stream by 4 bytes.

Editor:
- Implement ISaveableEditor with a Save button and dirty tracking.
- Per-category transform editing, exposing only the degrees of freedom the
  format actually stores: full TRS for props/decals/VFX/composite scenes and
  polymesh v>3; position+rotation for spot lights; position only for point
  lights, light probes, terrain hole vertices, sounds, and polymesh v<=3
  (bulk vertex offset). Transforms are edited as position / euler degrees /
  scale rather than raw matrices.
- Add BmdGizmoComponent (ported from CscGizmoComponent) driving the same
  properties, with rotate/scale gated to categories that support them.
- Replace the text-dump details panel with per-category templates of real
  controls, and make paths editable (prop model, VFX, sound event, polymesh
  material, composite scene file).
- Group the component tree into collapsible per-category sections and split
  decals out from props.
- Add an "Add" menu covering all ten categories, matching the CSC editor.
- Add Terry project export (.terry/.layer) via pack file context menu.
- Remove the unused BmdSceneView/Bmd3DSceneViewer/BmdSceneViewModel trio and
  the unreferenced BmdBmdReferenceKey class.

Verified: all 44 local .bmd files (36 campaign prefabs, 8 terrain tile_maps)
round-trip byte-for-byte identical; edits through the view models change only
the intended bytes; the ten Add-menu defaults write and re-parse correctly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GameSkeleton.DeleteBone rebuilt the entire bone list by re-numbering
every bone via a depth-first traversal of the parent/child tree. That
traversal order doesn't necessarily match the skeleton's original bone
order (siblings whose subtrees aren't contiguous in the flat list get
shuffled), so deleting one bone could silently reorder every other
bone's index. Rewritten to remove only the deleted bone (and its
descendants) while keeping the relative order of the remaining bones
unchanged.
@donkeyProgramming
donkeyProgramming merged commit 81ef26c into donkeyProgramming:master Aug 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants