Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

composite

Composite (kitbashed) voxel props. A composite is a named arrangement of child templates — each with a voxel offset and axis-aligned yaw — that can be saved either as a flat .voxbin (baked) or a .voxcomp manifest (linked, with the children re-resolved at instantiation time so edits to a child template propagate to every composite that references it).

Authoring flows via the voxelEngine.toolbox/composite.tool; calling Voxel.composite.new(name) from Luau works too. The parent voxelEngine module injects itself via M._bindParent(parent) so :explode can call back into parent.fromTemplate without a require cycle.

Exports

  • M.new(name: string, opts: BuilderOpts?) -> Builder — start a new composite builder.
  • M.inspect(name: string) -> Manifest — read a saved .voxcomp manifest.
  • M.bake(srcName: string, dstName: string?) -> (string, string) — flatten a .voxcomp into a .voxbin.
  • M.loadForTemplate(name: string) -> (record?, path?, deps?) — bake-on-demand entry point used by Voxel.fromTemplate. Returns nil when no manifest exists.
  • M._bindParent(p: any) — internal hook for the parent voxelEngine module.

Builder methods:

  • builder:addChild(templateName: string, opts: ChildOpts?) -> Builder
  • builder:saveBaked(name: string?) -> (string, string) — write a flat .voxbin.
  • builder:saveLinked(name: string?) -> (string, string) — write a .voxcomp manifest.
  • builder:explode(opts?) -> (rootId, childIds) — materialise as a hierarchy of live entities.
  • builder:saveAsBundle(bundleName: string, opts?) -> (string, assetId) — explode and compose into an asset bundle.
  • builder:children() -> { entry } — read-only view of accumulated children.

Types:

  • Vec3 = { x: number, y: number, z: number }
  • ColorRGBA = { number }
  • ChildOpts = { offset?: { number }, rotation?, pivot? }
  • BuilderOpts = { blockSize?: number }
  • Manifest = { version?, kind?, name?, blockSize?, children }
  • VoxbinRecord = { kind?, size, blockSize?, palette?, grid }

Usage

local Voxel = require("@builtin::systems.voxelEngine.voxelEngine")

local c = Voxel.composite.new("car_assembly")
    :addChild("body",  { offset = {  0, 0, 0 } })
    :addChild("wheel", { offset = { -3, 0, -2 }, rotation = 0   })
    :addChild("wheel", { offset = {  3, 0, -2 }, rotation = 0   })
    :addChild("wheel", { offset = { -3, 0,  2 }, rotation = 180 })

c:saveBaked()       -- writes .voxbin (self-contained)
c:saveLinked()      -- writes .voxcomp (live-linked to children)
c:explode()         -- materialises as live entities

Notes

  • Baked saves accept only axis-aligned yaws (0/90/180/270) with zero pitch/roll — voxel grids can't represent freeform rotations without resampling. :explode allows arbitrary angles because entity rotations compose naturally.
  • All children of a baked composite must share the same blockSize. First child wins; mismatched children error at bake time.
  • Linked composites detect cycles via a visited set during resolution and error with a descriptive message.
  • M.loadForTemplate returns the manifest's transitive dependencies so callers can register live-link watchers; edits to any .voxbin or .voxcomp in the dep set trigger a rebuild of the consuming instance.
  • The module is loaded by the parent voxelEngine.module which calls M._bindParent(M) — don't require this module standalone for features that depend on the parent (:explode etc.).