@genex-ai/cli-demo 1.31.2 → 1.32.0-dev.653
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.
- package/README.md +18 -0
- package/dist/blender-mcp-Q6PSFYSE.js +241 -0
- package/dist/blender-serve-BF4FZ55Z.js +244 -0
- package/dist/chunk-2COG4P3T.js +968 -0
- package/dist/chunk-HYCSNWYX.js +126 -0
- package/dist/index.js +4759 -2830
- package/package.json +3 -3
- package/templates/blender-service/demo/castle.py +117 -0
- package/templates/blender-service/gpu_witness.py +245 -0
- package/templates/blender-service/ops.py +225 -0
- package/templates/blender-service/pool.py +910 -0
- package/templates/blender-service/server.py +611 -0
- package/templates/blender-service/supervisor.py +221 -0
- package/templates/blender-service/views.py +281 -0
- package/templates/controllers/character/follow-camera.ts +16 -1
- package/templates/controllers/character/meshy/meshy-loader.ts +3 -2
- package/templates/controllers/quality/deadline.ts +117 -0
- package/templates/controllers/quality/pick-asset.ts +49 -16
- package/templates/controllers/shared/physics-world.ts +6 -4
- package/templates/skills/genex-ai-character/SKILL.md +77 -15
- package/templates/skills/genex-ai-menu/SKILL.md +15 -11
- package/templates/skills/genex-ai-model/SKILL.md +45 -7
- package/templates/skills/genex-ai-texture/SKILL.md +1 -1
- package/templates/skills/genex-ai-video/SKILL.md +75 -17
- package/templates/skills/genex-blender-scene/SKILL.md +243 -0
- package/templates/skills/genex-game-director/SKILL.md +112 -46
- package/templates/skills/genex-game-director/references/design-contract.md +13 -5
- package/templates/skills/genex-game-director/references/routing-map.md +30 -45
- package/templates/skills/genex-getting-started/SKILL.md +2 -2
- package/templates/skills/genex-lane-card/SKILL.md +78 -0
- package/templates/skills/genex-monetization/SKILL.md +11 -17
- package/templates/skills/genex-threejs-adaptive-quality/SKILL.md +21 -0
- package/templates/skills/genex-threejs-character-controller/SKILL.md +17 -5
- package/templates/skills/genex-threejs-creatures/SKILL.md +8 -1
- package/templates/skills/genex-threejs-embed-auth/SKILL.md +12 -8
- package/templates/skills/genex-threejs-game-ui/SKILL.md +55 -6
- package/templates/skills/genex-threejs-procedural-assets/SKILL.md +17 -10
- package/templates/skills/genex-threejs-visual-validation/SKILL.md +12 -2
- package/templates/skills/genex-tool-audio/SKILL.md +3 -2
- package/templates/skills/genex-tool-character/SKILL.md +36 -5
- package/templates/skills/genex-tool-image/SKILL.md +4 -2
- package/templates/skills/genex-tool-model/SKILL.md +32 -6
- package/templates/skills/genex-tool-publish/SKILL.md +100 -0
- package/templates/skills/genex-tool-texture/SKILL.md +1 -1
- package/templates/skills/genex-tool-video/SKILL.md +28 -5
- package/templates/skills/genex-tool-workflow/SKILL.md +4 -1
- 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@
|
|
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@
|
|
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
|
|
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;
|
|
331
|
-
|
|
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
|
|
429
|
-
`google/gemini-3.8-flash` and `z-ai/glm-5.3-flash
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
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(); //
|
|
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).
|
|
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;
|
|
163
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
142
|
-
position UI by mutating inline pixel styles per
|
|
143
|
-
a health bar floating over an enemy, a
|
|
144
|
-
exception for things that belong to the
|
|
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 —
|
|
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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
19
|
-
|
|
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
|
|
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
|
-
|
|
57
|
-
|
|
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: **
|
|
79
|
-
character · **
|
|
80
|
-
|
|
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
|
-
|
|
47
|
-
|
|
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
|
|