Builtin Library
README.md
MaterialAuthor
Stand up new materials and textures fast — the go-to surface for making materials at design time, each in one call instead of a hand-rolled asset-create-and-wire dance.
Every tool writes a source material asset and hands back a live AssetRef<material> you can apply straight to a Model. Wrap a texture (a proxy, a .texture asset, or an image path) into a new material with its PBR slot inferred from the texture name; make a flat-colour material from an RGB(A) value; clone an existing material under a new name with property or texture overrides; or scan a folder of textures — loose images and .texture assets — inferring each one's slot from its name and composing them into a single material. It pairs with the SVG → texture importer: drop a .svg, get a .texture, wrap it.
This is authoring, not runtime. Every tool creates source assets, which is a design-time action — never call it from gameplay code (components, controllers, per-frame updates, spawn logic). At runtime you consume an already-authored material by name or ref through the lower-level Material surface (create / apply / get / set), which is the gameplay-safe layer this one is built on. Reach here to make materials; reach for Material to apply and tweak them.
Material properties
Beyond the keys a tool reads itself (name, shader, overwrite, and slot on fromTexture), every option names a property of the shader the material is authored against — so anything pbr declares is reachable in one call: roughness, metallic, clearcoat, transmission, anisotropy, ior, uv_scale, and the texture slots. A custom shader's own properties work the same way, since the vocabulary is read from the shader.
Spell a property in snake_case or camelCase (uv_scale or uvScale); tiling names uv_scale and color names base_color. A single number fills a vector property's components, so tiling = 300 tiles 300×300. An option the shader doesn't declare is refused, naming the closest accepted spelling — the material is not written.
tools.use("MaterialAuthor", "fromTexture", "cliff_diff.texture",
{ name = "Cliff", tiling = 300, roughness = 0.9 })
Slot inference
When no slot is given, the texture stem picks the PBR slot: albedo / basecolor / base_color / diffuse / col → base colour; normal / nrm → normal; roughness / metallic / metalness / metallic_roughness / orm → roughness-metallic; emissive / emission / emit → emissive; ao / occlusion → occlusion. Pass an explicit slot to override.