Files
Faset_Engine/docs/manual/editor/assets.md
T

145 lines
7.9 KiB
Markdown

# Assets and Blender
Keep source assets under your project's `Assets` directory. Faset imports PNG/JPEG,
static glTF/GLB, and manifests published by the optional Blender helper. The import
service runs in the Editor; exported games load cooked data and need no Blender.
## Import a model
1. Copy a `.glb`, or a `.gltf` with its relative buffers and images, into `Assets`.
2. In the **Assets** panel select the source and use **Import**. Watch the job state
and diagnostics. Import is asynchronous; the previous working generation stays
available until a complete replacement is ready.
3. Place the imported scene in the viewport. The Faset object stores the AssetId;
its transform, gameplay components, and physics remain authoring data.
4. Add a rigid body explicitly if needed. Import does not infer gameplay collisions
from the visual mesh.
The same operation works through the command line:
```sh
build/linux-debug/faset_editor --project MyGame --command \
'{"name":"faset_import","arguments":{"path":"Assets/door.glb"}}' --wait
```
With MCP, call `faset_import`, then query `faset_job` using the returned job ID.
`faset_job_cancel` requests cancellation. Cancelling an import does not Undo an
authoring edit. See [MCP and CLI](mcp.md) for transport setup and errors.
The Assets panel marks an imported asset **Stale** when its source, external glTF
buffer/image, Blender bundle, saved import settings, importer, or target profile
differs from the active generation. Select the imported row, then **Import / Reimport**;
the Console reports the changed input. **Refresh** checks immediately, and the panel
also refreshes periodically. `faset_assets` exposes the same `freshness.state` and
structured `freshness.reasons` to MCP clients. Checks compare contents, including
files whose size and timestamp stayed unchanged. The last good cooked asset remains
visible until reimport succeeds; checking freshness never publishes a generation.
Cook and export refuse referenced stale or unavailable sources and explain which
input needs reimport. A standalone exported game uses only its packaged cooked
generation and never needs the original source files.
## Import an image
PNG and JPEG become image assets. Drag an imported image into a scene to create a
sprite. `pixels_per_unit` is a positive import setting, defaulting to 100; it controls
the sprite's natural size. Color, transform, and layer remain scene properties.
```json
{"name":"faset_import","arguments":{
"path":"Assets/player.png","settings":{"pixels_per_unit":32}
}}
```
Omitting `settings` reuses the saved recipe. Providing an object replaces the recipe;
it is not a partial merge. Malformed or oversized images produce diagnostics and
retain the last successful generation.
## Use the optional Blender helper
The helper works in unmodified Blender. Blender 4.5.3 LTS is the version used for
the observed round-trip test. Ordinary GLB import remains available without it.
1. Zip the repository's `tools/blender_addon` directory with that directory at the
ZIP's top level. Install the ZIP through Blender's add-on preferences and enable
**Faset GLB Export**.
2. Build a static scene using ordinary meshes and glTF-compatible PBR materials.
3. Choose **File → Export → Faset GLB Bundle** and place `manifest.json` in a directory
inside the Faset project's `Assets` directory.
4. **Save the `.blend` after the first export.** The helper assigns `faset_id` custom
properties to objects, meshes and materials, and `faset_asset_id` to the scene.
5. Import the exported `manifest.json` in Faset. Keep the manifest and its
`payload/<sha256>.glb` files together.
The helper publishes the manifest only after the payload is complete. It exports
the active Blender scene, not just the current selection. Gameplay and physics
components are added in Faset and are never written by the Blender helper.
## Rename, duplicate, and reimport
Renaming an object with a saved `faset_id` preserves its source identity. Re-export
and reimport update the shared asset; scene placements using that AssetId load the
new geometry while keeping their own transforms and components.
Duplicating an object can also duplicate its custom ID. The exporter rejects
ambiguous IDs. Select the new copy and run **Faset: New IDs for Selected**. Shared
mesh datablocks remain shared. Repair deliberately duplicated material IDs in
Blender's Custom Properties. Save the `.blend` again.
Removing an exported output produces an import conflict. Faset keeps the old
generation active. In **Jobs**, choose **Review removals** to open **Conflicts**.
Review the removed stable IDs and their last-good names; **Copy removed IDs** helps
locate references. Update affected references, then use **Accept reviewed removal**.
If source data or the active generation has changed since review, the acceptance
fails safely; use **Reimport / review again** and inspect the new result.
The same explicit API action uses `allow_removed_outputs: true`, with
`expected_generation` and `expected_active_generation` taken from the reviewed
job's `result.generation` and `result.previous_generation`. Use the same source and
settings. This accepts removal; it does not automatically remap references or delete
scene components. A normal GLB without persistent custom
IDs uses structural matching, which cannot guarantee identity after rename or
restructuring.
## Coordinates and supported content
The static profile uses right-handed glTF coordinates: metres, Y up. The Blender
helper enables glTF's Y-up conversion; do not add a second manual axis conversion.
Transforms and hierarchy are retained. Physics currently supports explicit boxes
on root-level objects. A visual imported mesh is not a mesh collider.
The renderer uses static triangle meshes, UV0, base-color factor/texture, metallic
and roughness factors, and directional light/shadows. Import can retain additional
glTF material metadata, but normal/occlusion/emissive/metallic-roughness texture maps,
glTF alpha-mode selection, unlit selection and per-material face-culling behavior
are not all implemented in the baseline renderer. Diagnostics identify unsupported
material features. Procedural Blender node networks need baking or simplification.
Skinning, animation playback, morph targets and compressed geometry are outside this
profile. Imported material records use the versioned `faset.material` format inside
the asset manifest; a standalone material editor is later work.
## What to commit and how to rebuild caches
Commit your source files, Blender bundle manifests/payloads, and
`<source>.faset-import.json` sidecars. Sidecars preserve AssetId and import settings.
Also commit `<source>.faset-overrides.json` if used. Commit `.blend` sources when they
are part of your project. Do not commit `.faset/cache`.
After clearing the cache or cloning a project, import the same sources again. Their
sidecars restore identities and recipes. Rebuild C++ to restore gameplay metadata.
Deleting the **entire** `.faset` directory also removes recovery journals and local
editor state; preserve unsaved work before doing that. An export fails if a referenced
asset has not yet been rebuilt.
The cache key includes source/dependency hashes, settings, importer recipe, pinned
importer dependencies and the desktop target profile. Linux and Windows share this
portable content profile; runtime executable builds remain platform-specific.
For an end-to-end example, open `examples/projects/collect-3d`. Its exit arch includes
a `.blend`, reproducible Blender script and a published bundle. The repository's
`tools/verify_blender_roundtrip.py` runs the actual Blender helper and Editor imports
to check rename, geometry changes, removal conflicts and failure preservation.
Pass `--ui-probe build/linux-debug/faset_blender_editor_probe` to also test two
instances in one live editor session: both receive new geometry while preserving
placement, tint, opaque gameplay fields and the authoring revision. This additional
probe requires Vulkan and produces before/after captures.