Compare commits

..

6 Commits

Author SHA1 Message Date
634ec16c5e test(editor): satisfy strict thumbnail cache lint
Some checks failed
CI / Format, lint, test, build (push) Has been cancelled
2026-07-22 17:23:45 -04:00
cadb37341d test(editor): complete content browser fixtures 2026-07-22 17:20:54 -04:00
106d947c98 feat(editor): finalize M2 content workspace UX 2026-07-22 17:14:07 -04:00
93e23ba194 feat(editor): unify renderer materials and content browser shell
Some checks failed
CI / Format, lint, test, build (push) Has been cancelled
2026-07-18 14:05:26 -04:00
53dc1e44d8 feat: add production UI gallery and inspector system
Some checks are pending
CI / Format, lint, test, build (push) Waiting to run
2026-07-18 12:05:26 -04:00
cf6eaba534 feat: complete M2 content workspace and inspector 2026-07-17 23:40:49 -04:00
498 changed files with 71727 additions and 19346 deletions

View File

@ -0,0 +1,23 @@
---
name: blacksite-build-storage
description: Keep Blacksite Cargo and package build artifacts within a configured disk budget by selecting stable build lanes, measuring target/build directories, pruning only verified disposable caches, and preserving warm development performance. Use before or after heavy builds, when disk use grows, or when compile performance degrades from artifact accumulation.
---
# Blacksite build storage
Read `.codex/workflow.toml` and [the storage policy](references/build-storage-policy.md). Use `scripts/codex/cargo_lane.py` for every Cargo invocation and `scripts/codex/build_storage.py` for measurement or cleanup.
Trigger this Skill for candidate, all-feature, all-target, package, hot-reload, full-debug, cache-growth, low-space, unexplained rebuild, and cleanup requests.
- Keep one persistent `dev` lane. Candidate, hot-reload, full-debug, cross-target, and package lanes are exceptional and disposable.
- Use stable separate `CARGO_BUILD_BUILD_DIR` when supported; otherwise use bounded external `CARGO_TARGET_DIR` lanes.
- Account for repository final targets, external intermediates, package caches, Cargo timings/docs, free space, and an already-enabled `sccache`.
- Run storage preflight/postflight around heavy gates. When configured, pressure may prune only
expired disposable lanes after their complete checked plan is printed and flushed.
- Require valid sentinels, canonical workspace identity, no symlink traversal, and no active Cargo/rustc/linker/packager before deletion.
- Delete whole managed lanes only. Never delete individual Cargo internal files and never install cleanup/cache tools without explicit approval.
- Every apply prints and flushes its complete byte-counted checked plan before deletion begins.
- Preserve candidate binaries/packages and evidence outside the disposable lane, then establish the
generation-bound marker with `build_storage.py mark-candidate-preserved`; an absent, stale, or
hash-mismatched marker blocks candidate deletion.
- Report reclaimed bytes plus expected cold-build impact.

View File

@ -0,0 +1,27 @@
# Build-storage policy
The tracked limits live in `.codex/workflow.toml`. Defaults are a 55 GiB soft total, 80 GiB hard total, at least 40 GiB or 15% free space, a 40 GiB persistent-lane ceiling, and a 35 GiB ceiling per disposable lane.
The canonical workspace path is hashed so `/home/.../Bevy` and `/mnt/Fedora/.../Bevy` share one cache identity. Managed lanes carry a sentinel with workspace path/hash, lane, toolchain, feature/profile signature, target/build directories, and timestamps.
Enforcement order:
1. Report total/per-lane size and largest children.
2. Under storage pressure, print the checked byte plan and prune expired marked disposable lanes.
3. Prune stale package intermediates after preserving published output.
4. Remove non-evidence Cargo timing/doc output.
5. Block a new heavy gate if the hard limit or free-space floor still fails.
6. Reset the persistent lane only at a safe slice boundary, after a dry run and verification-ledger update.
`enforce --phase pre|post` automatically prunes only when tracked policy enables it, storage pressure
exists, and a disposable lane has expired. Automatic and explicit prune/reset paths first print and
flush the complete byte-counted plan, including sentinel, path, process, and preservation checks,
before deleting any lane. A candidate lane additionally requires
`.codex/session/candidate-prune-safe.json`, created only after preserved evidence and at least one
distinct binary/package file have been hashed with `mark-candidate-preserved`; any later candidate
lane use makes that generation-bound marker stale.
Never prune an active lane, an unmarked directory, a symlink, another workspace, `/`, home, Cargo
home, the workspace root, `.git`, or a parent of any protected path. `cargo clean` is not a routine
operation; the one-time legacy-target migration is the sole exception documented by the workflow
installation record.

View File

@ -0,0 +1,21 @@
---
name: blacksite-doc-integrity
description: Prevent stale or contradictory Blacksite documentation from becoming design context by enforcing documentation authority, archiving superseded plans, comparing changed behavior with canonical docs and accepted ADRs, and running the documentation audit.
---
# Blacksite documentation integrity
Read `.codex/workflow.toml`, `docs/authority.toml`, and [the authority reference](references/documentation-authority.md) before treating repository prose as design guidance.
Trigger this Skill for user-visible behavior, schema/command/component renames, architectural changes, candidate preparation, documentation requests, or discovered contradictions.
1. Identify the changed public behavior from code and focused tests.
2. Load only the canonical docs for its topic and relevant accepted ADRs.
3. Read the exact Gitea acceptance criteria when tracked.
4. Search historical material only for contradictions, never as authority.
5. Write a bounded `.codex/session/doc-contradictions.md` listing claim, source, current truth, and action.
6. Update the smallest canonical owner at the stable slice boundary, within the same task.
7. Mark completed plans historical and freeze their substantive contents. Add required banners and replacement links.
8. Run `python scripts/codex/docs_audit.py --changed`, then the full audit at a documentation slice gate.
Keep README as an overview. Do not duplicate detailed contracts across guides, plans, ADRs, and tracker bodies. Coordinate a dry-run Gitea scope/status update when tracker truth has drifted.

View File

@ -0,0 +1,16 @@
# Documentation authority
`docs/authority.toml` is the machine-readable registry. Roles mean:
- `canonical`: current user or developer behavior.
- `architecture`: accepted decisions and constraints.
- `overview`: a high-level entry point linking to canonical owners.
- `active-plan`: approved incomplete work.
- `evidence`: dated acceptance or evaluation, not product specification.
- `historical`: preserved record no longer used as guidance.
- `superseded`: replaced material that links to its replacement.
- `draft`: non-authoritative work.
Code, schemas, tests, and deterministic output define actual behavior. Accepted ADRs define architecture. Gitea defines accepted current scope and work state. Canonical docs describe shipped/current workflows. When they conflict, identify and reconcile the conflict; never silently combine old and new claims.
Historical, evidence, and superseded files require a visible warning and current canonical link. Active plans require an incomplete-work banner and shipped-behavior link. Session state and raw logs are never documentation.

View File

@ -0,0 +1,14 @@
---
name: blacksite-editor-ux
description: Design and evaluate Blacksite editor UI/UX changes using a production editor interaction rubric, explicit state matrices, existing visual language, and native acceptance criteria. Use for Content Browser, Inspector, viewport, dialogs, material UI, and other interactive editor work.
---
# Blacksite editor UX
Read [the editor UX rubric](references/editor-ux-rubric.md). Before implementing meaningful UI behavior, record a compact interaction-state matrix in session state or the active plan.
Cover only relevant states, but explicitly consider empty, single/multi-selection, narrow/resized, invalid/broken, inherited/read-only/built-in, loading, confirmation, cancel/failure, undo/redo, and restart persistence.
Keep egui rendering thin and reuse established components, spacing, icons, cards, badges, drag/drop feedback, and editor language. Move reusable models and transactions to the lightest owning module/crate. Keep IDs, fingerprints, provenance, and implementation-owned data out of primary editing surfaces.
Create named native scenarios and hand them to `blacksite-native-qa`. Unit tests and screenshots alone are not acceptance; exercise the interaction. If the user says behavior still does not work properly, return to acceptance-in-progress and record a scope delta rather than treating it as unrelated by default.

View File

@ -0,0 +1,29 @@
# Blacksite editor UX rubric
## Product intent
- What familiar editor or file-manager interaction is being matched?
- What is the primary action and what must be obvious without documentation?
- What happens on invalid input?
## Interaction matrix
Include relevant rows for mouse click, double click, right click, shortcut, drag start/hover/drop, multi-selection, empty-space action, narrow panel, modal/review, cancel, undo/redo, and restart.
## Visual design
- Reuse current typography, spacing, icons, cards, and status badges.
- Provide visible hover, drop, focus, invalid, and disabled states.
- Avoid duplicated controls and competing presentations.
- Hide managed/internal data unless diagnosing a failure.
- Support resizing and narrow layouts.
- Distinguish inherited/default/read-only state from explicit editable state.
## Acceptance
- Focused logic tests in the lightest owning crate.
- Focused UI wiring tests when editor-owned state matters.
- Native interaction against the intended build/profile.
- Targeted screenshot or recording of the relevant state.
- Cancel/failure proof and saved-state restart proof when applicable.
- Canonical documentation update after the behavior stabilizes.

View File

@ -0,0 +1,20 @@
---
name: blacksite-gitea-sync
description: Read and synchronize exact Blacksite Gitea issues, epics, and milestones with current scope, implementation state, verification evidence, canonical documentation, and release-candidate status while avoiding duplicate issues and noisy updates.
---
# Blacksite Gitea synchronization
Read `.codex/workflow.toml` and [the state model](references/gitea-state-model.md). Use the configured Gitea connector; do not scrape or invent tracker state.
Supported modes are `read`, `plan`, `status`, `scope-delta`, `candidate`, and `close`.
1. Read exact known issue, parent epic, milestone, and recent relevant comments first. Search broadly only to locate an unknown item or prevent a duplicate.
2. Summarize acceptance locally and create a dry-run mutation plan before every write.
3. Follow configured permissions. Creation and scope/milestone changes require explicit authority; closure is candidate-only; delete/reopen is explicit.
4. Add at most one meaningful status comment per completed slice.
5. Distinguish working-tree implementation from engineering-complete, acceptance-in-progress, candidate-ready, and closure evidence.
6. Mark acceptance only when code, focused tests, and required native/package evidence exist and remain valid.
7. On failure, re-read the exact item, detect partial success, and retry only the missing operation.
Never push or close as a side effect. Record remote mutations and their readback in session state.

View File

@ -0,0 +1,14 @@
# Gitea state model
Gitea owns accepted scope, criteria, priority, dependencies, work state, candidate/evidence links, blockers, and milestone composition. It does not replace code, tests, ADRs, canonical docs, or native evidence.
States:
- `Implementing`: active local work.
- `Engineering-complete`: relevant engineering gates pass; native/product acceptance may remain.
- `Acceptance-in-progress`: native or stakeholder validation is active or exposed a gap.
- `Candidate-ready`: stable scope and a nominated tree are ready for remaining release gates.
- `Blocked`: an external condition prevents progress.
- `Closed`: candidate evidence and every criterion are accepted.
User-discovered UX gaps return an item to acceptance-in-progress and become scope deltas, not automatic new issues. Close children, final signoff, epic, then milestone. Never close a milestone with open assigned issues unless the user explicitly changes its definition.

View File

@ -0,0 +1,18 @@
---
name: blacksite-native-qa
description: Run deterministic named Blacksite editor or packaged-runtime scenarios on the actual desktop session, target the exact window, capture concise evidence, and restore test fixtures. Use only when visual or interactive acceptance is required.
---
# Blacksite native QA
Use only when the user requests native/visual QA or the active acceptance target explicitly requires it. Read `.codex/workflow.toml` and [the scenario format](references/scenario-format.md), then use `scripts/codex/native_qa.sh`.
- Build through `cargo_lane.py` in the named lane and resolve binary, intermediate `deps`, runtime environment, and PID from lane JSON. Never hard-code `target/debug/deps`.
- Target the exact PID/window/class/workspace. Bring offscreen dialogs on-screen and prefer accessibility or window-relative input over desktop coordinates.
- Capture only the target window or relevant crop under `.codex/evidence/`, with a hash and result record.
- Reuse one editor session while code is unchanged.
- Record fixture mutations and restore/trash them transactionally.
- Close processes spawned by the scenario.
- Keep full compositor/accessibility dumps out of the task unless they explain a failure.
Do not claim acceptance from a screenshot alone. Exercise the named steps, invalid/cancel path, and persistence where required.

View File

@ -0,0 +1,46 @@
# Named native scenario format
Scenario files use these top-level fields:
```yaml
name:
purpose:
preconditions:
build_lane:
package:
binary:
fixture:
steps:
assertions:
evidence:
cleanup:
invalidates:
```
`package` and `binary` are optional and default to `editor`. Focused tools such as the UI gallery
can therefore use the same exact-window evidence and cleanup workflow without launching a project.
Keep steps deterministic and phrased as user actions. Assertions describe visible behavior, state transitions, persistence, and failure recovery. Evidence names the target window/crop and expected files. Cleanup must identify every spawned process and fixture mutation.
The runner exposes the scenario instead of pretending manual interactions are automated:
```bash
bash scripts/codex/native_qa.sh plan <scenario>
bash scripts/codex/native_qa.sh launch <scenario>
bash scripts/codex/native_qa.sh attach <scenario> <existing-editor-pid>
bash scripts/codex/native_qa.sh capture <scenario> <runner-pid>
bash scripts/codex/native_qa.sh record <scenario> <assertion-index> pass|fail [note]
bash scripts/codex/native_qa.sh status <scenario>
bash scripts/codex/native_qa.sh close <scenario> <runner-pid>
bash scripts/codex/native_qa.sh restore <scenario> --dry-run
bash scripts/codex/native_qa.sh restore <scenario> --apply
```
`launch` snapshots a workspace-contained regular-file fixture before the editor starts; `attach`
does the same while reusing an existing editor and never closes that user-owned process. `restore --apply`
prints and flushes the baseline/current hash plan, refuses to run while the recorded process
is alive, validates the snapshot hash, and restores atomically. A scenario is accepted only when all
named assertions are recorded as passing and the required evidence exists; visual interaction remains
user-controlled unless explicitly delegated.
Recurring scenario families include Content Browser item/empty-space menus, multi-selection, destination-first import, move/reference repair, duplicate/undo/derived cleanup, material-slot assignment/inheritance, DefaultGrid Forward/Solari, and package launch.

View File

@ -0,0 +1,30 @@
name: content-browser-card-layout
purpose: Verify that the production Content Browser uses the shared Penpot body presentation at wide and compact sizes.
preconditions: The focused shared-UI checks pass and the project Content Browser contains folders, long asset names, and the Poly Haven desk.
build_lane: dev
fixture:
steps:
- Open the Content Browser grid at the project assets root with Sources and Details visible.
- Confirm folders and assets form one continuous row-major stream under the 56 px content heading.
- Navigate to the Office model folder.
- Inspect long Material, Texture, and model names with clean and dirty status states.
- At an expanded width, confirm Name sort and the thumbnail-size slider are visible in the toolbar.
- Sweep the thumbnail-size slider through its minimum, default, and maximum positions.
- Resize the Content Browser and Details splitter through narrow and wide layouts.
- Switch to list view and compare status markers and column alignment.
- Inspect the Poly Haven metal office desk card and one mesh-subasset preview.
assertions:
- Toolbar, body, and footer form one continuous stack with no unowned horizontal gutter.
- Folders and assets use the same bounded card footprint and assets fill the remaining cells of a folder row.
- Grid cards show one clipped and ellipsized name plus a separate kind line with no status overlap.
- Every thumbnail scale preserves the complete name/kind footer and square image aspect; the minimum card never paints its preview through the footer.
- Sort and thumbnail size are first-class controls at expanded width, remain in overflow below the expanded breakpoint, and never appear twice.
- Every asset category keeps its distinct bottom-card keyline across placeholder, pending, ready, failed, hovered, and selected states; folders remain neutral.
- Dirty, processing, and error state use the fixed top-right status rail rather than text over the label.
- Sources labels and Details identity, paths, dependencies, and status remain clipped to their owning panes.
- List status markers occupy fixed space and do not shift or truncate neighboring columns unpredictably.
- Toolbar, Details splitter, and cards remain usable without clipped controls at narrow sizes.
- The office desk and mesh-subasset thumbnails show rendered geometry, never an albedo texture substitute.
evidence: Target-window captures for root-grid wide, Office-grid wide, compact grid, list, and desk geometry states plus hashes.
cleanup: Close only a runner-spawned editor; this scenario does not mutate project fixtures.
invalidates: Asset-card, Content Browser layout, status model, or thumbnail-routing changes.

View File

@ -0,0 +1,26 @@
name: material-slot-live-edit
purpose: Verify persistent live Material edits, explicit save separation, and the unified responsive slot widget.
preconditions: editor_scene contains a primitive and static mesh using a project Material; no editor process is running.
build_lane: dev
fixture: assets/materials/pebble_bricks.ron
steps:
- Select the primitive using pebble_bricks and expand its material parameters.
- Drag a scalar control, release it, and observe the surface for at least five seconds.
- Switch selection away and back, then compare the scalar value and rendered surface.
- Narrow and widen the Inspector around the responsive threshold.
- Save the active Material document and observe status and processing indicators.
- Select a static mesh material slot and compare its slot presentation.
- Leave the expanded material card idle for five minutes while sampling the editor process GPU memory and terminal diagnostics.
- Close and relaunch the editor, then reopen the same Material slot.
assertions:
- The surface changes continuously, does not flicker back after release, and the editor remains responsive.
- Selection changes preserve the live value and the compact amber dirty indicator without label overlap.
- Scalar save becomes clean without a PROCESSING state or a long-running UI operation.
- Primitive and static-mesh slots use the same compact header and schema-driven parameter layout.
- Narrow and wide layouts contain every control without overlap, clipping, garbled rows, or redundant diagnostics prose.
- No Apply, Revert, Ctrl+S hint, inline Explicit label, or inline Source & Diagnostics section appears.
- GPU memory remains bounded, no repeated egui multipass ID warning appears, and the editor stays alive without a renderer Out of Memory error.
- Relaunch preserves the saved Material value and rendered result.
evidence: Target-window captures for dirty-wide, dirty-narrow, saved, and relaunched states plus hashes.
cleanup: Close the spawned editor and atomically restore pebble_bricks.ron from the runner snapshot.
invalidates: Material UI, material persistence, or slot-resolution code changes.

View File

@ -0,0 +1,27 @@
name: penpot-material-inspector
purpose: Verify the current Penpot Materials list and material-slot panel at its 620 px and 420 px Inspector reference widths with side-by-side design evidence.
preconditions: editor_scene contains primitive, static-mesh, and skinned-mesh material users; no editor process is running.
build_lane: dev
fixture: assets/materials/pebble_bricks.ron
steps:
- Launch the editor on the real desktop and size the Inspector to the 620 px reference width.
- Select a primitive, static mesh, and skinned mesh in turn and expand each material panel.
- Compare Materials ownership, expanded slot header, PARAMETERS spine, Surface, six Inputs rows, UV, and Advanced geometry with the current Penpot reference.
- Narrow the Inspector to the 420 px floor and verify every value, channel, texture, Locate, and Clear control reflows.
- Open the material picker, dismiss it without selection, then assign a valid project Material and inspect inherited and direct states.
- Drop a Texture onto the material assignment target and inspect the invalid state without assigning it.
- Open Base Color and exercise Wheel, Sliders, Presets, Apply, Cancel, Escape, and outside dismissal.
- Edit a scalar and color, release the controls, switch actors, then save and relaunch the editor.
- Inspect imported-source, DefaultGrid, and broken-reference presentations through the available fixture states.
assertions:
- The 620 px Inspector matches the current Penpot palette, Source Sans Pro typography, 32 px Materials heading, 82 px expanded slot header, 596 px slot, 569 px parameter body, six 30 px input rows, spacing, borders, and fixed property geometry without visible drift.
- Primitive, static-mesh, and skinned-mesh slots use the same panel geometry and have no redundant second slot presentation.
- At the 420 px Inspector floor, six 56 px input rows put paired texture controls on the second line with no horizontal scrolling, clipping, compressed labels, or missing actions.
- Direct assignments have no Explicit badge; inherited, dirty, processing, failed, read-only, imported-source, and built-in states retain one header geometry.
- Picker dismissal and invalid Texture drops make no assignment or source save; valid Material or Instance drops use the blue accent state.
- Wheel, Sliders, and Presets preview live; Apply retains the dirty in-memory value and Cancel, Escape, or outside dismissal restores the exact pre-open value.
- Material controls perform no pointer-release write or scalar/color processing job and keep the existing live GPU handle visible across actor selection.
- Save and relaunch preserve the authored value, while broken explicit references retain failed identity and visible DefaultGrid fallback.
evidence: Font-faithful Penpot PNGs paired beside fresh target-window captures for 620 px primitive/static/skinned, 420 px reflow, component headers, renderer composition, color modes, invalid drop, dirty state, and relaunch plus hashes and a written delta matrix.
cleanup: Close the spawned editor and atomically restore pebble_bricks.ron from the runner snapshot.
invalidates: Design tokens, fonts, material panel geometry, material picker, color picker, authored documents, or material resolver changes.

View File

@ -0,0 +1,23 @@
name: ui-gallery-framework
purpose: Prove the lightweight production-component gallery launches independently and exposes the Penpot comparison workflow.
preconditions: The focused ui_gallery build and workflow tests pass in the managed dev lane.
build_lane: dev
package: ui_gallery
binary: ui_gallery
fixture:
steps:
- Launch the standalone Blacksite UI Gallery without a project, scene, renderer, or gameplay runtime.
- Inspect the default Content Browser 1240 side-by-side reference and production component canvases.
- Switch through Content Browser 620, Materials 620, Materials 420, Renderer 760, and Renderer 480 presets.
- Exercise Live, Overlay, and Difference modes and inspect the reported difference statistics.
- Switch through direct, inherited, imported, dirty, processing, failed, read-only, and built-in fixtures.
assertions:
- The gallery opens as one responsive native window without launching the Blacksite editor or game runtime.
- All six exact reference presets render the direct Penpot PNG and shared production component without clipping the gallery chrome.
- Content Browser 1240 and Content Browser 620 each report fewer than 15 percent changed pixels in Difference mode.
- Side-by-side, overlay, and difference modes remain interactive and Difference reports numeric delta statistics.
- Representative material ownership and health fixtures preserve the same shared panel geometry.
- Theme and material fixture JSON changes appear without rebuilding or restarting the gallery.
evidence: Exact ui_gallery window capture plus the hashed native-QA record.
cleanup: Close the runner-owned ui_gallery process; no project fixture is mutated.
invalidates: editor_ui, material_schema, ui_gallery, Penpot references, gallery fixtures, or gallery workflow scripts change.

View File

@ -0,0 +1,17 @@
---
name: blacksite-release-candidate
description: Nominate and verify one Blacksite candidate tree or commit, reuse still-valid selective verification evidence, run the remaining full release gates once, produce an evidence manifest, and hand results to Gitea synchronization.
---
# Blacksite release candidate
Read `.codex/workflow.toml` and [the release gates](references/release-gates.md). Require stable scope, no pending major delta, and `Candidate-ready` session state.
1. Record the candidate SHA or dirty-tree digest.
2. Read the verification ledger and reuse every gate whose relevant input digest and lane signature remain valid.
3. Run only missing/invalid release gates via `verify.py candidate` and managed candidate/package lanes.
4. Preserve final binaries/package output and required native evidence before disposable-lane pruning.
5. Write `.codex/session/candidate-evidence.json` with commands, digests, results, artifacts, screenshots, and documentation status.
6. Run documentation integrity and hand a dry-run/authorized candidate update to `blacksite-gitea-sync`.
Do not push, close, or change tracker scope outside direct or configured authority. Run full workspace/all-feature tests and strict lint only once per candidate code digest.

View File

@ -0,0 +1,14 @@
# Candidate release gates
A nominated Blacksite candidate requires, when relevant:
- Full workspace/all-feature tests.
- Strict all-target/all-feature Clippy with warnings denied.
- Deterministic content processing and read-only check parity.
- Level/sample/project validators and migration idempotence.
- Packaging, packaged artifact validation, and launch.
- Named native editor/runtime scenarios against candidate binaries.
- Documentation authority/contradiction audit.
- Clean candidate-tree or nominated dirty-tree digest evidence.
Do not precede workspace tests with a redundant workspace check unless a target is otherwise uncovered. Documentation-only changes do not invalidate code gates when recorded inputs are unchanged. Closure additionally requires every issue criterion, epic checklist synchronization, and configured Gitea evidence.

View File

@ -0,0 +1,18 @@
---
name: blacksite-selective-verify
description: Select and run the smallest valid Blacksite formatting, compile, test, lint, processing, validation, packaging, and native gates based on changed files and the current task state. Use after edits or before slice/candidate completion; do not default to full workspace gates.
---
# Blacksite selective verification
Read `.codex/workflow.toml` and [the verification matrix](references/verification-matrix.md), then invoke `python scripts/codex/verify.py`.
- `plan` explains selected and skipped gates without executing them.
- `fast` runs the smallest useful edit loop.
- `slice` adds affected-package tests, strict Clippy, domain checks, docs integrity, and named native requirements.
- `candidate` is permitted only for a nominated Candidate-ready state and runs missing release gates once.
- `status` reads the digest ledger; `invalidate --reason ...` invalidates only when inputs or acceptance change.
Every Cargo command must go through `cargo_lane.py`. Do not run overlapping Cargo processes. Reuse a PASS when its relevant input digest, command, lane signature, toolchain, features, and environment are unchanged. Store complete output under `.codex/logs/` and show only the compact result or the first bounded actionable failure.
Do not append workspace tests, workspace Clippy, processing, validators, packaging, or native QA to an ordinary fast loop. Prefer focused tests in the lightest crate that owns the invariant.

View File

@ -0,0 +1,19 @@
# Blacksite verification matrix
| Changed area | Fast loop | Slice gate | Candidate impact |
|---|---|---|---|
| Markdown only | docs audit | docs audit | Rust gates remain valid |
| `AGENTS.md`, Skills, workflow scripts | script self-tests/dry run | docs audit and workflow acceptance | No Rust gate unless Rust changed |
| `crates/content_pipeline/**` | pipeline check and focused tests | pipeline tests and strict Clippy; processing if output changed | Full gate later |
| `crates/shared/**` schemas/types | shared check and focused tests | shared tests, dependent checks, migration dry run if needed | Full gate later |
| `crates/editor/src/ui/**` | editor library check; focused wiring tests | editor tests/Clippy and named native scenario | Full gate later |
| `crates/blacksite_surface/**`, shaders | surface check/tests | surface Clippy and relevant renderer scenarios | Full gate later |
| `xtask/**` packaging | focused xtask/package test | repeat package test and package dry run | Package candidate required |
| Registry/catalog inputs | processing check | validators and deterministic write/check | Package/native as relevant |
| Migration/schema versions | focused migration tests/dry run | fixture apply, idempotence, rollback | Full gate later |
| Gitea only | No Cargo | Tracker readback | No code gate |
| Session/evidence only | No Cargo | Evidence integrity | No code gate |
Fast checks normally use the `dev` lane. Candidate, package, hot-reload, and full-debug work use their named disposable lanes. A docs-only edit never invalidates a code gate whose recorded input digest is unchanged.
Rust gate digests fingerprint the owning package and its local dependency closure, relevant Cargo and workflow configuration, the exact gate/lane, tool versions, and build-affecting environment. Documentation and unrelated packages are excluded, so their edits preserve valid focused Rust evidence; changes to a dependency, relevant configuration, toolchain, or environment invalidate it.

View File

@ -0,0 +1,19 @@
---
name: blacksite-task-state
description: Maintain resumable Blacksite task state, scope deltas, verification validity, and exact next actions during multi-step implementation, user steering, reconnects, or context compaction. Use for long or multi-subsystem work; do not use for trivial one-file edits.
---
# Blacksite task state
Read `.codex/workflow.toml`, then use `python scripts/codex/state.py` to create or update the ignored `.codex/session/STATE.md`.
Use this Skill for `continue`, `resume`, plan implementation, multi-crate work, material scope changes, native acceptance discoveries, reconnects, and path remapping.
1. Verify the canonical repository path, branch, HEAD, dirty summary, and relevant live processes.
2. Resume an existing valid state instead of rediscovering the repository.
3. Keep the active goal, slice, acceptance target, non-goals, intentional files, decisions, evidence validity, and one exact next action current.
4. Record steering with `state.py scope-delta`. Classify it as an active-slice refinement, newly discovered blocker, added acceptance criterion, or separate follow-up.
5. State which evidence remains valid and invalidate only affected gates with `verify.py invalidate`.
6. Update state after a completed slice, native checkpoint, or remote mutation.
Keep the file below the configured line limit. Never copy logs, issue bodies, large plans, or desktop dumps into it.

View File

@ -5,9 +5,9 @@ linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"] rustflags = ["-C", "link-arg=-fuse-ld=mold"]
[alias] [alias]
clean-target = "run -p xtask --bin clean-target --"
validate-levels = "run -p xtask --features validate-levels --bin validate-levels --" validate-levels = "run -p xtask --features validate-levels --bin validate-levels --"
validate-samples = "run -p xtask --features validate-samples --bin validate-samples --" validate-samples = "run -p xtask --features validate-samples --bin validate-samples --"
bake-navigation = "run -p xtask --features validate-levels --bin bake-navigation --" bake-navigation = "run -p xtask --features validate-levels --bin bake-navigation --"
package-project = "run -p xtask --features validate-levels --bin package-project --" package-project = "run -p xtask --features validate-levels --bin package-project --"
upgrade-project = "run -p xtask --features validate-levels --bin upgrade-project --" upgrade-project = "run -p xtask --features validate-levels --bin upgrade-project --"
process-assets = "run -p xtask --features content-pipeline --bin process-assets --"

14
.codex/ARCHITECTURE.md Normal file
View File

@ -0,0 +1,14 @@
# Architecture debt ratchet
Blacksite keeps extension seams sustainable at the point of change. New behavior belongs in the
smallest domain module that owns it; an already-large file is not permission to add more behavior
there.
`architecture.toml` is the machine-readable policy. `scripts/codex/architecture_audit.py` enforces
three default nonblank-line budgets: 500 for UI shells, 800 for other UI modules, and 1,200 for
other production Rust modules. Existing files above those budgets have frozen ceilings and may
shrink but never grow.
An exception is temporary and must name a tracker issue, rationale, hard maximum, extraction
target, and expiry milestone. Passing the audit means the debt did not regress; it does not mean an
exception is complete. Candidate review must reject expired exceptions.

34
.codex/architecture.toml Normal file
View File

@ -0,0 +1,34 @@
version = 1
[limits]
ui_shell = 500
ui_module = 800
production_rust_module = 1200
[shells]
"crates/editor/src/ui/asset_browser/panel.rs" = 500
"crates/editor/src/ui/inspector.rs" = 500
# Frozen baselines are debt ceilings, not targets. They may shrink but never grow.
[baselines]
"crates/scene/src/project_validation.rs" = 4685
"crates/editor/src/assets/prefab_overrides.rs" = 4238
"crates/editor/src/scene/scene_io.rs" = 4196
"crates/editor/src/history/mod.rs" = 3651
"crates/editor/src/assets/catalog.rs" = 2077
"crates/scene/src/navigation.rs" = 2346
"crates/shared/src/components.rs" = 1831
"crates/game/src/animation.rs" = 1690
"crates/editor/src/project/collaboration.rs" = 1649
"crates/editor/src/ui/viewport_chrome.rs" = 1575
"crates/content_pipeline/src/transaction.rs" = 1477
"crates/content_pipeline/src/import.rs" = 1417
"crates/editor/src/viewport/brush_edit.rs" = 1286
"crates/editor/src/viewport/material_drop.rs" = 1269
"crates/editor/src/viewport/visualizers.rs" = 1221
"crates/scene/src/upgrade.rs" = 1203
"crates/editor/src/ui/navigation_inspector.rs" = 1210
"crates/editor/src/ui/hierarchy.rs" = 1149
"crates/editor/src/ui/material_library.rs" = 1011
"crates/editor/src/ui/animation_inspector.rs" = 971
"crates/editor/src/ui/component_registry.rs" = 864

2
.codex/config.toml Normal file
View File

@ -0,0 +1,2 @@
approval_policy = "on-request"
workspace_root = "/home/Rbanh/Documents/Bevy"

View File

@ -0,0 +1,19 @@
## Codex status — <state>
**Scope completed**
- ...
**Verification**
- `<command>` — PASS
- Native scenario `<name>` — PASS/NOT RUN
**Documentation**
- Canonical docs updated: ...
- Contradiction audit: PASS/remaining ...
**Candidate**
- Commit: working tree only | `<sha>`
- This is/is not closure evidence.
**Remaining**
- ...

View File

@ -0,0 +1,7 @@
### Delta N — title
- Source:
- Classification: active-slice refinement | newly discovered blocker | added acceptance criterion | separate follow-up
- Added/changed requirement:
- Prior evidence still valid:
- Invalidated gates:
- Tracker sync required: yes | no

View File

@ -0,0 +1,36 @@
# Codex session state
## Repository
- Root:
- Real path:
- Branch:
- HEAD:
- Worktree status summary:
- Active processes/windows:
## Active task
- Goal:
- Current state: Implementing
- Gitea issue(s):
- Gitea milestone:
- Active slice:
- Non-goals:
## Acceptance target
- [ ] Criterion
## Scope deltas
## Files intentionally changed
## Verification ledger summary
## Native evidence
## Decisions
## Remote actions already performed
- None.
## Exact next action
- One concrete next step.

81
.codex/workflow.toml Normal file
View File

@ -0,0 +1,81 @@
version = 1
[session]
state_file = ".codex/session/STATE.md"
verification_file = ".codex/session/verification.json"
max_state_lines = 180
[output]
log_dir = ".codex/logs"
evidence_dir = ".codex/evidence"
max_failure_lines = 120
progress_mode = "meaningful-checkpoints"
[verification]
default_tier = "fast"
candidate_requires_explicit_state = true
reuse_by_input_digest = true
offline_after_bootstrap = true
cargo_lane_wrapper = "scripts/codex/cargo_lane.py"
persistent_lane = "dev"
candidate_lane = "candidate"
hot_reload_lane = "hot-reload"
full_debug_lane = "full-debug"
package_lane = "package"
parallel_cargo = false
run_workspace_check_before_workspace_test = false
[build_storage]
enabled = true
strategy = "separate-build-dir-when-supported"
cache_root = "workspace-parent-cache"
workspace_partition = "canonical-path-hash"
dev_target_dir = "target"
exceptional_target_root = "target/lanes"
soft_total_gib = 55
hard_total_gib = 80
min_free_gib = 40
min_free_percent = 15
persistent_lane_max_gib = 40
disposable_lane_max_gib = 35
candidate_retention_hours = 24
hot_reload_retention_hours = 24
full_debug_retention_hours = 12
failed_lane_retention_hours = 24
auto_prune_disposable = true
persistent_reset = "safe-slice-boundary-after-dry-run"
delete_only_marked_lanes = true
preflight = true
postflight = true
[git]
large_task_branch = true
local_checkpoint_commits = true
push = "explicit"
force_push = false
dirty_main_policy = "preserve-and-isolate-when-safe"
[gitea]
repository = "Falling-Metal-Interactive/Blacksite"
read_exact_items_first = true
routine_status_comments = true
sync_acceptance_checkboxes = true
sync_epic_checklists = true
create_issues = "explicit"
change_scope_or_milestone = "explicit"
close_issues = "candidate-only"
close_milestones = "candidate-only"
delete_or_reopen = "explicit"
max_status_comments_per_slice = 1
[documentation]
authority_manifest = "docs/authority.toml"
classify_all_docs = true
historical_banner_required = true
canonical_topic_unique = true
completed_plans_become_historical = true
[native_qa]
reuse_running_session = true
capture_target_window_only = true
restore_fixtures = true

View File

@ -1,5 +1,7 @@
# Skeletal Animation Import, Preview, And Authoring # Skeletal Animation Import, Preview, And Authoring
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea issue Working implementation plan for Gitea issue
[`#46`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/46). [`#46`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/46).
This is the minimum production animation loop required by the M7 content-production milestone. This is the minimum production animation loop required by the M7 content-production milestone.

View File

@ -1,5 +1,7 @@
# Audio Authoring And Runtime Parity # Audio Authoring And Runtime Parity
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea issue Working implementation plan for Gitea issue
[`#47`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/47). [`#47`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/47).
This is the minimum complete audio loop required by the M7 content-production milestone. This is the minimum complete audio loop required by the M7 content-production milestone.

View File

@ -1,5 +1,7 @@
# Blacksite Editor Production Readiness Program # Blacksite Editor Production Readiness Program
> **Active plan — desired scope and acceptance, not implementation truth.** Current shipped behavior is indexed in the [canonical documentation](../../docs/README.md).
Working milestone plan for the production expansion tracked by Gitea epic Working milestone plan for the production expansion tracked by Gitea epic
[`#1`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/1). [`#1`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/1).
The existing Jackdaw-inspired M0-M5 roadmap remains the authoring/tool foundation. This plan adds The existing Jackdaw-inspired M0-M5 roadmap remains the authoring/tool foundation. This plan adds

View File

@ -1,5 +1,7 @@
# Collider Authoring Diagnostics - 2026-07-12 # Collider Authoring Diagnostics - 2026-07-12
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Issue: Gitea #26 (`BS-JD-305`) Issue: Gitea #26 (`BS-JD-305`)
## Outcome ## Outcome

View File

@ -1,5 +1,7 @@
# Component System Refactor Plan - 2026-06-05 # Component System Refactor Plan - 2026-06-05
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
## Goal ## Goal
Align the actor inspector and static mesh authoring model with Align the actor inspector and static mesh authoring model with

View File

@ -0,0 +1,480 @@
# Content Workspace And Import Authoring Refactor
> **Active plan — desired scope and acceptance, not implementation truth.** Current shipped behavior is documented in the [Content Workspace guide](../../docs/editor/content-workspace.md).
Date: 2026-07-13
## Status
Active acceptance plan for Gitea milestone **M2 - Content workspace and asset pipeline**. Current
implementation state, user steering, invalidated evidence, and the exact next action live in the
ignored `.codex/session/STATE.md`; accepted scope and closure state live in Gitea #59 and #65. The
local candidate tree passed the complete candidate gate on 2026-07-17; its exact commit is assigned
at publication, so this plan must not be read as remote completion evidence yet. It remains the
desired acceptance target until M2 is accepted, then becomes a frozen historical record.
## Gitea Tracking
- Milestone: [M2 - Content workspace and asset pipeline](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/milestone/12)
- Epic: [#59 BS-JD-211 - Content workspace and import authoring refactor](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/59)
- Contract and catalog: [#60 BS-JD-212](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/60), [#62 BS-JD-214](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/62)
- File operations and import: [#20 BS-JD-205](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/20), [#61 BS-JD-213](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/61)
- Model materials: [#64 BS-JD-215](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/64), [#63 BS-JD-216](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/63)
- Final gate: [#65 BS-JD-217](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/65)
- Engine fallback: [#66 BS-JD-218](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/66)
- Responsive authored documents: [#67 BS-JD-219](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/67)
- Modular editor architecture: [#68 BS-JD-220](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/68)
## Goal
The active corrective slice also requires one overlay-first Material handle authority, conditional
ARM/ORM-only derived processing, registry-only Inspector dispatch, shared Material/asset-card UI,
and the ADR 0048 architecture ratchet. Both large UI files are now <=500-line shells; #68 remains
open until selective verification, critical native acceptance, and publication approval are
complete.
The current #68 refinement adopts the Penpot **Inspector Material Slot** as the first Blacksite
design-system reference. Penpot owns geometry, typography, and interaction-state references;
Blacksite's editor-owned semantic palette owns color and is published into Penpot Assets / Colors.
The current palette is the default, with preference selection deferred behind the same palette
seam. Shared semantic tokens, Source Sans Pro typography, action-returning
material panels, responsive property grids, and custom asset/color pickers must match the 620 px
and 420 px references. The Inspector has a hard 420 px floor and one actor-body scroll region.
Runtime material authority and explicit-save behavior remain
owned by #67 and ADR 0047; wider editor-panel migration is not part of this slice.
Make the Content Browser behave like a project file manager and make imported models behave like
editable engine assets:
- users organize source and authored assets in any folder beneath the project `assets/` content
root;
- importing copies into the current or explicitly chosen project folder instead of sorting by file
extension;
- static and skinned model assets expose stable material slots whose defaults can use source
materials, existing project Materials/Material Instances, or extracted editable Materials;
- move, rename, reimport, validation, packaging, and headless processing preserve stable identity
and never silently overwrite authored material work.
This matches the portable project-content model used by Unity and Unreal. Arbitrary absolute paths
outside the project are not part of this milestone: external linked assets require a separate
virtual-filesystem, packaging, and source-control decision.
## Existing Foundation To Reuse
- `AssetRegistry` owns UUIDs, source fingerprints, import settings, and generated-manifest paths.
- The Content Browser already scans nested folders below `assets/`, renders thumbnails and model
subassets, stages import settings, reimports, and moves deleted files to `assets/.trash/`.
- Static and skinned renderers already share stable material-slot IDs, imported-source fallback,
explicit scene-level project Material assignments, and orphan preservation.
- Project Materials and direct-base Material Instances are editable, schema-driven assets with a
dedicated Material Library. Parameter edits update shared runtime handles every frame and mark an
asset-keyed document dirty; pointer release performs no persistence or processing. Explicit Save
publishes guarded source and queues affected-only derived processing in the background.
- Imported-source fingerprints are content-addressed, and FBX dependency bundles already use a
sandboxed transactional copy.
The refactor must extend these contracts rather than add a second catalog, material type, or model
loader.
## Implementation Snapshot
- [Implemented] Destination-first Import Here/Import To, in-project adoption, exact-path review,
dependency/source fingerprint guards, dependency-bundle preflight, and whole-batch rollback.
- [Implemented] Folder-independent registry-v3 classification and one `content_pipeline` engine for
editor transactions, watcher refresh, validation, headless processing, and packaging catalogs.
- [Implemented] File-manager selection, folders, item/batch/visible-empty-space context menus,
content-scoped keyboard operations, protected managed folders, safe navigation and subasset
semantics, guarded undo, transaction review, collaboration state, trash, stable-reference
rewrites, hidden-selection clearing when filters change, consistent right-click targeting, and
restart-safe explicit identity selection for ambiguous out-of-editor moves.
- [Implemented] Stable per-slot model defaults, orphan reconciliation, six-layer material
precedence, project fallback, immutable DefaultGrid, and reviewed exact-slot
MaterialPropertyBlock promotion with transactional rollback.
- [Implemented] Transactional glTF/GLB/FBX material extraction with provenance, explicit
diff/apply/create-new re-extraction, plus loose-texture PBR grouping.
- [Implemented 2026-07-15] Scene schema v6 and actor-only `MaterialSlot` ownership for
primitives/static/skinned renderers; primitive-local `MaterialDesc` hydration and the synthetic
Authoring Material card are removed. The unified slot widget supports valid/invalid drag state,
inherited effective status, guarded shared parameter editing, direct-base instance creation,
actor-exact source extraction, and property-block promotion.
- [Implemented 2026-07-14] Typed thumbnail keys separate textures, models, mesh subassets, and
source materials. Models always queue geometry rendering and static draw previews request their
exact mesh subasset; the Poly Haven metal office desk regression is unit-covered.
- [Implemented 2026-07-19] Typed texture/model/mesh/material previews persist as content-addressed
256 px artifacts under the managed `.thumbnails` cache. Visual source/dependency hashes and a
renderer version invalidate only affected entries; catalog refresh retains last-good GPU images,
corrupt artifacts self-heal, studio retries are bounded, and manual regeneration evicts one key.
- [Implemented 2026-07-14] Asset-keyed authored documents separate live Material/Instance and
import-setting edits from explicit source publication. Context Save, Save All, recovery,
conflict state, separate Git/processing badges, and revisioned background processing remove
pointer-release writes and synchronous content work from material controls.
- [Implemented 2026-07-17] Penpot-led design-system foundations and the unified
primitive/static/skinned material panel are in the local worktree. The revised handoff adds
field-click texture pickers with Locate/Clear, Separate/ORM presentation, and shared UV
Offset/Tiling controls. Blacksite's default semantic palette now replaces the panel-private
prototype colors. Exact 640/420 px native acceptance and responsive resize/deep-scroll scenarios
pass on the final geometry.
- [Implemented 2026-07-17] #67/#68 corrective sampler and Penpot v2.3 slice: project textures use
catalog-authored Repeat/Clamp/Mirror sampling across Standard and Surface paths; the shared panel
has one Shader selector, UV before Advanced, typed texture thumbnails, and a disabled Advanced
preview with no authored/runtime state.
- [Implemented 2026-07-17] #68 Penpot v2.3.1 corrective pass: the design component and every state
reference remove Shading Model and UV/Advanced overlap; the shared Material asset zone owns
assignment and its current/recent/project picker; Surface, Packed Maps, inputs, UV, and Advanced
use the locked reference heights; and the actor-salted Inspector body is clipped below its fixed
identity header. Managed verification and Codex-owned native visual acceptance pass.
- [Implemented 2026-07-17] Direct exports of the default, expanded Advanced, Material picker, and
color picker are now the numeric baseline. The exact pass removes the invented drop cue and Blend
label, restores the fixed Inputs columns, boxed ORM guidance, `UV` label, Advanced summary, compact
Material menu, paired color/HEX values, normal strength, and the seventh Emissive Intensity row.
- [Implemented 2026-07-17] The final #68 micro-geometry pass makes the exported 420 x 350 color
overlay Inspector-centered and modal, locks its value/alpha/recents/footer coordinates, keeps the
eyedropper as a disabled planned preview, replaces stock material sliders with the 130 px Penpot
scalar control, and scroll-reveals the complete expanded Advanced body. Geometry and popup
interaction tests plus native captures pass.
- [Implemented 2026-07-17] Native Inspector splitter endurance exposed a viewport-target ownership
leak: every intermediate width allocated another full-resolution HDR Image and Egui retained each
strong registration until Solari terminated on GPU OutOfMemory. The corrective path resizes one
stable Image asset in place, unregisters exceptional replacements/absent targets, and requires a
repeated wide/narrow drag endurance pass before #68 visual acceptance resumes.
- [Implemented 2026-07-17] Native top-level window resizing exposed a distinct NVIDIA Wayland
swapchain-acquire timeout loop after the target-ownership leak was removed. The editor host now
prefers an Immediate/Mailbox presentation path while packaged game windows retain VSync; repeated
native-window resize remains the focused acceptance gate.
- [Implemented 2026-07-17] Native narrow/tall Inspector captures exposed a universal overflow
boundary defect: solid scrollbar allocation changed responsive widths and nested component cards
could replace the actor-body clip. The shared Inspector now keeps a stable floating scroll rail,
intersects every touched child clip, and ready texture fields omit the redundant image glyph.
- [Implemented 2026-07-17] The final #68 Penpot boards supersede the earlier v2.2/v2.3 slot
geometry. Inspectors render a 32 px **Materials** heading and ordered 82/52 px collapsible slots,
a nested PARAMETERS spine, 616/396 px slot references, 592/372 px parameter bodies, and one
420 px Inspector floor. Surface owns Separate/ORM; Inputs has six 30/56 px primary rows, with
independently stored Emissive Intensity presented as the Emissive color companion.
- [Implemented 2026-07-17] The exact geometry correction replaces flow-derived Surface, input,
texture-action, and UV placement with clipped owning-rectangle models for the exported 592/372 px
sections. Texture names can no longer move row actions, UV labels no longer share coordinates,
and transient sub-minimum widths use a bounded overflow fallback. Focused engineering verification
and 640/420/short-height native captures pass.
- [Candidate gate passed 2026-07-17; pending publication] The complete all-feature test and strict
lint gates, deterministic processing, level/sample validators, QA package, architecture audit,
and documentation audit pass on the local candidate tree. Native runtime-injected property-block
promotion, skeletal import, explicit scene-slot assignment, and broken project-fallback behavior
also pass. Exact-commit clean-tree readback, evidence publication, and Gitea closure remain.
- [Corrective acceptance in progress 2026-07-17] The current Penpot README and active 0130 boards
supersede the earlier 640/420 material-only references and invalidate the prior candidate's UI
acceptance. M2 now requires the shared 50 px Inspector Header, renderer Array Header/panels,
foundation controls, overlays, and current 620/420 Material references across the complete
Inspector. The new wide/narrow Material canvases are 596/396 px with 569/369 px parameter
sections, 32/58 px rows, and 54/94 px UV sections. Candidate publication and issue closure remain
blocked until refreshed engineering and Codex-owned native evidence pass on one exact tree.
- [Engineering-complete; acceptance in progress 2026-07-18] A lightweight `ui_gallery` now renders
the same `editor_ui` production components without project/scene/renderer/gameplay startup. It
provides exact Materials 620/420 and Renderer 760/480 presets, direct Penpot side-by-side,
overlay, and Difference modes, all material ownership/health fixtures, runtime token/fixture
reload, and a managed last-good rebuild/restart loop with bounded dependency progress. Focused
tests, strict lint, and architecture audit pass; paired full-editor evidence remains required.
- [Acceptance-in-progress 2026-07-18] The current Page 03 Content Browser boards supersede the earlier
Asset Browser chrome. Production maps the standalone 36 px title row to the existing dock tab,
owns an 88 px deterministic toolbar, uses 216/290 px wide Sources/Details panes, and exposes
compact Sources/Details drawers alongside preserved Search, Grid/List, Import, New, and overflow.
Engineering verification, paired wide/compact native captures, Sources/Details interaction, and
repeated 1200×760 through 1800×1100 resize stress pass. Exact candidate publication remains
pending.
- [Corrective implementation 2026-07-19; production acceptance pending] Content Browser Gallery
evidence exposed a split renderer: only toolbar/status and item ordering were shared, while the
fixture hand-painted Sources, cards, content heading, and Details. Those body presentations now
live in `editor_ui::content_browser` and are invoked by both Gallery fixtures and production state.
Production also removes the unowned toolbar/body/footer gutter, clips every exact panel region,
uses one bounded name plus kind per card, and ellipsizes Details values. The shared implementation
now also owns the Penpot panel fill/border, 16+6 px grid surface/card inset, card preview and status
rail coordinates, and the fixed Details heading/identity stack; production no longer inserts a
private spacer before Details. The prior Gallery-only pixel score is invalid as production
evidence until a refreshed full-editor capture passes.
## Target Contracts
### Project content boundary
- User-managed content may live in any normal nested folder under `assets/`.
- Folder names are organizational only and never determine asset type.
- `assets/.index/`, `assets/.trash/`, thumbnail storage, and UUID-keyed derived artifacts remain
editor-managed and protected from ordinary file operations.
- The storage ADR decides whether existing generated directories remain in place or migrate behind
`.index`; either way, they stay hidden and are never presented as imported user content.
### Registry and type authority
- `AssetId` remains authoritative identity; the current project-relative path is mutable metadata.
- Extension plus parsed document schema/registry kind determines type. Moving a Material beside a
model does not turn it into a level.
- All editor, hydration, validation, and packaging paths resolve current locations through stable
identity before consulting cached path hints.
- Existing projects migrate without replacing UUIDs or rewriting semantically unchanged files.
### Filesystem operations
- Create Folder, Rename, Move, Duplicate, Cut/Copy/Paste, drag-to-folder, trash, and restore work on
assets and folders.
- Ref-affecting operations show collisions, dependencies, collaboration state, and affected authored
files before commit. They use guarded, staged filesystem transactions with rollback on failure.
- Reversible filesystem operations create guarded content-undo entries. Undo is refused after an
external fingerprint change; trash/restore remains the recovery model for deletion.
- External filesystem changes reconcile by stable ID/fingerprint where unambiguous and otherwise
produce an explicit repair flow.
### Destination-first import
- **Import Here** targets the selected Content Browser folder. **Import To...** chooses another
folder beneath `assets/` without changing the browser location. The native picker opens only
after the destination is pinned, then a second review previews every dependency and final path.
- External files are copied into the chosen project folder; files already inside project content
are registered/processed in place instead of copied again.
- Import never silently creates visible `models/`, `textures/`, `audio/`, or `materials/` folders.
- Dependency-relative bundles, overwrite conflicts, collaboration guards, staging, and rollback
are resolved before registry publication.
- Registry records retain optional source provenance and a deterministic reimport recipe without
making an external absolute path a runtime dependency.
### Model asset material defaults
Material resolution uses the strongest valid authored layer in this order:
1. runtime `MaterialPropertyBlock`;
2. placed renderer/prefab slot assignment;
3. model-asset per-slot default;
4. imported source material;
5. project default Material/Instance;
6. immutable engine DefaultGrid.
Mappings are keyed by stable imported slot/subasset IDs, never display names. Changing a model-asset
default updates existing and future placements that do not carry a scene override; clearing a scene
override returns to the next intentional layer. A configured-but-broken explicit reference reports
a diagnostic and renders DefaultGrid instead of exposing a weaker assignment. Static and skinned
renderers use the same resolution rules without sharing geometry/hydration components.
Reimport reconciles by stable slot ID. Removed mappings become visible orphans and are never moved to
a similarly named slot automatically.
### Editable imported materials
- A model import can keep source fallback, map a slot to an existing project material, extract a
supported source material into an editable project Material, or intentionally select Default.
- Extraction previews destination paths, naming collisions, external texture channels, render
state, provenance, and supported PBR parameters before writing. Embedded texture payloads remain
source-owned and are not misrepresented as extracted project textures.
- Extracted Materials are ordinary project assets and may live beside the model or anywhere else
under `assets/`.
- Source provenance is recorded, but reimport never overwrites an edited Material silently. Updating
an extracted material requires an explicit diff/apply decision.
- Unsupported source features produce diagnostics and preserve a predictable source/fallback path;
partial conversion is never presented as lossless.
## Milestone Work Packages
### Epic — Content workspace and import authoring refactor
Tracks the milestone contract, dependencies, sequencing, and exit evidence. It is not an
implementation substitute for the focused issues below.
### Architecture — Project content and derived-artifact contract
- [Implemented] Add ADR 0045 covering the content root, registry/type authority, mutable paths,
protected managed directories, import provenance, and the six-layer material resolution contract.
- [Implemented] Define explicit migrations for registry v1, project settings, legacy cached refs,
whole-model material policy, and mesh material overrides.
- [Implemented] Replace fixed-folder consumers across editor, shared hydration, scene validation, project
settings, and packaging.
### Existing BS-JD-205 — Content Browser file operations and reference-safe moves
Expand the existing rename/move repair ticket instead of duplicating it:
- [Implemented] create folder, rename, move, duplicate, cut/copy/paste, drag-to-folder, and
transactional trash/restore with stable-ID manifests and collision guards;
- [Implemented] file-manager selection for assets and folders (single, Ctrl/Cmd toggle, Shift range, select all),
batch operations, keyboard shortcuts, and scoped context menus on assets, folders, and unused
content space;
- [Implemented] asset/folder collision, collaboration, external-fingerprint, and dependency-impact preview;
- [Implemented] atomic registry/reference repair and external-change reconciliation;
- [Implemented] selection, breadcrumb, thumbnail, and Material Library continuity after moves.
### Destination-first transactional import
- [Implemented] Replace extension-to-directory routing with current-folder/explicit-folder import.
- [Implemented] Register files already under project content in place.
- [Implemented] Preserve FBX/glTF relative dependencies safely and reject collisions before any
selected source mutates the destination.
- [Implemented] Roll back the complete multi-source publication batch on failure; cancellation
remains non-mutating.
### Path-agnostic catalog, loading, validation, and packaging
- [Implemented] Remove folder-name asset classification and fixed material/shader/model discovery paths.
- [Implemented] Resolve stable IDs to current paths in editor and runtime consumers.
- [Implemented] Make the live editor watcher, headless processing, validators, and build manifests
share the same catalog rules. Live refresh debounces changes, ignores generated/managed noise,
suppresses editor transactions, republishes registry/runtime catalog, and invalidates thumbnails.
- [Implemented] Migrate representative registry/model records while preserving UUIDs and
semantically unchanged user-authored bytes.
### Built-in DefaultGrid and project fallback
- [Implemented] Provide one immutable, UV-independent engine material with forward/Solari parity and a shared
emergency StandardMaterial handle.
- [Implemented] Let Project Settings select a registry-backed project Material/Instance fallback; Clear or an
invalid reference returns to DefaultGrid with diagnostics.
- [Implemented] Apply the fallback to unresolved static/skinned slots, primitives without an active material,
unassigned brush faces, and model/mesh previews. Terrain keeps its specialized layer fallback.
### Unified actor material slots and previews
- [Implemented] `MaterialSlot`/`MaterialSlotSet` are the primary contracts; schema-v4 renderer names
remain compatibility aliases for one cycle. `Primitive.surface` always uses
`slot:primitive:surface` and new placements begin unassigned.
- [Implemented] Hydration binds the exact primitive/static/skinned slot to one cached emergency
handle, then resolves explicit/model source/project default/DefaultGrid without actor-local
material creation. Component-form `MaterialDesc` remains only for the brush fallback path.
- [Implemented] One inspector widget exposes the effective Material sphere/name/status,
Browse/Locate/Clear, a full-width Material/Instance target, red explanatory Texture rejection,
expandable guarded shared parameters, exact-slot instance creation, imported-source extraction,
and property-block information/promotion.
- [Implemented] Scene schema v6 stores actor-only slot assignments; the explicit upgrader converts primitive, mesh-wide, and per-slot legacy values
into saved slots and deterministic deduplicated project Materials. Normal loading remains
non-writing and validation diagnoses unmigrated actor components.
- [Implemented] Model cards always use the offscreen scene studio; texture loading is texture-only.
Typed cache keys prevent cross-category collisions and static mesh inspector previews request
exact mesh-subasset renders.
### Model-asset material slot mapping
- [Implemented] Persist model-default mappings by stable slot/subasset ID.
- [Implemented] Add Content Browser model-details controls to Browse, Assign, Locate, Clear, and inspect orphans.
- [Implemented] Apply the six-layer resolution contract to static and skinned hydration.
- [Implemented] Reimport without rewriting scene overrides or resetting skinned animation state.
### Editable source-material extraction and import-policy UX
- [Implemented] Convert supported glTF/GLB/FBX PBR source values and external textures into guarded
`MaterialAsset` documents.
- [Implemented] Let each slot choose Source, Existing Project Material, Extract Editable, or Default.
- [Implemented] Integrate PBR texture-set detection from BS-JD-202 without conflating filename
grouping with model source-material conversion. The folder action now previews confidence,
supports manual roles and target merge/split, and publishes no-overwrite Material batches through
the shared transaction engine.
- [Implemented] Preview converted values, destinations, collisions, provenance, and render state.
Provenance-matched re-extraction requires an explicit diff-backed Apply or Create New choice;
Apply is fingerprint-guarded and byte-restoring, while unrelated provenance is never overwritten.
### Migration and acceptance signoff
Use a representative project workflow:
1. Create `assets/Props/Office/` in the Content Browser.
2. Import a static model and a skeletal model directly into that folder.
3. Extract one valid source material, map another slot to an existing Material Instance, and keep a
third slot on source fallback.
4. Place both models, add one scene-level material override, save, close, and reopen.
5. Move/rename the containing folder, reimport both models, and resolve a removed-slot orphan.
6. Verify unchanged UUIDs, model defaults, scene override precedence, editable Material contents,
thumbnails, selection, PIE/runtime rendering, headless validation, and release packaging.
7. Verify a failed/cancelled import or move leaves the exact pre-operation filesystem and registry.
No M2 milestone issue of any priority may remain open at signoff.
## Sequencing
1. Epic and ADR/storage contract.
2. Path-agnostic registry/type resolution foundation.
3. BS-JD-205 file operations and destination-first import.
4. DefaultGrid/project fallback and model-asset material mapping.
5. Editable extraction plus BS-JD-202 PBR grouping integration.
6. [Implemented] BS-JD-204 live refresh and BS-JD-206 headless parity.
7. Migration/native/headless/package acceptance.
[Implemented] BS-JD-208 runtime MaterialPropertyBlocks applies after resolved bases with cached
per-owner/slot handles and exact-slot transactional promotion.
Solari dynamic-deformation work remains independent and is not a prerequisite for this refactor.
## Documentation On Implementation
- [Implemented] Create and index ADR 0045; update ADR 0035 and ADR 0044 where contracts changed.
- [Implemented] Add `docs/editor/content-workspace.md` as the canonical workflow/reference document and index it
from `docs/README.md` and `docs/editor/README.md`.
- [Implemented] Update root README controls, troubleshooting, and implementation checklist.
- [Implemented] Add the M2 Content Workspace feature-level native evaluation record with capture
checksums and headless/package evidence links.
- [Pending signoff] Upload the native PNGs to Gitea and rerun the record from the exact committed
implementation revision.
## Verification Matrix
- Unit tests: path/type resolution, collision planning, slot mapping precedence, orphan
reconciliation, conversion fidelity, provenance, and migration.
- Transaction fixtures: recursive move/rename, bundle import rollback, collaboration conflict,
cancelled extraction, and external filesystem moves.
- Editor tests: file-manager actions, exact model-slot mapping, static/skinned parity, save/reopen,
and no scene dirtiness from previews.
- [Passed 2026-07-13] Focused unit/transaction/editor suites; `cargo process-assets` write followed
by read-only check over 42 assets; project validation over 97 dependencies with 0 blockers.
- [Passed 2026-07-13] Five sample projects validate with 0 blockers; repeated QA packaging reuses
unchanged files, includes/fingerprints the runtime catalog, and the native executable remains
healthy through a bounded launch smoke test.
- [Passed 2026-07-13] Development packaging publishes after accepting an equivalent legacy lock
output with a trailing separator; the regression is unit-covered, the packaged runtime catalog
is byte-identical to the headless catalog, and an eight-second native launch leaves no process
behind.
- [Passed 2026-07-13] `cargo fmt --all -- --check`, strict workspace/all-target/all-feature Clippy,
and the complete workspace/all-feature unit and documentation test suite.
- [Passed 2026-07-13] Native Content Browser selection, batch and empty-space menus, basic item
actions, managed-folder hiding, background/item interaction priority, and Details resizing; see
`docs/editor/evaluations/content-workspace-m2/`.
- [Passed 2026-07-14] All-feature workspace tests, strict all-target/all-feature Clippy, 48-asset
write/check parity, 116/121-dependency validators with no blockers, byte-identical packaged
catalog, and live mapped editor/package windows.
- [Passed locally 2026-07-14] Destination-first skeletal import and placement, broken project
fallback to DefaultGrid, and exact-slot skinned scene override. The registry was restored to the
built-in default before the final deterministic refresh.
- [Passed locally 2026-07-14] Focused Import To/review tests prove pinned destinations, no mutation
before confirmation, collision refusal, source/dependency fingerprint conflicts, and complete
textual-glTF dependency tracking. Focused promotion tests prove direct-base/exact-slot
publication, one history edit, cancel/conflict/stale-input non-mutation, schema validation, and
byte-exact file/catalog rollback after a failed scene edit.
- [Passed natively 2026-07-14] Import To selected `assets/Furniture/Office` while the browser stayed
at `assets`, the second review showed the exact target for a temporary PNG, and Cancel published
no file. Capture hashes are recorded in the M2 evaluation.
- [Passed 2026-07-14] The material-slot consistency follow-through migrated the active project to
the then-current scene schema, processed 71 assets with write/check parity, passed 330 editor tests plus the
complete all-feature workspace suite and strict Clippy, published the development package, and
kept both the live editor and packaged runtime healthy through bounded Wayland launches. Native
inspection confirmed the primitive-owned Surface Material slot and expandable shared parameters;
typed thumbnail tests confirm the Poly Haven office desk queues geometry renders rather than its
albedo texture.
- [Corrected 2026-07-14] Assigned Standard Materials now detach from the singleton emergency
handle during resolution. The regression begins with a neutral-grey hydrated handle, verifies
that fallback remains unchanged, and checks the resolved project asset's base color, metallic,
and roughness on its reference-scoped cached handle.
- [Passed natively 2026-07-17] Editor-only BRP injected a two-parameter
`MaterialPropertyBlock` into Ground's `slot:primitive:surface`; the Inspector promoted one sparse
direct-base Material Instance, assigned the exact slot through one history edit, and removed the
runtime block only after successful publication. Undo restored the prior slot, and the temporary
instance, registry, catalog, scene, and Pebble fixture were restored byte-for-byte afterward.
- [Passed on candidate tree 2026-07-17; exact-commit readback pending] Refresh/validation of
unchanged content writes no files (`process-assets --check`: 78 discovered, zero changes).
# Material authoring UI and Texture processing completion (2026-07-14)
- [x] Replace duplicated Standard fields with schema-v2 `MaterialInputSchema` and
`MaterialInputSet` documents; keep Material Instance overrides sparse.
- [x] Use one compact primitive/static/skinned material-slot widget with an embedded sphere,
assignment status/actions, responsive parameters, and diagnostics outside parameter rows.
- [x] Pair Standard Lit multipliers with textures and expose ARM/ORM, Separate Maps, and custom
channel selection.
- [x] Add registry-v3 typed Texture properties and a shared deterministic UASTC/KTX2 processor.
- [x] Canonicalize AO/Roughness/Metallic selections to R/G/B ARM and publish runtime-catalog v2
paths for Forward and Surface/Solari consumers.
- [x] Extend the explicit transactional upgrader for registry v2 and Material/Instance/Shader
Schema v1 documents; current normal loading remains non-writing.
- [ ] Codex-owned critical native acceptance covers persistent live edits, scalar Save without
processing, ARM background processing, final wide/narrow material cards, long Content Browser
labels/status, clean-value recovery retirement, restart persistence, and Forward/Solari
presentation. The user explicitly delegated this QA; low-quality UI is a failure, not
acceptable evidence.

View File

@ -1,5 +1,7 @@
# Deterministic Imported-Asset Fingerprints # Deterministic Imported-Asset Fingerprints
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
**Status:** Complete at `cbd380a9413411667a83f74b66c5a2feda5e1af7`; see **Status:** Complete at `cbd380a9413411667a83f74b66c5a2feda5e1af7`; see
[`docs/editor/evaluations/deterministic-asset-fingerprints/`](../../docs/editor/evaluations/deterministic-asset-fingerprints/). [`docs/editor/evaluations/deterministic-asset-fingerprints/`](../../docs/editor/evaluations/deterministic-asset-fingerprints/).

View File

@ -1,5 +1,7 @@
# Editor Sample Regression Pack # Editor Sample Regression Pack
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Date: 2026-07-13 Date: 2026-07-13
Issue: BS-JD-501 / Gitea #32 Issue: BS-JD-501 / Gitea #32
Milestone: M5 - Regression, docs, and first-hour UX Milestone: M5 - Regression, docs, and first-hour UX

View File

@ -1,5 +1,7 @@
# FBX External Texture Dependencies # FBX External Texture Dependencies
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
**Issue:** Gitea #58 (`BS-JD-210`) **Issue:** Gitea #58 (`BS-JD-210`)
## Goal ## Goal

View File

@ -1,5 +1,7 @@
# Guarded Shutdown And History Savepoints # Guarded Shutdown And History Savepoints
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Date: 2026-07-13 Date: 2026-07-13
Issue: BS-PR-709 / Gitea #55 Issue: BS-PR-709 / Gitea #55
Milestone: M7 - Production Readiness Milestone: M7 - Production Readiness

View File

@ -1,5 +1,7 @@
# Blacksite Editor Roadmap: Jackdaw-Inspired Feature Tickets # Blacksite Editor Roadmap: Jackdaw-Inspired Feature Tickets
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) and exact current Gitea scope instead of its original ticket drafts.
Date: 2026-06-06 Date: 2026-06-06
Target repository: `Falling-Metal-Interactive/Blacksite` on `main`. Target repository: `Falling-Metal-Interactive/Blacksite` on `main`.
@ -15,7 +17,7 @@ Blacksite already has the hard foundation pieces: an editor crate, ordered plugi
Recommended sequence: Recommended sequence:
- **M0 - Foundation and polish seams:** Make the sandbox easy to start, easy to extend internally, and safe to mutate. This is the prerequisite for bigger tools. - **M0 - Foundation and polish seams:** Make the sandbox easy to start, easy to extend internally, and safe to mutate. This is the prerequisite for bigger tools.
- **M1 - Brush-based blockout:** Add the Jackdaw-inspired level-blockout workflow: brush schema, draw/edit modes, CSG, per-face materials. - **M1 - Brush-based blockout:** Add the Jackdaw-inspired level-blockout workflow: brush schema, draw/edit modes, CSG, per-face materials.
- **M2 - Materials and asset pipeline:** Make assets feel live and production-like: material browser, PBR grouping, drag/drop assignment, reference repair, headless processing. - **M2 - Content workspace and asset pipeline:** Make project content user-organized and production-like: file-manager operations, destination-first import, model-asset material mapping and extraction, live refresh, reference repair, and headless processing. The expanded implementation contract lives in [`content_workspace_and_import_authoring_2026-07-13.plan.md`](content_workspace_and_import_authoring_2026-07-13.plan.md).
- **M3 - Terrain and physics placement:** Add larger-world authoring and practical prop placement: terrain sculpting plus physics drop/settle. - **M3 - Terrain and physics placement:** Add larger-world authoring and practical prop placement: terrain sculpting plus physics drop/settle.
- **M4 - Extensibility and runtime integration:** Turn Blacksite from a single editor crate into a future-game editor platform through static extensions and narrow remote prototypes. - **M4 - Extensibility and runtime integration:** Turn Blacksite from a single editor crate into a future-game editor platform through static extensions and narrow remote prototypes.
- **M5 - Regression, docs, and first-hour UX:** Lock in quality: samples, tests, profiling, docs, and first-run guidance. - **M5 - Regression, docs, and first-hour UX:** Lock in quality: samples, tests, profiling, docs, and first-run guidance.
@ -40,6 +42,7 @@ Recommended sequence:
| Operator framework | Blacksite has EditorHistory and EditorCommandRegistry. | Unify all mutating actions behind preview/commit/cancel/undo operators. | BS-JD-004 | | Operator framework | Blacksite has EditorHistory and EditorCommandRegistry. | Unify all mutating actions behind preview/commit/cancel/undo operators. | BS-JD-004 |
| Brushes and CSG | Blacksite has primitives/static meshes, no native brush geometry yet. | Add authoring brush data, draw/edit modes, CSG, per-face material/UV. | BS-JD-101 to BS-JD-106 | | Brushes and CSG | Blacksite has primitives/static meshes, no native brush geometry yet. | Add authoring brush data, draw/edit modes, CSG, per-face material/UV. | BS-JD-101 to BS-JD-106 |
| Material browser and PBR auto-detection | Blacksite has MaterialAsset, material overrides, asset browser, thumbnails. | Add dedicated Material Browser, texture-set detection, drag/drop material assignment. | BS-JD-201 to BS-JD-203 | | Material browser and PBR auto-detection | Blacksite has MaterialAsset, material overrides, asset browser, thumbnails. | Add dedicated Material Browser, texture-set detection, drag/drop material assignment. | BS-JD-201 to BS-JD-203 |
| Content workspace and model import authoring | The browser scans nested folders, but imports use fixed type directories and imported model defaults are not editable project mappings. | Make folders organizational, import to a chosen destination, add safe file operations, and expose editable model material defaults/extraction. | BS-JD-205, BS-JD-211 to BS-JD-217 |
| Terrain sculpting | No native terrain authoring found in inspected Blacksite editor modules. | Add heightmap/chunk terrain MVP and brush tools. | BS-JD-301 to BS-JD-303 | | Terrain sculpting | No native terrain authoring found in inspected Blacksite editor modules. | Add heightmap/chunk terrain MVP and brush tools. | BS-JD-301 to BS-JD-303 |
| Physics placement tool | Blacksite has Avian, ColliderDesc/RigidBodyDesc, visualizers, PIE sim. | Add selected-body drop/settle/commit tool and collider diagnostics. | BS-JD-304 to BS-JD-305 | | Physics placement tool | Blacksite has Avian, ColliderDesc/RigidBodyDesc, visualizers, PIE sim. | Add selected-body drop/settle/commit tool and collider diagnostics. | BS-JD-304 to BS-JD-305 |
| Dylib extensions | Blacksite has EditorPlugin, command palette, ActorInspectorSection, optional game hot reload. | Stabilize static extension API first; treat dylib as later experimental. | BS-JD-401 to BS-JD-403 | | Dylib extensions | Blacksite has EditorPlugin, command palette, ActorInspectorSection, optional game hot reload. | Stabilize static extension API first; treat dylib as later experimental. | BS-JD-401 to BS-JD-403 |
@ -71,16 +74,27 @@ Add the Jackdaw-inspired level-blockout workflow: brush schema, draw/edit modes,
- **BS-JD-105 [P1] Per-face material and UV controls** - Allow brush faces to reference textures/materials and edit UV offset, scale, and rotation. - **BS-JD-105 [P1] Per-face material and UV controls** - Allow brush faces to reference textures/materials and edit UV offset, scale, and rotation.
- **BS-JD-106 [P2] Brush validation, repair, and diagnostics** - Add robust error handling for degenerate brushes, inverted normals, zero-area faces, and non-manifold results. - **BS-JD-106 [P2] Brush validation, repair, and diagnostics** - Add robust error handling for degenerate brushes, inverted normals, zero-area faces, and non-manifold results.
### M2: Materials and asset pipeline ### M2: Content workspace and asset pipeline
Make assets feel live and production-like: material browser, PBR grouping, drag/drop assignment, reference repair, headless processing. Make project content user-organized and production-like. The original material browser, PBR grouping,
drag/drop, watcher, reference-repair, and headless-processing slices remain; destination-first import,
path-agnostic asset typing, model-asset material defaults, and editable source-material extraction are
specified in
[`content_workspace_and_import_authoring_2026-07-13.plan.md`](content_workspace_and_import_authoring_2026-07-13.plan.md).
- **BS-JD-201 [P0] Material Browser and shared material catalog** - Create a dedicated Material Browser panel for named PBR materials, scene-local materials, and project-wide material assets. - **BS-JD-201 [P0] Material Browser and shared material catalog** - Create a dedicated Material Browser panel for named PBR materials, scene-local materials, and project-wide material assets.
- **BS-JD-202 [P1] PBR texture-set auto-detection** - Detect texture sets from filenames and generate draft materials automatically. - **BS-JD-202 [P1] PBR texture-set auto-detection** - Detect texture sets from filenames and generate draft materials automatically.
- **BS-JD-203 [P0] Drag/drop material and texture application** - Make texture/material drag/drop work consistently for static mesh actors, primitive actors, and brush faces. - **BS-JD-203 [P0] Drag/drop material and texture application** - Make texture/material drag/drop work consistently for static mesh actors, primitive actors, and brush faces.
- **BS-JD-204 [P1] Live asset watcher and refresh** - Watch assets/ and refresh asset catalog, thumbnails, and material registry without manual refresh. - **BS-JD-204 [P1] Live asset watcher and refresh** - Watch assets/ and refresh asset catalog, thumbnails, and material registry without manual refresh.
- **BS-JD-205 [P1] Asset rename/move reference repair** - Track asset moves/renames and repair scene/material/prefab references. - **BS-JD-205 [P0] Content Browser file operations and reference-safe moves** - Add file-manager operations with stable identity, reference repair, and transactional rollback.
- **BS-JD-206 [P2] Headless asset processing command** - Add xtask/cargo-style command to process assets without opening the editor UI. - **BS-JD-206 [P2] Headless asset processing command** - Add xtask/cargo-style command to process assets without opening the editor UI.
- **BS-JD-211 [P0] Content workspace and import authoring refactor** - Coordinate the expanded M2 product contract and acceptance path.
- **BS-JD-212 [P0] Project content and derived-artifact contract** - Fix the storage, identity, typing, provenance, and material-resolution contract before implementation.
- **BS-JD-213 [P0] Destination-first transactional asset import** - Import or adopt content in the current or explicitly selected project folder.
- **BS-JD-214 [P0] Path-agnostic asset catalog, loading, validation, and packaging** - Remove conventional-folder semantics from every asset consumer.
- **BS-JD-215 [P0] Static and skinned model-asset material slot mappings** - Persist project Material defaults by stable imported slot ID.
- **BS-JD-216 [P1] Editable imported-material extraction and per-slot import policy** - Extract supported source materials as ordinary editable project assets without silent reimport overwrite.
- **BS-JD-217 [P0] M2 content-workspace migration and acceptance signoff** - Gate migration, native editor, headless, and packaged behavior with one representative workflow.
### M3: Terrain and physics placement ### M3: Terrain and physics placement
@ -763,38 +777,43 @@ Lock in quality: samples, tests, profiling, docs, and first-run guidance.
**Docs to update:** **Docs to update:**
- docs/editor/assets.md. - docs/editor/assets.md.
### BS-JD-205 - Asset rename/move reference repair ### BS-JD-205 - Content Browser file operations and reference-safe moves
**Milestone:** M2 **Milestone:** M2
**Priority:** P1 **Priority:** P0
**Area:** Assets **Area:** Assets
**Summary:** Track asset moves/renames and repair scene/material/prefab references. **Summary:** Turn the Content Browser into a safe project file manager while preserving stable asset identity and authored references.
**Why this matters:** General editors need robust asset references. Jackdaw has project-wide catalog concepts; Blacksite already has stable UUIDs in AssetRegistry, so this is a natural improvement. **Why this matters:** Users need to organize content entirely inside the editor without losing scene, prefab, material, model-slot, thumbnail, or registry continuity.
**Implementation notes:** **Implementation notes:**
- Treat AssetId as source of truth and path as mutable metadata. - Treat AssetId as source of truth and path as mutable metadata.
- On file watcher rename or Asset Browser rename, update AssetRecord.path and all EditorAssetRef paths where asset_id matches. - Add Create Folder, Rename, Move, Duplicate, Cut/Copy/Paste, drag-to-folder, trash, and restore.
- Add a missing-reference resolver dialog for files changed outside the editor. - Use guarded staged filesystem transactions with collision and dependency previews.
- Add Asset Browser actions: Rename, Move, Duplicate, Delete with reference impact preview. - Repair cached paths across scenes, prefabs, Materials/Instances, model material mappings, generated manifests, thumbnails, and registry metadata.
- Reconcile unambiguous external moves by stable identity and send ambiguous cases through an explicit repair flow.
- Protect editor-managed index, trash, thumbnail, and derived-artifact locations.
**Acceptance criteria:** **Acceptance criteria:**
- Renaming a material or model inside editor updates scene refs and registry. - Arbitrary nested folders and all scoped file operations work entirely in the Content Browser.
- Opening a scene with missing path but matching AssetId repairs path if registry knows it. - Moving supported authored/imported assets or a containing folder retains UUID identity and valid references after save/reopen.
- Deleting an asset warns about usages before commit. - Recursive operations preview collisions and reference impact before commit.
- Cancelled or failed operations leave the filesystem and registry byte-for-byte unchanged.
- Trash/restore retains identity; ambiguous external moves are never guessed.
**Polish details:** **Polish details:**
- Reference impact dialog lists affected scenes/entities/material slots. - Reference impact dialog lists affected scenes/entities/material slots.
- Offer 'Keep broken reference' for deliberate missing assets. - Selection, breadcrumbs, thumbnails, Material Library usage, validation, and PIE remain coherent after moves.
- Add undo for in-editor rename/move where practical. - Offer an explicit broken-reference choice when retaining a missing dependency is deliberate.
**Tests:** **Tests:**
- Registry path update tests. - Recursive transaction/rollback and registry-path tests.
- Scene ref repair tests with missing asset path. - Reference-repair fixtures across scenes, prefabs, Materials, and model mappings.
- Native drag-to-folder, restart, and external-move acceptance.
**Docs to update:** **Docs to update:**
- docs/editor/assets.md reference model. - Canonical content-workspace guide defined by the expanded M2 plan.
### BS-JD-206 - Headless asset processing command ### BS-JD-206 - Headless asset processing command

View File

@ -1,5 +1,7 @@
# Material Library And Targeted Viewport Drop # Material Library And Targeted Viewport Drop
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea issues Working implementation plan for Gitea issues
[`#16`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/16) and [`#16`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/16) and
[`#18`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/18). [`#18`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/18).

View File

@ -1,5 +1,7 @@
# Navigation Mesh Authoring, Bake Diagnostics, And Path Preview # Navigation Mesh Authoring, Bake Diagnostics, And Path Preview
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea issue Working implementation plan for Gitea issue
[`#48`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/48). [`#48`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/48).
This is the navigation production loop required by the M7 content-production milestone. This is the navigation production loop required by the M7 content-production milestone.

View File

@ -1,5 +1,7 @@
# Non-Blocking Native Dialogs # Non-Blocking Native Dialogs
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for the production-readiness defect discovered during live acceptance Working implementation plan for the production-readiness defect discovered during live acceptance
of collaborative file safety. Opening an `rfd` picker synchronously from an egui/Bevy system stops of collaborative file safety. Opening an `rfd` picker synchronously from an egui/Bevy system stops
window event processing long enough for Hyprland to report Blacksite as unresponsive. window event processing long enough for Hyprland to report Blacksite as unresponsive.

View File

@ -1,5 +1,7 @@
# Operator Invariants Completion # Operator Invariants Completion
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working plan for Gitea Working plan for Gitea
[`#33`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/33). [`#33`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/33).

View File

@ -1,5 +1,7 @@
# Physics Placement Tool - 2026-07-12 # Physics Placement Tool - 2026-07-12
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Issue: Gitea #25 (`BS-JD-304`) Issue: Gitea #25 (`BS-JD-304`)
## Outcome ## Outcome

View File

@ -1,5 +1,7 @@
# Production-Readiness Acceptance Gate # Production-Readiness Acceptance Gate
> **Active plan — desired scope and acceptance, not implementation truth.** Current shipped behavior is indexed in the [canonical documentation](../../docs/README.md).
Working plan for Gitea issue Working plan for Gitea issue
[`#50`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/50). [`#50`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/50).
This gate is broader than the M7 feature list: it proves the complete daily authoring, content, This gate is broader than the M7 feature list: it proves the complete daily authoring, content,

View File

@ -71,6 +71,8 @@ todos:
isProject: false isProject: false
--- ---
> **Superseded plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) and exact current Gitea scope.
## Project Roadmap (Plan of Plans) ## Project Roadmap (Plan of Plans)
This is the top-level strategy. Each milestone (M0-M8) becomes its own detailed sub-plan when started. Milestone M1 (Editor Build-Out) is fully contained inline in the "M1 detail" section below; later milestones get their detailed plans spun out as they begin. This is the top-level strategy. Each milestone (M0-M8) becomes its own detailed sub-plan when started. Milestone M1 (Editor Build-Out) is fully contained inline in the "M1 detail" section below; later milestones get their detailed plans spun out as they begin.
@ -212,4 +214,4 @@ M1 out of scope (later): per-field inspector undo, multi-scene tabs, full PBR ma
This roadmap is the index, and M1's full detail is contained inline above. Starting a later milestone expands its detailed scope/files/todos the same way (either inline or as a spun-out plan). M0 and M2 are the immediate next planning targets; M3 begins with a time-boxed Lightyear spike before committing. This roadmap is the index, and M1's full detail is contained inline above. Starting a later milestone expands its detailed scope/files/todos the same way (either inline or as a spun-out plan). M0 and M2 are the immediate next planning targets; M3 begins with a time-boxed Lightyear spike before committing.
### Out of scope for now ### Out of scope for now
- Concrete release dates/staffing (cadence assumptions only), console ports, peer-to-peer topology, and full anti-cheat beyond server authority. - Concrete release dates/staffing (cadence assumptions only), console ports, peer-to-peer topology, and full anti-cheat beyond server authority.

View File

@ -1,5 +1,7 @@
# Renderer Foundation Acceptance Split - 2026-07-12 # Renderer Foundation Acceptance Split - 2026-07-12
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Issue: Gitea #51 (`BS-JD-207`) Issue: Gitea #51 (`BS-JD-207`)
## Outcome ## Outcome

View File

@ -1,5 +1,7 @@
# Renderer, material, and component foundation # Renderer, material, and component foundation
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
## Goal ## Goal
Separate static and skinned renderer ownership, restore deterministic skinned edit poses, add shared Separate static and skinned renderer ownership, restore deterministic skinned edit poses, add shared

View File

@ -1,5 +1,7 @@
# Rendering Unification Plan # Rendering Unification Plan
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
## Summary ## Summary
Unify the Bevy 0.18 rendering framework around a single effective render-stack contract. Preserve Unify the Bevy 0.18 rendering framework around a single effective render-stack contract. Preserve

View File

@ -1,5 +1,7 @@
# Source-Control Status And Collaborative File Safety # Source-Control Status And Collaborative File Safety
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea issue Working implementation plan for Gitea issue
[`#49`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/49). [`#49`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/49).
This is the final M7 implementation slice before the production-readiness acceptance gate. This is the final M7 implementation slice before the production-readiness acceptance gate.

View File

@ -1,5 +1,7 @@
# Static Mesh Asset Refactor Plan # Static Mesh Asset Refactor Plan
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Date: 2026-06-05 Date: 2026-06-05
## Scope ## Scope

View File

@ -1,5 +1,7 @@
# Terrain Authoring Foundation # Terrain Authoring Foundation
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
Working implementation plan for Gitea Working implementation plan for Gitea
[`#22`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/22). [`#22`](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/22).
This establishes the persistent and hydrated terrain contract required by sculpting `#23`, layer This establishes the persistent and hydrated terrain contract required by sculpting `#23`, layer

View File

@ -1,5 +1,7 @@
# Terrain Material Layers And Weight Painting (#24) # Terrain Material Layers And Weight Painting (#24)
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
## Scope ## Scope
- Persist up to four shared Material/Material Instance references on each `TerrainDesc`. - Persist up to four shared Material/Material Instance references on each `TerrainDesc`.

View File

@ -1,5 +1,7 @@
# Terrain Sculpt Tools (#23) # Terrain Sculpt Tools (#23)
> **Historical plan — not current implementation guidance.** Use the [documentation index](../../docs/README.md) for current behavior and architecture.
## Scope ## Scope
- Add a modal terrain sculpt operator for raise, lower, flatten, smooth, and deterministic noise. - Add a modal terrain sculpt operator for raise, lower, flatten, smooth, and deterministic noise.

View File

@ -1,42 +1,13 @@
--- ---
description: Keep project documentation current—ADRs, mission, editor docs, README checklist description: Follow Blacksite repository and documentation authority rules
alwaysApply: true alwaysApply: true
--- ---
# Documentation Maintenance # Repository instructions
When changing behavior, architecture, or user-facing workflows, **update docs in the same task**—do not defer. Follow the root [`AGENTS.md`](../../AGENTS.md) and the closest subtree `AGENTS.md`. Documentation
work also follows [`docs/AGENTS.md`](../../docs/AGENTS.md), with document status and authority read
from [`docs/authority.toml`](../../docs/authority.toml).
## Doc map (single source of truth: [docs/README.md](../../docs/README.md)) This Cursor rule is intentionally only a pointer so workflow and documentation policy have one
maintained source.
| Change type | Update |
|-------------|--------|
| Architecture / crate boundary / sim-network split | New or updated ADR in `docs/adr/` |
| Editor framework intent, principles, non-goals | `docs/mission.md` |
| Editor feature design or phase status | `docs/editor/` (see its README) |
| User controls, run commands, troubleshooting | Root `README.md` |
| Shipped feature completion | Root `README.md` Implementation Checklist |
| Bevy upgrade policy | ADR 0002 + migration notes in `docs/adr/` |
| Milestone scope (pre-implementation) | `.cursor/plans/` plan file |
## ADRs
Create `docs/adr/NNNN-short-title.md` when a decision is **hard to reverse** or affects multiple crates (rendering path, scene format, PIE semantics, settings schema, netcode choice).
Format: Status, Context, Decision, Consequences. Number sequentially. Link from `docs/README.md` and root README.
## Coherence rules
- **One home per fact.** Link across docs; do not copy paragraphs between README, mission, and ADRs.
- **Intent vs implementation:** mission/ADRs = *why*; README = *how to use*; crate module docs = *local API*.
- **Plans vs permanent docs:** `.cursor/plans/` holds working roadmaps; promote stable decisions into `docs/` when implemented.
- **Stale docs are bugs.** If code contradicts docs, fix both or fix docs in the same PR/task.
- **New subsystems** get a short entry in `docs/README.md` and, if editor-facing, `docs/editor/README.md`.
## Agent checklist (end of relevant tasks)
1. Did behavior or UX change? → README controls / checklist
2. Did architecture or policy change? → ADR or mission
3. Did editor workflow change? → `docs/editor/`
4. Added a new doc file? → index in `docs/README.md`
5. Left a deliberate gap? → "Future work" in README or an ADR Consequences section—not silent omission

1
.gitattributes vendored
View File

@ -20,6 +20,7 @@
*.tga filter=lfs diff=lfs merge=lfs -text *.tga filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text *.exr filter=lfs diff=lfs merge=lfs -text
*.hdr filter=lfs diff=lfs merge=lfs -text *.hdr filter=lfs diff=lfs merge=lfs -text
*.basis filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text *.wav filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text *.mp3 filter=lfs diff=lfs merge=lfs -text

View File

@ -48,6 +48,9 @@ jobs:
- name: Check formatting - name: Check formatting
run: cargo fmt --all --check run: cargo fmt --all --check
- name: Check architecture debt ratchet
run: python scripts/codex/architecture_audit.py check
- name: Check workspace - name: Check workspace
run: cargo check --workspace --all-targets run: cargo check --workspace --all-targets

12
.gitignore vendored
View File

@ -2,9 +2,12 @@
/target/ /target/
/dist/ /dist/
# Local automation and assistant state # Local automation and assistant state. Repository instructions, Skills,
/.agents/ # configuration, and templates remain tracked.
/.codex/ /.codex/session/
/.codex/logs/
/.codex/cache/
/.codex/evidence/
# Local environment files # Local environment files
.env .env
@ -14,9 +17,12 @@
# Editor/runtime generated session state # Editor/runtime generated session state
/assets/levels/.pie_session.scn.ron /assets/levels/.pie_session.scn.ron
/assets/.trash/ /assets/.trash/
/assets/.thumbnails/
/.blacksite/backups/ /.blacksite/backups/
# Backup, temporary, and log files # Backup, temporary, and log files
__pycache__/
*.py[cod]
**/*.rs.bk **/*.rs.bk
Cargo.lock.bak Cargo.lock.bak
*.bak *.bak

58
.vscode/launch.json vendored
View File

@ -43,35 +43,6 @@
"sourceLanguages": ["rust"], "sourceLanguages": ["rust"],
"gracefulShutdown": "SIGINT" "gracefulShutdown": "SIGINT"
}, },
{
"type": "lldb",
"request": "launch",
"name": "Editor: Hot reload",
"cargo": {
"args": [
"build",
"-p",
"editor",
"--bin",
"editor",
"--features",
"dev,hot-reload"
],
"filter": { "name": "editor", "kind": "bin" },
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
"problemMatcher": "$rustc"
},
"args": [],
"env": {
"RUST_BACKTRACE": "1",
"WGPU_VALIDATION": "0",
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
},
"cwd": "${workspaceFolder}",
"terminal": "integrated",
"sourceLanguages": ["rust"],
"gracefulShutdown": "SIGINT"
},
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
@ -174,35 +145,6 @@
"sourceLanguages": ["rust"], "sourceLanguages": ["rust"],
"gracefulShutdown": "SIGINT" "gracefulShutdown": "SIGINT"
}, },
{
"type": "lldb",
"request": "launch",
"name": "Game: Hot reload",
"cargo": {
"args": [
"build",
"-p",
"game",
"--bin",
"game",
"--features",
"dev,hot-reload"
],
"filter": { "name": "game", "kind": "bin" },
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
"problemMatcher": "$rustc"
},
"args": [],
"env": {
"RUST_BACKTRACE": "1",
"WGPU_VALIDATION": "0",
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
},
"cwd": "${workspaceFolder}",
"terminal": "integrated",
"sourceLanguages": ["rust"],
"gracefulShutdown": "SIGINT"
},
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",

106
.vscode/tasks.json vendored
View File

@ -35,9 +35,15 @@
}, },
{ {
"label": "cargo clippy (launch feature matrix)", "label": "cargo clippy (launch feature matrix)",
"type": "cargo", "type": "shell",
"command": "clippy", "command": "python",
"args": [ "args": [
"scripts/codex/cargo_lane.py",
"exec",
"hot-reload",
"--",
"cargo",
"clippy",
"-p", "-p",
"editor", "editor",
"-p", "-p",
@ -101,52 +107,34 @@
"group": "build" "group": "build"
}, },
{ {
"label": "clean dev-link crates", "label": "build storage status",
"type": "cargo",
"command": "clean",
"args": ["-p", "editor", "-p", "game", "-p", "game_hot", "-p", "shared"],
"options": {
"cwd": "${workspaceFolder}",
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
},
"problemMatcher": []
},
{
"label": "clean build editor (dev)",
"dependsOrder": "sequence",
"dependsOn": ["clean dev-link crates", "build editor (dev fast-link)"],
"problemMatcher": [],
"group": "build"
},
{
"label": "target cleanup (dry run)",
"type": "shell", "type": "shell",
"command": "cargo clean-target", "command": "python",
"args": ["scripts/codex/build_storage.py", "status"],
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}"
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
}, },
"problemMatcher": [], "problemMatcher": [],
"group": "build" "group": "build"
}, },
{ {
"label": "target cleanup (safe apply)", "label": "build storage prune (dry run)",
"type": "shell", "type": "shell",
"command": "cargo clean-target --apply", "command": "python",
"args": ["scripts/codex/build_storage.py", "prune", "--dry-run"],
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}"
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
}, },
"problemMatcher": [], "problemMatcher": [],
"group": "build" "group": "build"
}, },
{ {
"label": "target cleanup (deep stale, 3 days)", "label": "build storage prune (apply)",
"type": "shell", "type": "shell",
"command": "cargo clean-target --include-artifacts --days 3 --apply", "command": "python",
"args": ["scripts/codex/build_storage.py", "prune", "--apply"],
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}"
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
}, },
"problemMatcher": [], "problemMatcher": [],
"group": "build" "group": "build"
@ -185,9 +173,15 @@
}, },
{ {
"label": "run editor (hot reload)", "label": "run editor (hot reload)",
"type": "cargo", "type": "shell",
"command": "run", "command": "python",
"args": [ "args": [
"scripts/codex/cargo_lane.py",
"exec",
"hot-reload",
"--",
"cargo",
"run",
"-p", "-p",
"editor", "editor",
"--bin", "--bin",
@ -199,8 +193,7 @@
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"RUST_BACKTRACE": "1", "RUST_BACKTRACE": "1",
"WGPU_VALIDATION": "0", "WGPU_VALIDATION": "0"
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
} }
}, },
"problemMatcher": ["$rustc"], "problemMatcher": ["$rustc"],
@ -208,15 +201,27 @@
}, },
{ {
"label": "run game (hot reload)", "label": "run game (hot reload)",
"type": "cargo", "type": "shell",
"command": "run", "command": "python",
"args": ["-p", "game", "--bin", "game", "--features", "dev,hot-reload"], "args": [
"scripts/codex/cargo_lane.py",
"exec",
"hot-reload",
"--",
"cargo",
"run",
"-p",
"game",
"--bin",
"game",
"--features",
"dev,hot-reload"
],
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"env": { "env": {
"RUST_BACKTRACE": "1", "RUST_BACKTRACE": "1",
"WGPU_VALIDATION": "0", "WGPU_VALIDATION": "0"
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
} }
}, },
"problemMatcher": ["$rustc"], "problemMatcher": ["$rustc"],
@ -259,10 +264,23 @@
{ {
"label": "watch game_hot (hot reload)", "label": "watch game_hot (hot reload)",
"type": "shell", "type": "shell",
"command": "cargo watch -w crates/game_hot -w crates/sim -x \"build -p game_hot --features dylib\"", "command": "python",
"args": [
"scripts/codex/cargo_lane.py",
"exec",
"hot-reload",
"--",
"cargo",
"watch",
"-w",
"crates/game_hot",
"-w",
"crates/sim",
"-x",
"build -p game_hot --features dylib"
],
"options": { "options": {
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}"
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
}, },
"problemMatcher": ["$rustc"], "problemMatcher": ["$rustc"],
"group": "build", "group": "build",

191
AGENTS.md
View File

@ -1,35 +1,174 @@
# Agent Instructions # Blacksite Codex operating rules
## Documentation Maintenance ## Sources of truth
When changing behavior, architecture, or user-facing workflows, update documentation in the same task. Do not defer documentation updates for implemented work. For desired scope and acceptance:
Use `docs/README.md` as the documentation map and keep each fact in one home: 1. The user's latest instruction.
2. The current Gitea issue, epic, and milestone scope, including newer explicit scope-change comments.
3. The active implementation plan, when one exists.
| Change type | Update | For actual implemented behavior:
|-------------|--------|
| Architecture, crate boundaries, or sim/network split | New or updated ADR in `docs/adr/` |
| Editor framework intent, principles, or non-goals | `docs/mission.md` |
| Editor feature design or phase status | `docs/editor/` |
| User controls, run commands, or troubleshooting | Root `README.md` |
| Shipped feature completion | Root `README.md` implementation checklist |
| Bevy upgrade policy | ADR 0002 and migration notes in `docs/adr/` |
| Milestone scope before implementation | `.cursor/plans/` plan file |
Create an ADR in `docs/adr/NNNN-short-title.md` when a decision is hard to reverse or affects multiple crates, such as rendering path, scene format, PIE semantics, settings schema, or netcode choice. Use this format: Status, Context, Decision, Consequences. Number ADRs sequentially and link new ADRs from `docs/README.md` and the root README when relevant. 1. Current source code and schemas.
2. Current tests and deterministic generated outputs.
3. Current native acceptance evidence.
4. Canonical current documentation.
Coherence rules: For architecture:
- One home per fact. Link across docs; do not copy paragraphs between README, mission, and ADRs. 1. Accepted ADRs.
- Intent vs implementation: mission/ADRs explain why, README explains how to use, crate module docs explain local API. 2. Current public types and dependency boundaries.
- Plans vs permanent docs: `.cursor/plans/` holds working roadmaps; promote stable decisions into `docs/` when implemented. 3. Canonical architecture documentation.
- Stale docs are bugs. If code contradicts docs, fix both or fix docs in the same PR/task.
- New subsystems get a short entry in `docs/README.md` and, if editor-facing, `docs/editor/README.md`.
End-of-task checklist for relevant implementation work: Before using repository documentation as design guidance, read `docs/authority.toml`. Historical
plans, evaluations, session logs, archived docs, and superseded docs are not current implementation
guidance. When sources conflict, do not silently blend them. Reconcile current code, canonical docs,
active tracker scope, and the user's latest direction.
1. Did behavior or UX change? Update README controls or checklist. ## Work modes and remote authority
2. Did architecture or policy change? Update or create an ADR or mission note.
3. Did an editor workflow change? Update `docs/editor/`. - "Plan", "audit", "investigate", "review", and "propose" are read-only unless the user explicitly
4. Added a new doc file? Index it in `docs/README.md`. authorizes mutation.
5. Left a deliberate gap? Record it as future work in README or an ADR Consequences section. - "Implement", "fix", "apply", and equivalent wording authorize local repository edits.
- Do not push, force-push, close tracker items, create tracker items, or change milestone scope without
authority from `.codex/workflow.toml` or a direct user instruction.
- Routine Gitea comments and checklist synchronization may occur only through
`blacksite-gitea-sync` and within its configured permissions.
## Start of task
1. Read `.codex/session/STATE.md` when it exists.
2. Verify repository root, canonical real path, branch, HEAD, dirty state, and relevant active
processes.
3. Read the closest applicable `AGENTS.md` files.
4. Read only canonical docs for the affected topic as classified by `docs/authority.toml`.
5. Read exact linked Gitea items when the task is tracked.
6. Establish the goal, acceptance criteria, non-goals, affected subsystem, and verification tier.
Do not repeat broad repository discovery when valid session state already exists.
## User steering and scope deltas
User steering is authoritative. When the target changes materially:
1. Record a scope delta in `.codex/session/STATE.md`.
2. Classify it as an active-slice refinement, discovered blocker, added acceptance criterion, or
separate follow-up.
3. Record which evidence remains valid and which gates are invalidated.
4. Synchronize active tracker scope/status through the configured workflow when appropriate.
5. Continue without rerunning unrelated gates or rediscovering the repository.
A missing product behavior found during native acceptance is not unrelated merely because it was
absent from the first prompt.
## Token and context discipline
- Search before reading large files; use targeted ranges and do not reread unchanged files.
- Keep raw command output in `.codex/logs/`; report concise results and bounded actionable excerpts.
- Never dump full issue lists, accessibility trees, desktop state, or build logs when exact queries
are available.
- Keep `.codex/session/STATE.md` current for compaction, reconnects, and path remapping.
- Use subagents only for narrow independent work that does not duplicate repository context.
## Architecture for fast iteration
- Minimize technical debt at the point of change. New behavior belongs in the smallest owning
domain module; an already-large file is not permission to grow it.
- Keep Inspector and Content Browser panel shells thin and dispatch through registered/domain
extension seams. Run `python scripts/codex/architecture_audit.py check` for production changes.
- Architecture-audit exceptions must name a tracker issue, rationale, hard cap, extraction target,
and expiry milestone; passing with an exception is not completion evidence.
- Keep UI-independent logic out of the heavy editor UI crate when practical.
- Prefer `shared`, `content_pipeline`, or another lightweight core crate for schemas, transactions,
classification, import planning, validation, and deterministic processing.
- The editor renders state and dispatches operations; it should not own reusable headless logic.
- `xtask` and headless processors must not depend on the editor crate.
- Put non-rendering tests in the lightest crate that owns the invariant.
- Do not add Bevy rendering dependencies to headless code without a proven requirement.
## Verification
Use `blacksite-selective-verify` and its verification matrix.
- **Fast loop:** formatting as needed, affected-package check, and focused tests.
- **Slice gate:** affected-package tests and Clippy plus relevant domain checks.
- **Candidate gate:** full workspace/all-feature tests and lint, deterministic content checks,
validators, packaging, and named native scenarios.
Do not run the candidate gate during ordinary iteration. Do not run a full workspace check directly
before a full workspace test unless it covers an otherwise-uncompiled target. Do not rerun a passed
gate when its inputs are unchanged. Never use unscoped `cargo clean`; scoped lane deletion is allowed
only through the build-storage workflow. Keep toolchain, features, profile, target, build directory,
and `RUSTFLAGS` stable within a lane.
## Build artifacts and disk budget
- Every Codex Cargo invocation runs through `scripts/codex/verify.py` or
`scripts/codex/cargo_lane.py`.
- Do not invent ad hoc target directories.
- Use one persistent ordinary-development cache. Candidate, all-feature/hot-reload, full-debug,
cross-target, and package caches are exceptional lanes with explicit retention limits.
- Run `scripts/codex/build_storage.py enforce --phase pre` before a heavy build and `--phase post`
afterward.
- Do not contaminate the persistent lane with a different feature set, profile, target, wrapper,
linker configuration, or `RUSTFLAGS`.
- Preserve required binaries/evidence before pruning a disposable lane.
- Never delete individual files from Cargo's `deps`, `.fingerprint`, `build`, or `incremental`
layouts by age. Delete only a complete verified workflow-managed lane.
- At the hard limit or free-space floor, stop starting heavy builds, prune safe expired lanes, and
schedule a persistent-lane reset at a safe slice boundary if still required.
## Documentation maintenance
Update documentation in the same task when behavior, architecture, or user workflows change, but
publish canonical updates at a stable slice boundary rather than after every tiny edit. Use
`blacksite-doc-integrity`; classify every document in `docs/authority.toml`; and treat historical
plans and evidence as records, not current requirements.
| Change type | Canonical home |
|-------------|----------------|
| Architecture or crate boundary | Accepted ADR in `docs/adr/` |
| Editor framework intent or non-goals | `docs/mission.md` |
| Editor feature workflow | `docs/editor/` |
| User controls, commands, troubleshooting | Root `README.md` |
| Shipped feature completion | Root README implementation checklist |
| Bevy upgrade policy | ADR 0002 and its migration notes |
| Milestone scope before implementation | An active `.cursor/plans/` plan |
Keep one home per fact. Link instead of copying contracts across README, guides, plans, ADRs, and
tracker bodies. New subsystems must be indexed in `docs/README.md` and, when editor-facing,
`docs/editor/README.md`. Record deliberate gaps as future work in the owning canonical doc or an ADR
Consequences section.
## Gitea
- Read exact linked issues, epics, and milestones; avoid broad unfiltered listing.
- Distinguish Implementing, Engineering-complete, Acceptance-in-progress, Candidate-ready, and
Closed.
- Add at most one meaningful tracker update per completed slice or material scope change.
- Do not mark criteria complete without code/test/native evidence, and do not call an issue complete
from a dirty worktree.
- Closure requires a nominated commit and configured release evidence.
- Keep epic checklists and milestone composition aligned with material child-scope changes.
## Native editor quality
Use `blacksite-editor-ux` for editor UX changes and `blacksite-native-qa` for interactive evidence.
Automated tests are not user acceptance. For UI work, exercise the rendered interaction flow and
relevant empty, selection, invalid, read-only, narrow-layout, cancel, undo, and restart states. Honor
an explicit user instruction that they will perform visual QA.
## Completion states
Use these states precisely:
- Implementing
- Engineering-complete
- Acceptance-in-progress
- Candidate-ready
- Accepted/closed
Do not say "complete" when only engineering checks pass. Once the current acceptance target is met,
stop broad adjacent auditing unless a shared invariant requires a bounded sibling audit or the user
asks for more.

740
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,14 @@
[workspace] [workspace]
members = [ members = [
"crates/blacksite_surface", "crates/blacksite_surface",
"crates/content_pipeline",
"crates/editor_ui",
"crates/game", "crates/game",
"crates/game_hot", "crates/game_hot",
"crates/material_schema",
"crates/shared", "crates/shared",
"crates/editor", "crates/editor",
"crates/ui_gallery",
"crates/protocol", "crates/protocol",
"crates/sim", "crates/sim",
"crates/settings", "crates/settings",
@ -29,6 +33,8 @@ avian3d = { version = "0.7", default-features = false, features = [
] } ] }
bevy = { version = "0.19", features = [ bevy = { version = "0.19", features = [
"serialize", "serialize",
"basis-universal",
"ktx2",
"jpeg", "jpeg",
"vorbis", "vorbis",
"wav", "wav",
@ -38,11 +44,16 @@ bevy = { version = "0.19", features = [
bevy_core_pipeline = "0.19" bevy_core_pipeline = "0.19"
bevy_solari = "0.19" bevy_solari = "0.19"
blacksite_surface = { path = "crates/blacksite_surface" } blacksite_surface = { path = "crates/blacksite_surface" }
content_pipeline = { path = "crates/content_pipeline" }
bevy_ufbx = "0.18.1-rc.1" bevy_ufbx = "0.18.1-rc.1"
bevy_egui = "0.40" bevy_egui = "0.40"
egui = "0.34.3"
eframe = { version = "0.34.1", default-features = false, features = ["default_fonts", "glow", "wayland", "x11"] }
bevy-inspector-egui = "0.37" bevy-inspector-egui = "0.37"
egui_dock = { version = "0.19.1", features = ["serde"] } egui_dock = { version = "0.19.1", features = ["serde"] }
egui_phosphor_icons = { version = "0.3.1", default-features = false } egui_phosphor_icons = { version = "0.3.1", default-features = false, features = ["bold", "fill"] }
editor_ui = { path = "crates/editor_ui" }
material_schema = { path = "crates/material_schema" }
transform-gizmo-bevy = "0.9" transform-gizmo-bevy = "0.9"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
nav_glam = { package = "glam", version = "=0.30.10", features = ["serde"] } nav_glam = { package = "glam", version = "=0.30.10", features = ["serde"] }

150
README.md
View File

@ -17,6 +17,33 @@ native Bevy scene save/load, and BRP support for external tooling.
- A Vulkan-capable GPU + drivers (developed against an NVIDIA RTX 3080 Ti) - A Vulkan-capable GPU + drivers (developed against an NVIDIA RTX 3080 Ti)
- Linux build deps for `winit`/`wgpu` (ALSA, udev, etc.) if not already present - Linux build deps for `winit`/`wgpu` (ALSA, udev, etc.) if not already present
## Repository Workflow
[`docs/authority.toml`](docs/authority.toml) classifies current documentation, active plans,
evidence, historical records, and superseded material. The complete workflow and policy index is
[`docs/workflow/codex-workflow.md`](docs/workflow/codex-workflow.md). Validate documentation changes
with `python scripts/codex/docs_audit.py`.
Codex compile/test work uses `scripts/codex/verify.py` and `scripts/codex/cargo_lane.py` so focused
checks reuse one stable development lane and broad candidate gates run only when explicitly
nominated. The direct Cargo examples below remain contributor commands, not an instruction to rerun
the full set after every edit.
| Workflow action | Command |
|-----------------|---------|
| Start a resumable task | `python scripts/codex/state.py init --goal "..." --accept "..." --slice "..." --next "..."` |
| Resume | `python scripts/codex/state.py resume` |
| Preview / run focused verification | `python scripts/codex/verify.py plan` / `python scripts/codex/verify.py fast` |
| Run a stable slice gate | `python scripts/codex/verify.py slice` |
| Inspect build storage | `python scripts/codex/build_storage.py status` |
| Run storage preflight / postflight | `python scripts/codex/build_storage.py enforce --phase pre` / `python scripts/codex/build_storage.py enforce --phase post` |
| Preview / apply safe pruning | `python scripts/codex/build_storage.py prune --dry-run` / `python scripts/codex/build_storage.py prune --apply` |
| Preserve a candidate before expiry | `python scripts/codex/build_storage.py mark-candidate-preserved --evidence <manifest> --artifact <binary-or-package>` |
| Audit documentation | `python scripts/codex/docs_audit.py` |
| Preview a named native scenario without launching | `bash scripts/codex/native_qa.sh plan material-slot-live-edit` |
| Sync tracker state | Ask Codex to use `blacksite-gitea-sync` in `read`, `plan`, or authorized `status` mode for exact issue IDs |
| Nominate / verify a candidate | `python scripts/codex/state.py nominate --commit <sha>` then `python scripts/codex/verify.py candidate` |
## Running ## Running
```bash ```bash
@ -29,6 +56,9 @@ cargo test --workspace
cargo validate-levels cargo validate-levels
cargo validate-samples cargo validate-samples
cargo bake-navigation --project . --check cargo bake-navigation --project . --check
cargo process-assets --project . --check
# Refresh registry v3 and the stripped runtime content catalog after external content changes
cargo process-assets --project .
# Validate one artifact without opening a game window # Validate one artifact without opening a game window
cargo run -p game -- --validate-navigation assets/navigation/generated/navigation_showcase_humanoid.nav.ron cargo run -p game -- --validate-navigation assets/navigation/generated/navigation_showcase_humanoid.nav.ron
# Machine-readable project dependency and finding report # Machine-readable project dependency and finding report
@ -59,7 +89,15 @@ cargo run -p editor --bin project_launcher --features dev
The installed **Blacksite Editor** desktop entry also exposes **Open Project Browser** from its The installed **Blacksite Editor** desktop entry also exposes **Open Project Browser** from its
desktop action menu. In the editor, **File > Switch Project...** uses the guarded Save All / Discard / desktop action menu. In the editor, **File > Switch Project...** uses the guarded Save All / Discard /
Cancel shutdown path before opening the same browser; choosing a project starts a fresh editor Cancel shutdown path before opening the same browser; choosing a project starts a fresh editor
process with that root. process with that root. A normal desktop click incrementally builds the editor and project browser
through Blacksite's persistent managed development lane before launching, so saved Rust changes are
always represented by the opened binary. The splash reports exact resolved-crate progress while
Cargo reuses warm artifacts; a build or storage-preflight failure leaves the splash open with an
actionable log. Run `~/.local/bin/blacksite-editor --build-only` to perform the same managed update
without opening the editor. Clicking the shortcut while an editor is open still performs the update
check. If the executable changed, Blacksite protects unsaved work by focusing the running process
and showing an explicit close-and-reopen notification instead of terminating it or pretending that
it has hot-swapped to the new binary.
### Hot reload (gameplay iteration) ### Hot reload (gameplay iteration)
@ -70,14 +108,17 @@ Add `--features hot-reload` for **in-process hot reload** of [`game_hot`](crates
**Two-terminal workflow (hot reload):** **Two-terminal workflow (hot reload):**
```bash ```bash
# Terminal 1 — rebuild the hot dylib on save # Terminal 1 — rebuild the hot dylib on save in the managed hot-reload lane
cargo watch -w crates/game_hot -w crates/sim -x "build -p game_hot --features dylib" python scripts/codex/cargo_lane.py exec hot-reload -- cargo watch -w crates/game_hot -w crates/sim -x "build -p game_hot --features dylib"
# Terminal 2 — run the editor once # Terminal 2 — run the editor once in the same lane
cargo run -p editor --features dev,hot-reload python scripts/codex/cargo_lane.py exec hot-reload -- cargo run -p editor --features dev,hot-reload
``` ```
Or use the VS Code task **watch game_hot (hot reload)** alongside **run editor (hot reload)**, or choose **Editor: Hot reload** in Run and Debug. The watcher task requires `cargo-watch` (`cargo install cargo-watch --locked`). Or use the VS Code task **watch game_hot (hot reload)** alongside **run editor (hot reload)**. The
managed tasks intentionally replace the former CodeLLDB hot-reload launch so lane-specific runtime
paths are never guessed. The watcher task requires an existing `cargo-watch` installation; this
workflow never installs it implicitly.
| Input | Action | | Input | Action |
|-------|--------| |-------|--------|
@ -90,24 +131,44 @@ Or use the VS Code task **watch game_hot (hot reload)** alongside **run editor (
> Note: the workspace uses the `mold` linker via `clang` (see `.cargo/config.toml`) for fast link times. > Note: the workspace uses the `mold` linker via `clang` (see `.cargo/config.toml`) for fast link times.
### Focused editor UI iteration
Use the lightweight gallery when changing shared Inspector/design-system components instead of
restarting the project editor for every visual edit:
```bash
python scripts/editor/ui_gallery.py watch
```
The gallery renders the production `editor_ui` components without loading a project, scene,
renderer, or gameplay runtime. It includes exact Materials 620/420 and Renderer 760/480 presets,
direct Penpot side-by-side/overlay/difference views, representative material states, and live
theme/material fixture reload. Rust edits rebuild the focused dependency closure with a bounded
`resolved/rebuilt` counter; the last-good gallery stays open unless its replacement launches
successfully. See the [Editor Design System](docs/editor/design-system.md#focused-ui-gallery-workflow)
for shortcuts, fixtures, and acceptance rules.
### Target Cache Cleanup ### Target Cache Cleanup
Cargo/Bevy debug artifacts can grow quickly. Use the workspace cleanup task before reaching for a full `cargo clean`: Cargo/Bevy artifacts are managed as whole, sentinel-marked build lanes. Inspect and plan cleanup
before applying it:
| Command | Effect | | Command | Effect |
|---------|--------| |---------|--------|
| `cargo clean-target` | Dry run: prints reclaimable `target/` cache. | | `python scripts/codex/build_storage.py status` | Measure repository output, managed lanes, package caches, and free space. |
| `cargo clean-target --apply` | Safe cleanup: removes incremental and rust-analyzer flycheck cache. | | `python scripts/codex/build_storage.py plan` | Explain policy actions without deleting anything. |
| `cargo clean-target --include-artifacts --days 3 --apply` | Deeper cleanup: also removes stale hashed `deps`, `build`, `.fingerprint`, and example artifacts older than 3 days. Cargo will rebuild anything still needed. | | `python scripts/codex/build_storage.py enforce --phase pre` | Enforce budgets before a heavy command; under pressure, prune only expired verified disposable lanes after printing their checked plan. |
| `python scripts/codex/build_storage.py enforce --phase post` | Recheck after the command and apply the same bounded expired-lane policy. |
| `python scripts/codex/build_storage.py prune --dry-run` | Byte-count expired disposable lanes after path/sentinel safety checks. |
| `python scripts/codex/build_storage.py prune --apply` | Remove only the verified complete lanes shown by the dry run. |
| `python scripts/codex/build_storage.py reset-lane <lane> --dry-run` | Preview an explicit whole-lane reset. |
| `python scripts/codex/build_storage.py reset-lane <lane> --apply` | Apply that explicit whole-lane reset only after reviewing its printed dry run. |
| `python scripts/codex/build_storage.py mark-candidate-preserved --evidence <manifest> --artifact <binary-or-package>` | Hash evidence and at least one preserved artifact outside the candidate lane before that lane can expire. |
Use the safe cleanup during normal iteration and the three-day deep cleanup after Bevy upgrades, Do not use an unscoped `cargo clean` as a troubleshooting reflex. Never delete individual Cargo
feature-matrix builds, or large test runs. The cutoff preserves recent artifacts and avoids the full `deps`, `.fingerprint`, `build`, or `incremental` files by age; preserve nominated binaries/evidence
rebuild caused by `cargo clean`. The workspace test profile keeps line tables but disables full test and remove only an entire verified disposable lane. See the
debuginfo and incremental test caches, so routine test binaries stay materially smaller without [build-storage policy](docs/workflow/build-storage-policy.md).
reducing normal editor debugging fidelity. The cleanup binary deliberately excludes the scene/Bevy
validation dependency; `cargo clean-target` therefore stays cheap even from a cold target. Use
`cargo validate-levels` when level and prefab-graph validation is required. VS Code tasks expose dry-run, safe, and
deep-stale variants.
### Launch Troubleshooting ### Launch Troubleshooting
@ -115,7 +176,10 @@ deep-stale variants.
- If the window maps but appears transparent on Hyprland or another Wayland compositor, launch with `BEVY_FPS_HDR=0` to force the SDR camera path while debugging monitor/compositor behavior. - If the window maps but appears transparent on Hyprland or another Wayland compositor, launch with `BEVY_FPS_HDR=0` to force the SDR camera path while debugging monitor/compositor behavior.
- Bevy 0.19 removed the prior local `bevy_render` swapchain-timeout patch; launch troubleshooting should start from current wgpu/driver/compositor logs. - Bevy 0.19 removed the prior local `bevy_render` swapchain-timeout patch; launch troubleshooting should start from current wgpu/driver/compositor logs.
- Normal Debug and run configurations preserve project HDR and set `WGPU_VALIDATION=0` to suppress known Bevy/Solari Vulkan memory-model VUID noise on this stack. Use **GPU validation** when actively debugging renderer work; it forces `WGPU_VALIDATION=1` and may report those known upstream/driver messages. Use **SDR fallback** for compositor/HDR mapping failures; it additionally sets `BEVY_FPS_HDR=0`. - Normal Debug and run configurations preserve project HDR and set `WGPU_VALIDATION=0` to suppress known Bevy/Solari Vulkan memory-model VUID noise on this stack. Use **GPU validation** when actively debugging renderer work; it forces `WGPU_VALIDATION=1` and may report those known upstream/driver messages. Use **SDR fallback** for compositor/HDR mapping failures; it additionally sets `BEVY_FPS_HDR=0`.
- If **CodeLLDB / mold** fails with hundreds of `undefined symbol` linker errors, the incremental `target/` cache is stale. Run the VS Code task **clean build editor (dev)** or `cargo clean -p editor -p game -p game_hot -p shared && cargo build -p editor --bin editor --features dev`, then launch **Editor: Debug** again. Use `cargo run -p editor --features dev` from the terminal if you need `libbevy_dylib` on `LD_LIBRARY_PATH` automatically. - If **CodeLLDB / mold** fails with hundreds of `undefined symbol` linker errors, inspect the active
lane signature first. Preview a development-lane reset with
`python scripts/codex/build_storage.py reset-lane hot-reload --dry-run`, apply it only at a safe
slice boundary, then rebuild through `python scripts/codex/cargo_lane.py exec hot-reload -- cargo build -p editor --bin editor --features dev`.
## Editor Controls ## Editor Controls
@ -152,13 +216,14 @@ deep-stale variants.
| Viewport selection/orientation HUD | Identify the primary selection, multi-selection count, overlapping-pick position, camera axes, shading mode, and active render path | | Viewport selection/orientation HUD | Identify the primary selection, multi-selection count, overlapping-pick position, camera axes, shading mode, and active render path |
| Click Player visualizer in Edit mode | Select or create the authored `PlayerSpawn` (`Player Start`) | | Click Player visualizer in Edit mode | Select or create the authored `PlayerSpawn` (`Player Start`) |
| Select Project Sun | Inspect project default lighting; create a scene sun override | | Select Project Sun | Inspect project default lighting; create a scene sun override |
| Asset Browser project/file views | Browse `assets/`, search/filter/sort models, textures, materials, audio clips, levels, and prefabs; switch grid/list; expand model subassets; inspect file details; audition audio; drag supported assets/submeshes into the viewport | | Content Browser project/file views | Browse `assets/` through a dense file-manager workspace: wide layouts keep navigation, breadcrumbs, import/new, search/filter, and view controls in one 55 px row; expanded widths also expose sort and thumbnail scale directly, while compact layouts use an 88 px two-row toolbar with Sources/Details drawers; folders and assets share one continuous card flow; search/filter/sort models, textures, materials, audio clips, levels, and prefabs; switch grid/list; expand model subassets; inspect file details; resize the wide Details pane by dragging its divider (double-click resets it); use click/Ctrl/Shift multi-selection and item/empty-space context menus; audition audio; drag supported assets/submeshes into the viewport |
| Drag audio clip into viewport | Create an authored audio source; when an audio source is selected, assign the clip instead | | Drag audio clip into viewport | Create an authored audio source; when an audio source is selected, assign the clip instead |
| Asset Browser context/details actions | Apply textures/materials, regenerate thumbnails, reimport models, place assets/submeshes, or move file assets to `assets/.trash/` | | Content Browser context/details actions | Preview affected IDs/reference rewrites, then create folders or Materials in the current folder; rename, duplicate, cut/copy/paste or drag-to-folder; undo an unchanged content move; use **Import Here** or **Import To...** and review every source dependency/final target before committing; review/group loose PBR textures into editable Materials; assign/locate/clear per-slot model materials and resolve preserved reimport orphans; extract editable glTF/GLB/FBX PBR materials, explicitly diff/apply or create-new on re-extraction, and atomically map their source slots; regenerate thumbnails; reimport; place assets/submeshes; or trash and collision-guarded restore complete deletion batches |
| Texture Details | Set semantic and sRGB/Linear intent, mip policy, Basis UASTC or uncompressed KTX2 output, size limit, filtering, wrapping, anisotropy, and OpenGL/DirectX normal convention; **Apply & Reprocess** publishes derived runtime data without altering the source image |
| Window → Material Library | Search/filter project Materials and Material Instances, inspect scene usage and dependency health, create/edit shared assets, and drag them into the viewport | | Window → Material Library | Search/filter project Materials and Material Instances, inspect scene usage and dependency health, create/edit shared assets, and drag them into the viewport |
| Drag Material/Instance onto viewport surface | Preview and assign the exact renderer slot, primitive, or brush face under the pointer; release commits one undo step, while Escape/right-click/outside restores the preview | | Drag Material/Instance onto viewport surface | Preview and assign the exact primitive/static/skinned slot or brush face under the pointer; release commits one undo step, while Escape/right-click/outside restores the preview |
| Drag Texture onto viewport surface | Set a primitive base-color texture or exact brush face; renderer slots reject loose textures and direct you to a Material Instance | | Drag Texture onto viewport surface | Primitive/static/skinned slots reject loose textures and explain that a Material/Instance is required; brush faces retain their specialized direct-texture path |
| Static/Skinned Mesh Renderer material slots | Assign a shared Material/Material Instance per slot; Browse/Select/Locate the reference, or Clear the override to restore the imported source material | | Primitive/Static/Skinned material slots | Use the same Penpot-led material panel: Drop or Browse a shared Material/Instance; Clear returns to model source, project default, or DefaultGrid; expand the panel for immediate shared-handle updates that mark the asset **UNSAVED** without writing on release, then use contextual Save/Save All; use **Create Instance and Assign** for actor variation or **Extract Editable…** for one imported source slot; runtime property-block promotion remains exact-slot and transactional |
| `Ctrl+P` | Centered command palette; search human labels or stable command IDs, use arrow keys to select, Enter to run | | `Ctrl+P` | Centered command palette; search human labels or stable command IDs, use arrow keys to select, Enter to run |
| `F7` | While paused in Play: advance one sim tick | | `F7` | While paused in Play: advance one sim tick |
| Shift/Ctrl + click (Hierarchy) | Additive selection | | Shift/Ctrl + click (Hierarchy) | Additive selection |
@ -332,7 +397,8 @@ the current process without changing preferences.
Clean editor exits restore the last authored scene, panel visibility, and viewport bookmarks from Clean editor exits restore the last authored scene, panel visibility, and viewport bookmarks from
the versioned machine-local session document. After an abnormal exit, Blacksite opens the safe the versioned machine-local session document. After an abnormal exit, Blacksite opens the safe
startup scene and asks whether to **Resume Last Scene** or **Continue Safe**; modal tools and dirty startup scene and asks whether to **Resume Last Scene** or **Continue Safe**; modal tools and dirty
preview state are never restored. Session metadata lives under preview state are never restored. The recovery prompt is modal and blocks interaction with the
safe scene until one of those choices is made. Session metadata lives under
`$XDG_STATE_HOME/blacksite-editor/session.ron` or `~/.local/state/blacksite-editor/session.ron` and `$XDG_STATE_HOME/blacksite-editor/session.ron` or `~/.local/state/blacksite-editor/session.ron` and
contains no scene contents or credentials. See [ADR 0024](docs/adr/0024-versioned-editor-session-state.md). contains no scene contents or credentials. See [ADR 0024](docs/adr/0024-versioned-editor-session-state.md).
@ -361,7 +427,10 @@ The `.vscode/` folder is preconfigured:
- `settings.json` runs `clippy` on save, enables proc-macro/build-script support, formats on save, - `settings.json` runs `clippy` on save, enables proc-macro/build-script support, formats on save,
and excludes `target/` from search/watch. and excludes `target/` from search/watch.
- `tasks.json` mirrors the full workspace formatting, all-target check, strict Clippy, test, level-validation, build/run, hot-reload, and target-cleanup workflows. **build editor (dev fast-link)** is the default build task. - `tasks.json` mirrors the full workspace formatting, all-target check, strict Clippy, test, level-validation, build/run, hot-reload, and target-cleanup workflows. **build editor (dev fast-link)** is the default build task.
- `launch.json` uses CodeLLDB Cargo artifact filtering for editor/game Debug, GPU-validation, hot-reload, SDR fallback, and Release configurations. Normal launches keep HDR enabled while quieting known Vulkan validation noise; dynamic-link launches set the required `LD_LIBRARY_PATH` automatically. - `launch.json` uses CodeLLDB Cargo artifact filtering for ordinary editor/game Debug,
GPU-validation, SDR fallback, and Release configurations. Managed hot reload uses the lane-aware
tasks above so exceptional artifacts cannot overwrite or borrow the ordinary editor's runtime
dependency path.
- `.github/workflows/ci.yml` mirrors local formatting, check, clippy, test, and binary build verification. - `.github/workflows/ci.yml` mirrors local formatting, check, clippy, test, and binary build verification.
## Architecture Decisions ## Architecture Decisions
@ -377,6 +446,9 @@ The `.vscode/` folder is preconfigured:
- [ADR 0017: Normalized Static Mesh Assets](docs/adr/0017-normalized-static-mesh-assets.md) - [ADR 0017: Normalized Static Mesh Assets](docs/adr/0017-normalized-static-mesh-assets.md)
- [ADR 0034: Registry-driven Authoring Components](docs/adr/0034-registry-driven-authoring-components.md) - [ADR 0034: Registry-driven Authoring Components](docs/adr/0034-registry-driven-authoring-components.md)
- [ADR 0037: Collaborative Authored-File Safety](docs/adr/0037-collaborative-authored-file-safety.md) - [ADR 0037: Collaborative Authored-File Safety](docs/adr/0037-collaborative-authored-file-safety.md)
- [ADR 0047: Editor Authored-Asset Documents](docs/adr/0047-editor-authored-asset-documents.md)
- [ADR 0048: Modular Editor Composition and Debt Ratchet](docs/adr/0048-modular-editor-composition-and-debt-ratchet.md)
- [ADR 0049: Penpot-Led Editor Visual System](docs/adr/0049-penpot-led-editor-visual-system.md)
- [ADR 0043: Content-Addressed Import Fingerprints](docs/adr/0043-content-addressed-import-fingerprints.md) - [ADR 0043: Content-Addressed Import Fingerprints](docs/adr/0043-content-addressed-import-fingerprints.md)
- [ADR 0044: Sandboxed FBX External Texture Dependencies](docs/adr/0044-sandboxed-fbx-external-texture-dependencies.md) - [ADR 0044: Sandboxed FBX External Texture Dependencies](docs/adr/0044-sandboxed-fbx-external-texture-dependencies.md)
@ -460,8 +532,17 @@ crates/
- [x] Independent scene tabs + stable subscene composition, recursive validation, ownership locks, active-world PIE consistency, and per-saved-tab recovery ([ADR 0026](docs/adr/0026-stable-scene-composition-and-active-document.md)) - [x] Independent scene tabs + stable subscene composition, recursive validation, ownership locks, active-world PIE consistency, and per-saved-tab recovery ([ADR 0026](docs/adr/0026-stable-scene-composition-and-active-document.md))
- [x] Editor lib/bin split + `EditorPluginGroup`; game EditorPlugin dogfood panel - [x] Editor lib/bin split + `EditorPluginGroup`; game EditorPlugin dogfood panel
- [x] FBX/glTF model import + normalized static/skinned renderer routing; explicit generic scene-instance load via `bevy_ufbx` / `ModelRef` - [x] FBX/glTF model import + normalized static/skinned renderer routing; explicit generic scene-instance load via `bevy_ufbx` / `ModelRef`
- [x] Asset browser model thumbnails (unified `assets/thumbnails/` pipeline; `ThumbnailState` cache; FBX via `FbxThumbnailSource`) - [x] Typed texture/model/mesh-subasset/source-material thumbnail cache keys; model and mesh cards always render geometry in the offscreen studio instead of substituting an albedo texture (`ThumbnailState`; FBX via `FbxThumbnailSource`)
- [x] Shared Material/Material Instance assets, stable static/skinned renderer material slots, imported-source fallback, orphan preservation, and a persistence-excluded property-block schema; runtime block application/promotion remains tracked in [Gitea #53](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/53) ([ADR 0035](docs/adr/0035-shared-material-assets-and-renderer-slots.md), [material-system guide](docs/editor/material-system.md)) - [x] Shared Material/Material Instance assets, generalized primitive/static/skinned slots, expandable guarded shared parameters, stable model defaults, six-layer fallback through immutable DefaultGrid, exact-actor source extraction, orphan preservation, cached Standard/Surface runtime property-block application, and exact-slot transactional instance creation/promotion ([ADR 0035](docs/adr/0035-shared-material-assets-and-renderer-slots.md), [ADR 0045](docs/adr/0045-content-workspace-and-material-fallback-contract.md), [material-system guide](docs/editor/material-system.md))
- [x] Path-agnostic content classification, reference-safe file operations, destination-first dependency-bundle import, deterministic runtime catalog/model manifests, shared debounced watcher core, and atomic GPU-free `cargo process-assets` write/check validation ([content workspace guide](docs/editor/content-workspace.md))
- [x] Registry v3 Texture properties, schema-v2 Material inputs, paired multiplier/texture controls, channel-selectable ARM/ORM repacking, and content-addressed UASTC/KTX2 runtime artifacts shared by editor refresh and `cargo process-assets` ([ADR 0046](docs/adr/0046-schema-driven-material-inputs-and-processed-textures.md), [material guide](docs/editor/material-system.md))
- [x] Asset-keyed dirty documents use one overlay-first live Material authority and conditional derived processing without pointer-release writes; contextual Save/Save All, recovery, background processing, and live-handle persistence passed native acceptance ([ADR 0047](docs/adr/0047-editor-authored-asset-documents.md))
- [x] Registry-only Inspector dispatch, shared material/asset-card UI, and the architecture debt ratchet are implemented; both Inspector and Content Browser shells are <=500 nonblank lines and pass the selective architecture gate plus native resize/deep-scroll acceptance ([ADR 0048](docs/adr/0048-modular-editor-composition-and-debt-ratchet.md))
- [ ] Penpot-led tokens, Source Sans Pro typography, responsive Inspector/material components, asset/color pickers, and exact current 620/420 px geometry are undergoing final M2 native acceptance ([ADR 0049](docs/adr/0049-penpot-led-editor-visual-system.md))
- [ ] Penpot-led Content Browser wide/compact composition, dock-header ownership, responsive Sources/Details access, and catalog-processing status pass current Page 03 native comparison and resize stress; exact candidate publication remains pending ([content workspace guide](docs/editor/content-workspace.md), [ADR 0049](docs/adr/0049-penpot-led-editor-visual-system.md))
- [x] File-manager Content Browser selection for assets and folders, Ctrl/Cmd toggle and Shift ranges, batch clipboard/duplicate/drag/trash operations, stable-ID moves, fresh-ID copies with internal-only reference remapping, concrete destructive-reference previews, exact cancel-state restoration, restart-safe explicit ambiguous external-move identity repair, fingerprint-guarded move/create/copy/trash undo, modal-safe content-scoped keyboard shortcuts, exact-name Cut/Paste collision review, safe navigation/filter selection clearing, consistent right-click targeting for files/folders/subassets, current-folder Material creation, and right-click menus on items and empty workspace space ([content workspace guide](docs/editor/content-workspace.md))
- [x] Transactional Content Trash with versioned batch manifests, stable-ID restore, generated model-manifest preservation, collision guards, legacy-batch discovery, and registry/runtime-catalog rollback ([content workspace guide](docs/editor/content-workspace.md))
- [x] Transactional loose-texture PBR grouping with suffix/confidence detection, manual role correction and target merge/split, packed ORM/ARM mapping, and no-overwrite Material publication ([material-system guide](docs/editor/material-system.md))
- [x] Docked Material Library with cross-folder type/usage filters, resolved Material Instance thumbnails, shared guarded editors, and exact reversible viewport Material/Texture drops for renderer slots, primitives, and brush faces ([material-system guide](docs/editor/material-system.md); [Gitea #16](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/16), [Gitea #18](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/18)) - [x] Docked Material Library with cross-folder type/usage filters, resolved Material Instance thumbnails, shared guarded editors, and exact reversible viewport Material/Texture drops for renderer slots, primitives, and brush faces ([material-system guide](docs/editor/material-system.md); [Gitea #16](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/16), [Gitea #18](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/18))
- [x] Prefab v2 core: shared stable nested override paths, property/component/structural scopes, recursive graph validation, linked-root variants, conflict recovery, transactional source Apply, and undoable unpack/convert ([ADR 0027](docs/adr/0027-stable-prefab-ownership-and-variants.md)) - [x] Prefab v2 core: shared stable nested override paths, property/component/structural scopes, recursive graph validation, linked-root variants, conflict recovery, transactional source Apply, and undoable unpack/convert ([ADR 0027](docs/adr/0027-stable-prefab-ownership-and-variants.md))
- [x] Prefab v2 production acceptance: committed base/nested/variant fixtures pass workspace tests, recursive headless validation, packaged release startup, and live editor placement/inspection regression coverage ([Gitea #43](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/43)) - [x] Prefab v2 production acceptance: committed base/nested/variant fixtures pass workspace tests, recursive headless validation, packaged release startup, and live editor placement/inspection regression coverage ([Gitea #43](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/43))
@ -471,7 +552,7 @@ crates/
- [x] Surface ABI v1 with shared raster/Solari evaluator dispatch, packed typed parameters/textures, exact cutout ray-candidate evaluation, last-good shader fallback, and explicit exclusion of skinned/morph-deformed Solari geometry ([ADR 0036](docs/adr/0036-surface-abi-and-solari-parity.md), [material-system guide](docs/editor/material-system.md)) - [x] Surface ABI v1 with shared raster/Solari evaluator dispatch, packed typed parameters/textures, exact cutout ray-candidate evaluation, last-good shader fallback, and explicit exclusion of skinned/morph-deformed Solari geometry ([ADR 0036](docs/adr/0036-surface-abi-and-solari-parity.md), [material-system guide](docs/editor/material-system.md))
- [x] Static mesh renderer component, generated normalized mesh artifacts, source/one-actor hierarchy placement, and inspector renderer slots ([ADR 0017](docs/adr/0017-normalized-static-mesh-assets.md)) - [x] Static mesh renderer component, generated normalized mesh artifacts, source/one-actor hierarchy placement, and inspector renderer slots ([ADR 0017](docs/adr/0017-normalized-static-mesh-assets.md))
- [x] Dedicated `SkinnedMeshRenderer`/`SkinnedMesh` actor path, skinned-part exclusion from static slots, dedicated runtime hierarchy hydration, and v2-to-v3 animated-scene migration ([ADR 0033](docs/adr/0033-dedicated-skinned-mesh-renderer.md)) - [x] Dedicated `SkinnedMeshRenderer`/`SkinnedMesh` actor path, skinned-part exclusion from static slots, dedicated runtime hierarchy hydration, and v2-to-v3 animated-scene migration ([ADR 0033](docs/adr/0033-dedicated-skinned-mesh-renderer.md))
- [x] Componentized actor inspector, unified component cards, thumbnail static mesh slots, imported asset Browse/Locate/Clear refs with inherited source defaults, collider split, shader-aware actor material data, and texture picker/drop refs ([ADR 0018](docs/adr/0018-componentized-actor-inspector-and-materials.md)) - [x] Componentized actor inspector with one primitive/static/skinned Material-slot widget, full-width valid/invalid drop feedback, material sphere and exact mesh-subasset previews, inherited status, Browse/Locate/Clear, guarded shared parameter foldouts, and no synthetic primitive Authoring Material card ([ADR 0018](docs/adr/0018-componentized-actor-inspector-and-materials.md), [ADR 0035](docs/adr/0035-shared-material-assets-and-renderer-slots.md))
- [x] Stable authoring component IDs, registry-built save filtering, reflected atomic add/remove/reset/copy/paste history, independent active state, static extension registration, and derived composable `ActorKind` hints ([ADR 0034](docs/adr/0034-registry-driven-authoring-components.md), [extensibility guide](docs/editor/extensibility.md)) - [x] Stable authoring component IDs, registry-built save filtering, reflected atomic add/remove/reset/copy/paste history, independent active state, static extension registration, and derived composable `ActorKind` hints ([ADR 0034](docs/adr/0034-registry-driven-authoring-components.md), [extensibility guide](docs/editor/extensibility.md))
- [x] Brush authoring schema MVP with `ActorKind::Brush`, cube `BrushDesc`, generated mesh hydration, scene migration, and inspector Add Component support ([ADR 0021](docs/adr/0021-brush-authoring-schema.md)) - [x] Brush authoring schema MVP with `ActorKind::Brush`, cube `BrushDesc`, generated mesh hydration, scene migration, and inspector Add Component support ([ADR 0021](docs/adr/0021-brush-authoring-schema.md))
- [x] Brush draw, vertex/edge/face gizmo editing, face material/UV authoring, clip, and bounds-based CSG preview/commit workflow ([brush guide](docs/editor/brushes.md)) - [x] Brush draw, vertex/edge/face gizmo editing, face material/UV authoring, clip, and bounds-based CSG preview/commit workflow ([brush guide](docs/editor/brushes.md))
@ -481,13 +562,16 @@ crates/
- Crouch lowers the camera and movement speed; the collider stays full-height for stability. - Crouch lowers the camera and movement speed; the collider stays full-height for stability.
- The editor asset browser is filesystem-backed with folder/tree navigation, grid/list views, - The editor asset browser is filesystem-backed with folder/tree navigation, grid/list views,
texture and model thumbnails (glTF albedo fast-path; offscreen render studio for FBX and direct texture thumbnails, offscreen geometry renders for all models and mesh subassets,
untextured models), material sphere thumbnails, search/filter/sort controls, expandable model material sphere thumbnails, and a managed content-addressed 256 px disk cache that reuses valid
previews across editor sessions while restoring the last-good image after a restart during
dependency-driven regeneration or source failure. It also provides search/filter/sort controls, expandable model
subasset shelves, and a staged details pane. **File -> Import Assets** subasset shelves, and a staged details pane. **File -> Import Assets**
accepts glTF/GLB and binary **FBX**. FBX import parses and transactionally preserves every safe accepts glTF/GLB and binary **FBX**. FBX import parses and transactionally preserves every safe
referenced sibling `textures/` or `.fbm/` file while rejecting traversal and external absolute referenced sibling `textures/` or `.fbm/` file while rejecting traversal and external absolute
paths before project content changes. Missing source textures appear once in validation and Asset paths before project content changes. Missing source textures appear once in validation and Asset
Browser dependency status; **Authoring Override** deliberately permits an untextured model. Browser dependency status; choosing **Project** or **Default** for every stable model slot
deliberately permits an untextured model, while any **Source** slot keeps the bundle required.
Model assets generate normalized model manifests under `assets/meshes/generated/`; drag/drop uses Model assets generate normalized model manifests under `assets/meshes/generated/`; drag/drop uses
**Renderable Asset (Auto)**. Unrigged sources use `StaticMeshRenderer` with imported asset refs **Renderable Asset (Auto)**. Unrigged sources use `StaticMeshRenderer` with imported asset refs
and optional separate static mesh colliders. Skin-bound or animated sources and their subasset placement use and optional separate static mesh colliders. Skin-bound or animated sources and their subasset placement use
@ -508,7 +592,7 @@ crates/
**Unpack Layer** preserves nested links; **Convert to Local** recursively removes them. Current **Unpack Layer** preserves nested links; **Convert to Local** recursively removes them. Current
authoring UI coverage and production-acceptance gaps are tracked in authoring UI coverage and production-acceptance gaps are tracked in
[prefab-authoring.md](docs/editor/prefab-authoring.md). [prefab-authoring.md](docs/editor/prefab-authoring.md).
- Material and direct-base Material Instance assets live under `assets/materials/`; shader schemas live under `assets/shaders/`. **Window > Material Library** provides cross-folder creation, editing, usage filters, and drag sources. Viewport Material drops target one exact renderer slot, primitive, or brush face and use reversible preview plus one-step history; loose Textures target primitives/brush faces and are rejected on renderer slots. Shared edits propagate through live-updated handles without reloading skinned geometry. Custom Surface evaluators share one constrained ABI between raster and Solari-eligible non-deformed geometry. Runtime property-block application/promotion is tracked in [#53](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/53); dynamic skinned/morph Solari geometry is tracked in [#54](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/54). See the [material-system guide](docs/editor/material-system.md). - Material and direct-base Material Instance assets may live anywhere under `assets/`; shader schemas are also folder-independent. **Window > Material Library** provides cross-folder creation, editing, usage filters, and drag sources. Material parameters update one live shared handle and mark the asset **UNSAVED**; releasing a control does not write or process. **Ctrl+S** saves the last edited context and **Ctrl+Shift+S** / **File > Save All** saves every dirty scene, asset, and project setting. Scalar/color/render-state Material saves finish without a processing job; ARM/ORM binding changes continue through affected-only background processing. Viewport Material drops target one exact primitive/static/skinned slot or brush face and use reversible preview plus one-step history; loose Textures are rejected by primitive/mesh slots while brushes retain their specialized face texture path. Runtime property blocks apply after resolved bases without mutating shared assets. Custom Surface evaluators share one constrained ABI between raster and Solari-eligible non-deformed geometry. Dynamic skinned/morph Solari geometry remains tracked in [#54](https://git.spacetrainclubhouse.com/Falling-Metal-Interactive/Blacksite/issues/54). See the [material-system guide](docs/editor/material-system.md).
- Per-field reflect undo for all components remains future work; typed `shared` inspectors cover the common authoring path. - Per-field reflect undo for all components remains future work; typed `shared` inspectors cover the common authoring path.
- The authoring/hydration layer is intentionally small so richer asset workflows (terrain, - The authoring/hydration layer is intentionally small so richer asset workflows (terrain,
material graphs, lighting profiles) can be added without changing the scene format foundation. material graphs, lighting profiles) can be added without changing the scene format foundation.

File diff suppressed because it is too large Load Diff

BIN
assets/Furniture/Office/blacksite-m2-robot-expressive.glb (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,116 @@
(
schema_version: 2,
label: "metal_office_desk",
shader: (
kind: StandardLit,
schema_path: None,
shader_path: None,
),
shader_ref: None,
render_state: (
alpha_mode: Opaque,
alpha_cutoff: 0.5,
double_sided: true,
),
provenance: Some((
source_path: "assets/Furniture/Office/metal_office_desk_2k.gltf",
source_fingerprint: "904f3af2a5283a08f60bcfb2651c5280f14f1232ec522154e4878e90909551ce",
source_sub_asset_id: "material:0",
source_label: "metal_office_desk",
)),
inputs: (
values: [
(
name: "base_color",
value: Color((
r: 1.0,
g: 1.0,
b: 1.0,
a: 0.0,
)),
),
(
name: "metallic",
value: Float(0.23189718),
),
(
name: "roughness",
value: Float(1.0),
),
(
name: "emissive_color",
value: Color((
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
)),
),
(
name: "emissive_intensity",
value: Float(0.0),
),
(
name: "occlusion",
value: Float(1.0),
),
],
textures: [
(
name: "base_color",
texture: Some((
asset_id: "481b1a35-75e4-4879-879d-ccab183ba2b7",
sub_asset_id: "texture:source",
label: "metal_office_desk_diff_2k",
source_path: Some("assets/Furniture/Office/textures/metal_office_desk_diff_2k.jpg"),
)),
channel: Rgba,
),
(
name: "normal",
texture: Some((
asset_id: "cadad4af-c24a-4d52-bdc4-8089dac67f30",
sub_asset_id: "texture:source",
label: "metal_office_desk_nor_gl_2k",
source_path: Some("assets/Furniture/Office/textures/metal_office_desk_nor_gl_2k.jpg"),
)),
channel: Rgb,
),
(
name: "occlusion",
texture: Some((
asset_id: "cef332e3-d0d1-41d7-adf2-87462c70f52c",
sub_asset_id: "texture:source",
label: "metal_office_desk_arm_2k",
source_path: Some("assets/Furniture/Office/textures/metal_office_desk_arm_2k.jpg"),
)),
channel: R,
),
(
name: "roughness",
texture: Some((
asset_id: "cef332e3-d0d1-41d7-adf2-87462c70f52c",
sub_asset_id: "texture:source",
label: "metal_office_desk_arm_2k",
source_path: Some("assets/Furniture/Office/textures/metal_office_desk_arm_2k.jpg"),
)),
channel: G,
),
(
name: "metallic",
texture: Some((
asset_id: "cef332e3-d0d1-41d7-adf2-87462c70f52c",
sub_asset_id: "texture:source",
label: "metal_office_desk_arm_2k",
source_path: Some("assets/Furniture/Office/textures/metal_office_desk_arm_2k.jpg"),
)),
channel: B,
),
(
name: "emissive_color",
texture: None,
channel: Rgb,
),
],
),
)

BIN
assets/Furniture/Office/metal_office_desk_2k.gltf (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,7 +8,6 @@
format: "glb", format: "glb",
fingerprint: ( fingerprint: (
byte_len: 463988, byte_len: 463988,
modified_unix_secs: 1783799272,
content_hash: "5869cb813e6a6093eda7af2824a9c13a582750e0443e88ce7c991a1f83415521", content_hash: "5869cb813e6a6093eda7af2824a9c13a582750e0443e88ce7c991a1f83415521",
), ),
dependencies: [], dependencies: [],
@ -233,4 +232,4 @@
), ),
], ],
diagnostics: [], diagnostics: [],
) )

View File

@ -0,0 +1,21 @@
(
schema_version: 3,
asset_id: "3076fad0-89ca-4307-b8d9-cb77fca41907",
label: "metal_office_desk_2k",
default_animation_clip_id: None,
source: (
path: "assets/models/metal_office_desk_2k.gltf",
format: "gltf",
fingerprint: (
byte_len: 13510,
content_hash: "904f3af2a5283a08f60bcfb2651c5280f14f1232ec522154e4878e90909551ce",
),
dependencies: [
"assets/models/metal_office_desk.bin",
],
),
runtime_supported: true,
skeletons: [],
clips: [],
diagnostics: [],
)

View File

@ -0,0 +1,21 @@
(
schema_version: 3,
asset_id: "36c51ff3-29ae-4ab1-aaca-f90f57e27966",
label: "metal_office_desk_2k",
default_animation_clip_id: None,
source: (
path: "assets/Furniture/Office/metal_office_desk_2k.gltf",
format: "gltf",
fingerprint: (
byte_len: 13500,
content_hash: "64fd91fbc603c9675f9c8b5f1291a654deff89b40aeb0a0b877b7b93f6ebf05e",
),
dependencies: [
"assets/Furniture/Office/metal_office_desk.bin",
],
),
runtime_supported: true,
skeletons: [],
clips: [],
diagnostics: [],
)

View File

@ -8,7 +8,6 @@
format: "glb", format: "glb",
fingerprint: ( fingerprint: (
byte_len: 463988, byte_len: 463988,
modified_unix_secs: 1783750957,
content_hash: "5869cb813e6a6093eda7af2824a9c13a582750e0443e88ce7c991a1f83415521", content_hash: "5869cb813e6a6093eda7af2824a9c13a582750e0443e88ce7c991a1f83415521",
), ),
dependencies: [], dependencies: [],
@ -233,4 +232,4 @@
), ),
], ],
diagnostics: [], diagnostics: [],
) )

View File

@ -0,0 +1,235 @@
(
schema_version: 3,
asset_id: "5b4640dd-fc17-4703-b9ea-e4eb49a8c7fc",
label: "blacksite-m2-robot-expressive",
default_animation_clip_id: None,
source: (
path: "assets/Furniture/Office/blacksite-m2-robot-expressive.glb",
format: "glb",
fingerprint: (
byte_len: 463988,
content_hash: "5869cb813e6a6093eda7af2824a9c13a582750e0443e88ce7c991a1f83415521",
),
dependencies: [],
),
runtime_supported: true,
skeletons: [
(
id: "animation:skeleton:0:skeleton_0",
label: "Skeleton 0",
source_index: 0,
signature: ("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b"),
joint_paths: [
"RootNode/RobotArmature/Bone",
"RootNode/RobotArmature/Bone/Foot.L",
"RootNode/RobotArmature/Bone/Body",
"RootNode/RobotArmature/Bone/Body/Hips",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Neck",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Neck/Head",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L/Middle1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L/Middle1.L/Middle2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Thumb.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Thumb.L/Thumb2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L/Index.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L/Index.L/Index2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L/Ring1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L/Ring1.L/Ring2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R/Middle1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R/Middle1.R/Middle2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Thumb.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Thumb.R/Thumb2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R/Index.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R/Index.R/Index2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R/Ring1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R/Ring1.R/Ring2.R",
"RootNode/RobotArmature/Bone/Body/UpperLeg.L",
"RootNode/RobotArmature/Bone/Body/UpperLeg.L/LowerLeg.L",
"RootNode/RobotArmature/Bone/Body/UpperLeg.R",
"RootNode/RobotArmature/Bone/Body/UpperLeg.R/LowerLeg.R",
"RootNode/RobotArmature/Bone/PoleTarget.L",
"RootNode/RobotArmature/Bone/Foot.R",
"RootNode/RobotArmature/Bone/PoleTarget.R",
],
),
(
id: "animation:skeleton:1:skeleton_1",
label: "Skeleton 1",
source_index: 1,
signature: ("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b"),
joint_paths: [
"RootNode/RobotArmature/Bone",
"RootNode/RobotArmature/Bone/Foot.L",
"RootNode/RobotArmature/Bone/Body",
"RootNode/RobotArmature/Bone/Body/Hips",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Neck",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Neck/Head",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L/Middle1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm2.L/Middle1.L/Middle2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Thumb.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Thumb.L/Thumb2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L/Index.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm1.L/Index.L/Index2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L/Ring1.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.L/UpperArm.L/LowerArm.L/Palm3.L/Ring1.L/Ring2.L",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R/Middle1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm2.R/Middle1.R/Middle2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Thumb.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Thumb.R/Thumb2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R/Index.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm1.R/Index.R/Index2.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R/Ring1.R",
"RootNode/RobotArmature/Bone/Body/Hips/Abdomen/Torso/Shoulder.R/UpperArm.R/LowerArm.R/Palm3.R/Ring1.R/Ring2.R",
"RootNode/RobotArmature/Bone/Body/UpperLeg.L",
"RootNode/RobotArmature/Bone/Body/UpperLeg.L/LowerLeg.L",
"RootNode/RobotArmature/Bone/Body/UpperLeg.R",
"RootNode/RobotArmature/Bone/Body/UpperLeg.R/LowerLeg.R",
"RootNode/RobotArmature/Bone/PoleTarget.L",
"RootNode/RobotArmature/Bone/Foot.R",
"RootNode/RobotArmature/Bone/PoleTarget.R",
],
),
],
clips: [
(
id: "animation:clip:0:dance",
label: "Dance",
source_index: 0,
duration_seconds: 3.3333333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:1:death",
label: "Death",
source_index: 1,
duration_seconds: 0.9583333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:2:idle",
label: "Idle",
source_index: 2,
duration_seconds: 3.3333333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:3:jump",
label: "Jump",
source_index: 3,
duration_seconds: 0.7083333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:4:no",
label: "No",
source_index: 4,
duration_seconds: 1.6666666,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:5:punch",
label: "Punch",
source_index: 5,
duration_seconds: 0.8333333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:6:running",
label: "Running",
source_index: 6,
duration_seconds: 0.9583333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:7:sitting",
label: "Sitting",
source_index: 7,
duration_seconds: 0.41666666,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:8:standing",
label: "Standing",
source_index: 8,
duration_seconds: 0.41666666,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:9:thumbsup",
label: "ThumbsUp",
source_index: 9,
duration_seconds: 1.5833334,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:10:walking",
label: "Walking",
source_index: 10,
duration_seconds: 0.9583333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:11:walkjump",
label: "WalkJump",
source_index: 11,
duration_seconds: 0.8333333,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:12:wave",
label: "Wave",
source_index: 12,
duration_seconds: 1.8333334,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
(
id: "animation:clip:13:yes",
label: "Yes",
source_index: 13,
duration_seconds: 1.6666666,
target_skeleton_signature: Some(("e9761f2a198d6a280afd0fc2aca6e8783dc6237bd85c90b8bc07a2e11271dc2b")),
events: [],
),
],
diagnostics: [],
)

View File

@ -8,7 +8,6 @@
format: "fbx", format: "fbx",
fingerprint: ( fingerprint: (
byte_len: 59964, byte_len: 59964,
modified_unix_secs: 1780713434,
content_hash: "b12973a62dcb44589e380ea833eade726ae98a86c81084c842ee3801866d6a46", content_hash: "b12973a62dcb44589e380ea833eade726ae98a86c81084c842ee3801866d6a46",
), ),
dependencies: [], dependencies: [],
@ -17,4 +16,4 @@
skeletons: [], skeletons: [],
clips: [], clips: [],
diagnostics: [], diagnostics: [],
) )

View File

@ -0,0 +1,21 @@
(
schema_version: 3,
asset_id: "bd495161-5ea8-48ef-b0db-5b1d57f33885",
label: "pebble_bricks_4k",
default_animation_clip_id: None,
source: (
path: "assets/materials/pebble_bricks_4k.gltf",
format: "gltf",
fingerprint: (
byte_len: 2788,
content_hash: "55a5374732e4174e33859cf415d22ac855cea3efe8d8ff78c6ee42c86d8fd5fb",
),
dependencies: [
"assets/materials/pebble_bricks.bin",
],
),
runtime_supported: true,
skeletons: [],
clips: [],
diagnostics: [],
)

909
assets/content.catalog.ron Normal file
View File

@ -0,0 +1,909 @@
(
version: 2,
defaults: (
default_material: None,
),
records: [
(
id: ("5b4640dd-fc17-4703-b9ea-e4eb49a8c7fc"),
path: "assets/Furniture/Office/blacksite-m2-robot-expressive.glb",
label: "blacksite-m2-robot-expressive",
kind: Model,
material_slots: [],
),
(
id: ("647a63d4-64c6-4431-ba46-9efdd515cd8f"),
path: "assets/Furniture/Office/metal_office_desk.material.ron",
label: "metal_office_desk.material",
kind: Material,
material_slots: [],
material: Some((
packed_arm_path: Some("assets/.import-cache/runtime/materials/647a63d4-64c6-4431-ba46-9efdd515cd8f/297372611543b1f7baa1e5e3-arm.basis"),
processing_key: Some("297372611543b1f7baa1e5e3"),
)),
),
(
id: ("36c51ff3-29ae-4ab1-aaca-f90f57e27966"),
path: "assets/Furniture/Office/metal_office_desk_2k.gltf",
label: "metal_office_desk_2k",
kind: Model,
material_slots: [
(
slot_id: ("slot:draw:scene0:node0:mesh0:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node1:mesh1:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node2:mesh2:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node3:mesh3:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node4:mesh4:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node5:mesh5:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node6:mesh6:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
(
slot_id: ("slot:draw:scene0:node7:mesh7:primitive0"),
selection: Project(((
asset_id: "647a63d4-64c6-4431-ba46-9efdd515cd8f",
sub_asset_id: "",
label: "metal_office_desk",
source_path: Some("assets/Furniture/Office/metal_office_desk.material.ron"),
))),
),
],
),
(
id: ("cef332e3-d0d1-41d7-adf2-87462c70f52c"),
path: "assets/Furniture/Office/textures/metal_office_desk_arm_2k.jpg",
label: "metal_office_desk_arm_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/Furniture/Office/textures/metal_office_desk_arm_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/cef332e3-d0d1-41d7-adf2-87462c70f52c/edf8ef1b2fc54bbe4eafc16d/texture.basis"),
processing_key: Some("edf8ef1b2fc54bbe4eafc16d"),
settings: (
semantic: MaskData,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("481b1a35-75e4-4879-879d-ccab183ba2b7"),
path: "assets/Furniture/Office/textures/metal_office_desk_diff_2k.jpg",
label: "metal_office_desk_diff_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/Furniture/Office/textures/metal_office_desk_diff_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/481b1a35-75e4-4879-879d-ccab183ba2b7/534c0d384d22c554b9597064/texture.basis"),
processing_key: Some("534c0d384d22c554b9597064"),
settings: (
semantic: Color,
color_space: Srgb,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: true,
)),
),
(
id: ("cadad4af-c24a-4d52-bdc4-8089dac67f30"),
path: "assets/Furniture/Office/textures/metal_office_desk_nor_gl_2k.jpg",
label: "metal_office_desk_nor_gl_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/Furniture/Office/textures/metal_office_desk_nor_gl_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/cadad4af-c24a-4d52-bdc4-8089dac67f30/cd1c550f437632f394bf7502/texture.basis"),
processing_key: Some("cd1c550f437632f394bf7502"),
settings: (
semantic: Normal,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("fe40db93-181f-4c79-86e6-26bd97464c4b"),
path: "assets/audio/Puzzle Lobby.mp3",
label: "Puzzle Lobby",
kind: AudioClip,
material_slots: [],
),
(
id: ("c0a7d10e-53c1-4de0-b0dc-34a66f44ba77"),
path: "assets/audio/editor_audition_tone.ogg",
label: "editor_audition_tone",
kind: AudioClip,
material_slots: [],
),
(
id: ("f3dfcd11-aa5b-4fd4-872b-06832b865c99"),
path: "assets/levels/audio_authoring_showcase.scn.ron",
label: "audio_authoring_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("a7ef65b4-24d6-4c3a-b637-5bb52d8e9a26"),
path: "assets/levels/collider_diagnostics_showcase.scn.ron",
label: "collider_diagnostics_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("dc13ce01-c7ce-43c5-974c-0e659ae49ab9"),
path: "assets/levels/editor_scene 2.scn.ron",
label: "editor_scene 2.scn",
kind: Level,
material_slots: [],
),
(
id: ("48bcef13-e6a6-4260-bb1b-c29787bd8c70"),
path: "assets/levels/editor_scene 3.scn.ron",
label: "editor_scene 3.scn",
kind: Level,
material_slots: [],
),
(
id: ("5a2307d0-48e5-40d3-a5c9-527c0cfd30f4"),
path: "assets/levels/editor_scene.scn.ron",
label: "editor_scene.scn",
kind: Level,
material_slots: [],
),
(
id: ("706e604e-1a63-4e97-b35d-eeb1d88fe3a9"),
path: "assets/levels/navigation_authoring_showcase.scn.ron",
label: "navigation_authoring_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("78c6850b-5a76-4a4f-b48e-7fb00f6dd1ed"),
path: "assets/levels/physics_placement_showcase.scn.ron",
label: "physics_placement_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("61802b85-fda9-4aff-94d9-fe5f0860c516"),
path: "assets/levels/rendering_showcase.scn.ron",
label: "rendering_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("bca13177-afa9-4691-9b40-288059c7a57e"),
path: "assets/levels/samples/brush_blockout.scn.ron",
label: "brush_blockout.scn",
kind: Level,
material_slots: [],
),
(
id: ("607864bf-fa77-4f9e-acc9-2c0906d34163"),
path: "assets/levels/samples/material_lab.scn.ron",
label: "material_lab.scn",
kind: Level,
material_slots: [],
),
(
id: ("1b25d451-7b54-41d6-af00-d2e6950f502d"),
path: "assets/levels/terrain_authoring_showcase.scn.ron",
label: "terrain_authoring_showcase.scn",
kind: Level,
material_slots: [],
),
(
id: ("782d9f6a-e965-41af-86e1-84ce44de1cd6"),
path: "assets/materials/chrome.ron",
label: "chrome",
kind: Material,
material_slots: [],
),
(
id: ("a57f2891-8536-47b8-b476-01c08b36ac43"),
path: "assets/materials/concrete.ron",
label: "concrete",
kind: Material,
material_slots: [],
),
(
id: ("4f684592-50b1-47e4-888c-8ba537e4c29d"),
path: "assets/materials/emissive_panel.ron",
label: "emissive_panel",
kind: Material,
material_slots: [],
),
(
id: ("0cb3fb85-db18-52ea-8c42-b5ab58e90965"),
path: "assets/materials/migrated/legacy-05a00cdd0a637f9e.material.ron",
label: "legacy-05a00cdd0a637f9e.material",
kind: Material,
material_slots: [],
),
(
id: ("250a0db7-7108-5adf-b759-39b30c692c35"),
path: "assets/materials/migrated/legacy-082ba03b8cbb710b.material.ron",
label: "legacy-082ba03b8cbb710b.material",
kind: Material,
material_slots: [],
),
(
id: ("5b60f0a9-53b8-56b4-8ee9-cffd2e117c55"),
path: "assets/materials/migrated/legacy-0a21ebb8e495bf57.material.ron",
label: "legacy-0a21ebb8e495bf57.material",
kind: Material,
material_slots: [],
),
(
id: ("8fd7f537-75c1-524d-9f09-6654a3718a8e"),
path: "assets/materials/migrated/legacy-1a259303a97c4ba9.material.ron",
label: "legacy-1a259303a97c4ba9.material",
kind: Material,
material_slots: [],
),
(
id: ("7a818722-7a73-5541-838c-cedbef0648f7"),
path: "assets/materials/migrated/legacy-2b86cae1d3bfacae.material.ron",
label: "legacy-2b86cae1d3bfacae.material",
kind: Material,
material_slots: [],
),
(
id: ("c6c84742-e395-5ccb-96bc-d1bd101623b5"),
path: "assets/materials/migrated/legacy-3546762bbff37951.material.ron",
label: "legacy-3546762bbff37951.material",
kind: Material,
material_slots: [],
),
(
id: ("3adc8ea9-1387-5f1c-9404-bbe057dd910d"),
path: "assets/materials/migrated/legacy-454bcd95aaa4f1ca.material.ron",
label: "legacy-454bcd95aaa4f1ca.material",
kind: Material,
material_slots: [],
),
(
id: ("2b67be74-d8b5-509a-9efe-dd58b8010a9a"),
path: "assets/materials/migrated/legacy-4f65eccbb7dac1a2.material.ron",
label: "legacy-4f65eccbb7dac1a2.material",
kind: Material,
material_slots: [],
),
(
id: ("231210a7-5d2a-5d06-b3ec-b3ee0bde636a"),
path: "assets/materials/migrated/legacy-62ef60a686be94f1.material.ron",
label: "legacy-62ef60a686be94f1.material",
kind: Material,
material_slots: [],
),
(
id: ("c98f2306-b6f1-5d02-b232-19e74e886e20"),
path: "assets/materials/migrated/legacy-77cc6503f24bb9e8.material.ron",
label: "legacy-77cc6503f24bb9e8.material",
kind: Material,
material_slots: [],
),
(
id: ("6cc5ffc1-16fb-5652-ab6b-0bb9b4f36ae2"),
path: "assets/materials/migrated/legacy-78bc49856f47eae1.material.ron",
label: "legacy-78bc49856f47eae1.material",
kind: Material,
material_slots: [],
),
(
id: ("069977d1-acb8-5bf2-8afa-dfe2abbd4303"),
path: "assets/materials/migrated/legacy-964101ee77293501.material.ron",
label: "legacy-964101ee77293501.material",
kind: Material,
material_slots: [],
),
(
id: ("ee32fb60-4ef9-5b7f-a20d-ce216e915530"),
path: "assets/materials/migrated/legacy-97356bd0ac2f6198.material.ron",
label: "legacy-97356bd0ac2f6198.material",
kind: Material,
material_slots: [],
),
(
id: ("1cc3cb7a-7ddd-55e3-ba91-71071f30dc83"),
path: "assets/materials/migrated/legacy-9a630ee3e4848d9d.material.ron",
label: "legacy-9a630ee3e4848d9d.material",
kind: Material,
material_slots: [],
),
(
id: ("81212e15-4fc8-50ca-bd7d-ac596505cb4c"),
path: "assets/materials/migrated/legacy-a74f874eafd5d224.material.ron",
label: "legacy-a74f874eafd5d224.material",
kind: Material,
material_slots: [],
),
(
id: ("91e93c0c-4d4b-5e3f-adcd-6c15be6d0a74"),
path: "assets/materials/migrated/legacy-b278a62978900638.material.ron",
label: "legacy-b278a62978900638.material",
kind: Material,
material_slots: [],
),
(
id: ("0a4681e1-b5f0-57fa-8ee1-4431e14e322f"),
path: "assets/materials/migrated/legacy-c656429ce3668694.material.ron",
label: "legacy-c656429ce3668694.material",
kind: Material,
material_slots: [],
),
(
id: ("ba295f51-426f-5fdb-b444-a5f1cc5199da"),
path: "assets/materials/migrated/legacy-c6c02ef278fba7c3.material.ron",
label: "legacy-c6c02ef278fba7c3.material",
kind: Material,
material_slots: [],
),
(
id: ("6c8791ac-a746-58a2-b097-17d2fe0494dc"),
path: "assets/materials/migrated/legacy-c6fbbebd3e1a9943.material.ron",
label: "legacy-c6fbbebd3e1a9943.material",
kind: Material,
material_slots: [],
),
(
id: ("41dbf5a0-7a0a-5fac-9ec3-a0ceacb548a9"),
path: "assets/materials/migrated/legacy-c9d05c61e5cf348d.material.ron",
label: "legacy-c9d05c61e5cf348d.material",
kind: Material,
material_slots: [],
),
(
id: ("2fb3fcd4-f7b7-5f28-bf79-2241e47c7ea8"),
path: "assets/materials/migrated/legacy-cc0396f5c90fb7bb.material.ron",
label: "legacy-cc0396f5c90fb7bb.material",
kind: Material,
material_slots: [],
),
(
id: ("c512d6e2-272b-5e86-8235-4628ed3b6e8c"),
path: "assets/materials/migrated/legacy-e9671004b101f4df.material.ron",
label: "legacy-e9671004b101f4df.material",
kind: Material,
material_slots: [],
),
(
id: ("2db7e7f2-c0ab-51df-b71b-37f0e8c038f1"),
path: "assets/materials/migrated/legacy-fc132d9b30cc63d4.material.ron",
label: "legacy-fc132d9b30cc63d4.material",
kind: Material,
material_slots: [],
),
(
id: ("e9bd02c0-986f-4f90-a6d5-f04388622b94"),
path: "assets/materials/new_material.ron",
label: "new_material",
kind: Material,
material_slots: [],
),
(
id: ("d4387c2e-3ca2-4fca-862a-d86def44e424"),
path: "assets/materials/new_material_2.ron",
label: "new_material_2",
kind: Material,
material_slots: [],
),
(
id: ("c07a5b05-f27d-46c6-8b8c-9de9cdd14720"),
path: "assets/materials/pebble_bricks.ron",
label: "pebble_bricks",
kind: Material,
material_slots: [],
material: Some((
packed_arm_path: Some("assets/.import-cache/runtime/materials/c07a5b05-f27d-46c6-8b8c-9de9cdd14720/76a589e4456ec3320b876209-arm.basis"),
processing_key: Some("76a589e4456ec3320b876209"),
)),
),
(
id: ("bd495161-5ea8-48ef-b0db-5b1d57f33885"),
path: "assets/materials/pebble_bricks_4k.gltf",
label: "pebble_bricks_4k",
kind: Model,
material_slots: [
(
slot_id: ("slot:draw:scene0:node0:mesh0:primitive0"),
selection: Project(((
asset_id: "c07a5b05-f27d-46c6-8b8c-9de9cdd14720",
sub_asset_id: "",
label: "pebble_bricks",
source_path: Some("assets/materials/pebble_bricks.ron"),
))),
),
],
),
(
id: ("d6cb4151-7124-4237-aaf9-f7f8abd5fb76"),
path: "assets/materials/surface_tint.ron",
label: "surface_tint",
kind: Material,
material_slots: [],
),
(
id: ("cc2769da-c9a5-4cb3-866a-cc81d0688ee2"),
path: "assets/materials/surface_tint_instance.ron",
label: "surface_tint_instance",
kind: MaterialInstance,
material_slots: [],
),
(
id: ("25db6174-afcb-421f-8c1c-0c5ffde21b79"),
path: "assets/materials/textures/pebble_bricks_arm_4k.jpg",
label: "pebble_bricks_arm_4k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/materials/textures/pebble_bricks_arm_4k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/25db6174-afcb-421f-8c1c-0c5ffde21b79/552b39094506da0fbf4cd647/texture.basis"),
processing_key: Some("552b39094506da0fbf4cd647"),
settings: (
semantic: MaskData,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("d3b9bec5-c0ea-4f83-ad80-f9e2a8cb69ee"),
path: "assets/materials/textures/pebble_bricks_diff_4k.jpg",
label: "pebble_bricks_diff_4k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/materials/textures/pebble_bricks_diff_4k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/d3b9bec5-c0ea-4f83-ad80-f9e2a8cb69ee/644db179a14573b2a514e68f/texture.basis"),
processing_key: Some("644db179a14573b2a514e68f"),
settings: (
semantic: Color,
color_space: Srgb,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: true,
)),
),
(
id: ("7c5235a1-f5d7-4530-b29f-5ea075881df5"),
path: "assets/materials/textures/pebble_bricks_nor_gl_4k.jpg",
label: "pebble_bricks_nor_gl_4k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/materials/textures/pebble_bricks_nor_gl_4k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/7c5235a1-f5d7-4530-b29f-5ea075881df5/944b70940e3dd9a70e851d0e/texture.basis"),
processing_key: Some("944b70940e3dd9a70e851d0e"),
settings: (
semantic: Normal,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("113f74df-e39c-41d4-9b5b-e48efe541f7f"),
path: "assets/models/RobotExpressive.glb",
label: "RobotExpressive",
kind: Model,
material_slots: [],
),
(
id: ("3076fad0-89ca-4307-b8d9-cb77fca41907"),
path: "assets/models/metal_office_desk_2k.gltf",
label: "metal_office_desk_2k",
kind: Model,
material_slots: [],
),
(
id: ("b98ef565-3500-49e7-9935-f685fa9b2594"),
path: "assets/models/painted_wooden_chair_02_2k.fbx",
label: "painted_wooden_chair_02_2k",
kind: Model,
material_slots: [
(
slot_id: ("slot:draw:scene0:node1:material0"),
selection: Default,
),
],
),
(
id: ("3f63f359-45eb-4cb2-8970-71921cbd7bd0"),
path: "assets/models/robot_expressive.glb",
label: "robot_expressive",
kind: Model,
material_slots: [],
),
(
id: ("393414a8-3089-435f-b267-6dd3eac0285f"),
path: "assets/models/textures/metal_office_desk_arm_2k.jpg",
label: "metal_office_desk_arm_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/models/textures/metal_office_desk_arm_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/393414a8-3089-435f-b267-6dd3eac0285f/edf8ef1b2fc54bbe4eafc16d/texture.basis"),
processing_key: Some("edf8ef1b2fc54bbe4eafc16d"),
settings: (
semantic: MaskData,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("e5512ff1-aa00-4592-a740-4574e1059a99"),
path: "assets/models/textures/metal_office_desk_diff_2k.jpg",
label: "metal_office_desk_diff_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/models/textures/metal_office_desk_diff_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/e5512ff1-aa00-4592-a740-4574e1059a99/534c0d384d22c554b9597064/texture.basis"),
processing_key: Some("534c0d384d22c554b9597064"),
settings: (
semantic: Color,
color_space: Srgb,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: true,
)),
),
(
id: ("5212dba1-853f-4dab-98f3-e6395d05a4f7"),
path: "assets/models/textures/metal_office_desk_nor_gl_2k.jpg",
label: "metal_office_desk_nor_gl_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/models/textures/metal_office_desk_nor_gl_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/5212dba1-853f-4dab-98f3-e6395d05a4f7/cd1c550f437632f394bf7502/texture.basis"),
processing_key: Some("cd1c550f437632f394bf7502"),
settings: (
semantic: Normal,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("09762f59-bcd6-44fc-8157-2ad920177996"),
path: "assets/pebble_bricks_surface_instance.material-instance.ron",
label: "pebble_bricks_surface_instance.material-instance",
kind: MaterialInstance,
material_slots: [],
material: Some((
packed_arm_path: Some("assets/.import-cache/runtime/materials/09762f59-bcd6-44fc-8157-2ad920177996/76a589e4456ec3320b876209-arm.basis"),
processing_key: Some("76a589e4456ec3320b876209"),
)),
),
(
id: ("31963299-d4c1-45dc-8f67-2f469ca1ad6d"),
path: "assets/post_fx/chromatic_aberration.ron",
label: "chromatic_aberration",
kind: PostProcessEffect,
material_slots: [],
),
(
id: ("e14a9bc3-9a4e-47b0-901f-b31c004e1836"),
path: "assets/post_fx/vignette.ron",
label: "vignette",
kind: PostProcessEffect,
material_slots: [],
),
(
id: ("862530b2-8111-4ebb-9078-29723c002e08"),
path: "assets/prefabs/example_base.scn.ron",
label: "example_base.scn",
kind: Level,
material_slots: [],
),
(
id: ("682191d6-59cd-46a1-9560-6cf7bc1583b2"),
path: "assets/prefabs/example_nested.scn.ron",
label: "example_nested.scn",
kind: Level,
material_slots: [],
),
(
id: ("c14f6240-5654-4e80-9edb-2b4c44cf8d61"),
path: "assets/prefabs/example_variant.scn.ron",
label: "example_variant.scn",
kind: Level,
material_slots: [],
),
(
id: ("2c4a9866-17b5-4797-9a8f-726b2ffacdb9"),
path: "assets/rendering_profiles/cave_dark.ron",
label: "cave_dark",
kind: RenderingProfile,
material_slots: [],
),
(
id: ("802471df-8295-4997-80e2-db4191850fc9"),
path: "assets/rendering_profiles/outdoor_haze.ron",
label: "outdoor_haze",
kind: RenderingProfile,
material_slots: [],
),
(
id: ("addf6f7f-8114-45f3-8566-70d1eaa1fec3"),
path: "assets/shaders/standard_lit.shader.ron",
label: "standard_lit.shader",
kind: ShaderSchema,
material_slots: [],
),
(
id: ("a72943d6-3e9d-4629-8887-5c02d99d4f92"),
path: "assets/shaders/surface_tint.shader.ron",
label: "surface_tint.shader",
kind: ShaderSchema,
material_slots: [],
),
(
id: ("7b143cfb-a9e9-45d4-8f01-cfaa66fa9811"),
path: "assets/shaders/unlit.shader.ron",
label: "unlit.shader",
kind: ShaderSchema,
material_slots: [],
),
(
id: ("c7a227bc-2bae-4a41-857b-28cc6b432a9d"),
path: "assets/textures/metal_office_desk_arm_2k.jpg",
label: "metal_office_desk_arm_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_office_desk_arm_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/c7a227bc-2bae-4a41-857b-28cc6b432a9d/edf8ef1b2fc54bbe4eafc16d/texture.basis"),
processing_key: Some("edf8ef1b2fc54bbe4eafc16d"),
settings: (
semantic: MaskData,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("c644134e-87c7-43fb-ac30-31c4e0a78b48"),
path: "assets/textures/metal_office_desk_diff_2k.jpg",
label: "metal_office_desk_diff_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_office_desk_diff_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/c644134e-87c7-43fb-ac30-31c4e0a78b48/534c0d384d22c554b9597064/texture.basis"),
processing_key: Some("534c0d384d22c554b9597064"),
settings: (
semantic: Color,
color_space: Srgb,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: true,
)),
),
(
id: ("c661e66a-0745-4dd9-89b0-e611befab602"),
path: "assets/textures/metal_office_desk_nor_gl_2k.jpg",
label: "metal_office_desk_nor_gl_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_office_desk_nor_gl_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/c661e66a-0745-4dd9-89b0-e611befab602/cd1c550f437632f394bf7502/texture.basis"),
processing_key: Some("cd1c550f437632f394bf7502"),
settings: (
semantic: Normal,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("0496e62e-1837-4940-a9c9-b2b4ffe9ed90"),
path: "assets/textures/metal_stool_01_arm_2k.jpg",
label: "metal_stool_01_arm_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_stool_01_arm_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/0496e62e-1837-4940-a9c9-b2b4ffe9ed90/3ecc62c0eaf1672ca08fb59f/texture.basis"),
processing_key: Some("3ecc62c0eaf1672ca08fb59f"),
settings: (
semantic: MaskData,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
(
id: ("bddaa4d4-5097-42bf-8d51-dd9a3580442a"),
path: "assets/textures/metal_stool_01_diff_2k.jpg",
label: "metal_stool_01_diff_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_stool_01_diff_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/bddaa4d4-5097-42bf-8d51-dd9a3580442a/2276a96b1a148fd7c16977d5/texture.basis"),
processing_key: Some("2276a96b1a148fd7c16977d5"),
settings: (
semantic: Color,
color_space: Srgb,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: true,
)),
),
(
id: ("c4abe41c-ac88-4aec-8168-27e8a7c90583"),
path: "assets/textures/metal_stool_01_nor_gl_2k.jpg",
label: "metal_stool_01_nor_gl_2k",
kind: Texture,
material_slots: [],
texture: Some((
source_path: "assets/textures/metal_stool_01_nor_gl_2k.jpg",
processed_path: Some("assets/.import-cache/runtime/textures/c4abe41c-ac88-4aec-8168-27e8a7c90583/d0ec4224c3dcb6fa565c94bb/texture.basis"),
processing_key: Some("d0ec4224c3dcb6fa565c94bb"),
settings: (
semantic: Normal,
color_space: Linear,
mipmaps: Generate,
compression: Uastc,
max_dimension: None,
filter: Linear,
wrap: Repeat,
anisotropy: 8,
normal_map_convention: OpenGl,
),
is_srgb: false,
)),
),
],
)

View File

@ -1,4 +1,4 @@
(schema_version: 4,resources: { (schema_version: 6,resources: {
}, },
entities: { entities: {
4294969001: (components: { 4294969001: (components: {

Some files were not shown because too many files have changed in this diff Show More