BabylonJS / BabylonJS/Babylon-Lite

Babylon File System (BFS)

Open
#61 0 comments 0 reactions 1 assignee Claimed by @georginahalpern View on GitHub
enhancement sub-project
Dominant language
TypeScript
Stars
149
Forks
29
Avg merge
1d 5h
Merged PRs (30d)
106

Description

Owner: Georgie

Subproject for the Babylon File System (BFS) — Smart Assets, Override Persistence, and Project Save/Load — in Babylon Lite. See [`docs/architecture/29-babylon-file-system.md`](../blob/main/docs/architecture/29-babylon-file-system.md) for the full design. Milestones are feature-oriented — each one is independently shippable and lands with the tests that validate it.

## Milestones

- [ ] **Milestone 1 — SmartAsset loading** (key → URL → load/unload/reload)
Details

- Define `SmartAssetManager` handle + provenance + event types (`smart-assets/types.ts`); plain-data state.
- `createSmartAssetManager(scene)` + CRUD: `addSmartAsset`, `removeSmartAsset`, `setSmartAssetUrl`, `getSmartAssetUrl`, `listSmartAssetKeys`.
- `loadSmartAsset(mgr, key)` for GLB/glTF: resolve key → URL, call `loadGltf`, track `AssetContainer` per key, mark entities with key provenance (`WeakMap`).
- `unloadSmartAsset` (remove + dispose GPU) and `reloadSmartAsset` (unload + load).
- Extend to textures (`loadSmartAssetTexture2D`), env (`loadSmartAssetEnvironment`), and `.babylon` (`loadSmartAssetBabylon`) — thin wrappers over existing Lite loaders.
- `onAssetNotFound` callback (network/404 retry hook); default = warn.
- Observables: `onAssetLoaded`, `onUrlChanged`, `onAssetError`, `onAssetUnloaded`.
- _Validation_: Vitest unit tests in `tests/unit/smart-assets/` (manager CRUD, provenance, key-collision, events) using stub loaders; plumbing test driving real `loadSmartAsset` against a fixture GLB → unload → assert entity count + GPU buffers freed; bundle-size check (scenes not importing `smart-assets/manager` pay zero bytes).

- [ ] **Milestone 2 — Override persistence** (infrastructure for M3 — ship together)
Details

- _Note_: not user-facing on its own; pairs with smart-asset reload (M1+M2) and the project file (M3) for payoff.
- `IOverrideEntry { key?, targetType: "materials" | "meshes" | "lights" | "cameras" | "transformNodes" | "scene", targetName?, propertyPath, value }` matching BJS for project-file portability.
- `createOverrideManager(scene)` + `addOverride` / `removeOverride` / `listOverrides` / `linkOverrideManager(om, sam)`.
- Target resolution: `(key, targetType, targetName)` → entity, walking SAM containers for keyed targets and scene top-level lists for unkeyed.
- Dotted property-path setter (e.g. `material.coatLayer.intensity = 0.5`) over plain Lite objects/arrays; coerce array literals as needed.
- Original-value snapshot at add time for `resetToOriginal(om, ...)`.
- On SAM reload, OM reapplies all overrides whose `key` matches (first user-visible payoff).
- Call `markMaterialDirty(material)` after material-property overrides so the UBO refreshes.
- _Optional sub-feature_: tree-shakable `enableOverrideTracking(target, om, key?)` (auto-record via `Object.defineProperty` setters) — ship only if a real caller exists, else defer to M7.
- _Validation_: Vitest unit tests mirroring `overrideManager.test.ts` (CRUD, dotted setters, coercion, snapshot, reset, reapply-on-reload, scene-level overrides like clearColor/fog/environment); plumbing test exercising reload-reapply (load smart-asset GLB → apply albedoColor override → reload → assert reapplied to new material).

- [ ] **Milestone 3 — Project file save/load** (JSON, no bundle — first fully user-visible milestone; ship with M2)
Details

- `serializeProject(sam, om, opts) → ISerializedProject` (asset map key→URL, optionally relative to `baseUrl`; overrides pass through; inline objects skipped here, see M4).
- `deserializeProject(scene, json, opts) → Promise<{sam, om}>` (schema-version check, asset map rebuild, override rehydration, parallel `loadSmartAsset()`, then apply overrides).
- `ResolveAssetUrl(url, baseUrl)` matching BJS for portable shared project files.
- Wire `onAssetNotFound` from M1 into `deserializeProject` for missing-file callbacks (e.g. `` picker).
- Browser host helpers: `downloadProjectJson(json, filename)` (blob URL + ``); `pickProjectJson() → Promise<{json, baseUrl}>` (``); both pure browser APIs, tree-shakable.
- _Validation_: Vitest unit tests mirroring `projectSerializer.test.ts` (round-trip fidelity, schema version, missing-asset error, relative URL resolution); plumbing test — build 3-asset scene with overrides → serialize → reset → deserialize → pixel-equal render via parity oracle.

- [ ] **Milestone 4 — Inline objects** (in-tool-created entities)
Details

- Lazy `inlineObjectSerializers` registry keyed by Lite type tag (e.g. `"PbrMaterial"`, `"StandardMaterial"`, `"DirectionalLight"`, `"HemisphericLight"`, `"SpotLight"`, `"ArcRotateCamera"`); per-type `serialize`/`deserialize` pairs registered from owning modules — opt-in, tree-shakable.
- During `serializeProject`, walk materials/lights/cameras lists; for each NOT owned by any smart-asset key (per SAM provenance), serialize via the registry; skip silently if no serializer is registered.
- During `deserializeProject`, after assets load, walk `inlineObjects` and call matching deserializer; resolve scene-graph references (e.g. material assigned to mesh) by name.
- _Validation_: Vitest unit tests for registry CRUD, "no serializer registered → skip" behavior, and one round-trip per shipped type (PbrMaterial + DirectionalLight enough for v1); plumbing test — scene with one in-tool PbrMaterial assigned to smart-asset mesh, serialize → reset → deserialize → assert reattached and renders correctly.

- [ ] **Milestone 5 — Portable project bundle** (`.babylonzip`)
Details

- `saveProjectBundle(sam, om) → Promise` with dynamic `import("@zip.js/zip.js")`; layout `project.json` + `assets//`; rewrite asset URLs to relative `assets/...` paths in embedded `project.json`; fetch + inline each referenced URL.
- `loadProjectBundle(scene, blobOrFile) → Promise<{sam, om}>`: dynamic-import zip lib, unpack into `Map`, rewrite `assets/...` → in-memory `blob:` URLs, deserialize project.
- On load, validate schema + assert every referenced asset is present in the zip; return structured errors for missing files.
- `downloadProjectBundle(blob, filename)` and `pickProjectBundle() → File` host helpers.
- _Validation_: Plumbing test — build → save bundle → unload everything → load bundle → pixel-parity assert; bundle-size check that scenes not importing `smart-assets/bundle` pay zero bytes (dynamic-import keeps zip lib out of static analysis).

- [ ] **Milestone 6 — Loader composition for assembly workflows**
Details

- Confirm coverage of all atomic types as smart assets: GLB (M1 ✅), glTF (✅), PNG/JPG/EXR/ENV (wrap `loadTexture2D` / `loadEnvironment`), `.babylon` (wrap `loadBabylon`), animation-only files (verify Lite support — likely glTF animation extraction).
- Convenience assembly helpers: `assignSmartAssetTexture(mgr, materialKey, slotPath, textureKey)` recorded as overrides so they round-trip via the project file.
- Verify Lite has (or add) minimal `exportSceneToGlb(scene)` for "export to GLB"; if missing, mark as separate downstream task and ship M6 without it (project file is sufficient for round-trip authoring).
- _Validation_: Plumbing test — assemble scene from 1 mesh + 2 textures + 1 in-tool material → save project → reload → pixel-parity check.

- [ ] **Milestone 7 — Optional / later** (deferred until concrete demand; each item lands with its own unit or plumbing test)
Details

- Lite Inspector / external editor integration — wire override capture, missing-asset modals, smart-asset visualization pane when a Lite inspector or partner editor emerges.
- Auto-tracked overrides — promote the M2 sub-feature (`enableOverrideTracking`) to first-class once a real caller exists (typically the future inspector).
- `asset://` URL protocol convenience — route any Lite loader URL starting with `asset://key` through the SAM automatically.
- Multi-layer overrides (USD-style opinion stacks).
- Compression in bundles (Draco / Basis embedded in `.babylonzip`).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.