Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld c853eef7-f…

roombaTrail

Records the actual Roomba position at 8 cm intervals as a floor-level emissive ribbon. Distance integrates actual frame-to-frame movement. GPU instances are allocated in 256-segment chunks; the full route is retained for the current cleaning run. Hiding releases draw registration…

by◐Deata·posted 1mo ago
What it does

Records the actual Roomba position at 8 cm intervals as a floor-level emissive ribbon. Distance integrates actual frame-to-frame movement. GPU instances are allocated in 256-segment chunks; the full route is retained for the current cleaning run. Hiding releases draw registrations while recording continues; showing restores the complete history. New mess clears the route, pause adds no stationary points, and teleport discontinuities are never joined. Reuses the ZeroMind neon material.

Route visibility is independent of camera mode, including Follow pilot and GoPro.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

Actual travelled trajectory, sampled at 8 cm and rendered as instanced ribbons.

new( ) → void

clear( ) → void

draw(c: ?) → void

argtypedescription
c?

show(on: ?) → void

argtypedescription
on?

sample(p: ?) → void

argtypedescription
p?

status( ) → void

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

10+items
◐
material · pulled in
❒asset
# Neon A glowing cyan neon surface built on `@builtin::shaders.pbr` with emission enabled. It pairs a bright cyan-blue base colour (`0.2, 0.8, 1.0`) with a matching emissive colour driven hard by `emissive: 5.0`, so it reads as a self-lit light source. Low roughness (`0.2`), non-metallic, opaque, instanced, with the `_EMISSION` keyword enabled. ## Inputs - `colors.emissive` (`0.2, 0.8, 1.0, 1.0`) — cyan glow colour. - `floats.emissive_intensity` (`5.0`) — strong emissive intensity (feeds bloom). - `colors.base_color` (`0.2, 0.8, 1.0, 1.0`) — matching cyan base tint. - `floats.roughness` (`0.2`) — glossy surface under direct light.
▲ 0↓ import
·
assettype · pulled in
❒asset
# Material (asset type) A material is a named, configured instance of a `.shader`. The shader defines the surface look (lighting model, available property fields, texture slots); the material picks values for those fields and a shader to bind to. Renderable entities reference materials, not shaders, so the same geometry can wear different materials and the same material can be reused across many entities. Entities sharing one material can still differ in a value: every drawn object carries four `vec4` lanes of its own that a surface shader reads as `input.shader_data[lane]` and `renderer.instanceData.set` writes. Use that for a dissolve at its own progress per subject, a hit flash at its own age, a fill level per instance — a material per entity is for when the LOOK differs, not when a number does. > New to how a material relates to its shader, its textures, and the live GPU > material behind it? Read `core/resource-model` first. It also covers the > difference between an authored `.material` asset (this type) and a runtime GPU > material made with `renderer.material.create`. ## When to use one - You want a named surface configuration an entity wears by referencing it from its `Model` component (`material = "@.../<Name>"`). - You want runtime property tweaks (`asset.resolve(ref):setProperty(...)`) to affect every entity using the material at once. - You want to publish a curated look (`Gold`, `RedGlow`, `BrickWall`) other authors can reuse without re-typing shader bindings. If you need a brand-new lighting model or a custom visual effect, you need a `.shader` first; the material wraps it. ## Where it lives - Source: `/zero/source/.../<Name>.material/` - Identity: `<Name>` (the `.material` suffix strips). - Folder shape: - `mat.yaml` — canonical material spec (shader + property values). **Required.** - `preview.png` — the material's rendered shader-ball still, its persisted visual description. **Required.** Rendered when the material is staged (`zm add`) with its preview missing or stale, and by `generatePreviews`; it syncs, publishes, feeds image-based search, and gives browsers a thumbnail. - `README.md` / `.metadata` — optional prose + tags, indexed when an author writes real ones. - `textures/` — optional folder for embedded textures. Validator allows the folder; its interior is unrestricted. - `shaders/` — optional folder for a co-located custom shader. Same rule. ## How to create one ```luau asset.create("material", "<Name>") -- Creates: /zero/source/<Name>.material/ -- mat.yaml (shader binding + property scaffold) -- preview.png (rendered when the material is staged with `zm add`; the -- picture lands as a change the next `zm add` stages) -- `folder` places it in a subfolder of /source instead of the root: asset.create("material", "<Name>", { folder = "materials" }) ``` Pass the shader and initial values through `asset.create`, then tune with `setProperty` and keep what you tuned with `saveDefinition`: ```luau local mat = asset.create("material", "<Name>", { shader = "@builtin::shaders.pbr" }) mat:setProperty("base_color", { 0.8, 0.6, 0.1, 1 }) mat:setProperty("roughness", 0.3) mat:saveDefinition() -- writes the tuned values into mat.yaml ``` This mints the `.material` asset and returns a handle you tune with `setProperty`. A set is a runtime change: it reaches the GPU material and every entity wearing it, and `saveDefinition` is the call that writes it into `mat.yaml`, so a property driven every frame costs no file write and leaves the authored file as its author wrote it. A purely runtime `asset.create` lives only for the session. For an ephemeral, runtime-only GPU material that is not an asset at all, use `renderer.material.create` instead (see `core/resource-model`). ## How it operates 1. **Property reflection.** The bound shader's uniform struct fields become the material's configurable properties — no manual property declarations needed. `naga` introspects the shader at load. 2. **Property values.** `mat.yaml` groups values by type, each block keyed by the shader's field names: `properties:` holds scalars and colors/vectors, `ints:` holds integer-typed fields, `bools:` holds boolean-typed fields, and `textures:` holds texture slots. Omitted fields take the shader's default. A scalar is a bare number (`roughness: 0.5`); a color or vector is an array (`base_color: [1, 1, 1, 1]`). `shader:` is the shader's identity string. This is the shape every material the engine writes uses. A `saveDefinition` writes the changed values into the file where they already stand and leaves the rest of it — its comments, the order of its keys and blocks, the spelling of its literals — untouched. The older `floats:` / `colors:` blocks (with `{ r, g, b, a }` map colors) still load for materials hand-authored that way. 3. **Render state.** `render:` holds how the mesh is drawn rather than what the shader reads: `blend` (the equation the fragment composites with, also spelled `type`), `cull`, `depth_write`, `depth_compare` and `topology`. The `.shader` type README's "The render block" section lists every value each key takes, and `asset.create`'s `render` argument takes the same keys and values. 4. **Application.** An entity wears a material by referencing it from its `Model` component (`material = "@.../<Name>"`). Materials affect every entity that references them; runtime `asset.resolve(ref):setProperty(...)` changes propagate to all of them immediately, and last until the next mode change unless `saveDefinition` writes them into `mat.yaml`. 5. **Texture binding.** Texture slots accept `color:r,g,b,a` for solid colors, `default:white` / `default:black` / `default:normal` for the engine's own fallback texels, `@builtin::textures.<name>` for builtins, `path/to/image.png` for file textures, or a render-target handle for camera renders. The GPU texture cache reads the `color:` and `default:` forms from the string itself, so a slot written in one names no asset and carries nothing with the material when it travels; every other form names a texture asset the slot depends on. A texture in `base_color_texture` is multiplied by `base_color`: every built-in surface shader declaring both draws the texture's colour times `base_color`, channel by channel. Under the default white `base_color` the texture shows as itself, and a coloured `base_color` tints it. The two read a colour differently: `base_color` is linear, and the slot reads its texels as sRGB-encoded, a `color:` value's included, the way it reads an image. A colour stated in both places is therefore multiplied by a darker copy of itself: `color:0.62,0.14,0.05,1` in the slot decodes to `0.34, 0.017, 0.0039`, so beside `base_color` `0.62, 0.14, 0.05` the surface draws `0.21, 0.0024, 0.0002`, far darker than either. State a solid colour once, as `base_color`, and leave the slot at its default white. 6. **Hot reload.** Editing `mat.yaml` repacks the GPU uniform buffer on the next frame; visible immediately. 7. **Inspector.** `type.yaml` names `inspector: { type: "inspector.luau" }`, and `inspector.luau` declares the material's sections beside the generic ones: `shader` (the bound shader, swappable), `properties` (each shader field as its typed control) and `textures` (each texture slot as an asset chip). They read the material through `mat:getShaderRef()` (the bound shader's ref, `~` expanded) and `mat:getTextures()` (slot name → `{ ref, name }`: the bound texture's guid and the id the material names it by). An edit there is an authoring write: `mat:writeProperty(name, value)` and `mat:writeTexture(slot, texture)` write the value into `mat.yaml` (and drop the session's own value for it, so the material reads what the file holds), and `setShader` rewrites the file; inside an undo operation each file write is recorded, so undo puts `mat.yaml` back. `setProperty` / `setTexture` stay runtime writes that last until the next mode change. ## Discovery - `asset.list("material")` — every registered material. - `asset.inspect("<name>")` — shader binding, property values, source path, this type README. - `ls /zero/source/<Name>.material` lists the files the folder holds. - `asset.resolve("<name>"):getProperties()` — the property fields exposed by the bound shader, each at the value it currently holds: what `mat.yaml` authored until something writes to the material, and the written value from then on, whichever call wrote it. That is the value the surface is drawn with. Read them back rather than guessing names; which fields exist comes from the shader. - `asset.resolve("<name>"):getDefinition()` — the authored `mat.yaml` bytes, the value the material rests at. - `asset.resolve("<name>"):getShader()` — the shader the material binds. ## Authoring conventions - Use lowercase, descriptive names (`brushed_steel`, `red_glow`, `tarmac_wet`). Avoid shader-name suffixes in the material name — the binding lives in `mat.yaml::shader`. - Drive every property the shader exposes; defaults are a fallback, not a contract for which fields exist. - Embed textures alongside the material (`textures/` subfolder) when they're used only by this material; reference shared textures from `@builtin::textures.*` or a library. ## Common pitfalls - **Property names must match the shader's uniform struct exactly** (case-sensitive). Misnamed properties silently get the shader's default. - **`base_color_texture` multiplies `base_color`.** A `color:` texture holding the same value as `base_color` multiplies the colour by its own sRGB-decoded value, so the surface renders far darker than the value written. Write a solid colour as `base_color` alone. - **Broken shaders break the material.** A material whose shader has a parse error renders as the magenta checkerboard. Inspect the shader first if the material looks wrong. - **`setProperty` targets the material, not the entity.** Changes affect every entity that references the material. - **`setProperty` is a runtime change.** It reaches the GPU, not the file: call `saveDefinition` to write the current values into `mat.yaml`. For a per-entity override that no other entity sees, give the entity its own copy with `Model:applySessionMaterial(renderer.material.create(...))`. - **Renaming the folder changes the identity.** Update every `Model` component and `asset.create` callsite that references it. ## Related types - `.shader` — defines what properties exist; required before a material can bind to it. - `.preset` — captures a component configuration; conceptually similar to a material, but for components instead of shaders.
▲ 0↓ import
backing path · roombaTrail.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.