Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

material_utils

High-level wrappers around the __material FFI global. Convenience helpers for the common material-authoring operations: create a named material, apply it to an entity, query / set material properties, and bind textures.

Exposed as the Material Luau global via --!global (auto-injected by the prelude). Material lives ON the Model / SkinnedModel component — there is no standalone Material component, because a material only renders where there is a mesh. To apply a material, use Material.apply() (which errors if the entity has no model) or set the model's material field directly: entity(id).component.add("Model", { model = "cube", material = "gold" }).

PascalCase aliases (Material.Create, Material.Apply, etc.) are kept for back-compat with the wider codebase — 88+ call sites across demos, scenes, components, guides, and the engine test suite use the legacy names. The lowercase forms are canonical.

Exports

Canonical (lowercase) surface:

  • Material.create(name: string, opts: MaterialOpts?) -> MaterialRef? — register a named material; returns the AssetRef envelope.
  • Material.apply(entityId: string, materialRef: MaterialRefOrName) -> boolean — set the material field on the entity's Model / SkinnedModel. Errors if neither is present.
  • Material.exists(name: MaterialRefOrName) -> boolean — registry predicate.
  • Material.getPropertyNames(name: MaterialRefOrName) -> { string }? — list property names exposed by a material.
  • Material.getProperty(name: MaterialRefOrName, prop: string) -> any — read a property value.
  • Material.setProperty(entityId: string, property: string, value: any) — set a property on the material assigned to an entity's Model / SkinnedModel.
  • Material.setTexture(name: MaterialRefOrName, slot: string, textureRef: string) -> boolean — bind a texture slot.

PascalCase back-compat aliases:

  • Material.Create(name, opts_or_shader, props?) -> MaterialRef? — accepts the legacy (name, shaderString, opts) 3-arg form OR the canonical (name, opts) form.
  • Material.Apply / Material.Exists / Material.GetPropertyNames / Material.GetProperty / Material.SetTexture — direct aliases for the lowercase counterparts.
  • Material.SetProperty(materialName, property, value) — writes to the REGISTERED material by name (NOT on a component). Different from lowercase setProperty.

Types:

  • Color = { number } | { r: number, g: number, b: number, a?: number }
  • Textures = { [string]: string }
  • MaterialOpts = { shader?, color?, roughness?, metallic?, emissive?, textures?, [string]: any }
  • MaterialRef = { __ref?, type?, name?, guid? }
  • MaterialRefOrName = MaterialRef | string

Usage

local mat = Material.create("gold", {
    color    = { 1, 0.85, 0.2 },
    metallic = 1,
    roughness = 0.15,
})

-- entityId must already carry a Model / SkinnedModel (a material only
-- renders on a mesh); apply errors otherwise.
Material.apply(entityId, mat)                  -- AssetRef envelope
Material.apply(entityId, "gold")               -- bare name also works
Material.setProperty(entityId, "roughness", 0.3)
Material.setTexture("gold", "albedo", "@builtin::textures.gold")

Notes

  • Material.apply accepts either an AssetRef envelope or a bare name — the model's material field auto-wraps strings.
  • Material is a field on the Model / SkinnedModel component (declared as material, an AssetRef<material>). There is no standalone Material component — apply / setProperty route to whichever model is present and error when neither is.
  • Material.setProperty writes the property on the material assigned to the entity's model; Material.SetProperty writes on the REGISTERED material by name. They behave differently — keep them straight.
  • All argument validation raises on bad input rather than silently no-oping, so call sites surface mistakes early.