Blacksite/.cursor/plans/material_library_and_targeted_drop_2026-07-12.plan.md

5.7 KiB

Material Library And Targeted Viewport Drop

Working implementation plan for Gitea issues #16 and #18. The shared Material/Material Instance and stable renderer-slot foundation from #51 is already present; this slice completes the production-facing catalog and drag/drop workflow.

Status

Implemented on codex/material-library-targeted-drop after collaborative-safety #49 was published and integrated into main. Focused and full source-only verification plus live editor acceptance are green; ticket evidence remains before #16 / #18 close.

Resolved Gaps

  • The dockable Material Library now provides cross-folder Material/Instance catalog, usage counts, health, creation, thumbnails, drag sources, and the guarded existing details editors.
  • Viewport Material/Texture drops resolve the surface under the pointer and never broaden to the current selection or every renderer slot.
  • HydratedRendererMaterialBinding identifies the exact static/skinned renderer slot; primitives and stable brush-face IDs use their authored component paths.
  • Unsupported, locked, linked, missing, and payload-incompatible targets reject with an explicit reason and no scene mutation.
  • Hover previews are reversible, target changes restore the prior snapshot, and release records one typed operator/history transaction.
  • Viewport pointer tracking remains active while another egui widget owns the drag, so exact target resolution cannot stall at the viewport boundary.
  • Visibility hierarchy setup now precedes generated hydration content, preventing Bevy parent/child visibility warnings when brush draws are created after scene load.

Material Library

  1. Add a dockable Material Library panel, opened from Window and placed in the existing bottom dock without adding another permanent toolbar.
  2. Present project Materials and Material Instances with search, Material/Instance filter, thumbnail grid/list modes, base/dependency health, and source-control status.
  3. Add a scene-usage section that counts renderer-slot, primitive, and brush-face references and can select/locate users. Do not revive ambiguous hidden scene-local material clones.
  4. Reuse the existing guarded Material/Instance drafts for Apply, Revert, Create Instance, and texture-parameter editing. Shared-file edits remain explicit; scene assignment changes use history.
  5. Material and Instance cells are first-class drag sources and preserve the current pointer-following visual identity.

Targeted Drop Contract

Introduce a frame-updated ViewportAssetDropTarget resolved by the existing mesh-picking path:

  • A hydrated static/skinned draw maps through HydratedRendererMaterialBinding to the authored actor and exact stable slot ID.
  • A primitive maps to its authored actor-level MaterialDesc.
  • A brush performs authored face intersection and identifies the stable face ID.
  • An authored but unsupported target remains a visible invalid target with a specific reason.
  • Empty space remains placement-only for placeable assets and invalid for Material/Texture payloads.

Payload matrix:

Payload Renderer slot Primitive Brush face
Material / Material Instance Assign exact hit slot; one-slot actors may assign directly Replace actor material reference/values Replace the hit face material reference
Texture Reject with guidance to create/edit a Material Instance Set base-color texture Set hit-face base-color texture/material binding

An explicit Apply All Slots command remains available from the renderer inspector/library usage menu; a viewport hit never silently broadens from one slot to all slots.

Preview, Commit, And Cancel

  1. Start a persistent drop-preview session when a supported Material/Texture payload enters the viewport. Snapshot only the target's affected authored state.
  2. Apply a transient visual preview without pushing history or marking the scene dirty.
  3. When the pointer changes target, restore the previous snapshot before previewing the new target.
  4. On release, restore the transient state first, then commit exactly one typed history/operator transaction to the identified slot, primitive, or face.
  5. On Escape, drag cancellation, leaving the viewport, invalid target, or missing source, restore the exact snapshot and remove every preview/helper marker.
  6. The drag card and target outline name the payload, actor, slot/face, action, and invalid reason.

Verification

  • Focused tests cover exact multi-slot assignment/undo, brush-face-only preview/restore, primitive Material/Texture resolution, renderer Texture rejection, Material Library filtering, and scene usage counts.
  • Source checks include editor all-target check, focused tests, and strict editor Clippy.
  • Live acceptance covered the docked catalog, search/type/usage filters, grid/list views, resolved Material Instance thumbnails, exact primitive preview, green actor/surface feedback, one-step commit/undo, and Escape rollback. The same relaunch produced no hydration hierarchy warnings.
  • Static/skinned exact-slot, brush-face, locked/linked, incompatible Texture, and non-dirty preview contracts remain covered by focused automated tests; shared-asset file creation was deliberately not invoked during live QA to avoid adding throwaway authored files.
  • Full verification passed: workspace all-target check, strict workspace Clippy, all workspace tests, strict editor Clippy with both dev and hot-reload, level validation with zero blockers, and navigation artifact freshness. Packaged testing remains deferred until the project owner requests it again.