@genex-ai/cli-demo 1.31.2 → 1.32.0-dev.650

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +18 -0
  2. package/dist/blender-mcp-Q6PSFYSE.js +241 -0
  3. package/dist/blender-serve-BF4FZ55Z.js +244 -0
  4. package/dist/chunk-2COG4P3T.js +968 -0
  5. package/dist/chunk-HYCSNWYX.js +126 -0
  6. package/dist/index.js +4759 -2830
  7. package/package.json +3 -3
  8. package/templates/blender-service/demo/castle.py +117 -0
  9. package/templates/blender-service/gpu_witness.py +245 -0
  10. package/templates/blender-service/ops.py +225 -0
  11. package/templates/blender-service/pool.py +910 -0
  12. package/templates/blender-service/server.py +611 -0
  13. package/templates/blender-service/supervisor.py +221 -0
  14. package/templates/blender-service/views.py +281 -0
  15. package/templates/controllers/character/follow-camera.ts +16 -1
  16. package/templates/controllers/character/meshy/meshy-loader.ts +3 -2
  17. package/templates/controllers/quality/deadline.ts +117 -0
  18. package/templates/controllers/quality/pick-asset.ts +49 -16
  19. package/templates/controllers/shared/physics-world.ts +6 -4
  20. package/templates/skills/genex-ai-character/SKILL.md +77 -15
  21. package/templates/skills/genex-ai-menu/SKILL.md +15 -11
  22. package/templates/skills/genex-ai-model/SKILL.md +45 -7
  23. package/templates/skills/genex-ai-texture/SKILL.md +1 -1
  24. package/templates/skills/genex-ai-video/SKILL.md +75 -17
  25. package/templates/skills/genex-blender-scene/SKILL.md +243 -0
  26. package/templates/skills/genex-game-director/SKILL.md +112 -46
  27. package/templates/skills/genex-game-director/references/design-contract.md +13 -5
  28. package/templates/skills/genex-game-director/references/routing-map.md +30 -45
  29. package/templates/skills/genex-getting-started/SKILL.md +2 -2
  30. package/templates/skills/genex-lane-card/SKILL.md +78 -0
  31. package/templates/skills/genex-monetization/SKILL.md +11 -17
  32. package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +21 -0
  33. package/templates/skills/genex-threejs-character-controller/SKILL.md +17 -5
  34. package/templates/skills/genex-threejs-creatures/SKILL.md +8 -1
  35. package/templates/skills/genex-threejs-embed-auth/SKILL.md +12 -8
  36. package/templates/skills/genex-threejs-game-ui/SKILL.md +55 -6
  37. package/templates/skills/genex-threejs-procedural-assets/SKILL.md +17 -10
  38. package/templates/skills/genex-threejs-visual-validation/SKILL.md +12 -2
  39. package/templates/skills/genex-tool-audio/SKILL.md +3 -2
  40. package/templates/skills/genex-tool-character/SKILL.md +36 -5
  41. package/templates/skills/genex-tool-image/SKILL.md +4 -2
  42. package/templates/skills/genex-tool-model/SKILL.md +32 -6
  43. package/templates/skills/genex-tool-publish/SKILL.md +100 -0
  44. package/templates/skills/genex-tool-texture/SKILL.md +1 -1
  45. package/templates/skills/genex-tool-video/SKILL.md +28 -5
  46. package/templates/skills/genex-tool-workflow/SKILL.md +4 -1
  47. package/templates/skills/genex-updates/SKILL.md +1 -1
@@ -161,7 +161,7 @@ downloads the game too, binary assets and all:
161
161
 
162
162
  ```bash
163
163
  mkdir my-game && cd my-game
164
- npx @genex-ai/cli-demo@latest link <slug> # slug = the name in the play URL
164
+ npx @genex-ai/cli-demo@dev link <slug> # slug = the name in the play URL
165
165
  npm install
166
166
  ```
167
167
 
@@ -225,7 +225,7 @@ Safe to run any time — genex-owned skills are refreshed to the latest version,
225
225
  and your own files are never touched:
226
226
 
227
227
  ```bash
228
- npx @genex-ai/cli-demo@latest init
228
+ npx @genex-ai/cli-demo@dev init
229
229
  ```
230
230
 
231
231
  Use `--force` only if you intentionally want your own existing files overwritten
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: genex-lane-card
3
+ description: The asset belt on one page — the command, what comes back, how to place it so it is not a speck or a wall, and what to do when a lane is dead. Read this before your first `npx genex model` or `npx genex character`. The full lanes are `$genex-ai-model` and `$genex-ai-character`; this card is what you need to not get it wrong.
4
+ ---
5
+
6
+ # Genex · Lane card
7
+
8
+ ## Object → mesh
9
+
10
+ ```bash
11
+ npx genex model "weathered oak barrel, iron bands, damp staves" --no-wait
12
+ npx genex wait --all # prints every id this project enqueued, with its URL
13
+ ```
14
+
15
+ A specific prompt beats a noun: "barrel" gives you a barrel-shaped guess, the
16
+ line above gives you the one in your scene. The URL is permanent — paste it into
17
+ the loader, never download it into the repo.
18
+
19
+ ## Player body → character
20
+
21
+ ```bash
22
+ npx genex character "stylized desert courier, layered dust-worn cloth"
23
+ npx genex character preview <concept-id> --candidate 1 --user-approved
24
+ npx genex character finalize <preview-id> --user-approved --approve-remesh 10000
25
+ npx genex controller character --character <id> # the whole integration
26
+ ```
27
+
28
+ Look at the three concepts, pick the strongest yourself, say which and why, and
29
+ keep going. Never foreground-`wait` on a character stage — they take minutes.
30
+
31
+ ## Place it — a GLB arrives at any scale, with any origin
32
+
33
+ ```ts
34
+ const o = gltf.scene;
35
+ const box = new THREE.Box3().setFromObject(o);
36
+ const size = new THREE.Vector3();
37
+ box.getSize(size);
38
+ o.scale.multiplyScalar(TARGET_HEIGHT_M / size.y); // the metres you want
39
+ box.setFromObject(o); // re-measure, then ground it
40
+ o.position.y -= box.min.y;
41
+ scene.add(o);
42
+ ```
43
+
44
+ Skip this and the mesh is a speck or a wall — it is the single most common way a
45
+ generated asset ships broken. Rigged bodies mismeasure here; those go through
46
+ the controller's own boot path, not this snippet.
47
+
48
+ ## Generate in batches you can finish
49
+
50
+ The belt has a **shipping ratchet**: generations that have not been shown to the
51
+ player are counted, and the count resets to zero every time you `npx genex
52
+ preview`. Hit it and the command refuses with the number and the fix.
53
+
54
+ It is not a spend limit and there is no total — preview between batches and
55
+ generate as much as the game needs. What it stops is one thing: fanning out a
56
+ whole cast or a shelf of props before the player has seen any of it. If you are
57
+ refused, you are not out of anything. You have work that nobody has looked at.
58
+
59
+ ```bash
60
+ npx genex model "..." --no-wait # a batch you can finish
61
+ npx genex wait --all # collect it
62
+ # wire it, then:
63
+ npx genex preview # free, seconds — and the count is zero again
64
+ ```
65
+
66
+ ## The one rule
67
+
68
+ An asset is not done when the command exits. It is done when something in
69
+ `src/` loads it, you have run the game, and you have LOOKED at it. A generation
70
+ nobody wired is money spent on nothing — `npx genex wait --all` marks a row
71
+ `wired` only once its URL appears in your source.
72
+
73
+ ## When a lane is dead
74
+
75
+ A lane whose provider wallet is empty fails every call and refunds every one.
76
+ `npx genex doctor` prints each lane live/mock/paused with its credit state. If a
77
+ lane is red: **build that thing in code and move on** — do not re-run it, and do
78
+ not stall the game waiting for it. Say in chat what you fell back to.
@@ -323,14 +323,12 @@ generateButton.addEventListener('click', async () => {
323
323
 
324
324
  Call `generate()` before any await in the click handler. The SDK opens Genex's
325
325
  trusted modal or popup, showing the game, frozen request, fixed attempt price and
326
- USD equivalent. `estimateCoins` is required (integer 1..1,000,000 for API-backed selections); the player
326
+ USD equivalent. `estimateCoins` is required (integer 0..1,000,000); the player
327
327
  approves this fixed amount and the game cannot confirm. New `declared-v1`
328
328
  quotes charge the full price once model work starts, even if usage costs less,
329
329
  generation fails, is canceled, or reaches its budget limit before a usable result.
330
- Fixed 5 charges 5 even if actual usage would bill 2. No model work means zero; an
331
- unsuccessful attempt with verified zero model cost is also uncharged.
332
- Every Genex API model requires a positive price, including Gemini and GLM;
333
- personal funding in the Genex modal remains zero coin. Unknown
330
+ Fixed 5 charges 5 even if actual usage would bill 2. No model work means zero;
331
+ zero is accepted only for server-authorized free or personal options. Unknown
334
332
  provider expense keeps billing pending and its hold intact. The provider budget
335
333
  fits inside these coins after the frozen platform tariff. This
336
334
  compute price is independent of the shop's item grid and pays no developer share.
@@ -418,19 +416,15 @@ Previously issued `consumed-v1` quotes keep their actual-usage billing and
418
416
  untagged quotes keep original success/refund terms. Never substitute a current
419
417
  catalog policy for a saved quote. `resumeWorkflow(generationId)` reopens a
420
418
  saved approval from a click using GET only, with no new price or operation.
421
- Already-approved zero-price API requests retain their terms. An old unconfirmed
422
- zero-price API quote needs a fresh price review before coin approval; never
423
- silently reprice it or launch paid work during recovery.
424
419
  The trusted UI sends the exact policy acknowledgement. Backend validation and
425
420
  staging remain required before delivery; the browser cannot submit costs or
426
421
  settle a bill.
427
422
 
428
- The public workflow catalog contains paid API/model rows, including
429
- `google/gemini-3.8-flash` and `z-ai/glm-5.3-flash`. Airena sponsors those models
430
- through its own direct OpenRouter path, outside the Genex runtime API.
431
- Personal Claude/ChatGPT funding in the Genex modal costs **0 coins**, but is
432
- not an in-game model option. Do not infer a free API tariff from a low price or a
433
- client flag. Personal choices use the player's own account
423
+ The public workflow catalog contains API/model rows, including the designated
424
+ `google/gemini-3.8-flash` and `z-ai/glm-5.3-flash` offerings at **0 coins**.
425
+ Personal Claude/ChatGPT funding in the Genex modal also costs **0 coins**, but is
426
+ not an in-game model option. Do not infer free status from a low price or a client
427
+ flag. Personal choices use the player's own account
434
428
  through the provider-specific connector shown by Genex: `/player/mcp` for Claude,
435
429
  `/player/chatgpt/mcp` for ChatGPT. Account/plan limits apply; ChatGPT connector
436
430
  availability also depends on workspace policy. Genex gives the stage-by-stage
@@ -445,7 +439,7 @@ Persist the exact input, offering, idempotency key and generation ID through
445
439
  sign-in, cancellation and reload; never store the embed token. Recovery reads
446
440
  existing state and never auto-charges. A changed input or expired quote requires
447
441
  a new intentional request. The Genex workflow API requires signed-in production
448
- play even for personal funding. Keep Airena's separately sponsored direct guest
442
+ play even for zero-coin offerings. Keep a game's separately sponsored free guest
449
443
  path separate; do not weaken Genex's paid or session checks.
450
444
 
451
445
  ### Calibrate before choosing the public fixed price
@@ -456,8 +450,8 @@ maxCoins, request: { modelId, prompt, outputFormat, schema?, idempotencyKey? } }
456
450
  The full creator credential spends only your own wallet; never put it in a game,
457
451
  Vite environment or logs. No play token is needed. The browser export is blocked.
458
452
  Development bills actual usage under `consumed-v1`, including failed work,
459
- within your explicit maximum. A maximum 5 may charge 2. Every API model is
460
- developer-paid at the normal tariff in this lane; personal-only
453
+ within your explicit maximum. A maximum 5 may charge 2. Public-sponsored API
454
+ models are developer-paid at the normal tariff in this lane; personal-only
461
455
  options are rejected. Inspect the authoritative charged coins/USD and `usage`
462
456
  cost/unknown-exposure receipt before choosing the public fixed `estimateCoins`.
463
457
 
@@ -217,6 +217,27 @@ the same ladder through
217
217
  KTX2-capable games can also pass `ktx2Load` to `loadTextureWithFallback` so
218
218
  textures use their `.ktx2` variants.
219
219
 
220
+ **A texture that arrived through a `.ktx2` rung is NOT drawable.** Its `.image`
221
+ is `{ width, height, mipmaps }`, never an `HTMLImageElement` — so
222
+ `ctx.drawImage(tex.image, …)` throws *"The provided value is not of type
223
+ '(CSSImageValue or HTMLCanvasElement or …)'"*. MEASURED 2026-09-07: a village
224
+ build wrote its own `capTextures()` pass to cap every texture's long edge and
225
+ cast `tex.image as CanvasImageSource` to silence the type error. All ten of its
226
+ generated buildings and both villager bodies then failed to load behind a
227
+ swallowed warning — a fully generated, fully wired world that rendered EMPTY,
228
+ and scored 1/9 with the assets sitting in R2. **Do not hand-roll a texture
229
+ downscaler: the rungs ARE the downscaler**, and `@1024` already did it before
230
+ the bytes left our side. If you must touch pixels, skip the compressed ones
231
+ first — `if ((tex as THREE.CompressedTexture).isCompressedTexture) return;`.
232
+
233
+ Every generated GLB ladders — `genex model` including its `segment` / `rig` /
234
+ `animate` outputs, and generated characters. If `pickModel` hands a generated
235
+ model URL back unchanged, this game's vendored kit predates that role: the
236
+ quality kit is copied into the game ONCE and is yours from then on, so it
237
+ never updates itself. Re-vendor it with `npx genex controller quality --force`
238
+ (that overwrites the kit files — keep your own edits, if any, before running
239
+ it), and the ladder starts resolving for those models.
240
+
220
241
  ## Quality picker in settings
221
242
 
222
243
  The pause/settings screen (see `$genex-threejs-game-ui`) always carries a
@@ -85,7 +85,8 @@ npx genex controller character --character <character-id>
85
85
 
86
86
  Meshy Image-to-3D first produces an unremeshed high-detail model. Show its
87
87
  front, back, left, and right views and report its measured face count. Preserve
88
- that model in R2. The 10,000-face triangle remesh—not the high-detail
88
+ that model in R2. The triangle remesh at the approved face budget (10,000
89
+ by default; up to 100,000 for a hero)—not the high-detail
89
90
  source—is rigged and animated. In the default lane proceed to it directly;
90
91
  for a player-requested custom character, ask for their explicit approval
91
92
  first (question tool when you have one; a short numbered list in chat
@@ -135,6 +136,9 @@ fork as a migration strategy. Install a fresh copy elsewhere and port only the n
135
136
  ## Minimal wiring
136
137
 
137
138
  ```ts
139
+ import { initEmbed, waitForPlayer } from "@genex-ai/embed-sdk";
140
+ import { GENEX } from "./genex.config";
141
+ import * as THREE from "three";
138
142
  import { PhysicsWorld } from "./controllers/shared/physics-world.ts";
139
143
  import { CharacterController } from "./controllers/character/character-controller.ts";
140
144
  import { CharacterAnimations } from "./controllers/character/character-animations.ts";
@@ -145,7 +149,15 @@ import { createAimCue } from "./controllers/character/aim-cue.ts";
145
149
  import { KeyboardInput } from "./controllers/character/keyboard-input.ts";
146
150
  import { loadPlayerCharacter } from "./controllers/character/player-character.ts";
147
151
  import { capsuleFromModel } from "./controllers/character/vrm/capsule-fit.ts";
148
- import { waitForPlayer } from "@genex-ai/embed-sdk";
152
+
153
+ initEmbed({ slug: GENEX.slug, apiUrl: GENEX.apiUrl, dashboardOrigins: GENEX.dashboardOrigins }); // FIRST — before any await
154
+
155
+ // draw first; identity takes seconds on a hosted page
156
+ const renderer = new THREE.WebGLRenderer({ antialias: tier.antialias, ...depthRendererOptions() }); // tier + depthRendererOptions: the quality kit
157
+ const scene = new THREE.Scene();
158
+ const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, near, far);
159
+ document.body.appendChild(renderer.domElement);
160
+ renderer.render(scene, camera); // a frame is on screen before anything below is awaited
149
161
 
150
162
  const physics = await PhysicsWorld.create(); // nothing RAPIER-related may run before this resolves
151
163
 
@@ -154,13 +166,13 @@ const physics = await PhysicsWorld.create(); // nothing RAPIER-related may run b
154
166
  // (with that character's exact-rig clips and locomotion profile), and falls
155
167
  // back to the visiting player's own profile avatar when it isn't — retargeting
156
168
  // the bundled core library plus any packs installed by `genex controller
157
- // anims`. `user.avatarUrl` comes from the embed identity
158
- // ($genex-threejs-embed-auth boots before this) and is used only in that
169
+ // anims`. `user.avatarUrl` comes from the embed identity (the `initEmbed`
170
+ // call above — $genex-threejs-embed-auth owns it) and is used only in that
159
171
  // fallback lane; the baked `./assets/avatar.vrm` covers local dev and load
160
172
  // failures. WRITE THIS ONCE: when the generated character lands mid-build,
161
173
  // `genex controller character --character <id>` drops the manifest in and the
162
174
  // next reload swaps the body. Nothing below changes.
163
- const { user } = await waitForPlayer(); // from "@genex-ai/embed-sdk"
175
+ const { user } = await waitForPlayer(); // identity, awaited HERE — where the avatar is needed, never as the first line of the boot
164
176
  const player = await loadPlayerCharacter({ avatarUrl: user.avatarUrl });
165
177
 
166
178
  const fit = capsuleFromModel(player.scene); // collider fits THIS body's bounds
@@ -29,6 +29,10 @@ the rig). Route by silhouette:
29
29
  locomotion clips for exactly the shapes Meshy refuses — see
30
30
  `$genex-ai-model` for the full flow, presets, and honest limits (avian rigs
31
31
  have no preset clips; drive those bones in code).
32
+ - **A mesh the player already has** (their own creature file): `npx genex
33
+ model import <file.glb>` first — free — then the same routing by
34
+ silhouette: biped → `npx genex character import` (Uthana auto-rig),
35
+ anything else → `npx genex model rig`. Never rebuild what they handed you.
32
36
  - **Everything outside both** (swarms, blobs, amorphous things — no body plan
33
37
  to rig): the **static + procedural lane** — `npx genex model` for the body,
34
38
  motion authored in code. Say it honestly in the Assets table:
@@ -53,7 +57,10 @@ npx genex creature "hulking bone seraph, tattered wing membranes, upright stance
53
57
  ```
54
58
 
55
59
  Each creature is one Assets-table row (visible spend — the usual budget
56
- rules). The result is a rigged GLB whose clips play on a standard
60
+ rules). It runs Meshy 7 like the player body; the knobs are yours: a crowd
61
+ enemy is `--polycount 10000 --no-ultra --texture 2k`, a boss seen in close-up
62
+ `--polycount 30000` (`--texture 8k` if the camera lingers), `--pose t-pose`
63
+ when a rig keeps failing structural QA in a-pose. The result is a rigged GLB whose clips play on a standard
57
64
  `THREE.AnimationMixer`; Meshy limb rotations play unchanged — never apply
58
65
  post-mixer limb corrections. Prompt the body UPRIGHT and unpropped (held
59
66
  props fuse into bodies); prompt "facing the viewer" but never trust it —
@@ -54,6 +54,14 @@ initEmbed({
54
54
  });
55
55
  ```
56
56
 
57
+ **Create the renderer and draw a frame BEFORE you await identity; `await
58
+ waitForPlayer()` only where you need the name or the token.** On a hosted page
59
+ identity takes seconds (the dashboard handshake, or the standalone bounce), so
60
+ a `main.ts` whose first statement is `const { user } = await waitForPlayer()`
61
+ shows black for all of them — and forever when `initEmbed()` was never called,
62
+ because nothing else resolves that promise. Renderer, scene, camera, first
63
+ frame, then the await, down where the name or the avatar is actually used.
64
+
57
65
  Also give `<body>` a dark background in `index.html` (e.g.
58
66
  `<body style="margin:0;background:#080a14">`) — it makes the pre-boot frame
59
67
  (before any JS runs) match the SDK's own loading overlay instead of flashing
@@ -159,10 +167,8 @@ Runtime generation (SDK 0.21.0+, signed-in production play, default-off service)
159
167
  - Required `estimateCoins` is the fixed price of a started attempt, despite its
160
168
  name: fixed 5 charges 5 even if usage would cost 2. New `declared-v1` quotes
161
169
  charge that full price on failure, cancellation or a budget limit after work
162
- starts. No model work is zero; an unsuccessful attempt with verified zero model
163
- cost is also uncharged. A usable result is not guaranteed. Every API
164
- model requires a positive price, including Gemini and GLM. Personal funding
165
- selected in the trusted Genex modal remains zero coin.
170
+ starts. No model work is zero; a usable result is not guaranteed. Zero is
171
+ accepted only when the server allows a free or personal-only option.
166
172
  - `getGeneration(id)` reads the private player/game-scoped receipt;
167
173
  `waitForGeneration(id)` waits for execution. A timeout does not cancel.
168
174
  Keep reading while billing is pending; unknown expense retains the hold and
@@ -173,7 +179,7 @@ Registered workflows require an existing trusted, operator-registered executor:
173
179
  - `getWorkflowOfferings(workflowId)` supplies model, bundle, availability,
174
180
  suggested prices and frozen operator tariff. Calibrate the game's fixed price
175
181
  with development benchmarks, then show coin and USD beside the selected option.
176
- Its public offerings contain paid API/model rows;
182
+ Its public offerings contain API/model rows, including sponsored free models;
177
183
  personal plan funding appears only in the trusted Genex approval modal.
178
184
  - `requestWorkflow({ workflowId, offeringId, input, estimateCoins, allowExternal?,
179
185
  idempotencyKey?, timeoutMs? })` returns **approval**, not completion. Call from
@@ -183,8 +189,6 @@ Registered workflows require an existing trusted, operator-registered executor:
183
189
  reloads. Never persist the token or auto-charge on boot. Use
184
190
  `resumeWorkflow(generationId)` from a click to reopen saved approval through
185
191
  GET only, preserving pre-0.21 quotes without a replacement price.
186
- Already-approved zero-price API requests retain their terms; an old unconfirmed
187
- zero-price API quote needs a fresh price review before coin approval.
188
192
  - The server derives the hard model budget from the fixed price after its tariff.
189
193
  Only the selected model runs. The trusted executor validates staged artifacts;
190
194
  the browser cannot submit costs, settle a bill or claim delivery.
@@ -203,7 +207,7 @@ For calibration, server-only `@genex-ai/embed-sdk/development` uses your full
203
207
  creator bearer credential, owned project and explicit `maxCoins` to benchmark
204
208
  actual usage against your own wallet, with no production-play token. It uses
205
209
  `consumed-v1`, including failed work, and returns charged coins, output and
206
- actual/unknown provider cost. All API models are paid at the normal
210
+ actual/unknown provider cost. Public-sponsored API models are paid at the normal
207
211
  tariff here; personal-only options are refused. Never bundle a creator credential
208
212
  or expose it through Vite variables. Read `$genex-monetization` for generic and
209
213
  registered-workflow examples. Native WebViews and local-test player identity
@@ -134,14 +134,55 @@ overlay — HTML/CSS on top of the canvas, not text sprites inside the scene:
134
134
 
135
135
  ```css
136
136
  #ui { position: fixed; inset: 0; pointer-events: none; font-variant-numeric: tabular-nums; }
137
- #ui button, #ui .screen { pointer-events: auto; }
137
+ /* Layout belongs to the SHOWN screen only. Never `#ui .screen { display: }`:
138
+ that overrides the browser's `[hidden] { display: none }`, and every hidden
139
+ screen is laid out full-viewport, invisible, on top of the one that is up. */
140
+ #ui .screen:not([hidden]) { display: flex; }
141
+ /* Clickable only while shown (`.is-on` is the shown class — Motion, below). */
142
+ #ui .screen.is-on, #ui #hud button { pointer-events: auto; }
138
143
  ```
139
144
 
140
145
  `pointer-events: none` on the root keeps the canvas playable; re-enable it only
141
- on elements that are actually clickable. Keep ALL layout in CSS never
142
- position UI by mutating inline pixel styles per frame. In-world (diegetic) UI —
143
- a health bar floating over an enemy, a scoreboard mesh in a stadium — is the
144
- exception for things that belong to the world, not the default.
146
+ on elements that are actually clickable and only while they are on screen.
147
+ Keep ALL layout in CSS — never position UI by mutating inline pixel styles per
148
+ frame. In-world (diegetic) UI — a health bar floating over an enemy, a
149
+ scoreboard mesh in a stadium — is the exception for things that belong to the
150
+ world, not the default.
151
+
152
+ ### Inactive screens are gone, not see-through
153
+
154
+ An invisible screen that is still laid out is a click trap nobody can see: the
155
+ title's Start button renders, the pointer hovers it, and the click lands on a
156
+ transparent pause card sitting last in DOM order. Three rules:
157
+
158
+ 1. **An inactive screen is `display: none`** — via `hidden` or a class — never
159
+ merely `opacity: 0`. And NEVER set `display` on the `.screen` selector
160
+ itself: `.screen { display: flex }` beats the browser's `[hidden]` rule, so
161
+ `hidden` stops hiding anything. Put `display: flex` on
162
+ `.screen:not([hidden])` or on the shown class.
163
+ 2. **`pointer-events: auto` belongs only to the screen that is currently
164
+ shown.** An invisible screen with clickable descendants swallows every click
165
+ meant for the screen under it, so scope `pointer-events` to `.screen.is-on`
166
+ (and to HUD controls) — never to `#ui .screen` or `#ui button` at large.
167
+ 3. **The smoke check for every boot/title/pause screen:** for each visible
168
+ button, `document.elementFromPoint(cx, cy)` at its centre must return the
169
+ button or one of its descendants. A top hit whose effective (inherited)
170
+ opacity is 0 is a defect, not a styling choice — some screen is laid out
171
+ over the one the player sees. One paste in the console:
172
+
173
+ ```js
174
+ [...document.querySelectorAll("#ui button")].filter((b) => b.getClientRects().length).map((b) => {
175
+ const r = b.getBoundingClientRect(), top = document.elementFromPoint(r.x + r.width / 2, r.y + r.height / 2);
176
+ let o = 1; for (let e = top; e; e = e.parentElement) o *= +getComputedStyle(e).opacity;
177
+ const ok = !!top && b.contains(top);
178
+ return { button: b.textContent.trim(), ok, coveredBy: ok ? null : top?.closest(".screen")?.id ?? top?.tagName ?? "offscreen", topOpacity: o };
179
+ })
180
+ ```
181
+
182
+ Every row reads `ok: true`; a `coveredBy` naming a screen with
183
+ `topOpacity: 0` is rule 1 or 2 broken. Run it on the title screen and again
184
+ with the pause screen up — `$genex-threejs-visual-validation` carries the
185
+ same check in its smoke pass.
145
186
 
146
187
  ## The states every game needs
147
188
 
@@ -279,7 +320,8 @@ black reads as a broken page. The branded version costs nothing:
279
320
  ## Motion — screens move or the game feels dead
280
321
 
281
322
  Phase changes animate. `hidden` alone hard-cuts; pair it with a class so
282
- opacity can transition:
323
+ opacity can transition — the class owns opacity and `pointer-events`, `hidden`
324
+ keeps owning `display`:
283
325
 
284
326
  ```ts
285
327
  function setPhase(phase: "loading" | "playing" | "paused" | "over" | "won") {
@@ -298,6 +340,8 @@ function setPhase(phase: "loading" | "playing" | "paused" | "over" | "won") {
298
340
  ```
299
341
 
300
342
  ```css
343
+ /* Opacity only — `display` stays with `hidden` (Architecture, above). Setting
344
+ `display` here would lay every hidden screen out over the shown one. */
301
345
  #ui .screen { opacity: 0; transition: opacity 280ms ease; }
302
346
  #ui .screen.is-on { opacity: 1; }
303
347
 
@@ -431,6 +475,11 @@ widget gets its numbers.
431
475
  HUD — pick the 2–3 numbers that matter and style them by hierarchy.
432
476
  - Hard-cut phase swaps, a menu whose elements just appear, numbers that
433
477
  teleport.
478
+ - An invisible screen still laid out over the one the player sees — `display`
479
+ set on `.screen` (defeating `hidden`), or an `opacity: 0` screen that kept
480
+ `pointer-events: auto` — so the title's Start button never receives its
481
+ click; the hit-test in "Inactive screens are gone, not see-through" catches
482
+ it.
434
483
  - A silent menu; a bare "Loading…" over black.
435
484
  - Generated UI art enqueued and then left on the shelf — a landed sprite sheet
436
485
  that never got extracted, masked, and wired is worse than never running the
@@ -1,30 +1,34 @@
1
1
  ---
2
2
  name: genex-threejs-procedural-assets
3
- description: Build editable, parameterized Three.js objects in code — structures, buildings, modular kits, repeated or varied props whenever code is the more efficient engine for them, or the user asks for procedural/parametric work. A first-class lane alongside generated GLBs; mix both freely.
3
+ description: Build editable, parameterized Three.js objects in code — modular kits, structural pieces, repeated or varied props, and any object code will honestly make read as the thing it is or whenever the user asks for procedural/parametric work. A first-class lane alongside generated GLBs, held to the same bar; mix both freely.
4
4
  ---
5
5
 
6
6
  # Genex Three.js Procedural Assets
7
7
 
8
8
  Build a recognizable asset as local, editable Three.js code. This lane is a
9
- first-class engine, not a fallback: for structures, buildings, modular kits,
10
- and anything placed many times with variation, code is often more efficient
11
- than a generated GLB and mixing procedural pieces with generated hero
12
- pieces in the same scene is the normal way to build a detailed, lively world.
9
+ first-class engine, not a fallback and it is held to the same bar as a
10
+ generated GLB: the result must read as the thing it is when the player looks at
11
+ it, in the game's own style. A coloured box or a flat grey block is a blockout,
12
+ never a landed asset. Mixing procedural pieces with generated pieces in the
13
+ same scene is the normal way to build a detailed, lively world.
13
14
 
14
15
  ## Choose the route
15
16
 
16
17
  - Start directly when the user says procedural, parametric, code-built,
17
18
  customizable, seeded, or asks for controlled variations.
18
- - Also start directly when code is plainly the efficient route: buildings and
19
- structures, modular environment kits, fences, pipes, rails, and anything
20
- placed many times with variation.
19
+ - Also start directly for what is structural, repeated, distant, or
20
+ parametric: terrain, modular environment kits, fences, pipes, rails, walls,
21
+ paving, and anything placed many times with variation.
22
+ - For anything the player looks at up close, walks into, or interacts with — a
23
+ named building, a signature prop, a vehicle — code is a choice, not a
24
+ default: take it only when you will honestly reach the bar above, and confirm
25
+ it in a capture at gameplay distance before the row reads `landed`. Otherwise
26
+ `$genex-ai-model` owns it.
21
27
  - An attached or available image does not activate this skill by itself.
22
28
  - If “make this image 3D” could honestly mean either route, ask exactly one
23
29
  question: **“Do you want a generated textured GLB, or editable procedural
24
30
  Three.js code?”**
25
31
  - Use `$genex-ai-model` when the user chooses a generated textured GLB.
26
- - Use this skill for props, hard-surface objects, modular decorations, and
27
- simple structures or environment pieces.
28
32
  - Do not use it for characters, creatures, rigging, skeletal animation, or
29
33
  character likeness. Keep those in their existing specialist lanes.
30
34
 
@@ -60,6 +64,9 @@ proposed → planned → building (blockout | detail | material | runtime)
60
64
  → landed (<local TypeScript path>) → wired
61
65
  ```
62
66
 
67
+ `landed` means a capture at gameplay distance showed it reads as the thing it
68
+ is — not that the file exists.
69
+
63
70
  A Genex-generated reference keeps its separate image row and normal paid
64
71
  generation status. Note that the procedural-code row is derived from that
65
72
  image. A private user reference is not a paid generation row.
@@ -37,7 +37,8 @@ overlapping props or straps can fuse into the character or hide a limb.
37
37
 
38
38
  Meshy Image-to-3D first produces an unremeshed high-detail model. Show its
39
39
  front, back, left, and right views and report its measured face count. Preserve
40
- that model in R2. The 10,000-face triangle remesh—not the high-detail
40
+ that model in R2. The triangle remesh at the approved face budget (10,000
41
+ by default; up to 100,000 for a hero)—not the high-detail
41
42
  source—is rigged and animated. In the default lane the remesh proceeds
42
43
  directly; for a player-requested custom character, wait for their explicit
43
44
  approval first (question tool when you have one; a short numbered list in
@@ -72,7 +73,13 @@ everything twice.
72
73
  console errors). For an unpublished draft, open the dev server in local
73
74
  test mode — `http://localhost:5173/?genex_local_test=1` (the embed-auth
74
75
  skill's "Self-testing a draft" section) — so you see the game, not the
75
- sign-in gate.
76
+ sign-in gate. Then hit-test the screen that is up (title now, pause later):
77
+ for every visible button, `document.elementFromPoint(cx, cy)` at its centre
78
+ must return the button or one of its descendants — a top hit whose
79
+ effective (inherited) opacity is 0 is an invisible screen still laid out
80
+ over this one (a `display` rule on `.screen` defeating `hidden`, or an
81
+ `opacity: 0` screen keeping `pointer-events: auto`), and nobody can enter
82
+ the game. `$genex-threejs-game-ui` has the one-paste check and the fix.
76
83
  2. Press each documented control once (keys, pointer); assert a **visible
77
84
  response in its labeled direction** — this is the input-direction pass, and
78
85
  it is part of THIS check, not an extra testing loop. Hold `KeyD`/ArrowRight
@@ -359,6 +366,9 @@ visual-system work — the sequence above.
359
366
  - a non-cursor-core game that leaves the OS cursor visible during play;
360
367
  - a menu or settings click locks the pointer (or the cursor vanishes) while a
361
368
  menu screen is still up;
369
+ - a title, boot, or pause button whose centre hit-test returns an element of a
370
+ screen that is not visibly up (effective opacity 0) — an invisible overlay is
371
+ swallowing the click;
362
372
  - approval relies on a single frame;
363
373
  - post-processing cannot be disabled per pass;
364
374
  - random seeds are not reproducible;
@@ -53,8 +53,9 @@ and let the player skip.
53
53
 
54
54
  ## Cost
55
55
 
56
- Typical: **5 credits** an sfx · **40** a music track · **10** a voice line.
57
- Live prices and your balance: `npx genex doctor`.
56
+ From **2 credits** an sfx · **27** a 90 s music track · **2** a short voice line
57
+ (voice bills per character, up to 12 at the 1000-character cap; 1 credit = $0.01).
58
+ Longer `--duration`s cost more. Live prices and your balance: `npx genex doctor`.
58
59
 
59
60
  ## Waiting
60
61
 
@@ -24,13 +24,28 @@ npx genex character preview <concept-id> --candidate 2 --user-approved
24
24
  # → a 3D preview of that one, four views. Show it; wait for approval.
25
25
 
26
26
  npx genex character finalize <preview-id> --user-approved --approve-remesh 10000
27
- # → the rigged, game-ready character.
27
+ # → the rigged, game-ready character at that face budget.
28
28
  ```
29
29
 
30
30
  Each step needs the previous step's generation id. The approval flags are not
31
31
  ceremony: they record that a person actually looked and chose, and each step
32
32
  costs credits.
33
33
 
34
+ ## The knobs (Meshy 7 on every lane)
35
+
36
+ Ultra and 4k textures are the defaults; every knob is priced in the quote.
37
+ Pick per role and say so in one line:
38
+
39
+ - `--approve-remesh <faces>` (finalize) / `--polycount <faces>` (one shot):
40
+ the rigging copy's face budget, 10000-100000 — 10000 for crowds and
41
+ distance, 20000-30000 for a third-person player body, 50000+ only for a
42
+ close-up hero. Moves no cost.
43
+ - `--texture 2k|4k|8k` (preview / one shot): 8k is +5 credits, for close-ups.
44
+ - `--no-ultra` (preview / one shot): −5 credits, less surface detail — stand-ins
45
+ and crowd enemies.
46
+ - `--pose a-pose|t-pose` (one shot): the preferred rest pose.
47
+ - `--height <metres>`: 0.5-3, default 1.7.
48
+
34
49
  ## One shot
35
50
 
36
51
  When nobody is choosing — a background NPC, a quick test:
@@ -41,7 +56,21 @@ npx genex creature "hulking bone seraph, upright stance"
41
56
  ```
42
57
 
43
58
  `creature` is the same lane with enemy defaults: no approval steps, no player
44
- controller pack. Biped-shaped bodies only.
59
+ controller pack (and priced without one). Biped-shaped bodies only. The knobs
60
+ above apply: a crowd enemy is `--polycount 10000 --no-ultra --texture 2k`.
61
+
62
+ ## Import a character the user already has
63
+
64
+ ```bash
65
+ npx genex character import ./knight.glb --height 1.8 # free upload + Uthana auto-rig (finger joints; --no-fingers skips them)
66
+ npx genex character animate <id> --locomotion # then the walk/run set — an import has no clips yet
67
+ ```
68
+
69
+ Biped humanoid, T- or A-pose, feet on the ground, facing +Z, `.glb` ≤ 30 MB.
70
+ **Never rebuild a mesh the user gives you** — import it. The result is a
71
+ Uthana-rigged body: verbs, `--locomotion` and `--video` work; the Meshy
72
+ catalog and controller pack do not. Non-biped bodies: `npx genex model
73
+ import` + `npx genex model rig`.
45
74
 
46
75
  ## Animating it
47
76
 
@@ -75,9 +104,11 @@ look here first — a library clip costs nothing to generate.
75
104
 
76
105
  ## Cost
77
106
 
78
- Typical: **15** concept · **20** preview · **30** finalize · **50** one-shot
79
- character · **26 per clip** for a generated move · **free** for a library
80
- search. Live prices and your balance: `npx genex doctor`.
107
+ Typical: **32** concept · **41** preview · **29** finalize · **64** one-shot
108
+ character · **46** creature · **18** import (Uthana auto-rig; the upload is
109
+ free) · **46 per clip** for a generated move · **free** for a library search
110
+ (1 credit = $0.01). `--texture 8k` adds 6, `--no-ultra`
111
+ takes 6 off. Live prices and your balance: `npx genex doctor`.
81
112
 
82
113
  ## Waiting
83
114
 
@@ -43,8 +43,10 @@ Wire the **local path**. The URL is provenance — never fetch it at runtime.
43
43
 
44
44
  ## Cost
45
45
 
46
- Typical: **8 credits** per image (`--candidates` bills per variant). Live prices
47
- and your balance: `npx genex doctor`.
46
+ From **4 credits** per image at default quality (1 credit = $0.01);
47
+ `--transparent`, `--quality high`, `--edit` and 4K canvases cost more, and
48
+ `--candidates` bills per variant - the command prints the exact quote. Live
49
+ prices and your balance: `npx genex doctor`.
48
50
 
49
51
  ## Waiting
50
52