Files
sporel-lib-core.render/README.md
calic ce88d3c216 feat(render): per-entity sprite_scale on the Atlas-UV path
draw_entities path-1 reads an optional sprite_scale (number, default
1.0) and applies it as uniform scaleX/scaleY in
draw_sprite_transform around the visual center. Lets templates whose
native sprite resolution (e.g. TC_Basics 300×300 bed) doesn't match
the project tile-scale (~/sporel_tile_scale.md: 64 px = 0.5 m via the
puppet shoulder anchor) render at credible real-world sizes without
re-baking the atlas.

Consumers compute their per-atlas scale from
atlas_meta.pixels_per_meter (atlas-baker v0.4.0+ output) divided into
their project canonical px/m — one line in M.init, no per-entity
constants in the template.

Unset sprite_scale preserves v0.2.0 behavior — spine-prototype,
map-editor, vagrant's pre-TC_Basics items unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 11:42:17 +02:00

128 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# lib-core.render
Colored-quad tile-grid renderer + tag-driven entity-render. Reads
`lib-core.maps`'s tilemap (v0.1: `draw_map`), and `lib-core.composition`'s
tag-index (v0.2: `draw_entities`).
**Version:** 0.3.0
**Lib-ID:** lib-core.render
**Requires:** lib-core.maps v>=0.5.7, lib-core.composition v>=0.3.0
**Tags:** render, tiles, draw, colored-quads, entities
## Topology
<!-- topology:start (auto-generated; do not edit) -->
```mermaid
graph LR
this["lib-core.render"]
lib_core_maps["lib-core.maps"]
this --> lib_core_maps
lib_core_composition["lib-core.composition"]
this --> lib_core_composition
engine["engine.*"]
this --> engine
```
<!-- topology:end -->
## API
### `render.draw_map(map_id)`
**Syntax:** `render.draw_map(map_id: string | nil) -> integer`
**Example:**
```lua
function render(ctx)
engine.render.clear_color(engine.render.rgb(20, 20, 30))
local n = render.draw_map() -- uses current-map
end
```
**Description:** Iterates the tiles of the specified map (or current-map when nil), drawing one colored rect per tile at `(tx * tile_size, ty * tile_size)`. Tile color is read from the tilemap's `tile.color = {r, g, b}`; if missing or malformed, falls back to magenta as a visible "missing-color" debug-marker. Must be called from inside a render hook. Returns the number of tiles drawn (for smoke verification + debug).
### `render.draw_entities(filter)`
**Syntax:** `render.draw_entities({tag: string}) -> integer`
**Example:**
```lua
function render_fn(ctx)
camera.begin()
render.draw_map()
render.draw_entities{ tag = "renderable" }
camera.finish()
end
```
**Description:** Iterates entities tagged with `filter.tag` (via
`composition.list_by_tag`) and renders each according to its
sprite-properties. `position.x`/`position.y` is treated as the visual
CENTER of the entity in all render-paths. Returns the number of
entities drawn.
Three sprite-property paths are tried per entity, in order:
1. **`sprite_atlas` (string, atlas-texture-path) + `sprite_uv.{x,y,w,h}`
(numbers)** — renders the sub-rectangle of the atlas via
`engine.render.draw_sprite_transform`. Optional `sprite_scale`
(number, default 1.0) scales the rendered quad uniformly around its
visual center; useful when a sprite-atlas's native pixel size
doesn't match the project tile-scale. Atlas textures are loaded
once and cached internally on first use; no eviction.
2. **`sprite_color` (uint32 0xRRGGBBAA) + `sprite_w` + `sprite_h`
(numbers)** — renders a colored rect via `engine.render.draw_rect`.
3. **None of the above** — magenta 16×16 fallback rect (debug-marker).
Filter shape `{tag = "..."}` is the only supported form in v0.2.0;
template-id-based or property-predicate filters are deferred (loud-error
for malformed filters; see Phase-A Spec A-Q3).
## Conventions
- Colored-quads only in v0.1.0. Texture-rendering, multi-layer composition, post-processing, parallax, shaders, hot-reload all DEPRECATED-MVP.
- World-space coords; pair with `lib-core.camera` to support panning + zoom.
- Magenta fallback `[255, 0, 255]` is intentional: high-visibility debug-marker for malformed color-data.
- Y-down-positive per ADR-0031.
## Consumer pattern
```lua
local maps = require("lib-core.maps")
local render = require("lib-core.render")
local camera = require("lib-core.camera")
function render_fn(ctx)
engine.render.clear_color(engine.render.rgb(20, 20, 30))
camera.begin()
render.draw_map()
camera.finish()
end
```
## CHANGELOG
### v0.3.0 (2026-06-20)
- Added optional `sprite_scale` (number) on path (1). Defaults to 1.0
when absent — v0.2.0 consumers unchanged. Lets templates whose
native sprite resolution doesn't match the project tile-scale
rescale at render time without re-baking the atlas.
- Composition dep tightened to v0.3.0 (matches current sibling-tree
state; no API impact, just resolution-correctness).
### v0.2.0 (Phase A.2 — 2026-06-09)
- Added `draw_entities(filter)` tag-driven entity-render. Two sprite-
property paths (`sprite_atlas`+`sprite_uv` / `sprite_color`+`sprite_w`+
`sprite_h`) plus magenta-fallback. `position.x`/`.y` is visual-center.
- Atlas-texture cache (no eviction in v0.2.0).
- New dep: `lib-core.composition` v0.1.0.
### v0.1.0 (P.0)
- Initial release: `draw_map` colored-quad iterator.
## References
- Spec v0.1.0 (P.0): `meta/docs/superpowers/specs/2026-05-09-p0-lib-render-design.md`
- Spec v0.2.0 (Phase A): `meta/docs/superpowers/specs/2026-06-09-phase-A-inactive-entities-composition-actor-reentry-design.md`
- Architecture: `meta/docs/architecture/render-pipeline.md`
- ADR-0001 (engine knows verbs, libs bring nouns)
- ADR-0031 (pixel-convention: Y-down-positive)
- ADR-0038 (API-Doc-Convention)