Skip to content

BMD editor: editing, saving, and a real details UI - #382

Merged
donkeyProgramming merged 1 commit into
donkeyProgramming:masterfrom
robert-d-schultz:bmd-editor-editing-and-save
Aug 9, 2026
Merged

BMD editor: editing, saving, and a real details UI#382
donkeyProgramming merged 1 commit into
donkeyProgramming:masterfrom
robert-d-schultz:bmd-editor-editing-and-save

Conversation

@robert-d-schultz

Copy link
Copy Markdown
Contributor

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.

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>
@donkeyProgramming
donkeyProgramming merged commit d08ac07 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