72 lines
4.4 KiB
Markdown
72 lines
4.4 KiB
Markdown
# ADR 0044: Sandboxed FBX External Texture Dependencies
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
FBX texture references may use sibling folders such as `textures/`, exporter-created `.fbm/`
|
|
folders, absolute workstation paths, Windows separators, or repeated ufbx texture elements that
|
|
resolve to the same file. Blacksite previously discovered only files already present in a sibling
|
|
`{model}.fbm/` directory. The committed painted-chair FBX instead declares three files under
|
|
`textures/`; none were committed, so source-material thumbnails queued the same missing Bevy image
|
|
paths more than once.
|
|
|
|
Import, manifest generation, project validation, editor previews, and the runtime loader must agree
|
|
on one dependency graph. That graph also crosses a security boundary: an imported source must not
|
|
read or copy a parent-traversing path or an arbitrary absolute path outside its bundle. A missing
|
|
source texture is required when any stable model slot selects Source, but it can be an intentional
|
|
authoring condition when every slot selects a project Material/Instance or Default.
|
|
|
|
## Decision
|
|
|
|
The local `bevy_ufbx` compatibility crate owns FBX external-texture path discovery and
|
|
normalization. It converts separators to `/`, preserves safe sibling and `.fbm/` layouts,
|
|
deduplicates normalized paths, and rejects parent traversal, asset-path syntax, and absolute paths.
|
|
An absolute exporter path may be portably rebased only when it contains a `.fbm/` suffix; only that
|
|
sidecar-relative suffix is retained.
|
|
|
|
The FBX loader performs a discovery parse, drops the non-`Send` ufbx scene, reads every unique safe
|
|
dependency through Bevy's `LoadContext`, and then performs normal synchronous scene processing.
|
|
External images become FBX labeled assets from those bytes. Repeated texture elements share one
|
|
image handle. Missing, rejected, or undecodable references are skipped with one consolidated
|
|
loader warning instead of deferred asset-server requests.
|
|
|
|
Static-mesh manifests are the authoritative model import dependency graph. Their existing
|
|
`source.dependencies` list records every parsed FBX external texture, including unavailable files.
|
|
Project validation checks that list without loading native assets. Missing FBX textures are a
|
|
blocking consolidated finding while any slot selects Source and an informational consolidated
|
|
finding when every slot selects Project/Default. The former whole-model Authoring Override value is
|
|
accepted only as registry-v1 migration input and expands to explicit Default selections. Unsafe
|
|
paths remain blocking under either selection state. Model registry records
|
|
mirror the list for editor details, but validation does not duplicate it when a generated static
|
|
manifest exists.
|
|
|
|
File -> Import Assets treats an FBX plus its referenced textures as one bundle. The importer
|
|
preflights every source path and canonical containment before touching the project, rejects
|
|
destination paths with symlinked ancestors, stages only the referenced files, preserves their
|
|
normalized relative layout, backs up overwritten destinations, and rolls back a partial publish.
|
|
Unreferenced `.fbm` contents are not copied.
|
|
|
|
The Asset Browser renders FBX model and mesh thumbnails through the neutral direct mesh path.
|
|
Source-material thumbnails preflight the authoritative dependency resolver first and cache one
|
|
non-retryable actionable failure when required textures are unavailable. Dependency rows expose
|
|
present/missing state. The committed painted-chair fixture's legacy Authoring Override migrates to
|
|
per-slot Default selections and remains untextured; its three source paths stay visible in
|
|
manifests, validation, and asset details.
|
|
|
|
## Consequences
|
|
|
|
- FBX sibling `textures/` and `.fbm/` bundles import and validate with identical normalized paths.
|
|
- Missing texture files are visible before native loading and cannot create repeated Bevy
|
|
asset-server errors.
|
|
- Any Source slot fails release validation when its FBX textures are absent. An all-Project/Default
|
|
model remains release-valid but retains an informational dependency finding.
|
|
- Absolute exporter paths, traversal attempts, and destination symlink redirects cannot read or
|
|
copy arbitrary host files.
|
|
- FBX files with external textures are parsed twice during loading so no non-`Send` ufbx scene
|
|
crosses an async read. Files without external textures retain a single parse.
|
|
- External images are labeled children of the FBX and reload the owning FBX through loader
|
|
dependency tracking. Per-image import metadata is not yet exposed.
|