# Material Library And Targeted Viewport Drop

Working implementation plan for Gitea issues
[`#16`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/16) and
[`#18`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/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.
