Builtin Library
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.voxcompmanifest.M.bake(srcName: string, dstName: string?) -> (string, string)— flatten a.voxcompinto a.voxbin.M.loadForTemplate(name: string) -> (record?, path?, deps?)— bake-on-demand entry point used byVoxel.fromTemplate. Returnsnilwhen no manifest exists.M._bindParent(p: any)— internal hook for the parentvoxelEnginemodule.
Builder methods:
builder:addChild(templateName: string, opts: ChildOpts?) -> Builderbuilder:saveBaked(name: string?) -> (string, string)— write a flat.voxbin.builder:saveLinked(name: string?) -> (string, string)— write a.voxcompmanifest.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.
:explodeallows 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
visitedset during resolution and error with a descriptive message. M.loadForTemplatereturns the manifest's transitive dependencies so callers can register live-link watchers; edits to any.voxbinor.voxcompin the dep set trigger a rebuild of the consuming instance.- The module is loaded by the parent
voxelEngine.modulewhich callsM._bindParent(M)— don'trequirethis module standalone for features that depend on the parent (:explodeetc.).