a327ex.com

Visual Experiments 3

Summary

Continuation of the ricochet-template visual-experiments work (follows "Visual Experiments 2"). This session closed out the remaining icons/images roadmap items (image-as-SHAPE + image-as-CONTENT), added the rest of the geometric shapes plus shape rotation, and did a major API-simplification pass that culminated in a unified effect editor. Also patched the shared Anchor 2 engine to bind auxiliary sampler textures for the regular draw path. The 480×270 work and replacing the snkrx-template effect stack were explicitly deferred to later manual sessions.

Alignment + scope decisions (up front):

Engine patch — aux sampler binding for the draw path (Anchor2/engine/src/anchor.c):

Image-as-SHAPE (tiled icon masks) — sprite + sprite_field:

Image-as-CONTENT (effect over real images):

More geometric shapes + rotation:

Single-call API + the unified editor (API simplification):

Docs synced (final step):

Deferred (parked in the roadmap, user-driven): 480×270 support; replacing the snkrx-template edition.lua + dither stack with this system; flow-field per-cell shape rotation.


Let's continue on the visual experiments. Read the last session summary log to get aligned. I think this session we want to proceed with the rest of what we needed to do regarding icons/images, add more shapes and then I also want to do some API simplifications and also make sure that everything works on 480x270 as well, to make all these effects we implemented also replace the SNKRX template ones.

I'll start by finding and reading the last session summary log to get aligned.

Glob (*/logs/.md)

anchor.blot.im\logs\2026-01-02_18-59.md
anchor.blot.im\logs\2026-01-03_12-30.md
anchor.blot.im\logs\2026-01-03_15-30.md
anchor.blot.im\logs\anchor-phase-1.md
anchor.blot.im\logs\anchor-phase-10-part-1.md
anchor.blot.im\logs\anchor-phase-10-part-10.md
anchor.blot.im\logs\anchor-phase-10-part-2.md
anchor.blot.im\logs\anchor-phase-10-part-3.md
anchor.blot.im\logs\anchor-phase-10-part-4.md
anchor.blot.im\logs\anchor-phase-10-part-5.md
anchor.blot.im\logs\anchor-phase-10-part-6.md
anchor.blot.im\logs\anchor-phase-10-part-7.md
anchor.blot.im\logs\anchor-phase-10-part-8.md
anchor.blot.im\logs\anchor-phase-10-part-9.md
anchor.blot.im\logs\anchor-phase-2.md
anchor.blot.im\logs\anchor-phase-3-part-1.md
anchor.blot.im\logs\anchor-phase-3-part-2.md
anchor.blot.im\logs\anchor-phase-3-part-3.md
anchor.blot.im\logs\anchor-phase-3-part-4.md
anchor.blot.im\logs\anchor-phase-4.md
anchor.blot.im\logs\anchor-phase-5.md
anchor.blot.im\logs\anchor-phase-6.md
anchor.blot.im\logs\anchor-phase-7.md
anchor.blot.im\logs\anchor-phase-8.md
anchor.blot.im\logs\anchor-phase-9.md
anchor.blot.im\logs\anchor-review-1.md
anchor.blot.im\logs\anchor-review-2.md
anchor.blot.im\logs\audible-book-recommendations-2.md
anchor.blot.im\logs\audible-book-recommendations.md
anchor.blot.im\logs\anchor-phase-10-part-11.md
... [71 more lines]

Let me look for the visual experiments session log specifically and check the current logs location.

Glob (/logs/visual.md)

anchor.blot.im\logs\ebb-visual-polish.md
anchor.blot.im\logs\orblike-visual-aural-consistency.md
anchor.blot.im\logs\orblike-map-gen-wall-visuals.md
anchor.blot.im\logs\orblike-wall-visuals-ability-editions.md
anchor.blot.im\logs\orblike-more-visuals-edition-system.md
a327ex-site\logs\ebb-visual-polish.md
a327ex-site\logs\orblike-map-gen-wall-visuals.md
a327ex-site\logs\orblike-more-visuals-edition-system.md
a327ex-site\logs\orblike-visual-aural-consistency.md
a327ex-site\logs\orblike-wall-visuals-ability-editions.md
a327ex-site\logs\visual-experiments-1.md
a327ex-site\logs\visual-experiments-2.md

Glob (a327ex-site/logs/*.md)

a327ex-site\logs\2026-01-01-07-37.md
a327ex-site\logs\2026-01-01-19-37.md
a327ex-site\logs\2026-01-02-10-00.md
a327ex-site\logs\2026-01-02-18-59.md
a327ex-site\logs\2026-01-03-12-30.md
a327ex-site\logs\2026-01-03-15-30.md
a327ex-site\logs\2026-01-03-18-20.md
a327ex-site\logs\2026-01-04-12-15.md
a327ex-site\logs\anchor-app-design.md
a327ex-site\logs\anchor-app-phase-1-part-1.md
a327ex-site\logs\anchor-app-ui-discussion.md
a327ex-site\logs\anchor-arena-final-and-neovim-diff-tool.md
a327ex-site\logs\anchor-arena-test.md
a327ex-site\logs\anchor-phase-1.md
a327ex-site\logs\anchor-phase-10-part-1.md
a327ex-site\logs\anchor-phase-10-part-10.md
a327ex-site\logs\anchor-phase-10-part-11.md
a327ex-site\logs\anchor-phase-10-part-2.md
a327ex-site\logs\anchor-phase-10-part-3.md
a327ex-site\logs\anchor-phase-10-part-4.md
a327ex-site\logs\anchor-phase-10-part-5.md
a327ex-site\logs\anchor-phase-10-part-6.md
a327ex-site\logs\anchor-phase-10-part-7.md
a327ex-site\logs\anchor-phase-10-part-8.md
a327ex-site\logs\anchor-phase-10-part-9.md
a327ex-site\logs\anchor-phase-2.md
a327ex-site\logs\anchor-phase-3-part-1.md
a327ex-site\logs\anchor-phase-3-part-2.md
a327ex-site\logs\anchor-phase-3-part-3.md
a327ex-site\logs\anchor-phase-3-part-4.md
... [71 more lines]

There's visual-experiments-2.md — that's the most recent. Let me read it.

Read (E:\a327ex\a327ex-site\logs\visual-experiments-2.md)

File content (724.1KB) exceeds maximum allowed size (256KB). Use offset and limit parameters to read specific portions of the file, or search for specific content instead of reading the whole file.

The log is a full transcript. Let me read the summary at the top.

Read (E:\a327ex\a327ex-site\logs\visual-experiments-2.md)

1    Title: Visual Experiments 2
2   Date: 2026-05-29 21:38:44
3   
4   # Visual Experiments 2
5   
6   ## Summary
7   
8   Continuation of the `ricochet-template` visual-experiments work (follows "Visual Experiments 1"). Extended the pattern × color × dither effect system with **local gradient patterns**, a **second per-pattern knob**, a **SHAPE axis** (field rendered as a grid of shapes), a **`ramp` color recipe** + an in-app **ramp editor**, then pivoted to **icon research** — built an Iconify→PNG pipeline, compared Phosphor/Tabler/Remix in a flat themed UI screen, chose **Tabler**, and rebuilt that screen as a full-width Tabler **UI kit**. Also fixed and documented a recurring **sprite-centering** engine gotcha and a latent `layer_line` framework-copy bug.
9   
10  **Local gradient patterns (linear + radial):**
11  - Added two patterns sampled from the draw's own `vUV` (rect-local) instead of `vPos` (world/global): `linear_gradient` (kind 10) and `radial_gradient` (kind 11). The field is locked to the rectangle's own box, so it moves/scales with the rect.
12  - Aspect-corrected via the quad's pixel size: hoisted a `vec2 quad_px` in the shader `main()`, set per shape branch (rect = `vShape0.xy`, circle = `vec2(vShape0.x)`, sprite = `vec2(texSize)`, etc.). Widened `effect_field(world_pos)` → `effect_field(world_pos, uv, quad_px)`; both call sites updated.
13  - `linear_gradient`: `param` = ANGLE (0..1 → 0..2π), aspect-corrected; ramp normalized corner-to-corner along the direction. `radial_gradient`: `param` = SHAPE, blends a true circle (inscribed, short side) ↔ rect-fitting ellipse.
14  - Via AskUserQuestion, the "how fast the gradient goes" control was decided to mean **transition steepness**, which is mechanically the existing universal **CONTRAST** modifier — so no new uniform; SCALE + SPEED are inert for gradients.
15  
16  **Second per-pattern knob (`param2`):**
17  - Added a general second intrinsic knob (`u_pattern_param2`) mirroring `param`, with a *per-pattern* slider range (`param2_min`/`param2_max`). Linear → **OFFSET** ([-1,1], slides the f=0.5 midline along the angle); radial → **RANGE** (0.25..3, scales the circle's reach). Conditional 5th MODIFIERS slider shown only when `param2_label` is set; sidebar height bumped.
18  
19  **SHAPE axis (4th axis) — field as a grid of shapes:**
20  - New `shape` axis (`shape_kinds`, `u_shape_kind`, `u_shape_size`), `apply_shape` between `effect_field` and dither. Cells anchored to screen space (`gl_FragCoord`), the same space as the dither. Shared SHAPE + CELL SIZE controls (like color/dither).
21  - First pass had three circle variants (size/fill/hard). User: "Let's try all these options" → made them selectable shape kinds.
22  - **Warping bug:** circles warped into blobs/crescents because the field was sampled per-fragment (f varies across a cell). Fixed by sampling the field **once per cell at the cell center**, reconstructing world_pos/uv there from screen-space derivatives (`dFdx`/`dFdy`) — exact for the 2D affine camera. Introduced `effect_field_shaped`.
23  - **Mask × fill decouple:** user wanted each circle to carry the effect's internal variation, not a flat tone. Generalized to two roles: **coverage** (mask, from the per-cell `fc` → true circle boundary) and **color/fill** (per-fragment `ff`). `shape_mask()` isolated as the single extension point for future image-stencil shapes.
24  - Removed `circle (fill)` per user ("too close to the raw effect"); kept `circle` (size) + `circle_hard`.
25  
26  **SNKRX editions — conceptual placement (no code):**
27  - Discussed where SNKRX's `dynamic` / `polychrome` / `palette_cycle` / `silver` editions fit. Conclusion: they're **COLOR recipes**. SNKRX fused (shimmer field + color transform + animation) into one "edition"; our pipeline already split those. So an edition decomposes: shimmer → pattern, animation → pattern `speed`, dither → dither, the color transform → the color axis.
28  - Key payoff: animated color is **free** — feed an animated pattern into a hue/ramp recipe and it sweeps over time without the recipe knowing about time; spatial color comes from gradient patterns. Only field-independent uniform time-cycling would need a new color-stage input (better expressed as a pattern). Ricochet caveat: a continuous rainbow fights the limited palette → use a **palette-token ramp** (quantized "polychrome").
29  
30  **`ramp` color recipe:**
... [90 more lines]

Now let me read the ricochet-template's CLAUDE.md (the orientation file with the recorded roadmap and conventions).

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

1    # ricochet-template — orientation for new instances
2   
3   ## ⛔ WORKFLOW RULE — DESIGN BRIEF BEFORE CODE ⛔
4   
5   **This rule has no exceptions and is valid for every single
6   non-trivial change, every session, every file in this project.**
7   
8   Before calling `Write` or `Edit` on project code, post a **design
9   brief** in chat — a conceptual explanation of the approach, NOT the
10  code itself. Then wait. The user will usually reply with questions
11  and improvements; iterate the brief with them until you reach a
12  conclusion. Only then write the code.
13  
14  ### What a design brief contains
15  
16  1. **Approach.** A high-level explanation of how each feature works —
17     what it does, the strategy, the key data it holds, its lifecycle.
18  2. **Interfaces.** How the feature connects to existing features:
19     which existing functions / files / globals it touches or reuses,
20     and how. Include this whenever the feature is not self-contained.
21  3. **Functions.** For each new or changed function:
22     - its name,
23     - what it does,
24     - which other functions it calls — selective, not exhaustive,
25     - its general structure, when that isn't already obvious.
26  
27  The brief is a conceptual map, not a spec and not pseudocode. Aim for
28  "a reader could predict the shape of the code from this."
29  
30  ### After the brief is agreed
... [667 more lines]

I'm now fully aligned on where the project stands. Before proposing anything, let me read the current state of the core files so my briefs match the actual code.

Read (E:\a327ex\ricochet-template\effect.lua)

1    --[[
2     effect.lua — three-axis visual effect system (pattern × color × dither).
3   
4     THE 30-SECOND MENTAL MODEL
5       Every draw routes through assets/draw_shader.frag. The shader takes
6       three orthogonal selectors and composes them as:
7   
8           f = pattern(world_pos, time)          -- spatial structure + animation
9           f = dither(f, pixel_pos)              -- quantize to discrete levels
10          rgb = color(base_rgb, f, palette)     -- map f → palette token(s)
11  
12      Pattern owns "what the field looks like" AND "whether it moves over
13      time." Color is a pure recipe that picks (or mixes) palette tokens
14      by f. Dither inserts the pixel-art stipple between them. The three
15      are independent — any combination is valid.
16  
17    PUBLIC API
18      effect_setup(opts)                       install draw shader, cache its
19                                               GL program ID, push the palette
20      effect_set(layer, spec)                  write effect uniforms for this
21                                               layer's subsequent draws
22      effect_clear(layer)                      pattern/color/dither → 0 (passthrough)
23      effect_draw(layer, spec, fn, ...)        scoped form
24      effect_write_palette()                   re-push u_palette to the shader
25                                               (called automatically by palette_init
26                                               and effect_setup)
27  
28      Cycle helpers (return the NEXT/PREV name in each axis's cycle):
29        effect_next_pattern(cur), effect_prev_pattern(cur)
30        effect_next_color(cur),   effect_prev_color(cur)
... [425 more lines]

Now the shader and main.lua.

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

1    // =============================================================================
2   // ricochet-template — unified draw shader (single fragment shader for the
3   // whole project, installed via set_draw_shader as the engine's default).
4   //
5   // THREE-AXIS MODEL
6   //   Every fragment is processed as:
7   //
8   //       f   = pattern(world_pos, time, scale, param)   // [0, 1]
9   //       f   = dither(f, pixel_pos)                     // {0, 1/n, …, 1}
10  //       rgb = color(base_rgb, f, palette[color_a], palette[color_b])
11  //
12  //   Pattern owns spatial structure AND animation. Color is a pure recipe
13  //   that picks/mixes palette tokens by f. Dither inserts the pixel-art
14  //   stipple between them. The three are independent — any combination is
15  //   valid. See effect.lua for the registered names per axis.
16  //
17  // VARYING INPUTS (from engine vertex shader; do not rename)
18  //   vPos       World-space fragment position. For camera-attached layers
19  //              this is camera-transformed world space.
20  //   vUV        0..1 UV inside the draw's quad (or sprite UV for sprites).
21  //   vColor     Per-vertex RGBA color (the `color` arg passed to layer_*).
22  //   vType      Shape dispatch: 0=rect, 1=circle, 2=sprite, 3=line/capsule,
23  //              4=triangle, 5=polygon, 6=rounded rect.
24  //   vShape0..4 Per-shape parameter bundle.
25  //   vAddColor  Per-vertex additive RGB offset (engine 'flash' channel).
26  //
27  // UNIFORMS YOU SET FROM LUA (via effect.lua's effect_set)
28  //   u_pattern_kind   int   1=organic 2=solid 3=plasma 4=waves 5=marble
29  //                          6=sine_grid 7=wood 8=truchet 9=contours
30  //                          10=linear_gradient 11=radial_gradient (LOCAL)
... [721 more lines]

Now main.lua and showcase.lua.

Read (E:\a327ex\ricochet-template\main.lua)

1    --[[
2     ricochet-template — visual style + three-axis effect template.
3   
4     Entry point. Owns:
5       - configuration (resolution, render mode, monitor)
6       - boot order (palette → fonts → effect/shader → ui modules)
7       - layers (game, ui), camera
8       - current effect-spec state (pattern, color, dither, color_a/b, scale)
9       - sidebar control panel + keyboard input (both mutate the same state)
10      - test-scene draw (sample shapes through the effect pipeline)
11  
12    Delegates:
13      - palette.lua     — dark/light palette tables + palette_init
14      - effect.lua      — pattern × color × dither spec API + cycle helpers
15      - rectcut.lua     — RectCut layout primitive (cut/get/add/contract/...)
16      - ui_state.lua    — frame-local hot/active/focus + ui_claim_hot
17      - ui.lua          — five Ricochet-style widgets that mutate effect state
18  
19    Goal: visually evaluate any (pattern, color, dither, color_a, color_b,
20    scale) combination by clicking sidebar controls or pressing the hotkeys.
21    Both input modes update the same caller-owned state.
22  ]]
23  
24  require('anchor')({
25    width            = 1920,
26    height           = 1080,
27    title            = "ricochet-template",
28    scale            = 1,
29    filter           = "smooth",
30    render_uncapped  = true,
... [489 more lines]

Now showcase.lua and the tools directory.

Read (E:\a327ex\ricochet-template\showcase.lua)

1    --[[
2     showcase.lua — flat "UI KIT" screen (Tab toggles it from the pattern gallery).
3   
4     A live catalogue of themed UI elements built with the chosen icon pack
5     (TABLER) so the whole vocabulary can be eyeballed in the Ricochet theme.
6     Everything is FLAT: raw palette colors on `ui_layer`, NO effect pipeline.
7   
8     Icons are 44px white PNGs at assets/icons/tabler/<concept>.png, loaded into
9     the global `icons[concept]` table by main.lua and tinted to a palette token
10    on draw (white * token = token). Generated by tools/fetch_icons.mjs.
11  
12    Three columns of element groups (full screen width now that it's one pack):
13      HUD          resource badges, vitals bars, ability bar, life pips, wave bar
14      PROGRESSION  upgrade card, tooltip, leaderboard list
15      CONTROLS     tabs, toggle/checkbox/radio, stepper, stat block, keycaps, tags
16  
17    DRAW ORIGIN REMINDER: layer_image / layer_circle are CENTERED at (x,y);
18    layer_rectangle / layer_text are TOP-LEFT. (See the framework gotcha note.)
19  ]]
20  
21  local COL_W = 580
22  local COL_X = { 40, 670, 1300 }
23  local TOP   = 120
24  local HAIR  = 1
25  local ICON  = 44   -- matches the rasterized PNG size (tools/fetch_icons.mjs SIZE)
26  
27  -- ============================================================================
28  -- primitives (all draw to ui_layer, screen-space)
29  -- ============================================================================
30  
... [341 more lines]

Let me look at the tools directory, the engine texture-binding API, and the SNKRX template's existing effect system (the "ones to replace").

Grep (layer_shader_set_texture|COMMAND_SET_UNIFORM_TEXTURE|set_draw_shader)

Found 1 file
ricochet-template\anchor\layer.lua

Bash (ls -la E:/a327ex/ricochet-template/tools/ E:/a327ex/ricochet-template/assets/ E:...)

E:/a327ex/ricochet-template/assets/:
total 932
drwxr-xr-x 1 adn 197121      0 May 29 20:29 ./
drwxr-xr-x 1 adn 197121      0 May 29 21:26 ../
-rw-r--r-- 1 adn 197121 598060 May 28 05:55 CascadiaCode-Regular.ttf
-rw-r--r-- 1 adn 197121 200500 May 28 13:02 IBMPlexSans-Regular.ttf
-rw-r--r-- 1 adn 197121 107948 May 28 13:02 Oswald-Medium.ttf
-rw-r--r-- 1 adn 197121  35530 May 29 10:04 draw_shader.frag
drwxr-xr-x 1 adn 197121      0 May 29 21:22 icons/

E:/a327ex/ricochet-template/assets/icons/:
total 4
drwxr-xr-x 1 adn 197121 0 May 29 21:22 ./
drwxr-xr-x 1 adn 197121 0 May 29 20:29 ../
drwxr-xr-x 1 adn 197121 0 May 29 21:22 tabler/

E:/a327ex/ricochet-template/tools/:
total 25
drwxr-xr-x 1 adn 197121    0 May 29 21:22 ./
drwxr-xr-x 1 adn 197121    0 May 29 21:26 ../
-rw-r--r-- 1 adn 197121 2117 May 29 21:05 compare_packs.mjs
-rw-r--r-- 1 adn 197121 2612 May 29 21:22 fetch_icons.mjs
drwxr-xr-x 1 adn 197121    0 May 29 20:29 node_modules/
-rw-r--r-- 1 adn 197121 7252 May 29 20:29 package-lock.json
-rw-r--r-- 1 adn 197121  247 May 29 20:28 package.json

Grep (layer_shader_set_texture|function layer_shader_set)

70:  shader_set_texture = layer_shader_set_texture,
71-  get_texture = layer_get_texture,
72-  reset_effects = layer_reset_effects,
73-  clear = layer_clear,
74-  render = layer_render,
75-  draw_from = layer_draw_from,
76-  stencil_mask = layer_stencil_mask,
77-  stencil_test = layer_stencil_test,
78-  stencil_test_inverse = layer_stencil_test_inverse,
79-  stencil_off = layer_stencil_off,
80-}
81-
82---- Resolve layer state table or raw C handle (lightuserdata) for engine calls.
83-local function lyr_handle(lyr)
84-  if type(lyr) == 'table' then
85-    return lyr.handle
86-  end
87-  return lyr
88-end
89-
90---- Create a layer state table and optionally register in global `layers`.
--
219:function layer_shader_set_float(lyr, shader, name, value)
220-  eng.shader_set_float(lyr_handle(lyr), shader, name, value)
221-end
222-
223:function layer_shader_set_vec2(lyr, shader, name, x, y)
224-  eng.shader_set_vec2(lyr_handle(lyr), shader, name, x, y)
225-end
226-
... [29 more lines]

Let me check the engine's image/texture API to understand how to bind a mask texture and how sprites get their texture id.

Bash (cd E:/a327ex/ricochet-template && grep -n "shader_set_texture|COMMAND_SET_UNIFO...)

Binary file anchor/../anchor.exe matches
---- engine src ----
392:    COMMAND_SET_UNIFORM_TEXTURE, // Bind a texture to a sampler uniform
3943:static void layer_shader_set_texture(Layer* layer, GLuint shader, const char* name, GLuint tex_id, int unit) {
3950:    cmd->type = COMMAND_SET_UNIFORM_TEXTURE;
3988:    GLint tex_loc = glGetUniformLocation(shader, "u_texture");
4674:            cmd->type == COMMAND_SET_UNIFORM_TEXTURE) {
4693:                case COMMAND_SET_UNIFORM_TEXTURE: {
5810:// layer_shader_set_texture(layer, shader, name, texture_userdata, unit)
5811:static int l_layer_shader_set_texture(lua_State* L) {
5818:        layer_shader_set_texture(layer, shader, name, tex->id, unit);
5924:        GLint tex_loc = glGetUniformLocation(shader, "u_texture");
9472:    lua_register(L, "layer_shader_set_texture", l_layer_shader_set_texture);
9770:    "uniform sampler2D u_texture;\n"
9871:    "            ivec2 texSize = textureSize(u_texture, 0);\n"
9874:    "        vec4 texColor = texture(u_texture, sampleUV);\n"

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

3940 // Set a texture uniform on a shader (binds to texture unit 1+)
3941    // params[0] = texture unit index (1, 2, etc — 0 is reserved for the layer's own texture)
3942    // texture_id = the GL texture handle
3943    static void layer_shader_set_texture(Layer* layer, GLuint shader, const char* name, GLuint tex_id, int unit) {
3944        if (layer->command_count >= MAX_COMMAND_CAPACITY) return;
3945        GLint loc = glGetUniformLocation(shader, name);
3946        if (loc < 0) return;
3947    
3948        DrawCommand* cmd = &layer->commands[layer->command_count++];
3949        memset(cmd, 0, sizeof(DrawCommand));
3950        cmd->type = COMMAND_SET_UNIFORM_TEXTURE;
3951        cmd->shader_id = shader;
3952        cmd->uniform_location = (uint32_t)loc;
3953        cmd->texture_id = tex_id;
3954        cmd->params[0] = (float)unit;
3955    }
3956    
3957    // Execute shader application (ping-pong): read from current buffer, apply shader, write to alternate
3958    // Called during command processing when COMMAND_APPLY_SHADER is encountered
3959    static void execute_apply_shader(Layer* layer, GLuint shader) {
3960        // Ensure effect buffer exists
3961        layer_ensure_effect_buffer(layer);
3962    
3963        // Determine source and destination based on current state
3964        GLuint src_tex, dst_fbo;
3965        if (layer->textures_swapped) {
3966            src_tex = layer->effect_texture;
3967            dst_fbo = layer->fbo;
3968        } else {
3969            src_tex = layer->color_texture;
... [45 more lines]

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

4660     glUseProgram(shader_program);
4661        GLint aa_loc = glGetUniformLocation(shader_program, "u_aa_width");
4662        float aa_width = (layer->filter_mode == FILTER_SMOOTH) ? 1.0f : 0.0f;
4663        glUniform1f(aa_loc, aa_width);
4664    
4665        for (int i = 0; i < layer->command_count; i++) {
4666            const DrawCommand* cmd = &layer->commands[i];
4667    
4668            // Handle uniform setting commands
4669            // These need to temporarily switch programs, so flush batch first and restore after
4670            if (cmd->type == COMMAND_SET_UNIFORM_FLOAT ||
4671                cmd->type == COMMAND_SET_UNIFORM_VEC2 ||
4672                cmd->type == COMMAND_SET_UNIFORM_VEC4 ||
4673                cmd->type == COMMAND_SET_UNIFORM_INT ||
4674                cmd->type == COMMAND_SET_UNIFORM_TEXTURE) {
4675                // Flush any pending draws before switching programs
4676                batch_flush();
4677                current_batch_texture = 0;
4678    
4679                glUseProgram(cmd->shader_id);
4680                switch (cmd->type) {
4681                    case COMMAND_SET_UNIFORM_FLOAT:
4682                        glUniform1f((GLint)cmd->uniform_location, cmd->params[0]);
4683                        break;
4684                    case COMMAND_SET_UNIFORM_VEC2:
4685                        glUniform2f((GLint)cmd->uniform_location, cmd->params[0], cmd->params[1]);
4686                        break;
4687                    case COMMAND_SET_UNIFORM_VEC4:
4688                        glUniform4f((GLint)cmd->uniform_location, cmd->params[0], cmd->params[1], cmd->params[2], cmd->params[3]);
4689                        break;
... [60 more lines]

This is important — for the draw shader, COMMAND_SET_UNIFORM_TEXTURE only stashes the texture for the apply_shader (post-process) path, not for regular draws. Let me verify how regular draws bind their texture (unit 0, u_texture) via the batch system.

Bash (cd E:/a327ex/Anchor2/engine/src && grep -n "batch_flush|current_batch_texture|...)

868:    glBindTexture(GL_TEXTURE_2D, tex->id);
874:    glBindTexture(GL_TEXTURE_2D, 0);
897:    glBindTexture(GL_TEXTURE_2D, tex->id);
903:    glBindTexture(GL_TEXTURE_2D, 0);
1210:        glBindTexture(GL_TEXTURE_2D, font->atlas_texture);
1217:        glBindTexture(GL_TEXTURE_2D, 0);
1922:    glBindTexture(GL_TEXTURE_2D, layer->color_texture);
1994:    glBindTexture(GL_TEXTURE_2D, layer->effect_texture);
2015:    glBindTexture(GL_TEXTURE_2D, 0);
2364:static GLuint current_batch_texture = 0;  // Currently bound texture for batching
3992:    glActiveTexture(GL_TEXTURE0);
3993:    glBindTexture(GL_TEXTURE_2D, src_tex);
3997:        glActiveTexture(GL_TEXTURE1);
3998:        glBindTexture(GL_TEXTURE_2D, layer->extra_texture);
4000:        glActiveTexture(GL_TEXTURE0);
4010:        glActiveTexture(GL_TEXTURE1);
4011:        glBindTexture(GL_TEXTURE_2D, 0);
4012:        glActiveTexture(GL_TEXTURE0);
4024:static void batch_flush(void) {
4028:    if (current_batch_texture != 0) {
4029:        glActiveTexture(GL_TEXTURE0);
4030:        glBindTexture(GL_TEXTURE_2D, current_batch_texture);
4490:static void process_sprite(const DrawCommand* cmd) {
4497:    if (current_batch_texture != cmd->texture_id && batch_vertex_count > 0) {
4498:        batch_flush();
4500:    current_batch_texture = cmd->texture_id;
4545:    if (current_batch_texture != cmd->texture_id && batch_vertex_count > 0) {
4546:        batch_flush();
4548:    current_batch_texture = cmd->texture_id;
4579:static void process_spritesheet_frame(const DrawCommand* cmd) {
... [30 more lines]

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

4024 static void batch_flush(void) {
4025        if (batch_vertex_count == 0) return;
4026    
4027        // Bind texture if we have one (for sprites)
4028        if (current_batch_texture != 0) {
4029            glActiveTexture(GL_TEXTURE0);
4030            glBindTexture(GL_TEXTURE_2D, current_batch_texture);
4031        }
4032    
4033        glBindVertexArray(vao);
4034        glBindBuffer(GL_ARRAY_BUFFER, vbo);
4035        glBufferSubData(GL_ARRAY_BUFFER, 0,
4036                        batch_vertex_count * VERTEX_FLOATS * sizeof(float),
4037                        batch_vertices);
4038        glDrawArrays(GL_TRIANGLES, 0, batch_vertex_count);
4039        glBindVertexArray(0);
4040    
4041        batch_vertex_count = 0;
4042        draw_calls++;
4043    }
4044    
4045    // Process a rectangle command (SDF-based, UV-space approach)
4046    // The SDF is computed in local quad space using UV coordinates.
4047    // This handles rotation correctly because UV interpolation implicitly
4048    // provides the inverse rotation.
4049    static void process_rectangle(const DrawCommand* cmd) {
4050        float x = cmd->params[0];
4051        float y = cmd->params[1];
4052        float w = cmd->params[2];
4053        float h = cmd->params[3];
... [25 more lines]

Let me look at the SNKRX template's existing effect system (the "ones to replace") and confirm the 480×270 default the engine examples use.

Bash (cd E:/a327ex/snkrx-template && ls snkrx/ 2>/dev/null; echo "=== grep effect/edit...)

airborne.lua
area.lua
beam.lua
edition.lua
findings.md
flicker.lua
fx.lua
geometry.lua
gradient.lua
init.lua
palette.lua
player.lua
projectile.lua
prop.lua
seeker.lua
sound_tuner.lua
sound_tuning.lua
stats.lua
symbols.lua
ui/
wall.lua
=== grep effect/edition/dither/shader in snkrx ===
snkrx/area.lua
snkrx/beam.lua
snkrx/edition.lua
snkrx/findings.md
snkrx/flicker.lua
snkrx/fx.lua
snkrx/geometry.lua
snkrx/gradient.lua
... [15 more lines]

Let me quickly understand "the SNKRX template ones" (edition.lua / fx.lua) and how the SNKRX template sets its resolution, so I can speak accurately to the replacement goal.

Bash (cd E:/a327ex/snkrx-template && echo "=== main.lua require/anchor config ==="; se...)

=== main.lua require/anchor config ===
--[[
  snkrx-template / main.lua — clean reference scene.

  This is your file. It is a complete, minimal scene: a player you can
  move (WASD / arrows), the five-layer render stack, a camera, physics,
  the update / draw skeleton, AND the UI render pipeline — all wired
  and ready, but firing no attacks and drawing no UI widgets. Read it
  top to bottom; it is the contract you build on.

  TWO TOOLKITS, ONE REQUIRE.  `require('snkrx')` pulls in BOTH:

    snkrx/<carrier>.lua     attack toolkit — projectile / area / beam
                            / flicker / prop, the edition draw-shader
                            stack, fx, sounds, example entities.
    snkrx/ui/<module>.lua   UI toolkit — panel / button / slot / bar /
                            tabs / checkbox / radio / slider /
                            list_row / card / text_input / modal /
                            bracket_tag / stat_chip / pips / ...

  Both are plain, readable Lua, not opaque modules — open the files.

  ADDING AN ATTACK.  Every carrier already has its object list and its
  update / draw loop wired below. To add an attack:
    1. bind a key in the INPUT section,
    2. call the carrier's spawn_* helper on that press inside update()
       — see the ATTACKS comment block there.
  Nothing else: no new list, no new loop.

  DRAWING UI.  The UI toolkit is immediate-mode: call widget functions
... [108 more lines]

Bash (cd E:/a327ex/snkrx-template && grep -n "width\s=|height\s=|scale\s*=|requir...)

66:require('anchor')({
67:  width  = 480,
68:  height = 270,
70:  scale  = 3,
74:-- The SNKRX attack toolkit. Must come AFTER require('anchor') above —
=== edition draw_shader.frag field/dither size ===
main.lua:67:  width  = 480,
main.lua:68:  height = 270,
snkrx/edition.lua:20:                                                (+ u_field_scale, + u_dither_mode)
snkrx/edition.lua:69:    modes (30, 31) ignore u_dither_mode.
snkrx/edition.lua:72:    are computed directly from gl_FragCoord — no const-array matrices, so
snkrx/edition.lua:190:  layer_shader_set_float(layer, edition_draw_shader, 'u_field_scale', field_scale or 0.15)
snkrx/edition.lua:191:  layer_shader_set_float(layer, edition_draw_shader, 'u_dither_mode', dither_mode or 0)

I'm fully aligned now. Before diving in, one finding materially changes the plan, and three forks are worth settling up front. Here's where things stand and what I found.

Where we are

The four-axis effect system (pattern × color × dither × shape), gallery + inspector, ramp editor, and the flat Tabler UI-kit showcase are all built and settled. The recorded roadmap had three remaining items, which map onto what you listed:

  1. Image-as-SHAPE — per-cell dot becomes a tiled icon silhouette the effect fills
  2. Image-as-CONTENT — run the effect over a whole real image (dither + recolor)
  3. More geometric shapes — square / diamond / ring / cross / hexagon

Plus your three new ones: API simplifications, 480×270 support, and ultimately replacing the snkrx-template effect system (its edition.lua / dither stack) with this one.

The finding that changes the plan

The roadmap claimed image-as-SHAPE's hook was "READY" via layer_shader_set_texture / COMMAND_SET_UNIFORM_TEXTURE. It isn't. I traced the engine: for our draw shader (installed via set_draw_shader), COMMAND_SET_UNIFORM_TEXTURE does not bind a sampler for regular draws — it only stashes the texture into layer->extra_texture for the post-process apply_shader ping-pong path (anchor.c:4693). Regular draws bind only u_texture (unit 0) via the batch system, and only when drawing sprites. So binding a separate mask texture to a rect draw is currently a no-op. There's a clean fix and a hack — that's the first question below.

Context for the rest: snkrx-template runs at 480×270, scale 3; this template runs at 1920×1080, scale 1. Our dither and shape grids are anchored to gl_FragCoord (render-target pixels), so they're fine-grained here but would be crisp 1:1 pixel-art at 480×270 — which is exactly the regime that matters for porting into a real snkrx game.

I have a recommendation on each fork; let me confirm direction before writing any briefs.

AskUserQuestion

Your questions have been answered: "Image-as-SHAPE needs a mask texture bound to the rect draw, but the engine doesn't currently support that for the draw-shader path (only for post-process). How should I wire it?"="Patch the engine", "For 'effect over a real image,' what should drive the field f?"="Need to test options visually to see what's better.", "'Make everything work on 480×270' — the gallery + sidebar are hand-placed for 1920×1080. What's the scope?"="We'll do this later manually, piece-by-piece, don't worry about it now.". You can now continue with these answers in mind.

Settled. This session's scope is now: image-as-SHAPE (engine patch chosen), image-as-CONTENT (build both luminance- and pattern-driven so we can compare visually), more geometric shapes, then API simplifications. 480×270 and the snkrx-replacement are deferred to later manual sessions.

Before I write the first brief, let me ground two implementation facts: what image_load returns (so I can get a texture id to bind) and how the C texture-uniform binding reads its argument.

Bash (cd E:/a327ex/ricochet-template && echo "=== image.lua ==="; cat anchor/image.lua...)

=== image.lua ===
--[[
  image — thin wrapper for GPU texture handles.

  Usage:
    images.player = image_load('player', 'assets/player.png')
    layer_image(game_layer, images.player, 100, 100)

  An image is a plain table with .handle, .width, .height.
]]

image = class()

function image:new(handle)
  self.handle = handle
  self.width = texture_get_width(handle)
  self.height = texture_get_height(handle)
end

-- Load a texture from a file, wrap it, and add to the global `images` table.
function image_load(name, path)
  local handle = texture_load(path)
  local img = image(handle)
  if images then images[name] = img end
  return img
end
=== l_layer_shader_set_texture + l_image_load in engine ===
    int value = (int)luaL_checkinteger(L, 4);
    layer_shader_set_int(layer, shader, name, value);
    return 0;
... [18 more lines]

Grounded. image_load returns a table with .handle (the Texture userdata), and layer_shader_set_texture's 4th arg is exactly that userdata — so I can bind any loaded icon as a mask. The engine patch is safe (the post-process stash stays; I only add an immediate bind on a high unit the batch renderer never touches).

Here's the design brief for the first feature.

Design brief — Image-as-SHAPE (tiled icon masks)

Approach

The SHAPE axis re-expresses the field as a grid of circular dots today. This adds a sprite shape kind: each grid cell is stamped with a chosen icon silhouette (its alpha), and the effect fills that silhouette — "the effect is made of icons," tiled across the rect, like the Orblike/Invoker wall icons. SHAPE stays a shared control (one icon, one cell size, applied to every gallery rect), matching how circle/circle_hard already work. Three pieces: an engine patch, a shader branch, and Lua wiring + an icon picker.

1. Engine patch (Anchor2/engine/src/anchor.c)

The COMMAND_SET_UNIFORM_TEXTURE case in the command loop (anchor.c:4693) currently only stashes the texture for the post-process apply_shader path; for regular draws it never binds. Patch it to also immediately bind the texture to its requested unit and point the named sampler at that unit on the active draw shader. Because the batch renderer only ever touches unit 0 (u_texture for sprites), a mask bound on unit 2 stays bound across every subsequent SDF/sprite draw in the frame. The existing post-process stash is left untouched, so apply_shader still works. ~4 lines; no behavior change for existing callers. Then rebuild anchor.exe and copy it + anchor.c's effect into the ricochet-template's anchor/ copy (the engine binary is per-project here).

2. Shader (assets/draw_shader.frag)

3. Lua (effect.lua + main.lua)

Interfaces

Reuses the already-loaded icons[concept] table, the current_shape_* shared-control pattern, ui_field for the picker, and the existing coverage/backing composite. The engine patch is general: any future draw-shader effect can bind an aux sampler this way (image-as-CONTENT will lean on it too).

Visual unknowns I'll tune live (after you run it)

Sound right? Once you're good with this, I'll start with the engine patch (compile-check only — I won't run it), then the shader + Lua so you can test the whole thing visually.

Go ahead.

mcpccd_sessionmark_chapter

[
  {
    "type": "text",
    "text": "Chapter marked: \"Image-as-SHAPE\". Continue your current work."
  }
]

Starting with the engine patch. Let me read the exact block to patch.

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

4668         // Handle uniform setting commands
4669            // These need to temporarily switch programs, so flush batch first and restore after
4670            if (cmd->type == COMMAND_SET_UNIFORM_FLOAT ||
4671                cmd->type == COMMAND_SET_UNIFORM_VEC2 ||
4672                cmd->type == COMMAND_SET_UNIFORM_VEC4 ||
4673                cmd->type == COMMAND_SET_UNIFORM_INT ||
4674                cmd->type == COMMAND_SET_UNIFORM_TEXTURE) {
4675                // Flush any pending draws before switching programs
4676                batch_flush();
4677                current_batch_texture = 0;
4678    
4679                glUseProgram(cmd->shader_id);
4680                switch (cmd->type) {
4681                    case COMMAND_SET_UNIFORM_FLOAT:
4682                        glUniform1f((GLint)cmd->uniform_location, cmd->params[0]);
4683                        break;
4684                    case COMMAND_SET_UNIFORM_VEC2:
4685                        glUniform2f((GLint)cmd->uniform_location, cmd->params[0], cmd->params[1]);
4686                        break;
4687                    case COMMAND_SET_UNIFORM_VEC4:
4688                        glUniform4f((GLint)cmd->uniform_location, cmd->params[0], cmd->params[1], cmd->params[2], cmd->params[3]);
4689                        break;
4690                    case COMMAND_SET_UNIFORM_INT:
4691                        glUniform1i((GLint)cmd->uniform_location, (int)cmd->params[0]);
4692                        break;
4693                    case COMMAND_SET_UNIFORM_TEXTURE: {
4694                        // Store for binding during execute_apply_shader
4695                        layer->extra_texture = cmd->texture_id;
4696                        layer->extra_texture_loc = (GLint)cmd->uniform_location;
4697                        layer->has_extra_texture = true;
... [8 more lines]

The active program inside the switch is already cmd->shader_id, so I can set the sampler there directly. Applying the patch:

Edit (E:\a327ex\Anchor2\engine\src\anchor.c)

The file E:\a327ex\Anchor2\engine\src\anchor.c has been updated successfully. (file state is current in your context — no need to Read it back)

Now build the engine to verify it compiles.

Bash (cd E:/a327ex/Anchor2/engine && cmd /c build.bat 2>&1 | tail -25)

Microsoft Windows [Version 10.0.26200.8457]
(c) Microsoft Corporation. All rights reserved.

E:\a327ex\Anchor2\engine>

The build output was sparse. Let me check what build.bat does and whether it produced a fresh binary.

Bash (cd E:/a327ex/Anchor2/engine && echo "=== build.bat ==="; cat build.bat; echo "==...)

=== build.bat ===
@echo off
setlocal

cd /d "%~dp0"

:: Find and run vcvarsall.bat for Visual Studio
if exist "C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat" (
    call "C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul 2>&1
) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" (
    call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul 2>&1
) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" (
    call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul 2>&1
) else if exist "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" (
    call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 >nul 2>&1
) else (
    echo ERROR: Could not find Visual Studio
    exit /b 1
)

if not exist build mkdir build

:: Build Lua library if it doesn't exist
if not exist lib\lua.lib (
    echo Building Lua library...
    if not exist build\lua_obj mkdir build\lua_obj
    cl.exe /nologo /O2 /W3 /c /I"include/lua" ^
        include/lua/lapi.c include/lua/lauxlib.c include/lua/lbaselib.c ^
        include/lua/lcode.c include/lua/lcorolib.c include/lua/lctype.c ^
        include/lua/ldblib.c include/lua/ldebug.c include/lua/ldo.c ^
... [79 more lines]

The build didn't actually run (binary still dated 05-24, and cmd batch output gets swallowed in MINGW bash). Let me run it via PowerShell instead, which captures output properly.

PowerShell

Exit code 1
'build.bat' is not recognized as an internal or external command,
operable program or batch file.
---- EXIT: 1 ----

LastWriteTime      Length
-------------      ------
24/05/26 11:41:06 4185088

PowerShell

anchor.c
include/stb\stb_image_write.h(776): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(290): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(1095): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(1312): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(2759): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(2753): warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
src/anchor.c(3150): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3428): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3434): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3544): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3553): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3647): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(3649): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(4907): warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _strdup. See online help for details.
src/anchor.c(6026): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(6911): warning C4244: 'initializing': conversion from 'lua_Number' to 'float', possible loss of data
src/anchor.c(6912): warning C4244: 'initializing': conversion from 'lua_Number' to 'float', possible loss of data
src/anchor.c(8685): warning C4244: '=': conversion from 'lua_Integer' to 'int', possible loss of data
src/anchor.c(8686): warning C4244: '=': conversion from 'lua_Integer' to 'int', possible loss of data
src/anchor.c(8692): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(8806): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10144): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10148): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10153): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10157): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10163): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10167): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10173): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
src/anchor.c(10177): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
... [13 more lines]

Build succeeded (exit 0, fresh binary at 14:04; all warnings are pre-existing, none from my change). Now copy the new binary into the ricochet-template (its engine binary is per-project).

PowerShell

LastWriteTime      Length
-------------      ------
30/05/26 14:04:55 4185088

Engine patch deployed. Now the shader. Let me make the sprite shape-kind edits in draw_shader.frag.

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Shader done. Now the Lua side — effect.lua shape registries:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua — four edits: hoist the icon list, add the current_shape_icon global, add the sidebar ICON picker (with a cycler helper), and bind the mask texture in the draw loop.

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the cycle_icon helper and the sidebar ICON picker. First the helper, placed near the gallery state:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the sidebar ICON picker row, inside the current_shape ~= 'none' block:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now bind the mask texture in the draw loop, right after camera_attach:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now syntax-check the Lua changes:

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua

Both parse. Let me verify the shader has no stale call to the old shape_mask signature and that the SIDEBAR_H still fits the new ICON row.

Bash (cd E:/a327ex/ricochet-template && echo "=== shape_mask refs (shader) ==="; grep ...)

=== shape_mask refs (shader) ===
557:float shape_mask(int kind, float dist, float fc, vec2 cell_uv) {
588:    coverage = shape_mask(u_shape_kind, length(q) / 0.5, fc, cell_uv);
=== u_shape_tex refs ===
96:uniform sampler2D u_shape_tex;     // tiled mask for the 'sprite' shape kind; bound to
563:        return textureLod(u_shape_tex, vec2(cell_uv.x, 1.0 - cell_uv.y), 0.0).a;

Single call site, clean. The sprite ICON row adds one row to the sidebar, which can co-occur with the ramp editor (the existing worst case). Let me check the row constants to confirm SIDEBAR_H still fits.

Grep (ui_row_h\s=|ui_title_h\s=|ui_panel_inset\s=|ui_section_gap\s=|ui_swatch_size\s*=)

85:ui_row_h          = 32     -- height of one label row (PATTERN, COLOR, etc.)
90:ui_swatch_size    = 22     -- side of one palette-token swatch
92:ui_section_gap    = 12     -- vertical gap between groups of rows
93:ui_panel_inset    = 16     -- inner padding inside the panel
94:ui_title_h        = 28     -- title bar height

Worst case (sprite ICON row + ramp editor + a gradient's param2 slider, all at once) now totals ≈852px of content; SIDEBAR_H is 820, so it'd overflow by about one row. Bumping it — single-value tweak:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Let me re-verify main.lua parses after the final edits:

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: main.lua

Image-as-SHAPE is fully wired. Here's everything that changed:

Engine (anchor.c:4693) — COMMAND_SET_UNIFORM_TEXTURE now also binds the texture to its unit and sets the sampler on the draw shader immediately, so an aux mask on unit 2 persists across the SDF rect draws. Built clean (exit 0) and the new anchor.exe is copied into the template.

Shader (draw_shader.frag) — added u_shape_tex; shape_mask now takes cell_uv and, for kind 3 (sprite), returns the icon's alpha tiled one-per-cell; effect_field_shaped feeds it the cell UV. Coverage = the icon silhouette, fill = the per-fragment effect (same as circle), composited through the existing transparent/COLOR A backing + dither path.

Lua (effect.lua, main.lua) — sprite registered as shape kind 'icon'; new icon_names list + current_shape_icon; a sidebar ICON cycler (shown only for the sprite kind); the chosen icon's texture is bound on unit 2 each frame before the rects; SIDEBAR_H bumped to fit the extra row.

How to test

Run ./run.bat. In the pattern gallery:

  1. SHAPE cycler (sidebar) → step to icon. An ICON row appears above CELL SIZE.
  2. Cycle ICON through skull / sword / heart / star / … — every gallery rect should now be tiled with that icon, each icon filled by its rect's effect.
  3. CELL SIZE — sprite icons carry internal detail, so push this larger than for circles (try 32–64); small cells read as noise.
  4. BACKINGNONE lets the page show through the gaps between icons; COLOR A fills them.
  5. Confirm COLOR (mix/ramp/solid) and DITHER still re-skin the icon fill.

Two things to eyeball for me

Give it a run and let me know how it looks — especially orientation — before I move on to image-as-CONTENT.

[Pasted image/png]

Let's keep this one because it's nice as a way to do icons as a background effect. Let me also see how it looks with filled icons too. However, this only looks good with ramp because the icons become colored, with the default one it just looks like the icons are the background and there's black noise on top of them. We additionally want a mode that's closer to the circles, where the underlying effect itself is defined by the icons and not just as background, if that makes sense.

The icons-as-background mode works and the orientation is correct (bomb reads upright). Good. Let me read the fetch tool before I brief the two additions, so the filled-icon part is grounded.

Read (E:\a327ex\ricochet-template\tools\fetch_icons.mjs)

1    // Fetch the Tabler icon set used by the showcase, via the Iconify API, as white
2   // SVGs, thin the stroke (Tabler is stroke-based) toward the theme's 1px hairline
3   // UI, rasterize with resvg, and write to ../assets/icons/tabler/<concept>.png.
4   //
5   // Run from this directory:  node fetch_icons.mjs
6   //
7   // Tabler was chosen over Phosphor/Remix (most icons, best game coverage of the
8   // clean line packs, and a freely adjustable stroke). Icons are rasterized WHITE
9   // on transparent so the engine can tint them to any palette token.
10  
11  import { Resvg } from '@resvg/resvg-js';
12  import { mkdir, writeFile } from 'node:fs/promises';
13  import { dirname } from 'node:path';
14  
15  const SIZE = 44;
16  const OUT = '../assets/icons/tabler';
17  const STROKE = '0.75';   // Tabler ships stroke-width="2"; thin it to sit with the hairline UI
18  
19  // concept -> ordered candidate Tabler names (first that resolves wins).
20  const concepts = {
21    heart:   ['heart'],
22    star:    ['star'],
23    shield:  ['shield'],
24    sword:   ['sword'],
25    flame:   ['flame'],
26    bolt:    ['bolt'],
27    trophy:  ['trophy'],
28    coin:    ['coin'],
29    skull:   ['skull'],
30    gear:    ['settings'],
... [44 more lines]

The icons-as-background mode is keeper. Now your two additions — here's the design brief.

Design brief — sprite "field" mode + filled icons

1. Sprite field mode (the circle analog) — the core request

Right now the sprite kind is "background": the icon is always full-size (coverage = icon alpha), and the field only drives the fill color. That's why with mix it reads as icons-behind-noise — the field never decides where icons are.

Add a second sprite kind, sprite_field, that is the true analog of circle: the icon is sized by the per-cell field fc, exactly like a circle's radius tracks fc. Bright field → big icon filling its cell; dark field → the icon shrinks to a point / vanishes. So the effect's spatial structure is rendered as a grid of variably-sized icons, not painted behind a constant icon wall.

I'm going with size-by-field (not opacity-fade) because that's what makes it "closer to the circles" — circles vary size, so icons should too. (A flat-per-cell-color "hard" variant like circle_hard is an easy later add if you want it; starting with the circle-style per-fragment fill.)

2. Filled icons (to compare)

Tabler's base set is hollow line-art, which is exactly why the default fill looks like noise over outlines and why a shrunk outline becomes a tiny ring. Filled silhouettes will read far better, especially in the new field mode.

No new UI for fill — it's just more entries in the existing picker, which keeps this exploratory and reversible.

Sequence

Extend + run the fetch script first (so I know which filled variants exist), then the shader/effect.lua/main.lua wiring, then you run it and compare: icon (bg) vs icon (field), hollow vs filled, across mix/ramp/solid.

Good to go?

Go ahead, additionally also add a slider for spacing between icons.

Approved, and I'll fold in a SPACING slider. The mechanism: spacing insets the icon within its (unchanged shape_size) cell — fit = 1 - spacing is the icon's footprint fraction, applied as a UV scale about the cell center. It unifies cleanly with the field mode (field icon scale = fc * fit) and is a no-op at spacing 0, so the current look is preserved.

Starting with the fetch script so I know which filled variants exist. Extending it:

Edit (E:\a327ex\ricochet-template\tools\fetch_icons.mjs)

The file E:\a327ex\ricochet-template\tools\fetch_icons.mjs has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template/tools && node fetch_icons.mjs 2>&1)

OK    heart <- tabler:heart
  +    heart_filled <- tabler:heart-filled
OK    star <- tabler:star
  +    star_filled <- tabler:star-filled
OK    shield <- tabler:shield
  +    shield_filled <- tabler:shield-filled
OK    sword <- tabler:sword
OK    flame <- tabler:flame
  +    flame_filled <- tabler:flame-filled
OK    bolt <- tabler:bolt
  +    bolt_filled <- tabler:bolt-filled
OK    trophy <- tabler:trophy
  +    trophy_filled <- tabler:trophy-filled
OK    coin <- tabler:coin
  +    coin_filled <- tabler:coin-filled
OK    skull <- tabler:skull
OK    gear <- tabler:settings
  +    gear_filled <- tabler:settings-filled
OK    target <- tabler:target
OK    bomb <- tabler:bomb
  +    bomb_filled <- tabler:bomb-filled
OK    key <- tabler:key
  +    key_filled <- tabler:key-filled
OK    flask <- tabler:flask
  +    flask_filled <- tabler:flask-filled
OK    user <- tabler:user
  +    user_filled <- tabler:user-filled
OK    map <- tabler:map
OK    bag <- tabler:backpack
OK    bell <- tabler:bell
... [23 more lines]

22 filled variants pulled. Now the shader — spacing uniform + the unified bg/field sprite branch:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now effect.lua — registries, pretty names, and the u_shape_spacing uniform write:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the spec docs in effect.lua:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua. First, interleave the filled variants into icon_names:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the shape_is_sprite helper, next to cycle_icon:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

The sidebar sprite controls — ICON picker (widened to both kinds) plus the new SPACING slider:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the draw loop — widen the texture bind and pass shape_spacing:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now bump SIDEBAR_H for the added SPACING row (worst case ≈ 904px now):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Syntax-check the Lua and confirm every PNG referenced in icon_names exists on disk:

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua
=== verify every icon_names PNG exists ===
46/46 present, 0 missing

All wired — Lua parses, all 46 icon PNGs present, and no engine rebuild needed this round (shader + Lua only; the shader recompiles from the .frag at boot). Here's what changed:

How to test

Run ./run.bat, set SHAPE via the sidebar cycler. It now reads: off → circle (size) → circle (hard) → icon (bg) → icon (field).

  1. icon (field) is the headline. Pair it with BACKING = NONE and a filled icon (cycle ICON to e.g. heart_filled / skull / bomb_filled). You should see a grid of icons that grow where the effect is bright and vanish where it's dark — the field rendered as icons, like the circle dot grid but icon-shaped. Try it over plasma / marble / contours.
  2. Filled vs outline — cycle ICON one step (e.g. heartheart_filled) and compare. Filled should read much cleaner as a mask, especially in field mode and at small CELL SIZE.
  3. SPACING — slide it up to open gaps between the tiled icons; works in both icon (bg) and icon (field).
  4. Confirm icon (bg) still looks exactly as before at SPACING 0.
  5. Sweep COLOR (mix / ramp / solid) over both modes.

Have a look — especially icon (field) + filled + BACKING NONE — and tell me how it reads before I move to image-as-CONTENT.

Make it so that icon (field) can only go through filled icons, as it doesn't work with unfilled ones.

Makes sense — a scaled-down outline collapses to a ring, so field mode needs solid silhouettes. I'll restrict the ICON picker to filled icons when in icon (field) mode and snap the current selection to a filled one. This is your explicit spec, so I'll just make it.

First, a filled-only subset list:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: main.lua

Done. In icon (field) mode the ICON picker is now restricted to the 20 filled icons, and switching into field mode snaps the current selection to a filled icon (preferring its own _filled counterpart — heartheart_filled — else the first filled one). icon (bg) still cycles the full outline+filled list. Lua parses.

Test: set SHAPE to icon (field) — the ICON value should jump to a filled icon, and cycling </> should only step through solid icons (no more thin-ring outlines). icon (bg) is unchanged.

Give the whole sprite feature a final look (bg + field, filled, SPACING, across mix/ramp/solid) and let me know — then I'll move to image-as-CONTENT.

Great. However, spacing is decreasing the size of the icons instead of increasing the spacing within the view we have available.

Right — SPACING should add gaps between icons while keeping their size, not shrink them inside fixed cells. The fix: SPACING enlarges the grid pitch (cell-to-cell distance) while shape_mask keeps insetting the icon by the same factor — the two cancel so the icon's absolute size stays CELL SIZE and only the gap grows. That also makes CELL SIZE mean the icon's pixel size for sprites, so I'll relabel it accordingly.

Shader — grow the pitch for sprite kinds:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now the conditional slider label in main.lua:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: main.lua

Fixed. SPACING now enlarges the grid pitch (icons spread apart, bigger gaps) while their size stays constant — the slider that controls icon size is relabeled ICON SIZE in sprite mode. At SPACING 0 it's identical to before. Shader + label only, no rebuild.

Test: in icon (bg) or icon (field), raise SPACING — icons should keep their size and just get more space between them; ICON SIZE independently sets how big each icon is.

That wraps the full sprite/icon-mask feature (bg + field, filled-only field, ICON SIZE + SPACING, filled icons). Ready to move on to image-as-CONTENT (effect over a real image, both luminance- and pattern-driven so you can compare) whenever you've confirmed this reads right.

Great, what's next?

The sprite/icon-mask feature is done. Next on the list is image-as-CONTENT — running the effect over a whole real image so we can judge how the dither/color/pattern read on actual imagery (not icons). You wanted to compare both field sources visually, so I'll build them as a switchable MODE.

Design brief — image-as-CONTENT

Approach

A third screen, IMAGE (Tab cycles gallery → showcase → image), shows a real test image processed through the effect pipeline. A MODE control switches what drives the field f:

The screen reuses the sidebar's shared look controls (COLOR / DITHER / COLOR A·B / ramp editor), so you tune them live and watch the image change.

Shader

New uniform int u_image_field;. In the sprite branch: when set, f = luminance(texColor.rgb) (with the universal CONTRAST remap applied, so you get a tone-spread knob for free), then dither + color as usual, image alpha preserved. When unset, the current sprite path (pattern + shape stencil) is untouched.

effect.lua / main.lua

Interfaces

Reuses the existing sidebar, effect_set, the sprite render path, and the current_* shared-control pattern. Test images live in assets/images/.

The one thing I need from you is what to test on — it's an outward fetch and the content affects what you're judging:

AskUserQuestion

Your questions have been answered: "What test images should I source into assets/images/ for the image-as-CONTENT screen?"="I'll drop in my own". You can now continue with these answers in mind.

You'll provide your own — got it. To make that frictionless, let me check whether the engine can enumerate a directory at runtime (so the IMAGE picker just shows whatever you drop into assets/images/, no filenames to hand me).

Bash (cd E:/a327ex/Anchor2/engine/src && grep -niE "lua_register(L, \"(list|dir|read_...)

=== any dirent/FindFirstFile/readdir in engine ===
=== lua registers mentioning file/dir ===
9453:lua_register(L, "sound_get_path"
9455:lua_register(L, "file_write_string"
9474:lua_register(L, "shader_load_file"

No runtime directory listing in the engine, so the screen can't truly auto-discover. But I don't need you to recite filenames — once the files are in assets/images/, I'll glob the folder and populate the list myself. Let me check the current state of that folder.

Bash (cd E:/a327ex/ricochet-template && ls -la assets/images/ 2>/dev/null && echo "---...)

assets/images/ does not exist yet

Created context: the folder doesn't exist yet. Let me make it so you have somewhere to drop files.

Bash (cd E:/a327ex/ricochet-template && mkdir -p assets/images && echo "created: $(ls ...)

created: assets/images/

assets/images/ is ready. The screen, the LUMINANCE/PATTERN shader path, and the sidebar rows all hang off real files, so the cleanest path is to build the whole thing in one pass against your actual images (and let you test immediately) rather than build it blind.

Drop your test images into E:\a327ex\ricochet-template\assets\images\ and ping me — I'll glob the folder, wire them in, and build the screen. No need to recite filenames; I'll pick them up.

A couple of notes so the test is informative:

Once they're in, say the word and I'll build it.

I added girl.png and boy.png. What does pattern mode do?

Bash (cd E:/a327ex/ricochet-template/assets/images && ls -la *.png; echo "=== PNG head...)

-rw-r--r-- 1 adn 197121 3383629 May 30 15:01 boy.png
-rw-r--r-- 1 adn 197121 1845595 May 30 15:00 girl.png
=== PNG header info (width/height/bit-depth/colortype) ===
girl.png: 2600x1500  bitdepth=8  colortype=2 (RGB)
boy.png: 2048x1990  bitdepth=8  colortype=2 (RGB)

Both are opaque RGB (no alpha) — girl.png 2600×1500, boy.png 2048×1990. Let me look at them.

Read (E:\a327ex\ricochet-template\assets\images\girl.png)

[
  {
    "type": "image",
    "source": {
      "type": "base64",
      "data": "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",
      "media_type": "image/jpeg"
    }
  }
]

Read (E:\a327ex\ricochet-template\assets\images\boy.png)

[
  {
    "type": "image",
    "source": {
      "type": "base64",
      "data": "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Dz3xPqSy3czI2VzgfQcUuW7POjH2lVyOOmlLsTW0Y2PUhGyIqosKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAJIBmUCtIPcmexazzTMlsJcNmD8aipuh017xSqTYKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAAcGgDqtOuPtNmjn7w4b61tF3R9ThKvtaSl1E1G2+02jKB8w5X60SV0LF0fbUmupyxGDWJ8uFACgkUASx3DIeDSsZygmaNtqjpjJqXE5amGTN6x8VXMIAExK+j/ADCp5TLlqw+Fm1b+MAQPNhQ+6tilYar1F8US6nimyYfMki/kaLFfWl1TFfxRYqPlWVj9AP60WD61HomYer+K3miaKECJCMHByT+NNIlzqVdLWRxd7dGZzzVpHVSpcqKVUdAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAD4m2yA0XtsTJXRaPB4rVNSV0YobMf3P41nPdI0huVKRoFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGxoE2JJISeCNwq4PoevldS0nA261PcOa1e38i8YgfK/zCsZKzPmcdR9nVdtmUak4goAKADNADg5HegTSJFuHHelYh00yQXkg7mixPsYgb2Q9zRYFRRE8zN1NOxagkRE5oLCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgCzBKT8jfhSu4aoynHqhJzhQueaSbk7sIb3K9UahQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBb0uTy9QiPqcfnVR3OrBS5a8WdRWx9SZ2uQeZaeYBzGc/hUTWh5uZUualzdjnayPngoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAOlABnNABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUASW7bbiNvRh/OmjSk7TT8zr63PrxssYlieM9GBFJkVIqcXF9TkHUo7IeqnBrA+RlFxbTG0EhQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA5DtdT6HNA4uzTN9Nbtj95ZF/DNa86PfjmdJ7potQ39rMcJMufQ8U1JM6qeLo1NpGDq8Xl3746PhhWclqeFj4cld+epSqTiCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgB7yvIFDsW2jAz6UFSnKVrvYZQSFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf/Z",
      "media_type": "image/jpeg"
    }
  }
]

Both are opaque illustrations (no alpha) — girl.png is a pastel anime piece on a pale cyan ground, boy.png a neon piece on solid black.

Here's what PATTERN mode does, and why that matters for these two:

LUMINANCE mode is the meaningful one for these — it dithers/recolors the actual illustration by its own light and dark.

There's a nice way to make PATTERN useful for your opaque images, though: a background key — threshold the flat background (boy's black, girl's pale cyan) so it reads as transparent, and the pattern then carves the figure out and fills it with flowing effect. Both your images have clean flat backgrounds, so this would work well.

How do you want PATTERN mode to behave?

AskUserQuestion

Your questions have been answered: "Your test images are opaque, so plain PATTERN mode just fills the whole box. How should PATTERN mode treat them?"="Ah, I see, you can find a generic image online to be used as stencil to test the pattern mode.". You can now continue with these answers in mind.

Good call — I'll grab a transparent cut-out to exercise PATTERN mode, and keep girl/boy for LUMINANCE. Let me fetch a few candidate silhouettes (Iconify→resvg gives guaranteed clean alpha, and it's the network path proven to work here), view them, and keep the best.

Bash (cd E:/a327ex/ricochet-template/tools && mkdir -p _stencil_tmp && node - <<'JS' 2...)

OK   wolf <- game-icons:wolf-head
OK   eagle <- game-icons:eagle-emblem
OK   spartan <- game-icons:spartan-helmet
OK   dragon <- game-icons:dragon-head
OK   raven <- game-icons:raven
OK   flower <- game-icons:rose
OK   butterfly <- ph:butterfly-fill
OK   lion <- game-icons:lion
total 180
drwxr-xr-x 1 adn 197121     0 May 30 15:06 ./
drwxr-xr-x 1 adn 197121     0 May 30 15:06 ../
-rw-r--r-- 1 adn 197121 13786 May 30 15:06 butterfly.png
-rw-r--r-- 1 adn 197121 21150 May 30 15:06 dragon.png
-rw-r--r-- 1 adn 197121 25880 May 30 15:06 eagle.png
-rw-r--r-- 1 adn 197121 23081 May 30 15:06 flower.png
-rw-r--r-- 1 adn 197121 18496 May 30 15:06 lion.png
-rw-r--r-- 1 adn 197121 12558 May 30 15:06 raven.png
-rw-r--r-- 1 adn 197121 24347 May 30 15:06 spartan.png
-rw-r--r-- 1 adn 197121 19609 May 30 15:06 wolf.png

Let me render visible previews (white silhouettes on a dark background) so I can judge the shapes.

Bash (cd E:/a327ex/ricochet-template/tools && node - <<'JS' 2>&1 import { Resvg } from...)

previews written

Read (E:\a327ex\ricochet-template\tools_stencil_tmp_prev_wolf.png)

[
  {
    "type": "image",
    "source": {
      "type": "base64",
      "data": "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",
      "media_type": "image/png"
    }
  }
]

Wolf head is a strong stencil — bold silhouette with internal detail (the bolt cutout, teeth) that'll show the pattern fill at multiple scales. Let me glance at a couple alternatives.

Read (E:\a327ex\ricochet-template\tools_stencil_tmp_prev_dragon.png)

[
  {
    "type": "image",
    "source": {
      "type": "base64",
      "data": "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",
      "media_type": "image/png"
    }
  }
]

Read (E:\a327ex\ricochet-template\tools_stencil_tmp_prev_butterfly.png)

[
  {
    "type": "image",
    "source": {
      "type": "base64",
      "data": "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",
      "media_type": "image/png"
    }
  }
]

The wolf is the best stencil — bold silhouette with internal holes and fine teeth that'll show the pattern fill across scales. I'll use that one. Copying it in (full-res white-on-transparent version), adding an attribution note since game-icons.net is CC-BY, and cleaning up the temp files.

Bash (cd E:/a327ex/ricochet-template && cp tools/_stencil_tmp/wolf.png assets/images/w...)

--- assets/images/ now: ---
total 5137
drwxr-xr-x 1 adn 197121       0 May 30 15:08 ./
drwxr-xr-x 1 adn 197121       0 May 30 14:49 ../
-rw-r--r-- 1 adn 197121     258 May 30 15:08 CREDITS.txt
-rw-r--r-- 1 adn 197121 3383629 May 30 15:01 boy.png
-rw-r--r-- 1 adn 197121 1845595 May 30 15:00 girl.png
-rw-r--r-- 1 adn 197121   19609 May 30 15:08 wolf.png

Three test images ready: girl.png, boy.png (LUMINANCE), wolf.png (PATTERN stencil). Now I'll build the screen. First I need to confirm the engine's image-draw API — specifically whether layer_image can scale (the photos are 2600px wide and must fit the content area) and how to pass a plain white tint.

Bash (cd E:/a327ex/ricochet-template && echo "=== layer image/texture fns in framework...)

=== layer image/texture fns in framework ===
169:function layer_image(lyr, img, x, y, color, flash)
174:function layer_texture(lyr, tex, x, y, color)
178:function layer_spritesheet(lyr, sheet, frame, x, y, color, flash)
=== signatures (with bodies) ===
169:function layer_image(lyr, img, x, y, color, flash)
170-  eng.draw_texture(lyr_handle(lyr), img.handle, x, y, color or 0xFFFFFFFF, flash or 0)
171-end
172-
--
174:function layer_texture(lyr, tex, x, y, color)
175-  eng.draw_texture(lyr_handle(lyr), tex, x, y, color or 0xFFFFFFFF, 0)
176-end
177-
=== engine l_layer_image / texture draw args ===

layer_image has no scale param, but the photos are 2600px wide. Let me find how the engine scales textures (a scaled draw variant, or camera zoom).

Bash (cd E:/a327ex/Anchor2/engine/src && echo "=== draw_texture-related Lua bindings =...)

=== draw_texture-related Lua bindings ===
9418:lua_register(L, "layer_draw_texture"
9424:lua_register(L, "texture_load"
9425:lua_register(L, "texture_create"
9426:lua_register(L, "texture_unload"
9427:lua_register(L, "texture_get_width"
9428:lua_register(L, "texture_get_height"
9430:lua_register(L, "spritesheet_load"
9431:lua_register(L, "spritesheet_get_frame_width"
9432:lua_register(L, "spritesheet_get_frame_height"
9433:lua_register(L, "spritesheet_get_total_frames"
9434:lua_register(L, "layer_draw_spritesheet_frame"
9485:lua_register(L, "layer_shader_set_texture"
9488:lua_register(L, "layer_get_texture"

=== l_draw_texture signature/impl ===
5637:static int l_layer_draw_texture(lua_State* L) {
9418:    lua_register(L, "layer_draw_texture", l_layer_draw_texture);
=== framework draw_texture wrapper ===
E:/a327ex/ricochet-template/anchor/layer.lua:58:  draw_texture = layer_draw_texture,
E:/a327ex/ricochet-template/anchor/layer.lua:170:  eng.draw_texture(lyr_handle(lyr), img.handle, x, y, color or 0xFFFFFFFF, flash or 0)
E:/a327ex/ricochet-template/anchor/layer.lua:175:  eng.draw_texture(lyr_handle(lyr), tex, x, y, color or 0xFFFFFFFF, 0)

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

5637 static int l_layer_draw_texture(lua_State* L) {
5638        Layer* layer = (Layer*)lua_touserdata(L, 1);
5639        Texture* tex = (Texture*)lua_touserdata(L, 2);
5640        float x = (float)luaL_checknumber(L, 3);
5641        float y = (float)luaL_checknumber(L, 4);
5642        uint32_t color = (uint32_t)luaL_optinteger(L, 5, 0xFFFFFFFF);  // Default white (no tint)
5643        uint32_t flash = (uint32_t)luaL_optinteger(L, 6, 0x00000000);  // Default black (no flash)
5644        layer_add_image(layer, tex, x, y, color, flash);
5645        return 0;
5646    }
5647    
5648    static int l_layer_set_blend_mode(lua_State* L) {
5649        Layer* layer = (Layer*)lua_touserdata(L, 1);
5650        const char* mode = luaL_checkstring(L, 2);
5651        if (strcmp(mode, "alpha") == 0) {
5652            layer_set_blend_mode(layer, BLEND_ALPHA);
5653        } else if (strcmp(mode, "additive") == 0) {
5654            layer_set_blend_mode(layer, BLEND_ADDITIVE);
5655        } else {
5656            return luaL_error(L, "Invalid blend mode: %s (use 'alpha' or 'additive')", mode);
5657        }
5658        return 0;
5659    }
5660    
5661    // Stencil Lua bindings
5662    static int l_layer_stencil_mask(lua_State* L) {
5663        Layer* layer = (Layer*)lua_touserdata(L, 1);
5664        layer_stencil_mask(layer);
5665        return 0;
5666    }
... [30 more lines]

layer_add_image draws at native size only — no scale. The photos are 2600px, so I must scale at draw time. The clean way (without mutating your originals) is camera zoom. Let me read the camera API to see how zoom/position work.

Read (E:\a327ex\ricochet-template\anchor\camera.lua)

1    --[[
2     camera — procedural 2D camera with follow, bounds, and integrated shake.
3   
4     Usage:
5       main_camera = camera_new(width, height)
6   
7       -- In update:
8       camera_update(main_camera, dt)
9   
10      -- In draw:
11      camera_attach(main_camera, game_layer)
12      layer_circle(game_layer, 100, 100, 20, red())
13      -- ... more draws to game_layer
14      camera_detach(main_camera, game_layer)
15  
16      -- Follow a target:
17      camera_follow(main_camera, p1)
18      camera_follow(main_camera, p1, 0.9, 0.3)   -- 90% distance in 0.3s
19      camera_follow(main_camera, nil)             -- stop following
20  
21      -- Bounds:
22      camera_set_bounds(main_camera, 0, map_w, 0, map_h)
23  
24    Shake is an integrated sub-structure accessible as camera.shake.
25    Use the shake_* functions on it:
26      shake_push(main_camera.shake, angle, amount)
27      shake_shake(main_camera.shake, 10, 0.3)
28      shake_trauma(main_camera.shake, 0.5, 0.3)
29  
30    Design notes:
... [185 more lines]

Camera zoom would scale the whole layer including the background; the cleaner tool is the raw layer_push transform (translate + scale), which camera_attach itself uses. Let me confirm its signature and that it's exposed.

Bash (cd E:/a327ex/ricochet-template && grep -nA2 "function layer_push\b|function lay...)

198:function layer_push(lyr, x, y, r, sx, sy)
199-  eng.push(lyr_handle(lyr), x, y, r, sx, sy)
200-end
--
202:function layer_pop(lyr)
203-  eng.pop(lyr_handle(lyr))
204-end

All pieces confirmed. Building the feature now. Shader first — the u_image_field uniform and the luminance path in the sprite branch:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now effect.lua — write the uniform and document it:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua. Loading the content images:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Tab cycle to 3-way:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

cycle_content_image helper, next to shape_is_sprite:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the ui_update guards and MODE/IMAGE rows. Let me re-read the current ui_update to place them precisely.

Read (E:\a327ex\ricochet-template\main.lua)

238  local GAL_RECT_H      = 230
239 
240 -- Which gallery rect the modifier sliders edit. Click a rect to select it.
241 gallery_selected = 1
242 
243 -- Step through an icon-name list for the sprite icon picker. dir = +1 / -1;
244 -- list defaults to the full icon_names (the field mode passes icon_names_filled).
245 local function cycle_icon(cur, dir, list)
246   list = list or icon_names
247   for i, v in ipairs(list) do
248     if v == cur then return list[((i - 1 + dir) % #list) + 1] end
249   end
250   return list[1]
251 end
252 
253 -- True for the icon-mask shape kinds (bg + field), which share the ICON picker,
254 -- the SPACING slider, and the per-frame mask-texture bind.
255 local function shape_is_sprite(s) return s == 'sprite' or s == 'sprite_field' end
256 
257 -- Step through content_names for the IMAGE-screen picker. dir = +1 / -1.
258 local function cycle_content_image(cur, dir)
259   for i, v in ipairs(content_names) do
260     if v == cur then return content_names[((i - 1 + dir) % #content_names) + 1] end
261   end
262   return content_names[1]
263 end
264 
265 -- Screen rect for gallery entry i (row-major in the GAL grid). Shared by the
266 -- selection hit-test (ui_update), the rect draw, and the highlight (draw).
267 local function gallery_rect(i)
... [40 more lines]

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now insert the MODE/IMAGE rows after the PALETTE block:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now I need to wrap the SHAPE block and the MODIFIERS block as gallery-only. Let me read that region.

Read (E:\a327ex\ricochet-template\main.lua)

325    -- COLOR / DITHER cycler rows. (PATTERN + SCALE rows removed — in gallery
326   -- mode each rectangle bakes its own pattern + tuned scale; the sidebar now
327   -- only drives the SHARED look applied across all gallery rects.)
328   row = rect_cut_top(body, ui_row_h)
329   local f = ui_field{ rect = row, id = 'color', label = 'COLOR', value = current_color }
330   if f.prev_clicked then current_color = effect_prev_color(current_color) end
331   if f.next_clicked then current_color = effect_next_color(current_color) end
332 
333   row = rect_cut_top(body, ui_row_h)
334   f = ui_field{ rect = row, id = 'dither', label = 'DITHER',
335                 value = effect_dither_label(current_dither) }
336   if f.prev_clicked then current_dither = effect_prev_dither(current_dither) end
337   if f.next_clicked then current_dither = effect_next_dither(current_dither) end
338 
339   -- SHAPE cycler — re-express the field as a grid of dots. Shared across all
340   -- gallery rects. The SHAPE SIZE slider only appears when a shape is active.
341   row = rect_cut_top(body, ui_row_h)
342   f = ui_field{ rect = row, id = 'shape', label = 'SHAPE',
343                 value = effect_shape_label(current_shape) }
344   if f.prev_clicked then current_shape = effect_prev_shape(current_shape) end
345   if f.next_clicked then current_shape = effect_next_shape(current_shape) end
346 
347   -- Sprite-only controls (both icon-mask kinds): which ICON the mask uses, and
348   -- the SPACING gap between tiled icons. The chosen icon's texture is bound as
349   -- the per-cell mask in draw().
350   if shape_is_sprite(current_shape) then
351     -- field mode works only with filled icons (an outline scaled down by the
352     -- field becomes a thin ring) → restrict the picker to icon_names_filled and
353     -- snap the current selection to a filled icon, preferring its own filled
354     -- counterpart (heart → heart_filled) when one exists.
... [100 more lines]

Read (E:\a327ex\ricochet-template\main.lua)

454    row = rect_cut_top(body, ui_row_h + 20)
455   local ms = ui_slider{ rect = row, id = 'mod_scale', label = 'SCALE',
456                         value = sel.scale, vmin = 0.05, vmax = 1.2, fmt = '%.3f' }
457   if ms.changed then sel.scale = ms.value end
458 
459   row = rect_cut_top(body, ui_row_h + 20)
460   local msp = ui_slider{ rect = row, id = 'mod_speed', label = 'SPEED',
461                          value = sel.speed, vmin = 0, vmax = 4, fmt = '%.2f' }
462   if msp.changed then sel.speed = msp.value end
463 
464   row = rect_cut_top(body, ui_row_h + 20)
465   local mco = ui_slider{ rect = row, id = 'mod_contrast', label = 'CONTRAST',
466                          value = sel.contrast, vmin = 0, vmax = 2.5, fmt = '%.2f' }
467   if mco.changed then sel.contrast = mco.value end
468 
469   row = rect_cut_top(body, ui_row_h + 20)
470   local mpa = ui_slider{ rect = row, id = 'mod_param', label = sel.param_label,
471                          value = sel.param, vmin = 0, vmax = 1, fmt = '%.2f' }
472   if mpa.changed then sel.param = mpa.value end
473 
474   -- Second intrinsic knob — only patterns that define one (the gradients:
475   -- OFFSET / RANGE) get this row; it uses the pattern's own min/max range.
476   if sel.param2_label then
477     row = rect_cut_top(body, ui_row_h + 20)
478     local mp2 = ui_slider{ rect = row, id = 'mod_param2', label = sel.param2_label,
479                            value = sel.param2, vmin = sel.param2_min or 0,
480                            vmax = sel.param2_max or 1, fmt = '%.2f' }
481     if mp2.changed then sel.param2 = mp2.value end
482   end
483 end
... [10 more lines]

Now wrapping the SHAPE and MODIFIERS blocks as gallery-only. SHAPE block — open guard:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

MODIFIERS block — open and close guards:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the image_draw() function:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the draw() dispatch for the image screen:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Let me syntax-check the now-substantially-edited files:

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua
OK: showcase.lua

All parse. Let me re-read the shader's sprite branch to be sure the GLSL is balanced and correct (I can't run it; the user will).

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

646  
647     if (vType < 0.5) {
648         // Rectangle
649         vec2 quad_size = vShape0.xy;
650         quad_px = quad_size;
651         vec2 local_p = vUV * quad_size;
652         vec2 center = quad_size * 0.5;
653         vec2 half_size = vShape0.zw;
654         stroke = vShape1.x;
655         if (u_aa_width == 0.0) { local_p = floor(local_p) + 0.5; }
656         d = sdf_rect(local_p, center, half_size);
657     } else if (vType < 1.5) {
658         // Circle
659         float quad_size = vShape0.x;
660         quad_px = vec2(quad_size);
661         vec2 local_p = vUV * quad_size;
662         vec2 center = vec2(quad_size * 0.5);
663         float radius = vShape0.z;
664         stroke = vShape0.w;
665         if (u_aa_width == 0.0) { radius = floor(radius + 0.5); }
666         d = sdf_circle(local_p, center, radius);
667     } else if (vType < 2.5) {
668         // Sprite
669         ivec2 texSize = textureSize(u_texture, 0);
670         vec2 snappedUV = (floor(vUV * vec2(texSize)) + 0.5) / vec2(texSize);
671         vec4 texColor = texture(u_texture, snappedUV);
672         float sprite_alpha = texColor.a * vColor.a;
673         if (sprite_alpha <= 0.0) discard;
674         vec3 col = texColor.rgb * vColor.rgb + vAddColor;
675         if (u_color_kind > 0) {
... [22 more lines]

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

697                      } else {
698                         col = ccol;
699                         sprite_alpha *= cd;                              // transparent backing
700                     }
701                 }
702             }
703         }
704         FragColor = vec4(col, sprite_alpha);
705         return;
706     } else if (vType < 3.5) {
707         // Line / capsule
708         vec2 quad_size = vShape0.xy;
709         quad_px = quad_size;
710         vec2 local_p = vUV * quad_size;
711         vec2 center = quad_size * 0.5;
712         float half_len = vShape0.z;

The shader is balanced and correct. One gap I should close before handing it to you: the brief promised the CONTRAST remap as a "tone-spread knob," but right now nothing on the image screen drives it (so it'd sit at 1.0 — flat). Luminance dithering of these illustrations really wants that control (girl.png is mostly bright pastels). Let me expose a CONTRAST slider on the image screen for luminance mode.

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: main.lua

Image-as-CONTENT is fully built — shader + Lua only, so no rebuild (the shader recompiles at boot). Here's the whole thing:

New IMAGE screen (Tab now cycles gallery → showcase → image → gallery), with three test images: girl / boy (opaque, for luminance) and wolf (transparent stencil, for pattern). The sidebar stays focused — PALETTE, MODE, IMAGE, (CONTRAST), COLOR, DITHER, COLOR A·B, ramp — and re-skins the image live. SHAPE + gallery MODIFIERS are hidden there.

How to test

Run ./run.bat, press Tab twice to reach the IMAGE screen.

  1. Defaults to girl / LUMINANCE. With COLOR = none you see the original. Switch COLOR → mix (COLOR A = ink, COLOR B = field) + DITHER → bayer 4×4 / 2 lvl → a 1-bit dithered illustration. Raise CONTRAST to spread the tones (girl is bright, so it'll want a push).
  2. Try COLOR → ramp → the illustration recolored across the ramp by its own light/dark. Multi-level dithers (bayer4_8, noise_8) keep the mid-stops.
  3. Cycle IMAGE → boy (mostly dark) and adjust CONTRAST the other way.
  4. Switch MODE → PATTERN, cycle IMAGE → wolf → the selected gallery pattern fills the wolf silhouette, transparent background dropping to the page. To pick which pattern: Tab to the gallery, click a rect, Tab back (pattern mode reads the selected gallery rect). Over girl/boy, PATTERN fills the whole box (they're opaque) — that's the expected contrast.

Watch for / report

Have a look and let me know — then the remaining session items are more geometric shapes and the API simplifications.

Everything looks right. Some additional things: is there a way we can also have circles/icons when the effect is filling the shape?; is there any way we could have the pattern work on the images themselves? So the way the image is dithered is such that it uses the underlying moving pattern instead of just being dithered statically. Both of these are additional things on top of what we have now.

Both of these fall out of one clean move, and I want to confirm the approach (especially my read of request 2) before refactoring the shader.

Brief — SHAPE on images + moving-pattern dithering

The key insight: both come almost for free if I unify the image's field with the gallery's effect_field instead of keeping the separate luminance branch I added earlier.

The unification

Make effect_field() image-aware: when u_image_field == 1 it returns the image's luminance (contrast-remapped); otherwise the pattern (gallery unchanged). Then the sprite branch always runs the normal effect_field_shaped → dither → color → backing pipeline. Since effect_field_shaped already samples the field per cell, SHAPE starts working on images with no new shape code — and the separate luminance branch collapses away (simpler shader).

Request 1 — circles/icons in the image fill (both modes)

Re-enable the SHAPE controls on the image screen + pass them through (and bind the icon for sprite kinds):

Request 2 — moving-pattern dithering (luminance mode)

Add a PATTERN AMT slider (luminance mode) + u_image_pattern_amount. In the image branch: f = contrast(luminance) + (pattern − 0.5)·amount. The pattern is animated (u_time·speed), so as you raise the amount the dither's light/dark boundaries ripple and flow with the moving pattern rather than sitting static. At 0 it's today's static dither; higher gradually dissolves the image into the moving field. You choose which pattern + its speed via the gallery selection (same as PATTERN mode reads it).

Files

One thing to confirm: request 2 — I'm reading it as "the animated pattern perturbs the field so the dither stipple flows over time," keeping the fine Bayer/etc. stipple. (The alternative would be the pattern replacing the dither matrix entirely — smoother, blobbier.) The perturb approach keeps it reading as a dithered image that's alive. That match what you had in mind?

Yes, go ahead.

Approved. Implementing — shader first. Adding the pattern-amount uniform:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now make effect_field image-aware:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now collapse the sprite branch's two paths into the single unified pipeline:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now effect.lua — write the uniform and doc:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua. First, show SHAPE on the image screen too — remove its gallery-only guard (opening):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Closing — remove the now-orphaned end:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the current_image_pattern_amount global and the PATTERN AMT slider:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now rebuild image_draw's spec (shape on both modes, pattern+amount for luminance) and bind the icon for sprite shapes:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua

Both parse. Let me verify the unified sprite branch is balanced after collapsing the two paths.

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

678          vec2 local_p = vUV * quad_size;
679         vec2 center = vec2(quad_size * 0.5);
680         float radius = vShape0.z;
681         stroke = vShape0.w;
682         if (u_aa_width == 0.0) { radius = floor(radius + 0.5); }
683         d = sdf_circle(local_p, center, radius);
684     } else if (vType < 2.5) {
685         // Sprite
686         ivec2 texSize = textureSize(u_texture, 0);
687         vec2 snappedUV = (floor(vUV * vec2(texSize)) + 0.5) / vec2(texSize);
688         vec4 texColor = texture(u_texture, snappedUV);
689         float sprite_alpha = texColor.a * vColor.a;
690         if (sprite_alpha <= 0.0) discard;
691         vec3 col = texColor.rgb * vColor.rgb + vAddColor;
692         if (u_color_kind > 0) {
693             // The field comes from effect_field (the image's own luminance when
694             // u_image_field is set — optionally rippled by the moving pattern —
695             // else the pattern) and flows through the SAME shape / dither / color /
696             // backing pipeline as the gallery. So SHAPE works on images too
697             // (luminance + shape = halftone), and the image's alpha stays the base
698             // coverage that shape coverage multiplies into.
699             float coverage;
700             float f  = effect_field_shaped(vec2(texSize), coverage);
701             float fd = apply_dither(f, u_dither_kind, gl_FragCoord.xy);
702             vec3 ccol = apply_color(u_color_kind, col, fd, u_palette[u_color_a].rgb, u_palette[u_color_b].rgb);
703             if (u_shape_kind == 0) {
704                 col = ccol;
705             } else {
706                 float cd = apply_dither(coverage, u_dither_kind, gl_FragCoord.xy);
707                 if (u_shape_backing == 1) {
... [4 more lines]

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

711                      sprite_alpha *= cd;                              // transparent backing
712                 }
713             }
714         }
715         FragColor = vec4(col, sprite_alpha);
716         return;
717     } else if (vType < 3.5) {
718         // Line / capsule
719         vec2 quad_size = vShape0.xy;
720         quad_px = quad_size;

Balanced and clean — the sprite branch collapses to the single pipeline, and effect_field now carries the image. Both parse; shader recompiles at boot, so no rebuild.

Two additions are live:

1. SHAPE on the image screen (both modes). The SHAPE controls now appear on the image screen:

2. PATTERN AMT slider (luminance mode). Ripples the field with the selected gallery pattern before dithering, so the dither flows over time instead of sitting static.

How to test

Run ./run.bat, Tab to the IMAGE screen.

Moving dither (request 2):

  1. girl / LUMINANCE, COLOR → mix (ink / field), DITHER → bayer 4×4 / 2 lvl.
  2. Raise PATTERN AMT — the stipple boundaries should start flowing. The motion comes from the selected gallery pattern: Tab to the gallery, click e.g. MARBLE or PLASMA (its SPEED sets the flow rate), Tab back. CONTRAST still spreads tones.

Halftone / icons (request 1):

  1. Still on girl / LUMINANCE: set SHAPE → circle (size), BACKING → NONE, COLOR → solid (COLOR A = ink). You should get an ink dot-halftone of the portrait (dot size tracks brightness). Tune CELL SIZE.
  2. SHAPE → icon (field) + a filled icon → the portrait rendered as icons.
  3. Switch MODE → PATTERN, IMAGE → wolf, SHAPE → circle (size) → the pattern fills the wolf silhouette as a dot grid (transparent backing drops the gaps to the page).

Watch for / report

Have a look — then the last two session items are more geometric shapes and the API simplifications.

Perfect. the UI is missing being able to change the actual underlying pattern, but that's fine, and I think we'll tackle this on the API simplification portion. Next we have more shapes, right? Just do the ones you can do in the shader comfortably and that you think would look good.

Image-as-content's done. Noted on the pattern-picker UI — that fits naturally into the API-simplification pass.

Now: more geometric shapes. They slot into shape_mask as new branches, each just a different "distance" metric that grows with the per-cell field — comfortable and clean. Let me re-read the current shape_mask + its caller to edit precisely.

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

556  //     the color. For an image shape, `m` would be the sprite's alpha at the
557 //     cell-local UV; nothing downstream changes.
558 //   * COLOR — *what hue*. The field value handed to dither + the color recipe,
559 //     at FULL strength (never multiplied by the mask). circle (size) uses the
560 //     per-FRAGMENT value `ff` (color varies inside the dot); circle (hard) uses
561 //     the per-CELL value `fc` (one flat color per dot).
562 //
563 // Compositing happens in main() per u_shape_backing:
564 //   backing 0 (transparent) → final alpha *= coverage  (gaps show the page)
565 //   backing 1 (token)       → mix(palette[color_a], colored, coverage)
566 //
567 // Cells are u_shape_size px square, anchored to screen space (gl_FragCoord),
568 // the same space as the dither. dist = normalized distance from the cell
569 // center (0 → 1 at the inscribed-circle edge, ~1.41 in the corners).
570 // =============================================================================
571 
572 // Coverage mask of the shape at the fragment, in [0,1]. `dist` is the
573 // normalized distance from the cell center; `cell_uv` is the 0..1 position
574 // within the cell; `fc` is the per-cell field (sizes the circle variants).
575 // THIS is the single extension point for new shapes — add a branch returning
576 // the new shape's coverage; the rest of the pipeline is unchanged.
577 float shape_mask(int kind, float dist, float fc, vec2 cell_uv) {
578     if (kind == 3 || kind == 4) {
579         // sprite: the chosen icon's silhouette (its alpha), tiled one-per-cell.
580         // Flip Y (gl_FragCoord is bottom-up, texture origin top-left); textureLod
581         // (.,0) avoids cell-edge mip seams.
582         //   fit  = icon footprint as a fraction of the cell — SPACING insets it
583         //   kind 3 (bg)    : full footprint; the effect fills/colors a constant icon
584         //   kind 4 (field) : footprint also scaled by the per-cell field fc, so the
585         //                    icon grows with the effect and vanishes where it's dark
... [22 more lines]

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

606  float effect_field_shaped(vec2 quad_px, out float coverage) {
607     float ff = effect_field(vPos, vUV, quad_px);                // per-fragment field
608     coverage = 1.0;
609     if (u_shape_kind == 0) return ff;
610     // Grid pitch (cell-to-cell distance). For sprite kinds, SPACING enlarges the
611     // pitch (more gap between icons) while shape_mask insets the icon by the same
612     // factor — the two cancel, so the icon's absolute size stays u_shape_size and
613     // only the gap grows. Circles ignore spacing (their gaps come from fc).
614     float size = max(u_shape_size, 1.0);
615     if (u_shape_kind >= 3) size /= max(1.0 - u_shape_spacing, 0.05);
616     vec2 cc  = (floor(gl_FragCoord.xy / size) + 0.5) * size;    // cell center, screen px
617     vec2 dpx = cc - gl_FragCoord.xy;                            // fragment → cell center
618     vec2 wc  = vPos + dFdx(vPos) * dpx.x + dFdy(vPos) * dpx.y;  // world pos at cell center
619     vec2 uvc = vUV  + dFdx(vUV)  * dpx.x + dFdy(vUV)  * dpx.y;  // uv at cell center
620     float fc = effect_field(wc, uvc, quad_px);                 // per-cell field
621     vec2 cell_uv = fract(gl_FragCoord.xy / size);              // 0..1 within the cell
622     vec2 q   = cell_uv - 0.5;
623     coverage = shape_mask(u_shape_kind, length(q) / 0.5, fc, cell_uv);
624     return (u_shape_kind == 2) ? fc : ff;   // hard: flat per-cell color; size/sprite: per-fragment color
625 }

Now I have the exact text. Two notes before editing: I'll drop the now-redundant dist parameter (compute everything from cell_uv), and I caught a latent bug — the SPACING pitch-enlargement is gated >= 3, which would wrongly catch the new geometric kinds (5–9); it must be sprites-only (3, 4). Rewriting shape_mask:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now fix the spacing gate and simplify the caller in effect_field_shaped:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Update the uniform doc comment for the new kinds:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now effect.lua registries — add the five geometric kinds:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

main.lua needs no change — the SHAPE cycler picks up the new kinds automatically, and shape_is_sprite correctly excludes them (so geometric shapes get CELL SIZE + BACKING but not the ICON/SPACING rows). Syntax-checking effect.lua:

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: effect.lua
=== shape_mask call sites in shader (should be 1, new sig) ===
583:float shape_mask(int kind, float fc, vec2 cell_uv) {
641:    // pitch (more gap between icons) while shape_mask insets the icon by the same
652:    coverage = shape_mask(u_shape_kind, fc, cell_uv);

Single call site, new signature — clean. Five geometric shapes are in. No rebuild (shader + Lua; recompiles at boot).

Added shapes (each a dot grid sized by the per-cell field, exactly like circle, just a different distance metric):

The SHAPE cycler now reads: off → circle (size) → circle (hard) → square → diamond → hexagon → ring → cross → icon (bg) → icon (field). They work everywhere shapes work — gallery rects and the image screen (halftone/stencil).

I also fixed a latent bug while in there: the SPACING pitch-enlargement was gated >= 3, which would have wrongly caught the new kinds (5–9); it's now sprites-only (3, 4), and I dropped the redundant dist param from shape_mask.

How to test

Run ./run.bat. In the gallery, cycle SHAPE through square / diamond / hexagon / ring / cross — each re-skins all rects as that dot grid. Tune CELL SIZE + BACKING. Then Tab to the IMAGE screen and try them there too (e.g. girl / LUMINANCE / diamond or hexagon, BACKING NONE → a diamond/hex halftone).

Watch for: whether hexagon packs cleanly (no merging/overflow between cells), the ring and cross read well at small vs large CELL SIZE, and AA crispness on all of them.

Have a look — if hexagon or any need a tuning tweak, tell me. Otherwise the last item is the API simplifications (including the image-screen pattern picker you flagged).

All of these look good. More shapes? Or do you think the icons serve for the rest?

Honestly? I think icons serve the rest — with one exception: triangle.

Here's my reasoning. The geometric set now covers the abstract primitive families that read as halftone/texture:

What's conspicuously missing is the triangle — it's the one fundamental regular polygon we don't have (we've got 4-gon, 6-gon, ∞-gon but not 3-gon), and it has a directional quality (it points) that none of the others do. It's cheap — same gauge-metric pattern as the others (max(-p.y, 0.866·|p.x| + 0.5·p.y)), and it's genuinely distinct, not a duplicate of anything.

Beyond triangle, I'd stop and let icons carry the long tail. The reason: everything else worth adding — star, heart, arrow, leaf, gear… — are recognizable objects, not abstract primitives. Those are exactly what the icon path is for, and we already have arbitrary icon silhouettes (plus star/heart filled in the set). Adding them as hardcoded SDF branches would bloat shape_mask and duplicate the icon system. Pentagon/octagon I'd skip too — octagon ≈ square, pentagon is niche.

The only other direction that'd add real value isn't "more shapes" but a fill/outline modifier — hollow versions of every shape (the ring is already the hollow circle; a hollow square / hex outline would give a "wireframe dot grid"). But that's a feature (a modifier across all shapes), not a shape, and a bigger call — I'd park it unless you want that look.

So my recommendation: add triangle, then call the shape axis done and move to API simplifications. Want me to drop in the triangle?

Yep.

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now the effect.lua registries:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: effect.lua

Triangle's in — kind 10, upward-pointing, same gauge-metric pattern as the others (top vertex reaches the top edge midpoint at fc=1, so it packs within the cell without overflow). Registries updated; it sits after diamond in the cycler. No rebuild.

Test: the SHAPE cycler now reads off → circle (size) → circle (hard) → square → diamond → triangle → hexagon → ring → cross → icon (bg) → icon (field). Cycle to triangle in the gallery (and on the image screen) — dots sized by the field, pointing up. Watch that it packs cleanly like the others.

That wraps the shape axis: circle, square, diamond, triangle, hexagon, ring, cross, plus arbitrary icons (bg + field).

Once you've confirmed triangle looks right, the last session item is the API simplifications — and I'll fold in the image-screen pattern picker you flagged. When we get there it'd help to know what's been bugging you about the API specifically, but I also have my own list of candidates from having just worked through all of it.

Another generally useful slider for shapes, rotation, so that all shapes are rotated the same. Another we might want to add later might be rotation based on a flow field of sorts, this is how the wall icons worked, the icons rotated with the wall and along it and gave it a nice effect, although this might be harder to do in a general way, I don't know.

Good idea — a uniform ROTATION applies to every shape (and it's especially useful for triangle/cross/icons). The flow-field version is a nice "later," and you're right it's harder — it'd need a per-cell angle source; I'll note it and keep this one a single global angle. Let me wire the global rotation now.

Let me read the current shape_mask to edit precisely.

Read (E:\a327ex\ricochet-template\assets\draw_shader.frag)

578  // The geometric shapes share one idea: a "gauge" metric m(cell_uv) that is 0 at
579 // the cell center and reaches 1 at a cell mid-side, with the shape boundary at
580 // m == fc. So every shape grows with the per-cell field exactly like the circle
581 // — only the distance metric differs (Euclidean → circle, Chebyshev → square,
582 // Manhattan → diamond, hex gauge → hexagon). Ring + cross are handled specially.
583 float shape_mask(int kind, float fc, vec2 cell_uv) {
584     if (kind == 3 || kind == 4) {
585         // sprite: the chosen icon's silhouette (its alpha), tiled one-per-cell.
586         // Flip Y (gl_FragCoord is bottom-up, texture origin top-left); textureLod
587         // (.,0) avoids cell-edge mip seams.
588         //   fit  = icon footprint as a fraction of the cell — SPACING insets it
589         //   kind 3 (bg)    : full footprint; the effect fills/colors a constant icon
590         //   kind 4 (field) : footprint also scaled by the per-cell field fc, so the
591         //                    icon grows with the effect and vanishes where it's dark
592         //                    (the circle-analog — the effect IS the icon grid)
593         vec2 uv = vec2(cell_uv.x, 1.0 - cell_uv.y);
594         float fit = 1.0 - u_shape_spacing;
595         float s   = (kind == 4) ? fc * fit : fit;
596         s = max(s, 1e-4);
597         uv = (uv - 0.5) / s + 0.5;
598         if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) return 0.0;
599         return textureLod(u_shape_tex, uv, 0.0).a;
600     }
601 
602     float e = 0.04;                       // anti-alias edge width
603     vec2 p = (cell_uv - 0.5) * 2.0;       // [-1,1]^2; |component| = 1 at a cell mid-side
604     vec2 a = abs(p);
605 
606     // RING — annulus of the circle (hole = 50% of the outer radius).
607     if (kind == 8) {
... [22 more lines]

Now adding rotation to shape_mask — three targeted edits. The rotation computation + open:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now declare the uniform, near the other shape uniforms:

Edit (E:\a327ex\ricochet-template\assets\draw_shader.frag)

The file E:\a327ex\ricochet-template\assets\draw_shader.frag has been updated successfully. (file state is current in your context — no need to Read it back)

Now effect.lua — write the uniform and doc:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua. The rotation global, slider, spec wiring, and a SIDEBAR_H bump. First the global:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the ROTATION slider — adding it in the shape-active block after CELL SIZE:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Pass shape_rotation in the gallery spec and the image spec:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now bump SIDEBAR_H for the added ROTATION row (worst case ≈ 956):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua

Both parse. Rotation is wired — shader + Lua only, no rebuild.

What it does: u_shape_rotation rotates each shape's cell-local coordinate about its cell center, applied uniformly to both geometric shapes and icons. The cell grid stays axis-aligned; only the shape inside each cell spins. A ROTATION slider (0..1 = full turn) appears whenever a shape is active, on both the gallery and image screens.

How to test

Run ./run.bat. With SHAPE → square (or triangle / cross / icon), drag ROTATION:

Flow-field rotation (the wall-icon effect) — parked as you suggested. When we want it, it's a per-cell angle source feeding this same rotation (e.g. derived from the pattern's gradient, or a dedicated flow pattern), rather than the single global angle. Feasible, just a bigger piece.

That should close out the shape axis for real now. Next up whenever you're ready: the API simplifications — tell me what's been nagging you and I'll combine it with my own candidate list (the image-screen pattern picker included).

Marvelous. Now for the API simplification. This is a rather simple ask, I think. I want to be able to draw all these effects we just did in single calls. Just like you can draw a rectangle using a single call, we should be able to draw a rectangle with all these patterns using a single call, the sliders and settings we have on the side being arguments on the call. Similar for drawing images and so on. I'd like a new screen to see what the API looks like, so when you draw something, also draw text showing the call that drew it, and just draw as many variations as you can fit on a screen covering all cases for everything we implemented so far. Tell me your own plans first, though, if you had them.

Before I build, here's my read and plan — you asked for it, and I do have opinions on how to make this clean.

The core simplification

Right now every effect draw is three calls: effect_set(spec)layer_rectangle(...)effect_clear(). The spec table already encodes every slider/setting we built. So the simplification is thin: per-primitive wrappers that bundle set + draw + clear into one call, taking the spec as the last argument.

effect_rectangle(layer, x, y, w, h, spec)
effect_circle(layer, x, y, r, spec)
effect_image(layer, img, x, y, w, h, spec)   -- fits the image into the (x,y,w,h) box

Each one: binds the sprite icon if needed → effect_set → draws the primitive → effect_clear. Base draw color defaults to white (irrelevant for color≠none, which is the whole point of these). The spec is exactly the sidebar: { pattern, pattern_scale, speed, contrast, pattern_param/param2, color, color_a/b, ramp, dither, shape, shape_size, shape_spacing, shape_rotation, shape_backing, shape_icon, image_field, image_pattern_amount } — all optional, all defaulted.

One gap to close: the sprite icon is currently bound out-of-band via layer_shader_set_texture. I'll fold it into the spec as shape_icon = icons.skull and do the bind inside effect_set, so a single call is fully self-contained.

Dogfooding (validates the API + shrinks code)

I'll refactor the existing gallery loop and image_draw to use these wrappers. If they can express what we already built, the API is right — and image_draw collapses from ~8 lines to one.

The new API screen (4th screen, Tab-cycled)

A living reference: a grid of cards, each rendering one effect_* call and printing the exact call beside it. Key idea for correctness — the code is generated from the spec, not hand-written: each example is authored as a minimal spec (only the fields it demonstrates), and I both (a) render it and (b) serialize it to the displayed Lua source. Single source of truth, and the printed call is guaranteed to reproduce the swatch. Coverage: every pattern, every color recipe, a representative spread of dithers, every shape (geometric + icon bg/field), rotation, and the image modes (luminance / halftone / pattern-stencil). As many as fit readably (~24–30 cards, 3 columns, swatch + code beside it).

The pattern picker you flagged

Folds in naturally: on the IMAGE screen I'll add a PATTERN cycler (and reuse each pattern's gallery-tuned scale/param as its default) so the image screen stops depending on "go select a gallery rect." With the wrappers, the pattern is just spec.pattern anyway.

What I'd not do

The spec field names are already consistent enough — I won't rename image_field etc. (pure churn). I won't collapse the four axes into positional args (the spec table is the right shape for this many optional settings). The scoped effect_draw(layer, spec, fn) stays as the escape hatch for multi-draw blocks.


That's my plan. The one genuine fork is the API-screen layout (code beside each swatch in 3 wide columns, vs. code below in a denser 5–6 column grid). I lean beside-the-swatch for code readability. Sound good, or adjust before I start?

Go ahead.

Approved. Let me first verify how layer_rectangle/layer_circle take their color arg (int vs color object), since the wrappers pass a base color.

Bash (cd E:/a327ex/ricochet-template && grep -nA2 "function layer_rectangle\b|functio...)

108:function layer_rectangle(lyr, x, y, w, h, color)
109-  eng.rectangle(lyr_handle(lyr), x, y, w, h, color)
110-end
--
112:function layer_circle(lyr, x, y, radius, color)
113-  eng.circle(lyr_handle(lyr), x, y, radius, color)
114-end
=== how engine draw_rectangle reads color ===
4954:static int l_layer_rectangle(lua_State* L) {
4966:static int l_layer_rectangle_line(lua_State* L) {
4979:static int l_layer_rectangle_gradient_h(lua_State* L) {
4992:static int l_layer_rectangle_gradient_v(lua_State* L) {
9401:    lua_register(L, "layer_rectangle", l_layer_rectangle);
9402:    lua_register(L, "layer_rectangle_line", l_layer_rectangle_line);
9403:    lua_register(L, "layer_rectangle_gradient_h", l_layer_rectangle_gradient_h);
9404:    lua_register(L, "layer_rectangle_gradient_v", l_layer_rectangle_gradient_v);

Read (E:\a327ex\Anchor2\engine\src\anchor.c)

4954 static int l_layer_rectangle(lua_State* L) {
4955        Layer* layer = (Layer*)lua_touserdata(L, 1);
4956        float x = (float)luaL_checknumber(L, 2);
4957        float y = (float)luaL_checknumber(L, 3);
4958        float w = (float)luaL_checknumber(L, 4);
4959        float h = (float)luaL_checknumber(L, 5);
4960        uint32_t color = (uint32_t)luaL_checkinteger(L, 6);
4961        layer_add_rectangle(layer, x, y, w, h, 0.0f, color); // stroke=0 for filled
4962        return 0;
4963    }
4964    
4965    // layer_rectangle_line(layer, x, y, w, h, color, line_width?) -- rectangle outline
4966    static int l_layer_rectangle_line(lua_State* L) {
4967        Layer* layer = (Layer*)lua_touserdata(L, 1);

layer_rectangle takes color as an integer, and palette.ink() returns one — so 0xFFFFFFFF (white, opaque) works directly in the wrappers. Let me read the current effect_set shape-uniform block to anchor the icon-bind insertion.

Read (E:\a327ex\ricochet-template\effect.lua)

378    Performance: enqueues ~14 uniform writes per call (plus the ramp token list
379   when color='ramp'). Cheap (a few bytes each).
380 ]]
381 function effect_set(layer, spec)
382   spec = spec or {}
383   local p  = pattern_kinds[spec.pattern or 'solid'] or 2
384   local c  = color_kinds[spec.color or 'none'] or 0
385   local d  = dither_kinds[spec.dither or 'off'] or 0
386   local sh = shape_kinds[spec.shape or 'none'] or 0
387   local ca = resolve_color(spec.color_a or 'ink')
388   local cb = resolve_color(spec.color_b or 'field')
389   local scale    = spec.pattern_scale or effect_default_pattern_scale
390   local param    = spec.pattern_param or 0
391   local param2   = spec.pattern_param2 or 0
392   -- Universal modifiers. Default 1.0 = neutral (speed 1 = normal animation,
393   -- contrast 1 = field unchanged). MUST default to 1, not 0 — a 0 here would
394   -- freeze animation / flatten the field to mid-grey.
395   local speed    = spec.speed or 1.0
396   local contrast = spec.contrast or 1.0
397   local shape_sz = spec.shape_size or 24
398   local shape_sp = spec.shape_spacing or 0
399 
400   layer_shader_set_int  (layer, effect_draw_shader, 'u_pattern_kind',     p)
401   layer_shader_set_int  (layer, effect_draw_shader, 'u_color_kind',       c)
402   layer_shader_set_int  (layer, effect_draw_shader, 'u_dither_kind',      d)
403   layer_shader_set_int  (layer, effect_draw_shader, 'u_shape_kind',       sh)
404   layer_shader_set_float(layer, effect_draw_shader, 'u_shape_size',       shape_sz)
405   layer_shader_set_float(layer, effect_draw_shader, 'u_shape_spacing',    shape_sp)
406   layer_shader_set_float(layer, effect_draw_shader, 'u_shape_rotation',   spec.shape_rotation or 0)
407   -- shape gaps: 'transparent' (0, gaps show through) or 'token' (1, gaps = color_a)

Read (E:\a327ex\ricochet-template\effect.lua)

407    -- shape gaps: 'transparent' (0, gaps show through) or 'token' (1, gaps = color_a)
408   layer_shader_set_int  (layer, effect_draw_shader, 'u_shape_backing',
409                          (spec.shape_backing == 'token') and 1 or 0)
410   layer_shader_set_int  (layer, effect_draw_shader, 'u_color_a',          ca)
411   layer_shader_set_int  (layer, effect_draw_shader, 'u_color_b',          cb)
412   -- color='ramp': push the ordered token list (indices + count). Only when the
413   -- recipe is active — other recipes leave the (unused) ramp uniforms as-is.
414   if c == 3 then
415     local ramp = spec.ramp or effect_ramp
416     local rn = math.min(#ramp, 8)
417     layer_shader_set_int(layer, effect_draw_shader, 'u_ramp_count', rn)
418     for i = 1, rn do
419       layer_shader_set_int(layer, effect_draw_shader, 'u_ramp_tokens[' .. (i - 1) .. ']', resolve_color(ramp[i]))
420     end

Now add the icon-bind to effect_set, right after the shape uniforms:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now document shape_icon and add the wrapper functions. First the spec doc:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the wrapper functions — adding them after effect_draw (the scoped form):

Read (E:\a327ex\ricochet-template\effect.lua)

421    -- recipe is active — other recipes leave the (unused) ramp uniforms as-is.
422   if c == 3 then
423     local ramp = spec.ramp or effect_ramp
424     local rn = math.min(#ramp, 8)
425     layer_shader_set_int(layer, effect_draw_shader, 'u_ramp_count', rn)
426     for i = 1, rn do
427       layer_shader_set_int(layer, effect_draw_shader, 'u_ramp_tokens[' .. (i - 1) .. ']', resolve_color(ramp[i]))
428     end
429   end
430   layer_shader_set_float(layer, effect_draw_shader, 'u_pattern_scale',    scale)
431   layer_shader_set_float(layer, effect_draw_shader, 'u_pattern_param',    param)
432   layer_shader_set_float(layer, effect_draw_shader, 'u_pattern_param2',   param2)
433   layer_shader_set_float(layer, effect_draw_shader, 'u_pattern_speed',    speed)
434   layer_shader_set_float(layer, effect_draw_shader, 'u_pattern_contrast', contrast)
435   -- image_field: sprite draws only. 1 = the image's own luminance drives the
436   -- field (dither/recolor a real image); 0 = the pattern drives it (default).
437   layer_shader_set_int  (layer, effect_draw_shader, 'u_image_field',
438                          spec.image_field and 1 or 0)
439   -- image_pattern_amount: luminance mode only. How much the animated pattern
440   -- ripples the image's field before dither (0 = static, →1 = flowing).
441   layer_shader_set_float(layer, effect_draw_shader, 'u_image_pattern_amount',
442                          spec.image_pattern_amount or 0)
443   layer_shader_set_float(layer, effect_draw_shader, 'u_time',             time)
444 end
445 
446 --[[
447   effect_clear(layer)
448   Reset pattern/color/dither on this layer to passthrough. The other
449   uniforms (color_a/b, scale, param) are left as-is — they only have an
450   effect when a non-zero kind reads them.
... [10 more lines]

Read (E:\a327ex\ricochet-template\effect.lua)

459  --[[
460   effect_draw(layer, spec, fn, ...)
461   Scoped form: set the effect, run fn(...), then reset to passthrough.
462   Forwards extra arguments to fn so closures can stay light.
463 ]]
464 function effect_draw(layer, spec, fn, ...)
465   effect_set(layer, spec)
466   fn(...)
467   effect_clear(layer)
468 end
469 
470 -- =============================================================================
471 -- CYCLING — wrap-around step through each axis's named cycle.
472 -- Pass nil to get the first entry; pass an unknown name to get the first too.
473 -- =============================================================================
474 

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now main.lua. Refactor the gallery loop to use effect_rectangle. Let me read the current section.

Read (E:\a327ex\ricochet-template\main.lua)

485               palette.ink())
486 
487   row = rect_cut_top(body, ui_row_h + 20)
488   local ms = ui_slider{ rect = row, id = 'mod_scale', label = 'SCALE',
489                         value = sel.scale, vmin = 0.05, vmax = 1.2, fmt = '%.3f' }
490   if ms.changed then sel.scale = ms.value end
491 
492   row = rect_cut_top(body, ui_row_h + 20)
493   local msp = ui_slider{ rect = row, id = 'mod_speed', label = 'SPEED',
494                          value = sel.speed, vmin = 0, vmax = 4, fmt = '%.2f' }
495   if msp.changed then sel.speed = msp.value end
496 
497   row = rect_cut_top(body, ui_row_h + 20)
498   local mco = ui_slider{ rect = row, id = 'mod_contrast', label = 'CONTRAST',
499                          value = sel.contrast, vmin = 0, vmax = 2.5, fmt = '%.2f' }
500   if mco.changed then sel.contrast = mco.value end
501 
502   row = rect_cut_top(body, ui_row_h + 20)
503   local mpa = ui_slider{ rect = row, id = 'mod_param', label = sel.param_label,
504                          value = sel.param, vmin = 0, vmax = 1, fmt = '%.2f' }
505   if mpa.changed then sel.param = mpa.value end
506 
507   -- Second intrinsic knob — only patterns that define one (the gradients:
508   -- OFFSET / RANGE) get this row; it uses the pattern's own min/max range.
509   if sel.param2_label then
510     row = rect_cut_top(body, ui_row_h + 20)
511     local mp2 = ui_slider{ rect = row, id = 'mod_param2', label = sel.param2_label,
512                            value = sel.param2, vmin = sel.param2_min or 0,
513                            vmax = sel.param2_max or 1, fmt = '%.2f' }
514     if mp2.changed then sel.param2 = mp2.value end
... [22 more lines]

Read (E:\a327ex\ricochet-template\main.lua)

536    local cx, cy = ax + aw/2, ay + ah/2
537 
538   -- Both modes share the selected gallery pattern (LUMINANCE uses it to ripple
539   -- the dither; PATTERN uses it as the field), the shared color/dither, and the
540   -- shared SHAPE controls (so the image can be halftoned / icon-filled).
541   local g = gallery[gallery_selected]
542   local spec = {
543     pattern = g.pattern, pattern_scale = g.scale, speed = g.speed,
544     pattern_param = g.param, pattern_param2 = g.param2,
545     color = current_color, dither = current_dither,
546     color_a = current_color_a, color_b = current_color_b,
547     shape = current_shape, shape_size = current_shape_size,
548     shape_spacing = current_shape_spacing, shape_rotation = current_shape_rotation,
549     shape_backing = current_shape_backing,
550   }
551   if current_image_mode == 'luminance' then
552     spec.image_field = true
553     spec.contrast = current_image_contrast
554     spec.image_pattern_amount = current_image_pattern_amount
555   else
556     spec.contrast = g.contrast
557   end
558   effect_set(game_layer, spec)
559   -- Bind the icon mask for sprite shapes (same as the gallery), on unit 2.
560   if shape_is_sprite(current_shape) and icons[current_shape_icon] then
561     layer_shader_set_texture(game_layer, effect_draw_shader, 'u_shape_tex',
562                              icons[current_shape_icon].handle, 2)
563   end
564   layer_push(game_layer, cx, cy, 0, sc, sc)   -- translate + scale the image draw
565   layer_image(game_layer, img, 0, 0)          -- centered at the pushed origin
... [10 more lines]

Now refactor image_draw to use effect_image + the pattern picker:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the gallery loop refactor — read its current exact text:

Read (E:\a327ex\ricochet-template\main.lua)

615  
616   -- The UI runs HERE, not in update(). Under render_uncapped on a monitor
617   -- faster than the 120Hz fixed-timestep update, render frames can fire
618   -- without a preceding update step; anything queued only in update() gets
619   -- consumed by layer_render and then renders empty (blank FBO) on those
620   -- frames → flicker. Queueing the UI in draw() (which runs every render
621   -- frame) avoids that entirely. ui_update reads the edge globals captured
622   -- in update() and may mutate current_* — run before the game shapes so a
623   -- click applies to the scene the same frame.
624   ui_state_begin_frame()
625   ui_update()
626 
627   -- IMAGE screen: content is the chosen test image through the effect (no camera
628   -- — the image is screen-space via layer_push). Composite, consume edges, done.
629   if current_screen == 'image' then
630     image_draw()
631     layer_render(game_layer)
632     layer_render(ui_layer)
633     layer_draw(game_layer)
634     layer_draw(ui_layer)
635     ui_mouse_pressed  = false
636     ui_mouse_released = false
637     return
638   end
639 
640   -- Background fill in the active palette's field token. Drawn WITHOUT the
641   -- effect pipeline (color='none' default state at top of game_layer), so
642   -- the background stays a clean flat token regardless of the spec.
643   layer_rectangle(game_layer, 0, 0, width, height, palette.field())
644 
... [22 more lines]

Read (E:\a327ex\ricochet-template\main.lua)

666        contrast      = g.contrast,
667       pattern_param = g.param,
668       pattern_param2 = g.param2,
669       color         = current_color,
670       color_a       = current_color_a,
671       color_b       = current_color_b,
672       dither        = current_dither,
673       shape         = current_shape,
674       shape_size    = current_shape_size,
675       shape_spacing = current_shape_spacing,
676       shape_rotation = current_shape_rotation,
677       shape_backing = current_shape_backing,
678     })
679     layer_rectangle(game_layer, r.x, r.y, GAL_RECT_W, GAL_RECT_H, palette.ink())
680   end
681 
682   effect_clear(game_layer)
683 
684   camera_detach(main_camera, game_layer)
685 
686   -- Gallery labels on ui_layer (no effect pipeline). Drawn after detach;
687   -- ui_layer is screen-space and the camera is identity here, so these
688   -- align under their rects. "<name>  (<scale>)" per cell.
689   for i, g in ipairs(gallery) do
690     local r = gallery_rect(i)
691     layer_text(ui_layer, g.label .. '  (' .. string.format('%.2f', g.scale) .. ')',

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the image PATTERN picker. First the global:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the PATTERN cycler row in the image controls (after IMAGE):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now wire the 4th screen. The require:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the new screen file. Writing api_showcase.lua — a grid where each example's source is generated from its spec (single source of truth) and rendered beside the live swatch:

Write (E:\a327ex\ricochet-template\api_showcase.lua)

File created successfully at: E:\a327ex\ricochet-template\api_showcase.lua (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua
OK: api_showcase.lua

All three parse. This round is Lua-only (shader untouched), so no rebuild — just run. Here's everything that landed:

Single-call API (in effect.lua): lua effect_rectangle(layer, x, y, w, h, spec) effect_circle(layer, x, y, r, spec) effect_image(layer, img, x, y, w, h, spec) -- fits img into the box Each bundles set + draw + clear. The sprite icon is now folded into the spec (shape_icon = icons.skull) and bound inside effect_set, so a single call is fully self-contained.

Dogfooded: the gallery loop and image_draw now use these wrappers (the gallery's manual icon-bind + trailing effect_clear are gone; image_draw collapsed to one effect_image call).

Image PATTERN picker: the image screen got a PATTERN cycler — pick the moving/fill pattern right there instead of routing through the gallery selection (resolves your earlier flag).

New API screen (api_showcase.lua, 4th via Tab): ~28 cards, each rendering one effect_* call beside its generated source — the code is serialized from the same minimal spec that draws the swatch, so it's guaranteed to reproduce it. Covers every pattern, the color recipes, a few dithers, every shape + rotation, effect_circle, and the three image modes.

How to test

Run ./run.bat. Tab now cycles gallery → showcase → image → api → gallery.

  1. Regression check — the gallery and image screens should look/behave exactly as before (they were refactored onto the new wrappers). On the image screen, the new PATTERN cycler should change the moving/fill pattern.
  2. API screen — a grid of swatches, each with the literal call that drew it (e.g. effect_rectangle(l, x, y, w, h, { pattern = 'marble', color = 'mix', shape = 'hexagon', shape_size = 20 })). Confirm the code reads cleanly and matches its swatch.

Tell me

Once you've confirmed it works, I'll sync the docs (the CLAUDE.md Spec API section + roadmap) to cover the single-call API and the new screen.

Great, when we actually work in games with this I'll use the editors because they're easier to understand than the text API, so now that I've seen it work, you can actually replace the API screen with a single editor that allows me to edit things with everything we did, covering all possible cases.

The editor over text makes sense — and now that the text screen proved the calls work, replacing it with a real editor is the right move. Let me lay out the plan and surface two choices before I build.

Design brief — the unified Editor (replaces the API screen)

Concept: swap api_showcase.lua for editor.lua. The 4th screen becomes a single-drawable inspector — a full control panel on the left, one large live preview on the right — that can express every case we built.

Target selector (the new bit): RECT / CIRCLE / IMAGE.

Full control panel, top to bottom:

It reuses the existing ui_* widgets, rectcut, and the shared current_* look state (color/dither/shape/…), plus the effect_* wrappers for the preview (dogfooding them once more). New state is just editor_target + the editor's pattern/modifier values.

Layout: single-column sidebar at near-full height + a large preview. Realistic configs fit comfortably; only a pathological combo (image + sprite + ramp + gradient all at once) would slightly overrun — acceptable for a dev tool, and I'll two-column it later if it bugs you.

Keeps: gallery (the all-patterns comparison is distinct), showcase. Removes: the text API screen.

Two genuine choices before I start:

AskUserQuestion

Your questions have been answered: "The editor will have an IMAGE target, which makes the separate IMAGE screen redundant. Keep both, or fold it in?"="Fold into editor, drop it", "Include a small live code readout under the preview (the effect_* call your edits build), or keep the editor purely visual?"="No, editor only". You can now continue with these answers in mind.

Decisions locked: fold the image screen into the editor, no code readout. Tab will be gallery → showcase → editor.

To avoid duplicating the intricate shared control blocks (shape sub-controls with the filled-icon snap, color A/B, ramp editor) across the gallery sidebar and the editor, I'll factor them into shared global functions, then both screens call them. Let me re-read the current ui_update to extract them cleanly and plan the image-screen removal.

Read (E:\a327ex\ricochet-template\main.lua)

290    -- MODIFIERS section below reflects the new selection this same frame.
291   if current_screen == 'gallery' and ui_mouse_pressed then
292     local mx, my = mouse_position()
293     for i = 1, #gallery do
294       if ui_point_in_rect(mx, my, gallery_rect(i)) then gallery_selected = i end
295     end
296   end
297 
298   local panel_r = rect_new(SIDEBAR_X, SIDEBAR_Y, SIDEBAR_W, SIDEBAR_H)
299   ui_panel{ rect = panel_r, title = 'effect control', corner_brackets = true }
300 
301   -- Carve out the panel body: title bar at top, inset on the remaining area.
302   local body = rect_new(panel_r.x, panel_r.y, panel_r.w, panel_r.h)
303   rect_cut_top(body, ui_title_h)                         -- skip the title bar
304   body = rect_contract(body, ui_panel_inset)             -- inner padding
305 
306   -- PALETTE — dark/light segmented toggle.
307   local row = rect_cut_top(body, ui_row_h)
308   local seg = ui_segment{
309     rect = row, id = 'palette', label = 'PALETTE',
310     options = { 'DARK', 'LIGHT' },
311     index   = palette_mode == 'dark' and 1 or 2,
312   }
313   if seg.changed then
314     palette_init(seg.index == 1 and 'dark' or 'light')
315   end
316 
317   -- IMAGE-screen-only controls: field-source MODE + which test IMAGE. The COLOR
318   -- / DITHER / COLOR A·B / ramp rows below are shared and re-skin the image live.
319   if current_screen == 'image' then
... [145 more lines]

Read (E:\a327ex\ricochet-template\main.lua)

464      if rc.next_clicked and #effect_ramp < 8 then
465       table.insert(effect_ramp, ramp_selected + 1, effect_ramp[ramp_selected])
466       ramp_selected = ramp_selected + 1
467     end
468     if rc.prev_clicked and #effect_ramp > 2 then
469       table.remove(effect_ramp, ramp_selected)
470       if ramp_selected > #effect_ramp then ramp_selected = #effect_ramp end
471     end
472 
473     row = rect_cut_top(body, swatch_row_h)
474     local rs = ui_swatch_row{ rect = row, id = 'ramp_stops', label = 'RAMP',
475                               tokens = effect_ramp, selected_index = ramp_selected }
476     if rs.index then ramp_selected = rs.index end
477 
478     row = rect_cut_top(body, swatch_row_h)
479     local rp = ui_swatch_row{ rect = row, id = 'ramp_pick', label = 'STOP',
480                               tokens = palette_token_names,
481                               selected = effect_ramp[ramp_selected] }
482     if rp.changed then effect_ramp[ramp_selected] = rp.selected end
483   end
484 
485   -- ---- MODIFIERS for the selected gallery rect (GALLERY screen only) ----
486   -- Per-pattern scale / speed / contrast + the pattern's intrinsic knob.
487   -- Each gallery entry stores its own values; these sliders edit whichever
488   -- rect is selected (click a rect to switch which one they drive).
489   if current_screen ~= 'image' then
490   local sel = gallery[gallery_selected]
491   rect_cut_top(body, ui_section_gap)
492   local mhead = rect_cut_top(body, ui_row_h)
493   layer_text(ui_layer, 'MODIFIERS  ' .. sel.label, ui_font_label,
... [45 more lines]

I have the full picture. This is a multi-file refactor; I'll factor the shared control blocks into a new ui_controls.lua (used by both the gallery sidebar and the editor), then rewrite ui_update, build editor.lua, remove the image screen, and drop the api screen. Let me go step by step.

Step 1 — ui_controls.lua (shared cyclers + control blocks):

Write (E:\a327ex\ricochet-template\ui_controls.lua)

File created successfully at: E:\a327ex\ricochet-template\ui_controls.lua (file state is current in your context — no need to Read it back)

Step 2 — refactor main.lua. Requires first:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Remove the now-shared local helpers from main.lua:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the large ui_update simplification — replacing the image block + inline shared controls with the factored calls:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now remove the MODIFIERS gallery-only guard (it's always gallery now):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Simplify the gallery-rect-selection guard (always gallery now):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now remove the image_draw function. Let me read its current location:

Read (E:\a327ex\ricochet-template\main.lua)

360    if not img then return end
361 
362   local ax, ay = GAL_X0, GAL_Y0
363   local aw, ah = width - ax - 40, height - ay - 80
364 
365   local g = gallery[current_image_pattern_idx]
366   local spec = {
367     pattern = g.pattern, pattern_scale = g.scale, speed = g.speed,
368     pattern_param = g.param, pattern_param2 = g.param2,
369     color = current_color, dither = current_dither,
370     color_a = current_color_a, color_b = current_color_b,
371     shape = current_shape, shape_size = current_shape_size,
372     shape_spacing = current_shape_spacing, shape_rotation = current_shape_rotation,
373     shape_backing = current_shape_backing,
374     shape_icon = shape_is_sprite(current_shape) and icons[current_shape_icon] or nil,
375   }
376   if current_image_mode == 'luminance' then
377     spec.image_field = true
378     spec.contrast = current_image_contrast
379     spec.image_pattern_amount = current_image_pattern_amount
380   else
381     spec.contrast = g.contrast
382   end
383   effect_image(game_layer, img, ax, ay, aw, ah, spec)
384 
385   -- Label (ui_layer, screen-space) above the image.
386   layer_text(ui_layer,
387     string.upper(current_image) .. '  ·  ' .. string.upper(current_image_mode) .. '  (' .. g.label .. ')',
388     ui_font_label, ax, ay - 30, palette.ink())
389 end
... [30 more lines]

Read (E:\a327ex\ricochet-template\main.lua)

344                             vmax = sel.param2_max or 1, fmt = '%.2f' }
345     if mp2.changed then sel.param2 = mp2.value end
346   end
347 end
348 
349 -- -----------------------------------------------------------------------------
350 -- image_draw — IMAGE screen content: the chosen test image fit into the content
351 -- area, processed through the effect via the single-call effect_image. LUMINANCE
352 -- → the image's own brightness is the field (dither/recolor it, optionally
353 -- rippled by the moving pattern); PATTERN → the chosen pattern fills it, stenciled
354 -- by the image's alpha. The image PATTERN picker selects which gallery pattern
355 -- drives both (its entry supplies the tuned scale / param).
356 -- -----------------------------------------------------------------------------
357 local function image_draw()
358   layer_rectangle(game_layer, 0, 0, width, height, palette.field())
359   local img = content_imgs[current_image]
360   if not img then return end
361 

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now the Tab cycle and draw() dispatch. Update the cycle:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Read (E:\a327ex\ricochet-template\main.lua)

400      ui_mouse_pressed  = false
401     ui_mouse_released = false
402     return
403   end
404 
405   -- API reference screen: a grid of example effect_* calls, each rendered (on
406   -- game_layer, through the pipeline) next to its generated source (on ui_layer).
407   if current_screen == 'api' then
408     api_showcase_draw()
409     layer_render(game_layer)
410     layer_render(ui_layer)
411     layer_draw(game_layer)
412     layer_draw(ui_layer)
413     ui_mouse_pressed  = false
414     ui_mouse_released = false
415     return
416   end
417 
418   -- The UI runs HERE, not in update(). Under render_uncapped on a monitor
419   -- faster than the 120Hz fixed-timestep update, render frames can fire
420   -- without a preceding update step; anything queued only in update() gets
421   -- consumed by layer_render and then renders empty (blank FBO) on those
422   -- frames → flicker. Queueing the UI in draw() (which runs every render
423   -- frame) avoids that entirely. ui_update reads the edge globals captured
424   -- in update() and may mutate current_* — run before the game shapes so a
425   -- click applies to the scene the same frame.
426   ui_state_begin_frame()
427   ui_update()
428 
429   -- IMAGE screen: content is the chosen test image through the effect (no camera
... [30 more lines]

Restructure the draw() dispatch — drop the api + image branches, add the editor branch after ui_state_begin_frame:

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now clean up the image globals (the editor uses editor_contrast/editor_pattern instead):

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Now Step 3 — editor.lua (the unified editor: state, controls reusing the shared blocks, and the live preview):

Write (E:\a327ex\ricochet-template\editor.lua)

File created successfully at: E:\a327ex\ricochet-template\editor.lua (file state is current in your context — no need to Read it back)

Now delete the old api_showcase.lua and syntax-check everything:

Bash (cd E:/a327ex/ricochet-template && rm -f api_showcase.lua && echo "deleted api_sh...)

deleted api_showcase.lua
OK: main.lua
OK: effect.lua
OK: ui_controls.lua
OK: editor.lua
OK: showcase.lua

All five parse. Given the size of this refactor, let me grep for any dangling references to removed symbols (image_draw, the old globals, the old screen names, api_showcase):

Bash (cd E:/a327ex/ricochet-template && echo "=== dangling refs (should be empty) ==="...)

=== dangling refs (should be empty) ===
editor.lua:74:  if editor_target == 'image' and current_image_mode == 'luminance' then
editor.lua:107:  if editor_target == 'image' then
editor.lua:198:  if editor_target == 'image' then
=== current_screen usages ===
169:current_screen = 'gallery'   -- 'gallery' | 'showcase' | 'editor'
385:    if current_screen == 'gallery' then current_screen = 'showcase'
386:    elseif current_screen == 'showcase' then current_screen = 'editor'
387:    else current_screen = 'gallery' end
395:  if current_screen == 'showcase' then
416:  if current_screen == 'editor' then
=== confirm shared fns referenced ===
main.lua:301:  ui_shape_block(body)
main.lua:303:  ui_color_ab_block(body)
main.lua:304:  ui_ramp_block(body)
main.lua:417:    editor_ui()
main.lua:418:    editor_preview()
editor.lua:85:function editor_ui()
editor.lua:167:  ui_shape_block(body)
editor.lua:169:  ui_color_ab_block(body)
editor.lua:170:  ui_ramp_block(body)
editor.lua:174:function editor_preview()

No dangling references — the 'image' matches are all the editor's legitimate editor_target == 'image'. Let me verify the refactored ui_update reads cleanly end-to-end:

Read (E:\a327ex\ricochet-template\main.lua)

278    local panel_r = rect_new(SIDEBAR_X, SIDEBAR_Y, SIDEBAR_W, SIDEBAR_H)
279   ui_panel{ rect = panel_r, title = 'effect control', corner_brackets = true }
280 
281   -- Carve out the panel body: title bar at top, inset on the remaining area.
282   local body = rect_new(panel_r.x, panel_r.y, panel_r.w, panel_r.h)
283   rect_cut_top(body, ui_title_h)                         -- skip the title bar
284   body = rect_contract(body, ui_panel_inset)             -- inner padding
285 
286   -- PALETTE — dark/light segmented toggle.
287   local row = rect_cut_top(body, ui_row_h)
288   local seg = ui_segment{
289     rect = row, id = 'palette', label = 'PALETTE',
290     options = { 'DARK', 'LIGHT' },
291     index   = palette_mode == 'dark' and 1 or 2,
292   }
293   if seg.changed then
294     palette_init(seg.index == 1 and 'dark' or 'light')
295   end
296 
297   -- Shared look controls (color recipe + tokens + dither + shape + ramp), drawn
298   -- by the shared blocks in ui_controls.lua (reused by the editor screen too).
299   ui_color_recipe_row(body)
300   ui_dither_row(body)
301   ui_shape_block(body)
302   rect_cut_top(body, ui_section_gap)
303   ui_color_ab_block(body)
304   ui_ramp_block(body)
305 
306   -- ---- MODIFIERS for the selected gallery rect ----
307   -- Per-pattern scale / speed / contrast + the pattern's intrinsic knob.
... [42 more lines]

ui_update is clean. Let me do a final static check for any leftover dead code (e.g. an unused current_spec) and confirm the gallery draw still references the now-global shape_is_sprite:

Bash (cd E:/a327ex/ricochet-template && echo "=== current_spec (dead?) ==="; grep -n "...)

=== current_spec (dead?) ===
185:local function current_spec()
=== files present ===
editor.lua
effect.lua
main.lua
palette.lua
rectcut.lua
showcase.lua
ui.lua
ui_controls.lua
ui_state.lua
=== editor/ui_controls required? ===
24:require('anchor')({
34:require('palette')
35:require('effect')
36:require('rectcut')
37:require('ui_state')
38:require('ui')
39:require('ui_controls')
40:require('showcase')
41:require('editor')

current_spec is now dead (defined, never called). Let me read and remove it:

Read (E:\a327ex\ricochet-template\main.lua)

183  ui_mouse_released = false
184 
185 local function current_spec()
186   return {
187     pattern       = current_pattern,
188     color         = current_color,
189     dither        = current_dither,
190     color_a       = current_color_a,
191     color_b       = current_color_b,
192     pattern_scale = current_scale,
193   }
194 end
195 
196 -- -----------------------------------------------------------------------------

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Bash (cd E:/a327ex/ricochet-template && E:/a327ex/Anchor/reference/love-compare/tools/...)

OK: main.lua

All parse. The refactor is complete and the shader's untouched, so no rebuild — just run. Here's the shape of it:

New files

Changes

The editor (Tab to it): a full control panel + one large live preview.

How to test

Run ./run.bat. Tab cycles gallery → showcase → editor.

  1. Regression — the gallery should behave exactly as before (it's on the shared blocks now), and the showcase unchanged.
  2. Editor — flip TARGET through RECT / CIRCLE / IMAGE. Pick a PATTERN (the PARAM label should change per pattern, gradients show PARAM2). Drive every control and watch the preview. On IMAGE, try MODE luminance (with PATTERN AMT) and pattern, and cycle IMAGE through girl/boy/wolf.

Watch for / tell me

Once you've confirmed it works, I'll sync CLAUDE.md (the screen list + Spec API + the single-call wrappers + the new editor) — it's describing the old structure right now.

Great, seems like everything works. Update documents as you said.

Everything works. Let me sync the docs now. I'll update ricochet-template/.claude/CLAUDE.md (the biggest gaps: roadmap, shape axis, spec API + single-call wrappers, the screens/editor, file map, engine note), verify the effect.lua docblock, and add a cross-project memory for the engine patch.

Let me re-read the CLAUDE.md sections I'm changing to get exact current text.

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

46   ## What this is
47  
48  A starter Anchor 2 project that ships **Ricochet's visual identity** plus
49  a clean four-axis effect system (pattern × color × dither × shape). Fork the
50  folder, drop your game code into `main.lua`, prototype. The template
51  itself ships no gameplay — that's the forking dev's job.
52  
53  The full visual identity (palette philosophy, dotted motif, typography,
54  shape language, motion principles) lives in `Ricochet/design.md`. This
55  template implements the palette + the effect pipeline only; everything
56  else in design.md is guidance for how a forked project should look.
57  
58  Layout:
59  - **`main.lua`** — the test scene: a **pattern gallery** (one rect per
60    pattern, the `gallery` table) + a **click-to-select inspector** (the
61    sidebar edits the selected rect's modifiers). Owns boot order, layers,
62    the per-frame UI contract, and the keyboard hotkeys.
63  - **`palette.lua`** — `palette_dark` + `palette_light`, 13 named tokens
64    per palette. `palette_init('dark' | 'light')` selects the active one.
65  - **`effect.lua`** — the four-axis effect API: pattern/color/dither/shape
66    registries, `effect_set(layer, spec)`, cycle helpers.
67  - **`rectcut.lua`** — RectCut layout primitive (cut/get/add/contract/
68    center/split). Verbatim from snkrx-template's `snkrx/ui/rect.lua`.
69  - **`ui_state.lua`** — frame-local hot/active/focus tracking +
70    `ui_claim_hot`. Slimmed from snkrx-template's `snkrx/ui/state.lua`
71    (text-input + modal-lock bits removed).
72  - **`ui.lua`** — the five Ricochet-style widgets that build the sidebar
73    control panel (`ui_panel`, `ui_field`, `ui_segment`, `ui_swatch_row`,
74    `ui_slider`) plus internal `ui_icon_button`.
75  - **`assets/draw_shader.frag`** — the unified fragment shader. Replaces
... [45 more lines]

Now updating. Layout section — reflect the new files and the editor:

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the Roadmap section — most of it is done:

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the effect-system overview and pipeline. Let me read that section:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

122  1. **480×270 support.** Make the effects (and eventually the dev UI) read at the
123    SNKRX render target, where 1 logical px = 1 dither cell. The shader is already
124    `gl_FragCoord`-anchored, so it's mostly a verify + tune pass, but the user
125    wants to do it by hand.
126 2. **Replace the snkrx-template effect system** (its `edition.lua` + dither
127    stack) with this one, once 480×270 is settled. This is the end goal of the
128    whole template.
129 3. **Flow-field shape rotation** (the Orblike/Invoker "wall icon" effect): a
130    *per-cell* rotation angle from a field, vs. today's single global ROTATION.
131    Feasible; bigger. The hook is the rotation math at the top of `shape_mask`.
132 
133 **When this toolkit is used in a REAL game:** the showcase UI will want
134 restyling to match the Ricochet design sheets (`Ricochet/reference/`) more
135 closely in *feel*. (User flagged this explicitly.)
136 
137 ## The effect system (pattern × color × dither × shape)
138 
139 Every draw routes through `assets/draw_shader.frag`. The shader composes:
140 
141 ```
142 f   = pattern(world_pos, time*speed, scale, param, param2)   // [0,1]
143 f   = contrast_remap(f)                              // spread/compress around 0.5
144 f   = shape(f, pixel_pos, shape_size)                // carve into a dot grid (or passthrough)
145 f   = dither(f, pixel_pos)                           // {0, 1/n, …, 1}
146 rgb = color(base_rgb, f, palette[color_a], palette[color_b])
147 ```
148 
149 Four orthogonal selectors (pattern / color / dither / shape) plus three
150 universal **modifiers** (scale / speed / contrast) and **two per-pattern
151 intrinsic knobs** (`param` / `param2`). Pattern owns spatial structure AND

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

151  intrinsic knobs** (`param` / `param2`). Pattern owns spatial structure AND
152 animation; shape optionally re-expresses the field as a dot grid; color is a
153 pure recipe that picks/mixes palette tokens by f; dither inserts the
154 pixel-art stipple between them.
155 
156 ### Patterns (`pattern_kinds` in `effect.lua`; dispatch in the shader's `pattern_field`)
157 
158 Two base kinds + seven world-anchored "gallery" patterns + two **LOCAL**
159 gradient patterns. Each gallery pattern has ONE intrinsic `param` knob whose
160 meaning differs per pattern; its DEFAULT value reproduces the canonical look.
161 
162 | kind | name            | character                        | param (intrinsic knob)    | param2 (2nd knob)        |

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the Shape section — the biggest behavior change. Let me read its current text:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

250      trap). Use DITHER `off` for a smooth ramp, or a dither with **>= N levels**
251     (`bayer4_8`, `bayer8_16`, `noise_8`) to keep the middle stops.
252 
253 ### Dither (`dither_kinds` — 34 modes)
254 Full port of snkrx-template's dither catalog: a 2-level group (bayer4_2,
255 bayer8_2, noise_2) plus multi-level Bayer / white-noise / cluster-dot /
256 diagonal-line / scanline / triangle / hearts families. The complete list +
257 human labels are in `dither_kinds` and `dither_pretty_names` in `effect.lua`.
258 The level count is baked into each name (`bayer4_4` = 4×4 matrix, 4 levels);
259 2-level = hard A/B, higher = smoother `mix` transitions.
260 
261 ### Shape (`shape_kinds` — circle dot grid)
262 A stage between `effect_field` and dither that re-expresses the field as a grid
263 of shapes. It still dithers + colors normally afterward. `none` is passthrough.
264 Cells are `shape_size` px square, anchored to screen space (`gl_FragCoord`, the
265 same space as dither).
266 
267 **The general model (`shape_mask` + `effect_field_shaped`), built to extend to
268 image/sprite shapes later. The field has TWO roles, kept on SEPARATE channels
269 — conflating them is what made gaps + dot-edges collapse to `color_ramp`'s stop
270 0 (the "everything goes red" trap):**
271 - **Coverage** — *where* a dot is. The mask `m`, a disc whose size comes from
272   the **per-cell** value `fc` (sampled once at the cell center via
273   `effect_field_shaped`, reconstructing world/uv there from `dFdx`/`dFdy` —
274   exact for the 2D affine camera). Per-cell sampling keeps the boundary a
275   **true circle**. Coverage drives compositing (alpha / blend), **not** color.
276   `shape_mask()` is the single extension point: an image shape returns
277   `texture(u_shape_tex, cell_uv).a` there; nothing downstream changes.
278 - **Color** — *what hue*. The field value fed to dither + the color recipe at
279   **full strength** (never multiplied by the mask). `circle` uses the
... [38 more lines]

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

317    color_a = 'ink',         -- palette token name
318   color_b = 'field',       -- palette token name (used by mix)
319   ramp    = {'red','orange','yellow','green','blue','pink'},  -- token list, used by color='ramp'
320   pattern_scale  = 0.4,    -- feature size
321   speed          = 1.0,    -- animation rate (default 1)
322   contrast       = 1.0,    -- mid-range spread (default 1 = unchanged)
323   pattern_param  = 0.5,    -- the active pattern's intrinsic knob, [0,1]
324   pattern_param2 = 0,      -- 2nd intrinsic knob (gradient OFFSET / RANGE)
325 })
326 -- ... draws here ...
327 effect_clear(layer)        -- or the scoped effect_draw(layer, spec, fn)
328 ```
329 
330 Every field optional; omitted → documented default. **speed/contrast
331 default to 1.0, NOT 0** (0 would freeze animation / flatten the field to
332 mid-grey). Default spec is `color='none'`, so a bare `effect_set` is a
333 no-op until you set a color recipe.
334 
335 ---
336 
337 ## Pattern exploration history (don't re-tread)
338 
339 The pattern set was found by trial across the "Visual Experiments 1"
340 session. A new instance should NOT re-propose the rejected ideas without a
341 fresh reason — they were built and cut.
342 
343 **Rejected outright (built, looked wrong, removed):**
344 - **worley / cellular** — only read as cells in a narrow scale window;

Now the Shape section rewrite:

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the Spec API block + the single-call wrappers:

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the Test scene section + Keys table. Let me read them:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

386  ---
387 
388 ## Palette
389 
390 13 named tokens per palette mode. Light mode uses Ricochet's "ink on warm
391 paper" colors; dark mode uses the "blueprint room with the lights off"
392 counterparts (see `Ricochet/design.md` § Dark mode for the role mapping).
393 
394 Keys (shared across both palettes):
395 ```
396 neutrals:  field  panel  recess  ink  mid_light  mid_grey  deep_grey
397 accents:   blue   orange green   pink yellow     red
398 ```
399 
400 Light mode collapses panel→field and deep_grey→recess (no separate
401 elevation surface defined in design.md). Forked games that need
402 explicit elevation in light mode override the table.
403 
404 `palette.lua` exposes:
405 - `palette_dark`, `palette_light` — the two tables
406 - `palette` — the currently-active table (set by `palette_init`)
407 - `palette_mode` — `'dark'` or `'light'`
408 - `palette_token_names`, `palette_token_index`, `palette_token_count`
409 
410 For raw layer_* draws, call `palette.ink()` etc. (the parens trigger the
411 color metatable's __call → rgba tuple). For shader-pipeline draws, pass
412 the token NAME via `color_a`/`color_b` in the spec.
413 
414 ---
415 
... [30 more lines]

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

445  tooltip, leaderboard list), CONTROLS (tabs, toggle/checkbox/radio, stepper, stat
446 block, keycaps, bracket tags). Each is a small local helper taking `(x, y, …)`
447 and returning the next `y`.
448 
449 **Icon pack: Tabler** (chosen over Phosphor/Remix — most icons + best game
450 coverage of the clean line packs + freely adjustable stroke). Icons are 44px
451 white PNGs at `assets/icons/tabler/<concept>.png`, loaded flat into
452 `icons[concept]` and tinted to a palette token. Regenerate / extend the set via
453 `tools/fetch_icons.mjs` (Iconify API → resvg; `STROKE = 0.75` for the hairline
454 look). `tools/compare_packs.mjs` is the pack-comparison helper (counts + game
455 coverage).
456 
457 NOTE: `F1`/`F2` (pattern) and `[`/`]` (scale) still mutate
458 `current_pattern` / `current_scale`, but the gallery ignores those globals
459 (every rect is per-pattern, per-scale via the inspector), so they're inert
460 in gallery mode. Color / dither / tokens / palette ARE shared, so their
461 keys work.
462 
463 ---
464 
465 ## UI control panel
466 
467 A left-anchored sidebar (380×700, top-left at (32, 40)). The gallery sits
468 to its right. The sidebar has two regions:
469 - **Shared look controls** (apply to every gallery rect): PALETTE segment,
470   COLOR recipe, DITHER, SHAPE (+ CELL SIZE slider, shown only when SHAPE ≠
471   off), COLOR A, COLOR B.
472 - **MODIFIERS** (apply only to the currently-selected gallery rect):
473   SCALE / SPEED / CONTRAST sliders + the selected pattern's intrinsic-knob
474   slider(s) (labeled per pattern, e.g. WARP / VEIN / LINES; gradients add a

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the UI control panel section. Let me read it:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

461  
462 ## UI control panel
463 
464 A left-anchored sidebar (380×700, top-left at (32, 40)). The gallery sits
465 to its right. The sidebar has two regions:
466 - **Shared look controls** (apply to every gallery rect): PALETTE segment,
467   COLOR recipe, DITHER, SHAPE (+ CELL SIZE slider, shown only when SHAPE ≠
468   off), COLOR A, COLOR B.
469 - **MODIFIERS** (apply only to the currently-selected gallery rect):
470   SCALE / SPEED / CONTRAST sliders + the selected pattern's intrinsic-knob
471   slider(s) (labeled per pattern, e.g. WARP / VEIN / LINES; gradients add a
472   2nd knob OFFSET / RANGE). Click a rect to choose which one these edit.
473 
474 ### The widgets
475 
476 All five draw to `ui_layer`. Each is a function taking one opts table;
477 state is caller-owned (pass `value` / `selected` / `index`; widget
478 reports `clicked` / `changed` / new value/index; caller updates its
479 own globals).
480 
481 - **`ui_panel(opts)`** — hairline-bordered container with optional
482   title bar and optional corner brackets (small L shapes outside each
483   corner, per Ricochet/design.md's chamber treatment).
484 - **`ui_field(opts)`** — `LABEL  value  [<] [>]` row. The cycler used
485   for COLOR and DITHER.
486 - **`ui_segment(opts)`** — N-cell segmented control. Active cell is
487   drawn with an INVERTED fill (ink rectangle, field-colored label) —
488   matches the reference sheets' button-active idiom. The palette-mode
489   toggle uses it.
490 - **`ui_swatch_row(opts)`** — palette-token picker: label above, row

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the "Adding a shape" instructions (shape_mask signature changed) and the File map. Let me read those:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

640  ### Draw origin: images CENTER, rectangles/text TOP-LEFT
641 `layer_image` / `layer_texture` / `layer_circle` draw **centered** at `(x, y)`;
642 `layer_rectangle` / `layer_text` draw from the **top-left** `(x, y)`. Do NOT
643 subtract half the image size to "center" an image — it already centers, so that
644 double-offsets it up-left by half (the showcase icon bug). To center an icon in
645 a top-left box `{x, y, w, h}`: `layer_image(lyr, img, x + w/2, y + h/2, col)`.
646 See `showcase.lua`'s `icon()` helper.
647 
648 ### Color in draws vs in specs
649 - **Raw layer_* draws** (background fill, HUD text, anything that should
650   bypass the pipeline) → pass a color object directly, with parens:
651   `layer_rectangle(game_layer, 0, 0, w, h, palette.field())`.
652 - **Pipeline draws** (anything that should be re-colored by the effect) →
653   pass token NAMES in the spec: `color_a = 'ink'`. The base color of the
654   draw is then irrelevant (use any visible token so layout-only debugging
655   remains possible).
656 
657 ### `effect_clear` after a bracketed set
658 The shader uniforms persist on the layer until rewritten. Use
659 `effect_clear(layer)` after a bracketed pipeline draw, or use the scoped
660 `effect_draw(layer, spec, fn, ...)` form which clears for you.
661 
662 ### Don't run `./run.bat` yourself
663 The user runs and tests. After framework changes, syntax-check Lua with:
664 ```
665 E:/a327ex/Anchor/reference/love-compare/tools/lua54.exe -e "loadfile('main.lua')"
666 ```
667 
668 ---
669 
... [45 more lines]

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now the File map. Let me read it:

Read (E:\a327ex\ricochet-template.claude\CLAUDE.md)

714  
715 ---
716 
717 ## File map
718 
719 ```
720 ricochet-template/
721 ├── main.lua                    # pattern gallery + inspector sidebar + keys
722 ├── palette.lua                 # 2 palettes × 13 tokens; palette_init
723 ├── effect.lua                  # 4-axis spec API (pattern/color/dither/shape) + cycle helpers
724 ├── rectcut.lua                 # RectCut layout primitive
725 ├── ui_state.lua                # frame-local hot/active/focus + ui_claim_hot
726 ├── ui.lua                      # 5 Ricochet-style widgets + helpers
727 ├── anchor/                     # Anchor 2 framework
728 ├── anchor.exe                  # built engine
729 ├── assets/
730 │   ├── draw_shader.frag        # unified pattern+shape+dither+color shader
731 │   ├── Oswald-Medium.ttf       # UI titles + field labels
732 │   ├── IBMPlexSans-Regular.ttf # UI labels (alt)
733 │   └── CascadiaCode-Regular.ttf # UI value column + numeric readouts
734 ├── run.bat
735 └── .claude/CLAUDE.md           # this file
736 ```
737 
738 ---
739 
740 ## Working style
741 
742 Same conventions as Anchor 2 / Ricochet / Invoker:
743 
... [5 more lines]

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

Now add the Engine-patch note to Critical conventions. Let me find that section header:

Grep (## Critical conventions|### Boot order)

626:## Critical conventions
627-
628:### Boot order
629-1. `require('anchor')(...)` — engine init.
630-2. `require('palette')` + `require('effect')` — module loads.
631-3. `palette_init('dark')` — populates `palette`.
632-4. `font_register(...)` — fonts for HUD/text.
633-5. `effect_setup({ draw_shader = '...' })` — installs shader AND pushes
634-   the active palette to `u_palette[]`.
635-
636-Steps 3 and 5 can be reversed — `palette_init` checks if
637-`effect_write_palette` exists and calls it if so, otherwise `effect_setup`
638-picks up the current palette when it runs. Either order works.
639-
640-### Draw origin: images CENTER, rectangles/text TOP-LEFT
641-`layer_image` / `layer_texture` / `layer_circle` draw **centered** at `(x, y)`;
642-`layer_rectangle` / `layer_text` draw from the **top-left** `(x, y)`. Do NOT
643-subtract half the image size to "center" an image — it already centers, so that
644-double-offsets it up-left by half (the showcase icon bug). To center an icon in
645-a top-left box `{x, y, w, h}`: `layer_image(lyr, img, x + w/2, y + h/2, col)`.
646-See `showcase.lua`'s `icon()` helper.

Edit (E:\a327ex\ricochet-template.claude\CLAUDE.md)

The file E:\a327ex\ricochet-template\.claude\CLAUDE.md has been updated successfully. (file state is current in your context — no need to Read it back)

CLAUDE.md is thoroughly synced. Now let me verify the effect.lua top docblock still reads accurately (it predates several axes). Let me check it:

Read (E:\a327ex\ricochet-template\effect.lua)

1    --[[
2     effect.lua — three-axis visual effect system (pattern × color × dither).
3   
4     THE 30-SECOND MENTAL MODEL
5       Every draw routes through assets/draw_shader.frag. The shader takes
6       three orthogonal selectors and composes them as:
7   
8           f = pattern(world_pos, time)          -- spatial structure + animation
9           f = dither(f, pixel_pos)              -- quantize to discrete levels
10          rgb = color(base_rgb, f, palette)     -- map f → palette token(s)
11  
12      Pattern owns "what the field looks like" AND "whether it moves over
13      time." Color is a pure recipe that picks (or mixes) palette tokens
14      by f. Dither inserts the pixel-art stipple between them. The three
15      are independent — any combination is valid.
16  
17    PUBLIC API
18      effect_setup(opts)                       install draw shader, cache its
19                                               GL program ID, push the palette
20      effect_set(layer, spec)                  write effect uniforms for this
21                                               layer's subsequent draws
22      effect_clear(layer)                      pattern/color/dither → 0 (passthrough)
23      effect_draw(layer, spec, fn, ...)        scoped form
24      effect_write_palette()                   re-push u_palette to the shader
25                                               (called automatically by palette_init
26                                               and effect_setup)
27  
28      Cycle helpers (return the NEXT/PREV name in each axis's cycle):
29        effect_next_pattern(cur), effect_prev_pattern(cur)
30        effect_next_color(cur),   effect_prev_color(cur)
... [5 more lines]

The header says "three-axis" and omits shape, the wrappers, and image-as-content. Let me update it:

Edit (E:\a327ex\ricochet-template\effect.lua)

The file E:\a327ex\ricochet-template\effect.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Let me check main.lua's top docblock (it describes the old single-screen scene):

Read (E:\a327ex\ricochet-template\main.lua)

1    --[[
2     ricochet-template — visual style + three-axis effect template.
3   
4     Entry point. Owns:
5       - configuration (resolution, render mode, monitor)
6       - boot order (palette → fonts → effect/shader → ui modules)
7       - layers (game, ui), camera
8       - current effect-spec state (pattern, color, dither, color_a/b, scale)
9       - sidebar control panel + keyboard input (both mutate the same state)
10      - test-scene draw (sample shapes through the effect pipeline)
11  
12    Delegates:
13      - palette.lua     — dark/light palette tables + palette_init
14      - effect.lua      — pattern × color × dither spec API + cycle helpers
15      - rectcut.lua     — RectCut layout primitive (cut/get/add/contract/...)
16      - ui_state.lua    — frame-local hot/active/focus + ui_claim_hot
17      - ui.lua          — five Ricochet-style widgets that mutate effect state
18  
19    Goal: visually evaluate any (pattern, color, dither, color_a, color_b,
20    scale) combination by clicking sidebar controls or pressing the hotkeys.
21    Both input modes update the same caller-owned state.
22  ]]
23  

Edit (E:\a327ex\ricochet-template\main.lua)

The file E:\a327ex\ricochet-template\main.lua has been updated successfully. (file state is current in your context — no need to Read it back)

Let me syntax-check the files whose docblocks I edited:

Bash (cd E:/a327ex/ricochet-template && LUA=E:/a327ex/Anchor/reference/love-compare/to...)

OK: main.lua
OK: effect.lua

Both parse. Now a cross-project memory for the engine patch — it's a capability change to the shared Anchor 2 engine that any project (Invoker, etc.) could use, and isn't obvious from the code alone.

Write (C:\Users\adn.claude\projects\E--a327ex\memory\reference_anchor2_aux_sampler_draws.md)

File created successfully at: C:\Users\adn\.claude\projects\E--a327ex\memory\reference_anchor2_aux_sampler_draws.md (file state is current in your context — no need to Read it back)

Now add the index line to MEMORY.md:

Read (C:\Users\adn.claude\projects\E--a327ex\memory\MEMORY.md)

1    # Memory
2   
3   ## Code Style - Emoji Ball Battles (Lua)
4   
5   ### Operator spacing convention
6   - `*` and `/`: no spaces (e.g., `a*b`, `x/y`)
7   - `+` and `-`: spaces (e.g., `a + b`, `x - y`)
8   
9   Example:
10  ```lua
11  result = a*b + c/d - e
12  velocity = speed*math.cos(angle) + offset
13  ```
14  
15  ## Conversion History
16  
17  - **Emoji Ball Battles**: Converted from YueScript to Lua (2026-02-24). Archived `.yue` files in `emoji-ball-battles/reference/yue/`. Framework files copied from `Anchor/framework/anchor/`.
18  - **Invoker** (pre-reset): Converted from YueScript to Lua (2026-02-25). Archived `.yue` files now live in `Invoker-old/reference/yue/` after the 2026-05-27 reset to snkrx-template. The new Invoker has no YueScript history.
19  
20  ## Naming Conventions
21  
22  - Always capitalize "Invoker" (capital O) — it's a proper name, not a directory path reference.
23  
24  ## Critical Warnings
25  - [Invoker runs on Anchor 2](feedback_invoker_anchor_divergence.md) — use Anchor2/docs/, not Anchor/docs/ (v1); Invoker/anchor/ is the actual ground truth
26  - [Anchor 2 mouse buttons follow LÖVE2D](reference_anchor2_mouse_buttons.md) — `mouse:2` = RMB, `mouse:3` = MMB (engine swaps 2↔3 at SDL boundary as of 2026-05-17)
27  - [Anchor 2 input edge events are update-only](reference_anchor2_input_in_draw.md) — `mouse_is_pressed/released` and `key_is_pressed/released` always return false from `draw()`; run UI logic (hit-testing, state machines, layer command queueing) in `update()` and reduce `draw()` to `layer_render + layer_draw`
28  - [Anchor 2 sprites/images draw CENTERED at (x,y)](reference_anchor2_sprite_centered.md) — `layer_image`/`layer_texture`/`layer_circle` center at (x,y); `layer_rectangle`/`layer_text` are TOP-LEFT. Don't subtract half-size to "center" an image — it already centers, so that double-offsets it up-left by half. To center an icon in a top-left box {x,y,w,h}: `layer_image(lyr, img, x + w/2, y + h/2, col)`
29  
30  ## Workflow
... [10 more lines]

Edit (C:\Users\adn.claude\projects\E--a327ex\memory\MEMORY.md)

The file C:\Users\adn\.claude\projects\E--a327ex\memory\MEMORY.md has been updated successfully. (file state is current in your context — no need to Read it back)

Docs are fully synced. Summary of what I updated (docs only — no code changed, nothing to test):

ricochet-template/.claude/CLAUDE.md

Code docblockseffect.lua (now "four-axis" + wrappers + image-as-content) and main.lua (three screens, new delegates).

Memory — added a cross-project reference note (reference_anchor2_aux_sampler_draws) so any Anchor 2 project (Invoker, etc.) knows the engine can now bind a second sampler to the draw shader, plus its MEMORY.md index line.

That closes out everything this session set out to do — icons/images (shape + content), more shapes + rotation, and the API simplifications (single-call wrappers + the unified editor). The three deferred items (480×270, replacing the snkrx effect stack, flow-field rotation) are parked in the roadmap for the manual sessions you wanted to drive yourself. Ready for /end-session whenever you want to log it.

Let's end it, call it Visual Experiments 3

Skill

Launching skill: end-session

Base directory for this skill: E:\a327ex.claude\skills\end-session

End Session Workflow

This skill is invoked from the same conversation where the work was done. You already have the full session context in memory — you do NOT need to read the transcript.

Step 1: Get Session Info

Ask the user for the session title (max 30 characters). Examples: "Anchor Phase 10 Part 5", "Physics Arena Setup", "Timer System Fix", "Thalien Lune Design".

Determine the project yourself from your session context — you know which repo(s) were worked on, which files were created/modified, and where they live. No need to ask. See Step 5 for the list of known project roots; if the session touched something outside the list, infer the root from the paths you actually edited.

Step 2: Write Summary

Write the summary from your conversation memory. You have the full session context — no need to read any files.

The summary should be thorough and detailed. Each major topic deserves its own section with multiple specific bullet points. Don't compress — expand.

Purpose: These summaries serve as searchable records. Future Claude instances will grep through past logs to find how specific topics were handled. The more detail you include, the more useful the summary becomes for finding relevant context later.

Format (this is just an example structure — adapt sections to match what actually happened):

# [Title]

## Summary

[1-2 sentence overview of the session's main focus]

**[Topic 1 - e.g., "Spring Module Implementation"]:**
- First specific detail about what was done
- Second detail - include file names, function names
- User correction or feedback (quote if notable)
- Technical decisions and why

**[Topic 2 - e.g., "Camera Research"]:**
- What was researched
- Key findings
- How it influenced implementation

**[Topic 3 - e.g., "Errors and Fixes"]:**
- Specific error message encountered
- Root cause identified
- How it was fixed

[Continue for each major topic...]

---

[Rest of transcript follows]

Rules: - Be thorough — If in doubt, include more detail, not less. Each topic should be as detailed as possible while still being a summary. - Think searchability — Future instances will search these logs. Include keywords, function names, error messages that someone might grep for. - One section per major topic — Don't combine unrelated work into one section - Chronological order — Sections should match conversation flow - Specific details — Error messages, file names, function names, parameter values - Include user quotes — When user gave notable feedback, quote it (e.g., "k/d variables are not intuitive at all") - Weight planning equally — Research, proposals, alternatives considered, user feedback on approach are as important as implementation - Weight problems solved — Errors, root causes, fixes, user corrections all matter - Technical specifics — Include formulas, API signatures, parameter changes when relevant

Step 3: Proceed Without Approval

Do NOT show the summary to the user for approval. Write it directly. The user can review the committed log after the fact and request a follow-up edit if anything is off.

Step 4: Convert Transcript and Write the Log File

# Find recent sessions (Claude + Cursor + Codex). Same script lives in Anchor2:
python E:/a327ex/Anchor2/scripts/find-recent-session.py --limit 5
# or: python E:/a327ex/Anchor/scripts/find-recent-session.py --limit 5

The script shows sessions sorted by when they ended. The first result is the current conversation (since end-session was invoked here). Use it.

Use a lowercase hyphenated slug derived from the title (e.g., "anchor-primitives-hitstop-animation").

Get the end timestamp for the Date frontmatter — this is the wall-clock time when end-session was invoked, NOT the time the JSONL started. Sessions often span multiple days, and the log should be filed under the day the work was wrapped up:

date "+%Y-%m-%d %H:%M:%S"

Use this output verbatim. Do not substitute the JSONL start timestamp; the log appears in the sidebar sorted by Date, and a multi-day session with a Date pinned to day 1 will sort below sessions that ended later but started later, hiding the most recent work.

Convert the transcript to markdown:

python E:/a327ex/Anchor2/scripts/jsonl-to-markdown.py [SESSION_PATH] /tmp/session-log.md
# or: python E:/a327ex/Anchor/scripts/jsonl-to-markdown.py ...

The same script auto-detects Claude Code JSONL vs Cursor/Composer agent JSONL (~/.cursor/projects/.../agent-transcripts/...) vs Codex rollouts (~/.codex/sessions/...). For Composer sessions, use find-recent-session.py (it merges all sources) and pick the [cursor] line for the current chat.

Replace the default header (# Session YYYY-MM-DD...) at the top of /tmp/session-log.md with the approved title and summary, AND prepend frontmatter. The final file shape:

Title: [Title]
Date: YYYY-MM-DD HH:MM:SS

# [Title]

## Summary

[approved summary text from step 2]

---

[transcript content from jsonl-to-markdown script]

Frontmatter is non-negotiable. Every log file MUST start with Title: and Date: lines. Without them, the site's sidebar shows the slug as the title and 0 (epoch) as the sort date. The backfill script in a327ex-site/deploy/backfill_metadata.py is a safety net, not a substitute — write it correctly the first time.

Then copy the final file to the log destination:

cp /tmp/session-log.md E:/a327ex/a327ex-site/logs/[slug].md

Step 4.5: Decrement the lock (if active)

Read E:/a327ex/a327ex-site/.lock.json if it exists. If it contains {"remaining": N} with N > 0:

  • Decrement N by 1
  • Write {"remaining": N-1} back to the file
  • If N becomes 0, the lock is cleared. You may leave the file at {"remaining": 0} or delete it; both work.

The lock file lives in the a327ex-site repo, so the change is staged automatically by git add -A in Step 6.

If no lock file exists or remaining is already 0, do nothing. (See the /lock skill for the lock's full design.)

Step 5: Commit Project Repo

Identify the project repo(s) worked on this session from your own context — you already know which repos were touched and which files changed. For the common projects:

Project Root Stage command
Anchor E:/a327ex/Anchor git add docs/ framework/ engine/ scripts/ reference/
Anchor2 E:/a327ex/Anchor2 git add framework/ engine/ arena/ reference/ scripts/ docs/ .claude/
emoji-ball-battles E:/a327ex/emoji-ball-battles git add -A
invoker E:/a327ex/Invoker git add -A
thalien-lune E:/a327ex/thalien-lune git add -A
a327ex-site E:/a327ex/a327ex-site git add -A (this IS one of the web repos — the log file added in Step 4 is staged here automatically)

For a project not listed, infer the root from the files you actually created or modified this session and stage those. If multiple candidate roots look valid, ask the user which files to stage.

cd into the project root, stage, run git status to verify before committing.

IMPORTANT — FULL SUMMARY IN COMMIT: The commit message MUST include the FULL summary from the log file. Read the summary back from the log file to ensure nothing is missing.

IMPORTANT — COMMIT METHOD: The summary contains backticks, special characters, and markdown that WILL break heredocs and git commit -m. ALWAYS use the file-based method below. NEVER try a heredoc first — it will fail and produce a malformed commit that needs amending.

# Skip until we hit the line "## Summary", then take everything after the next
# blank line until the --- separator that precedes the transcript.
awk '/^## Summary$/{found=1; next} found && NR>1 && /^---$/{exit} found' \
    E:/a327ex/a327ex-site/logs/[slug].md > /tmp/commit_msg.txt

# Prepend the title (plain text, no #) and append attribution
sed -i "1i [Title]\n" /tmp/commit_msg.txt
printf "\nGenerated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n" >> /tmp/commit_msg.txt

git commit -F /tmp/commit_msg.txt

Step 6: Push the Repos

Two pushes — project (to GitHub) and a327ex-site (to the VPS):

# Project repo to GitHub. Skip this push if the project IS a327ex-site
# (handled by the second push below — don't duplicate).
git push origin main

# a327ex-site to the VPS (post-receive hook restarts the Lua server).
cd E:/a327ex/a327ex-site
git add -A
git commit -m "[Title]"
git push prod main 2>&1 | tail -3

Failure handling: if either push fails, the other still happens. Local commits stay intact, so the user can re-push manually once they've fixed whatever blocked it. Don't roll back; the committed state on disk is the source of truth.

Step 7: Confirm

Tell the user: - Project commit hash + GitHub push result - a327ex-site commit hash + VPS push result

Format:

Logged — "[Title]".
  project (Anchor2):  abc1234  pushed to GitHub
  a327ex-site:        ghi9012  pushed to a327ex.com (post-receive deployed)

If a push failed, surface that explicitly with the error.

Notes

  • Frontmatter is non-negotiable. Every log file MUST have Title: and Date: at the top. Enforced at write time in step 4. The backfill script is a safety net, not a substitute.
  • If the project IS a327ex-site (e.g., you spent the session writing the renderer or fixing the theme), there's no separate "project repo to GitHub" push — the a327ex-site push at the end IS the project push. Don't duplicate.
  • Legacy note: this skill used to also dual-write to anchor.blot.im/logs/ and anchor.blot.im/context/. Post-cutover (May 2026), anchor.blot.im is a JS redirect to a327ex.com and no longer receives content. Drop those steps if you find any older docs that still reference them.

ARGUMENTS: Visual Experiments 3

I have the full session context. Let me run the mechanical steps — find the session, get the timestamp, and check which repos were touched.

Bash (python E:/a327ex/Anchor2/scripts/find-recent-session.py --limit 5 2>&1; echo "==...)

2026-05-30T20:25:57.330Z 919f238e-264d-437b-8ab7-fc807e5302b7 [claude] <-- MOST RECENT
   C:\Users\adn\.claude\projects\E--a327ex\919f238e-264d-437b-8ab7-fc807e5302b7.jsonl

2026-05-30T20:00:42.308Z aca39077-9a40-4d7e-ac77-c4c05ac51979 [claude]
   C:\Users\adn\.claude\projects\E--a327ex\aca39077-9a40-4d7e-ac77-c4c05ac51979.jsonl

2026-05-30T18:17:12.676Z 06f5cfc2-4245-4927-9a2d-d7f372358eff [claude]
   C:\Users\adn\.claude\projects\E--a327ex\06f5cfc2-4245-4927-9a2d-d7f372358eff.jsonl

2026-05-30T00:45:02.609Z 8794b075-651a-4460-a6f1-0b750c98fa26 [claude]
   C:\Users\adn\.claude\projects\E--a327ex\8794b075-651a-4460-a6f1-0b750c98fa26.jsonl

2026-05-30T00:41:53.417Z ced0b502-30f5-45ac-8a67-dc25bf7aae84 [claude]
   C:\Users\adn\.claude\projects\E--a327ex\ced0b502-30f5-45ac-8a67-dc25bf7aae84.jsonl

=== end timestamp ===
2026-05-30 17:26:34

Bash (echo "=== ricochet-template git? ==="; cd E:/a327ex/ricochet-template 2>/dev/nul...)

=== ricochet-template git? ===
=== Anchor2 git? ===
true
origin  git@github.com:a327ex/Anchor2.git (fetch)
origin  git@github.com:a327ex/Anchor2.git (push)

Let me check the ricochet-template repo status definitively (the check returned nothing):

Bash (cd E:/a327ex/ricochet-template; echo "is-work-tree: $(git rev-parse --is-inside-...)

is-work-tree: fatal: not a git repository (or any of the parent directories): .git
git-dir: fatal: not a git repository (or any of the parent directories): .git
remote:
fatal: not a git repository (or any of the parent directories): .git
=== top of status ===
fatal: not a git repository (or any of the parent directories): .git

ricochet-template isn't a git repo (the work lives on disk + in the log, like the prior Visual Experiments sessions). The committable code change is the Anchor2 engine patch, plus the log to a327ex-site. Let me convert the transcript and check Anchor2's status.