@genex-ai/cli-demo 1.8.1-dev.501 → 1.9.0-dev.502
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/dist/index.js +186 -7
- package/package.json +1 -1
- package/templates/skills/genex-ai-character/references/motion-generation.md +4 -2
- package/templates/skills/genex-ai-model/SKILL.md +87 -10
- package/templates/skills/genex-game-director/SKILL.md +5 -2
- package/templates/skills/genex-game-director/references/routing-map.md +2 -2
- package/templates/skills/genex-threejs-creatures/SKILL.md +16 -7
package/dist/index.js
CHANGED
|
@@ -992,14 +992,14 @@ var CONTRACT_END = "<!-- genex:contract:end -->";
|
|
|
992
992
|
var GENEX_CONTRACT_BLOCK = `${CONTRACT_BEGIN}
|
|
993
993
|
# Genex build contract (always in effect for this game)
|
|
994
994
|
|
|
995
|
-
Your agentic capabilities that can boost your creation (all via \`npx genex \u2026\`): generate \`model\` \xB7 \`sfx\` \xB7 \`music\` \xB7 \`voice\` \xB7 \`texture\` \xB7 \`image\` (\`--edit\` \xB7 \`--inpaint\` \xB7 \`--glass\` \xB7 \`--clean\` \xB7 \`--upscale\`) \xB7 \`video\` \xB7 rigged \`character\` / \`creature\` \xB7 \`character animate <id> "<verb>"\` (also \`creature animate\`; \`--locomotion\` for the 8-way movement set, \`--video\` for your own footage) \xB7 the pixel toolbox \`ui extract|masks|plate|text-color|trim|audit\` \xB7 vendored \`controller character|car|drone|touch|quality|chat\` \xB7 \`animations search\` \xB7 \`wait <id>\` / \`wait --all\` \xB7 \`preview\` / \`publish\` \xB7 \`rename <name>\` (move the game to a new address \u2014 keeps its plays and likes, kills the old link, needs \`--yes\` once published, and the game must be rebuilt after). Full options: \`npx genex --help\`. There is NO sky generator: every sky, horizon, time of day and weather mood is built in code \u2014 your call how, from a background colour and fog to an atmospheric sky shader with a real sun. It costs nothing, weighs nothing on phones, and keeps the sun in sync with the scene's own lighting, which a painted panorama never can. Task\u2192lane routing lives in the \`genex-game-director\` skill's routing map \u2014 re-load it whenever you're unsure which lane owns a task.
|
|
995
|
+
Your agentic capabilities that can boost your creation (all via \`npx genex \u2026\`): generate \`model\` (\`--image\` from a reference image; \`model segment <id>\` into named parts; \`model rig <id>\` + \`model animate <rig-id> --preset walk\` for non-biped bodies \u2014 7 body plans) \xB7 \`sfx\` \xB7 \`music\` \xB7 \`voice\` \xB7 \`texture\` \xB7 \`image\` (\`--edit\` \xB7 \`--inpaint\` \xB7 \`--glass\` \xB7 \`--clean\` \xB7 \`--upscale\`) \xB7 \`video\` \xB7 rigged \`character\` / \`creature\` \xB7 \`character animate <id> "<verb>"\` (also \`creature animate\`; \`--locomotion\` for the 8-way movement set, \`--video\` for your own footage) \xB7 the pixel toolbox \`ui extract|masks|plate|text-color|trim|audit\` \xB7 vendored \`controller character|car|drone|touch|quality|chat\` \xB7 \`animations search\` \xB7 \`wait <id>\` / \`wait --all\` \xB7 \`preview\` / \`publish\` \xB7 \`rename <name>\` (move the game to a new address \u2014 keeps its plays and likes, kills the old link, needs \`--yes\` once published, and the game must be rebuilt after). Full options: \`npx genex --help\`. There is NO sky generator: every sky, horizon, time of day and weather mood is built in code \u2014 your call how, from a background colour and fog to an atmospheric sky shader with a real sun. It costs nothing, weighs nothing on phones, and keeps the sun in sync with the scene's own lighting, which a painted panorama never can. Task\u2192lane routing lives in the \`genex-game-director\` skill's routing map \u2014 re-load it whenever you're unsure which lane owns a task.
|
|
996
996
|
|
|
997
997
|
Important note: put soul into your creations, with many details and love. Aim to make them realistic and feel real. Use genex capabilities as an extension, but never limit your imagination \u2014 you are a powerful agent. Use your built-in sub-agents and iteration loops (\`/loop\` or your platform's equivalent) where you need them to reach outstanding results. Verify yourself. Anything you put in front of the player should already feel alive and impressive \u2014 never a bare scene waiting for "later". Build what's still missing before polishing what already works.
|
|
998
998
|
|
|
999
999
|
1. Load the \`genex-game-director\` skill before starting the requested work. Route from the player's latest clear request: a focused request starts directly without replaying discovery or commissioning unrelated lanes. After ANY context compaction or session resume, re-read this file and \`DESIGN.md\`, re-load the skill for the stage you are executing, and continue from the Build plan's \`Now:\` line \u2014 never from memory alone.
|
|
1000
1000
|
2. Ask only when one unresolved answer materially changes the work. If the request is clear, do not repeat an interview, confirm the pitch, force a concept round, or ask whole-game-vs-one-part again. For a genuinely broad new game, ask one decision: whole coordinated build or one request-relevant part first. If there is no clear request \u2014 a setup prompt pasted with nothing of their own \u2014 ask in PLAIN CHAT what they want to make, in their own words, and never fill the blank by pitching concepts. Once you know what you are building, ask one decision at a time with your built-in question tool with clickable answer options when you have one; use a short plain-chat question otherwise. If the player stays silent after a necessary question, proceed on stated assumptions where reasonable and record each as "assumed \u2014 player didn't answer" in DESIGN.md \u2192 Decisions.
|
|
1001
1001
|
3. \`DESIGN.md\` at the project root is the durable design contract AND build plan. Keep three truths distinct: the player's requested outcome, the current \`Now:\` focus, and open commitments. It must carry a \`## Build plan & status\` section with the working mode (\`whole coordinated build\`, \`step by step\`, or \`focused change\`), numbered milestones with status marks, and a \`Now:\` line naming the current one \u2014 a milestone is done only when its work reached a preview. The latest clear request may replace \`Now:\` immediately; it never silently shrinks the requested outcome or deletes unrelated commitments. Keep every decision, assumption, generation id/URL, local output, and wiring state current. When the plan first lands, tell the player in one plain line that you recorded what they asked for in \`DESIGN.md\` and will keep it current.
|
|
1002
|
-
4. Use \`genex\` commands to generate art, audio, video, characters, and UI. A local reference image is not a reason to switch tools: pass its file path to genex (\`--edit
|
|
1002
|
+
4. Use \`genex\` commands to generate art, audio, video, characters, and UI. A local reference image is not a reason to switch tools: pass its file path to genex (\`--edit\`, \`--inpaint\`, and model's \`--image\` accept local paths). Don't limit yourself: add details, and mix generated assets with procedural generation to make scenes and games detailed and lively.
|
|
1003
1003
|
5. When shipping your game / project: building, previewing, and publishing go only through \`genex preview\` / \`genex publish\` \u2014 never load your platform's own site-building, hosting, or deploy skills for this game.
|
|
1004
1004
|
6. Generated UI art is a tool you reach for, not a pipeline you owe. A restrained interface built in clean CSS is a finished, legitimate HUD \u2014 not a placeholder. Reach for the sprite lane (\`genex-ai-hud\`) when the game's own style genuinely wants drawn chrome \u2014 ornate, painterly, comic, hand-made \u2014 or when the player asks for HUD art. Generating ONE element you decided the game needs \u2014 a frame, a mask, an icon, a wordmark, a menu backdrop, a menu video \u2014 is a normal use of these tools, never a half-run pipeline. There is NO global game-concept image and no UI plan recited in chat: the art direction lives in the game's brief in words. A lane's own concept step survives only where the player is choosing a concrete thing (a character's candidates). Whatever you do generate, run its quality steps in full \u2014 extraction, masks, wiring, \`npx genex ui audit\`.
|
|
1005
1005
|
7. Never draw a rectangular backing plate behind bars, digits, or icons \u2014 in sprites or CSS. Ornament lives on the widget's own silhouette; a truly needed shaped plate comes from \`npx genex ui plate\`.
|
|
@@ -5498,6 +5498,11 @@ async function runShop(opts) {
|
|
|
5498
5498
|
process.exitCode = 1;
|
|
5499
5499
|
return;
|
|
5500
5500
|
}
|
|
5501
|
+
if (opts.type !== void 0 && opts.type !== "consumable" && opts.type !== "durable") {
|
|
5502
|
+
log.error(`Invalid --type value for shop: ${opts.type} (consumable or durable)`);
|
|
5503
|
+
process.exitCode = 1;
|
|
5504
|
+
return;
|
|
5505
|
+
}
|
|
5501
5506
|
const meta = await readProject();
|
|
5502
5507
|
if (!meta?.id) {
|
|
5503
5508
|
log.error("This folder isn't linked to a game.");
|
|
@@ -6818,6 +6823,7 @@ function applySkyboxGuard(prompt, raw) {
|
|
|
6818
6823
|
}
|
|
6819
6824
|
function buildGenOptions(kind, opts) {
|
|
6820
6825
|
const options = { ...opts.generationOptions };
|
|
6826
|
+
if (kind === "model" && opts.imageUrl) options.imageUrl = opts.imageUrl;
|
|
6821
6827
|
if (kind === "texture" && opts.terrain) options.terrain = true;
|
|
6822
6828
|
if ((kind === "sfx" || kind === "music") && opts.duration) options.durationSeconds = opts.duration;
|
|
6823
6829
|
if (kind === "voice") {
|
|
@@ -6862,7 +6868,11 @@ function buildGenOptions(kind, opts) {
|
|
|
6862
6868
|
}
|
|
6863
6869
|
async function runGenerate(kind, opts) {
|
|
6864
6870
|
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
6865
|
-
|
|
6871
|
+
let typedPrompt = opts.prompt?.trim();
|
|
6872
|
+
if (!typedPrompt && kind === "model" && opts.imageUrl) {
|
|
6873
|
+
const ref = opts.imageUrl.startsWith("data:") ? "local image" : opts.imageUrl;
|
|
6874
|
+
typedPrompt = `from image: ${path19.basename(ref).slice(0, 120)}`;
|
|
6875
|
+
}
|
|
6866
6876
|
if (!typedPrompt) {
|
|
6867
6877
|
log.error(`Missing prompt. Usage: ${c.cyan(`genex ${kind} "<prompt>"`)}`);
|
|
6868
6878
|
process.exitCode = 1;
|
|
@@ -6931,6 +6941,15 @@ async function runGenerate(kind, opts) {
|
|
|
6931
6941
|
}
|
|
6932
6942
|
opts = { ...opts, frameUrl: inlined.dataUri };
|
|
6933
6943
|
}
|
|
6944
|
+
if (kind === "model" && opts.imageUrl && !isRemoteRef(opts.imageUrl)) {
|
|
6945
|
+
const inlined = await inlineLocalImage(opts.imageUrl, "--image");
|
|
6946
|
+
if (!inlined.ok) {
|
|
6947
|
+
log.error(inlined.error);
|
|
6948
|
+
process.exitCode = 1;
|
|
6949
|
+
return;
|
|
6950
|
+
}
|
|
6951
|
+
opts = { ...opts, imageUrl: inlined.dataUri };
|
|
6952
|
+
}
|
|
6934
6953
|
if (kind === "voice" && prompt.length > 1e3) {
|
|
6935
6954
|
log.warn(
|
|
6936
6955
|
`Voice text is ${prompt.length} chars \u2014 the server clamps at 1000 (billing follows the clamp). Split longer copy into separate lines.`
|
|
@@ -7174,6 +7193,12 @@ async function reportTerminal(kind, view, log, open = false, json = false) {
|
|
|
7174
7193
|
}
|
|
7175
7194
|
log.plain("");
|
|
7176
7195
|
if (kind === "texture" && files[0]) await reportTextureSeam(files[0].url, log);
|
|
7196
|
+
if (kind === "model_segment") {
|
|
7197
|
+
const parts = metadataOf(view).partNames;
|
|
7198
|
+
if (Array.isArray(parts) && parts.length > 0) {
|
|
7199
|
+
log.dim(` Parts: ${parts.filter((p) => typeof p === "string").join(", ")}`);
|
|
7200
|
+
}
|
|
7201
|
+
}
|
|
7177
7202
|
if (open && files[0]) {
|
|
7178
7203
|
openUrl(files[0].url);
|
|
7179
7204
|
log.plain(
|
|
@@ -7322,7 +7347,10 @@ function printHint(kind, view, files, log) {
|
|
|
7322
7347
|
character_preview: "Show all four preview views to the user and wait for explicit approval before finalizing.",
|
|
7323
7348
|
character: `Install the controller and current manifest with genex controller character --character ${view.id}.`,
|
|
7324
7349
|
character_animation: "The action is now part of the character's current manifest; refresh the local controller manifest before testing.",
|
|
7325
|
-
character_motion: `The clips are part of the character's current manifest \u2014 install them with genex controller character --character ${view.id}, then play the game and watch the motion on the real character before calling it done
|
|
7350
|
+
character_motion: `The clips are part of the character's current manifest \u2014 install them with genex controller character --character ${view.id}, then play the game and watch the motion on the real character before calling it done.`,
|
|
7351
|
+
model_segment: `One GLB with NAMED parts \u2014 load with GLTFLoader, then getObjectByName / traverse scene.children to move, detach, or swap a part. Part names print above when the provider reports them. url = "${url}"`,
|
|
7352
|
+
model_rig: `Rigged GLB (Tripo skeleton) \u2014 load with GLTFLoader; give it motion with genex model animate ${view.id} --preset walk, or drive the bones in code. url = "${url}"`,
|
|
7353
|
+
model_animation: `Animated GLB \u2014 load with GLTFLoader and play its clips via THREE.AnimationMixer (gltf.animations). url = "${url}"`
|
|
7326
7354
|
};
|
|
7327
7355
|
log.dim(` ${hint[kind]}`);
|
|
7328
7356
|
log.dim(" Reference the URL directly in your code \u2014 don't download it into the repo.");
|
|
@@ -7488,6 +7516,97 @@ function writeJson(value) {
|
|
|
7488
7516
|
`);
|
|
7489
7517
|
}
|
|
7490
7518
|
|
|
7519
|
+
// src/commands/model-sub.ts
|
|
7520
|
+
var MODEL_SUBCOMMANDS = ["segment", "rig", "animate"];
|
|
7521
|
+
var SEGMENT_GRANULARITIES = ["simple", "balanced", "detailed"];
|
|
7522
|
+
var MODEL_RIG_TYPES = [
|
|
7523
|
+
"biped",
|
|
7524
|
+
"quadruped",
|
|
7525
|
+
"hexapod",
|
|
7526
|
+
"octopod",
|
|
7527
|
+
"avian",
|
|
7528
|
+
"serpentine",
|
|
7529
|
+
"aquatic"
|
|
7530
|
+
];
|
|
7531
|
+
var MODEL_ANIMATE_PRESETS = {
|
|
7532
|
+
biped: ["idle", "walk", "run", "dive", "climb", "jump", "slash", "shoot", "hurt", "fall", "turn"],
|
|
7533
|
+
quadruped: ["walk"],
|
|
7534
|
+
hexapod: ["walk"],
|
|
7535
|
+
octopod: ["walk"],
|
|
7536
|
+
avian: [],
|
|
7537
|
+
serpentine: ["march"],
|
|
7538
|
+
aquatic: ["march"]
|
|
7539
|
+
};
|
|
7540
|
+
var ALL_PRESETS = [...new Set(Object.values(MODEL_ANIMATE_PRESETS).flat())];
|
|
7541
|
+
function requireSourceId(opts, usage) {
|
|
7542
|
+
const id = opts.sourceId?.trim();
|
|
7543
|
+
if (id) return id;
|
|
7544
|
+
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
7545
|
+
log.error(`Missing generation id. Usage: ${c.cyan(usage)}`);
|
|
7546
|
+
process.exitCode = 1;
|
|
7547
|
+
return void 0;
|
|
7548
|
+
}
|
|
7549
|
+
async function runModelSegment(opts) {
|
|
7550
|
+
const sourceId = requireSourceId(opts, "genex model segment <generation-id>");
|
|
7551
|
+
if (!sourceId) return;
|
|
7552
|
+
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
7553
|
+
if (opts.granularity && !SEGMENT_GRANULARITIES.includes(opts.granularity)) {
|
|
7554
|
+
log.error(`Invalid --granularity value: ${opts.granularity} (expected ${SEGMENT_GRANULARITIES.join("|")})`);
|
|
7555
|
+
process.exitCode = 1;
|
|
7556
|
+
return;
|
|
7557
|
+
}
|
|
7558
|
+
await runGenerate("model_segment", {
|
|
7559
|
+
...opts,
|
|
7560
|
+
prompt: `segment ${sourceId}`,
|
|
7561
|
+
generationOptions: {
|
|
7562
|
+
sourceGenerationId: sourceId,
|
|
7563
|
+
...opts.granularity ? { granularity: opts.granularity } : {}
|
|
7564
|
+
}
|
|
7565
|
+
});
|
|
7566
|
+
}
|
|
7567
|
+
async function runModelRig(opts) {
|
|
7568
|
+
const sourceId = requireSourceId(opts, "genex model rig <generation-id>");
|
|
7569
|
+
if (!sourceId) return;
|
|
7570
|
+
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
7571
|
+
if (opts.type && !MODEL_RIG_TYPES.includes(opts.type)) {
|
|
7572
|
+
log.error(`Invalid --type value: ${opts.type} (expected ${MODEL_RIG_TYPES.join("|")})`);
|
|
7573
|
+
process.exitCode = 1;
|
|
7574
|
+
return;
|
|
7575
|
+
}
|
|
7576
|
+
await runGenerate("model_rig", {
|
|
7577
|
+
...opts,
|
|
7578
|
+
prompt: `rig ${sourceId}`,
|
|
7579
|
+
generationOptions: {
|
|
7580
|
+
sourceGenerationId: sourceId,
|
|
7581
|
+
...opts.type ? { rigType: opts.type } : {}
|
|
7582
|
+
}
|
|
7583
|
+
});
|
|
7584
|
+
}
|
|
7585
|
+
async function runModelAnimate(opts) {
|
|
7586
|
+
const rigId = requireSourceId(opts, "genex model animate <rig-generation-id> --preset walk");
|
|
7587
|
+
if (!rigId) return;
|
|
7588
|
+
const log = createLogger({ quiet: opts.quiet || opts.json });
|
|
7589
|
+
const presets = opts.presets ?? [];
|
|
7590
|
+
if (presets.length === 0) {
|
|
7591
|
+
log.error(`Missing --preset. Usage: ${c.cyan("genex model animate <rig-id> --preset walk,run")}`);
|
|
7592
|
+
log.dim(` Presets by body plan \u2014 biped: ${MODEL_ANIMATE_PRESETS.biped.join(", ")}; quadruped/hexapod/octopod: walk; serpentine/aquatic: march.`);
|
|
7593
|
+
process.exitCode = 1;
|
|
7594
|
+
return;
|
|
7595
|
+
}
|
|
7596
|
+
const unknown = presets.filter((p) => !ALL_PRESETS.includes(p));
|
|
7597
|
+
if (unknown.length > 0) {
|
|
7598
|
+
log.error(`Unknown preset${unknown.length > 1 ? "s" : ""}: ${unknown.join(", ")}. Valid: ${ALL_PRESETS.join(", ")}.`);
|
|
7599
|
+
log.dim(" (Which of these apply depends on the rig's body plan \u2014 the server checks that too.)");
|
|
7600
|
+
process.exitCode = 1;
|
|
7601
|
+
return;
|
|
7602
|
+
}
|
|
7603
|
+
await runGenerate("model_animation", {
|
|
7604
|
+
...opts,
|
|
7605
|
+
prompt: `animate ${rigId}: ${presets.join(", ")}`,
|
|
7606
|
+
generationOptions: { rigGenerationId: rigId, presets }
|
|
7607
|
+
});
|
|
7608
|
+
}
|
|
7609
|
+
|
|
7491
7610
|
// src/commands/wait.ts
|
|
7492
7611
|
var TERMINAL2 = /* @__PURE__ */ new Set(["completed", "failed"]);
|
|
7493
7612
|
async function runWait(opts) {
|
|
@@ -20243,6 +20362,7 @@ async function runAssetNew(options) {
|
|
|
20243
20362
|
}
|
|
20244
20363
|
|
|
20245
20364
|
// src/index.ts
|
|
20365
|
+
var MODEL_SUB_SET = new Set(MODEL_SUBCOMMANDS);
|
|
20246
20366
|
var GEN_KINDS = /* @__PURE__ */ new Set(["model", "skybox", "sfx", "music", "voice", "texture", "image", "video"]);
|
|
20247
20367
|
var HELP = `${c.bold("genex")} \u2014 set up your project's agent workspace, authorize, and publish 3D games.
|
|
20248
20368
|
|
|
@@ -20302,6 +20422,23 @@ ${c.bold("Usage")}
|
|
|
20302
20422
|
other on the market; durable items only, off by
|
|
20303
20423
|
default, and --no-resellable turns it back off.
|
|
20304
20424
|
genex model "<prompt>" [options] Generate a 3D model (GLB); prints a public asset URL.
|
|
20425
|
+
--image <path|url> builds it FROM a reference
|
|
20426
|
+
image instead (prompt optional).
|
|
20427
|
+
genex model segment <id> Split a generated model into NAMED parts \u2014
|
|
20428
|
+
one GLB, parts addressable by name (doors,
|
|
20429
|
+
magazines, turrets, destructibles).
|
|
20430
|
+
--granularity simple|balanced|detailed.
|
|
20431
|
+
genex model rig <id> Give any generated mesh a skeleton (7 body
|
|
20432
|
+
plans: biped|quadruped|hexapod|octopod|
|
|
20433
|
+
avian|serpentine|aquatic). Auto-detects the
|
|
20434
|
+
plan; --type picks it explicitly. Unriggable
|
|
20435
|
+
meshes are refused and auto-refunded.
|
|
20436
|
+
genex model animate <rig-id> --preset walk[,run,\u2026]
|
|
20437
|
+
Retarget ready-made motion clips onto a
|
|
20438
|
+
'model rig' result (billed per clip).
|
|
20439
|
+
biped: idle|walk|run|dive|climb|jump|slash|
|
|
20440
|
+
shoot|hurt|fall|turn; quadruped/hexapod/
|
|
20441
|
+
octopod: walk; serpentine/aquatic: march.
|
|
20305
20442
|
genex sfx "<prompt>" [options] Generate a sound effect (mp3); prints a public asset URL.
|
|
20306
20443
|
genex music "<prompt>" [options] Generate an instrumental music track (mp3); prints a
|
|
20307
20444
|
public asset URL. --duration 10-300s (default 90).
|
|
@@ -20384,6 +20521,16 @@ ${c.bold("Usage")}
|
|
|
20384
20521
|
--summary --tags --out --force.
|
|
20385
20522
|
|
|
20386
20523
|
${c.bold("Options for the generators (`model` `sfx` `music` `voice` `texture` `image` `video`)")}
|
|
20524
|
+
--image <path|url> (model) build the model FROM this reference image \u2014 a
|
|
20525
|
+
local file (\u22644 MB, inlined) or a previous generation's
|
|
20526
|
+
asset URL. The prompt becomes optional.
|
|
20527
|
+
--granularity <g> (model segment) part granularity: simple | balanced |
|
|
20528
|
+
detailed (default balanced).
|
|
20529
|
+
--type <plan> (model rig) body plan: biped | quadruped | hexapod |
|
|
20530
|
+
octopod | avian | serpentine | aquatic (default:
|
|
20531
|
+
auto-detected by the free rig check).
|
|
20532
|
+
--preset <list> (model animate) comma-separated motion clips (see the
|
|
20533
|
+
per-plan lists above); each clip is billed.
|
|
20387
20534
|
--terrain (texture) seamless tiling surface for terrain/ground.
|
|
20388
20535
|
--duration <sec> (sfx, video, music) target clip length in seconds;
|
|
20389
20536
|
(character/creature animate) 3-6 s of reference video for
|
|
@@ -20558,6 +20705,10 @@ ${c.bold("Examples")}
|
|
|
20558
20705
|
genex shop remove sku_123
|
|
20559
20706
|
genex publish --no-push --title "My Game"
|
|
20560
20707
|
genex model "weathered wooden barrel with iron bands"
|
|
20708
|
+
genex model --image ./concept.png
|
|
20709
|
+
genex model segment <model-generation-id> --granularity detailed
|
|
20710
|
+
genex model rig <model-generation-id> --type quadruped
|
|
20711
|
+
genex model animate <rig-generation-id> --preset walk
|
|
20561
20712
|
genex sfx "punchy laser zap" --duration 2
|
|
20562
20713
|
genex music "brooding orchestral battle loop, seamless loop, no intro or outro" --no-wait
|
|
20563
20714
|
genex voice "You shall not pass!" --voice gruff
|
|
@@ -20631,6 +20782,10 @@ function parseArgs(argv) {
|
|
|
20631
20782
|
"--first-frame",
|
|
20632
20783
|
"--last-frame",
|
|
20633
20784
|
"--resolution",
|
|
20785
|
+
// `genex model` mesh-lane value flags (AG-908).
|
|
20786
|
+
"--image",
|
|
20787
|
+
"--granularity",
|
|
20788
|
+
"--preset",
|
|
20634
20789
|
// `genex ui` string flags (the numeric ones come from UI_NUMBER_FLAGS).
|
|
20635
20790
|
"--in",
|
|
20636
20791
|
"--out-dir",
|
|
@@ -20803,6 +20958,13 @@ function parseArgs(argv) {
|
|
|
20803
20958
|
parsed.command = arg;
|
|
20804
20959
|
} else if (parsed.options.name === void 0) {
|
|
20805
20960
|
parsed.options.name = arg;
|
|
20961
|
+
} else if (parsed.command === "model" && MODEL_SUB_SET.has(parsed.options.name ?? "")) {
|
|
20962
|
+
if (parsed.options.sourceId === void 0) {
|
|
20963
|
+
parsed.options.sourceId = arg;
|
|
20964
|
+
} else {
|
|
20965
|
+
parsed.error = `Unexpected argument: ${arg}`;
|
|
20966
|
+
return parsed;
|
|
20967
|
+
}
|
|
20806
20968
|
} else if (parsed.command === "explore") {
|
|
20807
20969
|
parsed.options.name = `${parsed.options.name} ${arg}`;
|
|
20808
20970
|
} else if (parsed.command === "controller") {
|
|
@@ -21051,8 +21213,10 @@ function applyValueFlag(options, flag, value) {
|
|
|
21051
21213
|
options.icon = value;
|
|
21052
21214
|
break;
|
|
21053
21215
|
case "--type": {
|
|
21054
|
-
if (value !== "consumable" && value !== "durable") {
|
|
21055
|
-
throw new Error(
|
|
21216
|
+
if (value !== "consumable" && value !== "durable" && !MODEL_RIG_TYPES.includes(value)) {
|
|
21217
|
+
throw new Error(
|
|
21218
|
+
`Invalid --type value: ${value} (shop: consumable|durable; model rig: ${MODEL_RIG_TYPES.join("|")})`
|
|
21219
|
+
);
|
|
21056
21220
|
}
|
|
21057
21221
|
options.type = value;
|
|
21058
21222
|
break;
|
|
@@ -21121,6 +21285,15 @@ function applyValueFlag(options, flag, value) {
|
|
|
21121
21285
|
case "--frame":
|
|
21122
21286
|
options.frameUrl = value;
|
|
21123
21287
|
break;
|
|
21288
|
+
case "--image":
|
|
21289
|
+
options.imageUrl = value;
|
|
21290
|
+
break;
|
|
21291
|
+
case "--granularity":
|
|
21292
|
+
options.granularity = value;
|
|
21293
|
+
break;
|
|
21294
|
+
case "--preset":
|
|
21295
|
+
options.presets = value.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
21296
|
+
break;
|
|
21124
21297
|
case "--video":
|
|
21125
21298
|
options.video = value;
|
|
21126
21299
|
break;
|
|
@@ -21215,6 +21388,12 @@ async function main() {
|
|
|
21215
21388
|
return;
|
|
21216
21389
|
}
|
|
21217
21390
|
if (GEN_KINDS.has(parsed.command)) {
|
|
21391
|
+
if (parsed.command === "model" && MODEL_SUB_SET.has(parsed.options.name ?? "")) {
|
|
21392
|
+
if (parsed.options.name === "segment") await runModelSegment(parsed.options);
|
|
21393
|
+
else if (parsed.options.name === "rig") await runModelRig(parsed.options);
|
|
21394
|
+
else await runModelAnimate(parsed.options);
|
|
21395
|
+
return;
|
|
21396
|
+
}
|
|
21218
21397
|
await runGenerate(parsed.command, {
|
|
21219
21398
|
...parsed.options,
|
|
21220
21399
|
prompt: parsed.options.name
|
|
@@ -21278,7 +21457,7 @@ async function main() {
|
|
|
21278
21457
|
}
|
|
21279
21458
|
if (!parsed.options.json && !parsed.options.quiet) {
|
|
21280
21459
|
log.dim(
|
|
21281
|
-
" Biped-shaped creatures only (Meshy rig limit) \u2014 for true
|
|
21460
|
+
" Biped-shaped creatures only (Meshy rig limit) \u2014 for a true quadruped/flier/serpent, generate it with `npx genex model` and rig it with `npx genex model rig` (7 body plans), or go static + the genex-threejs-creatures procedural recipes."
|
|
21282
21461
|
);
|
|
21283
21462
|
}
|
|
21284
21463
|
await runCharacter({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genex-ai/cli-demo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0-dev.502",
|
|
4
4
|
"description": "Set up your project's agent workspace (.claude/.codex/.cursor in the game folder), authorize, create a game project, generate AI assets, and publish (genex CLI).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -53,8 +53,10 @@ These will not come back usable — pick a different approach instead:
|
|
|
53
53
|
- **Anything a prop defines** — swinging on a rope, climbing a specific ladder,
|
|
54
54
|
sitting in a specific chair. The clip does not know your geometry; drive those
|
|
55
55
|
with `$genex-threejs-procedural-animation` instead.
|
|
56
|
-
- **Non-bipeds** — quadrupeds, fliers,
|
|
57
|
-
those
|
|
56
|
+
- **Non-bipeds** — quadrupeds, fliers, serpents. See `$genex-threejs-creatures`;
|
|
57
|
+
those route to the model-rig lane (`npx genex model rig` +
|
|
58
|
+
`npx genex model animate`, 7 body plans — `$genex-ai-model`). Blobs and
|
|
59
|
+
swarms stay static models plus procedural motion.
|
|
58
60
|
|
|
59
61
|
## Room to land the beats: `--duration`
|
|
60
62
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: genex-ai-model
|
|
3
|
-
description: Generate a real 3D model (GLB mesh) from a text prompt with `npx genex model`, then load it into the Three.js scene
|
|
3
|
+
description: Generate a real 3D model (GLB mesh) from a text prompt or a reference image with `npx genex model`, then load it into the Three.js scene — and, when the game needs it, split it into named parts (`model segment`), or rig and animate any mesh (`model rig` / `model animate`, 7 body plans incl. quadrupeds, birds, snakes). Use for any concrete object as an actual mesh rather than a procedurally-coded shape.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Genex AI · Model
|
|
@@ -17,13 +17,17 @@ Turn a text prompt into a real, game-ready **GLB** and drop it into the project.
|
|
|
17
17
|
scene is the normal way to build a detailed world — generated hero pieces
|
|
18
18
|
over procedural dressing.
|
|
19
19
|
|
|
20
|
-
**The output is a STATIC, unrigged mesh — no skeleton, no animation
|
|
21
|
-
A "wolf" or "guard" from this command can be posed and moved as one
|
|
22
|
-
but its limbs cannot animate
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
**The output is a STATIC, unrigged mesh by default — no skeleton, no animation
|
|
21
|
+
clips.** A "wolf" or "guard" from this command can be posed and moved as one
|
|
22
|
+
object, but its limbs cannot animate out of the box. When the game needs more,
|
|
23
|
+
this same lane goes further: `npx genex model segment <id>` splits the mesh
|
|
24
|
+
into named parts (doors, magazines, turrets), and `npx genex model rig <id>` +
|
|
25
|
+
`npx genex model animate <rig-id> --preset walk` give any mesh a real skeleton
|
|
26
|
+
and motion — including body plans Meshy refuses (quadrupeds, birds, snakes,
|
|
27
|
+
fish, multi-legged things). See the sections below. For a biped-shaped enemy,
|
|
28
|
+
`npx genex creature` (real rig + the animation library) is still the default,
|
|
29
|
+
and `$genex-threejs-creatures` owns that split. The player's own character is
|
|
30
|
+
`$genex-ai-character`.
|
|
27
31
|
|
|
28
32
|
## Run
|
|
29
33
|
|
|
@@ -44,6 +48,74 @@ download it** and **nothing is committed to your repo** — copy the URL the com
|
|
|
44
48
|
prints into your loader. The URL is permanent, so it works the same in local dev, your
|
|
45
49
|
published game, and remixes.
|
|
46
50
|
|
|
51
|
+
## From a reference image
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx genex model --image ./concept.png
|
|
55
|
+
npx genex model --image https://assets.genex.technology/generations/<id>/image-main
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`--image` builds the model FROM a picture instead of a prompt — a user's
|
|
59
|
+
reference photo, a concept the image lane generated, a screenshot. A local file
|
|
60
|
+
(png/jpg/webp, ≤4 MB) is inlined automatically; a previous generation's asset
|
|
61
|
+
URL passes through. The prompt becomes optional (it's recorded for the ledger,
|
|
62
|
+
the provider works from the image alone). A clear, single-object image on a
|
|
63
|
+
plain background converts best.
|
|
64
|
+
|
|
65
|
+
## Split into parts (`model segment`)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx genex model segment <model-generation-id> --granularity detailed
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Takes a finished model generation's id and returns ONE new GLB whose meshes are
|
|
72
|
+
**named parts** — a rifle becomes body/magazine/scope, a car becomes
|
|
73
|
+
doors/wheels/chassis. What the parts are for is your call per game: detach a
|
|
74
|
+
magazine for a reload animation, swing a door on its own pivot, blow a turret
|
|
75
|
+
off a destructible tank, recolor one part.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const gltf = await loader.loadAsync(SEGMENTED_URL);
|
|
79
|
+
const magazine = gltf.scene.getObjectByName("magazine"); // names print on completion
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`--granularity simple|balanced|detailed` sets how finely it splits (default
|
|
83
|
+
balanced). The provider owns the split and the part textures — ship its output
|
|
84
|
+
as-is; if a part comes back oddly textured, regenerate rather than patching
|
|
85
|
+
pixels. Part names print with the result when the provider reports them;
|
|
86
|
+
otherwise `traverse` the scene and read `child.name`.
|
|
87
|
+
|
|
88
|
+
## Rig and animate any mesh (`model rig` / `model animate`)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx genex model rig <model-generation-id> # body plan auto-detected (free check)
|
|
92
|
+
npx genex model rig <model-generation-id> --type quadruped
|
|
93
|
+
npx genex model animate <rig-generation-id> --preset walk
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This is the route for **non-biped bodies that must move** — the lane Meshy
|
|
97
|
+
refuses. Seven body plans: `biped`, `quadruped`, `hexapod`, `octopod`, `avian`,
|
|
98
|
+
`serpentine`, `aquatic`. A free rig-check runs first: an unriggable mesh is
|
|
99
|
+
refused and auto-refunded before anything is charged.
|
|
100
|
+
|
|
101
|
+
`model animate` retargets ready-made clips onto the rig (billed per clip).
|
|
102
|
+
Presets by plan — biped: `idle walk run dive climb jump slash shoot hurt fall
|
|
103
|
+
turn`; quadruped/hexapod/octopod: `walk`; serpentine/aquatic: `march`; avian
|
|
104
|
+
has a rig but no preset clips (drive its bones in code). Play the result like
|
|
105
|
+
any animated GLB:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const gltf = await loader.loadAsync(ANIMATED_URL);
|
|
109
|
+
const mixer = new THREE.AnimationMixer(gltf.scene);
|
|
110
|
+
mixer.clipAction(gltf.animations[0]).play(); // and mixer.update(dt) per frame
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Honest limits, so you plan around them and never oversell: **no finger bones**
|
|
114
|
+
on any plan; presets are generic locomotion/action clips, not bespoke motion;
|
|
115
|
+
and this rig is a plain Tripo skeleton — it does NOT join the character lane's
|
|
116
|
+
manifest/controller system. The player's own body and biped enemies with the
|
|
117
|
+
full animation library stay on `$genex-ai-character` / `npx genex creature`.
|
|
118
|
+
|
|
47
119
|
## Models that point somewhere must face forward
|
|
48
120
|
|
|
49
121
|
Any model with a "front" the game aims — the hero the player controls, an **NPC that
|
|
@@ -178,8 +250,13 @@ scene is a ghost: players and objects pass straight through it.
|
|
|
178
250
|
|
|
179
251
|
## Options
|
|
180
252
|
|
|
181
|
-
- `--
|
|
182
|
-
|
|
253
|
+
- `--image <path|url>` — build from a reference image (local file ≤4 MB, or a
|
|
254
|
+
generated-asset URL); the prompt becomes optional.
|
|
255
|
+
- `--granularity simple|balanced|detailed` — (`model segment`) part granularity.
|
|
256
|
+
- `--type <plan>` — (`model rig`) body plan; omit to let the free rig-check pick.
|
|
257
|
+
- `--preset walk[,run,…]` — (`model animate`) clips to retarget; billed per clip.
|
|
258
|
+
- `--no-wait` — enqueue and return immediately (won't print the URL; pick it up
|
|
259
|
+
with `npx genex wait <id>`).
|
|
183
260
|
- `--api-url <url>` — override the API base (local dev).
|
|
184
261
|
|
|
185
262
|
## Troubleshooting
|
|
@@ -104,7 +104,9 @@ modules are conditional on the request and existing project.
|
|
|
104
104
|
Use the [routing map](references/routing-map.md) for exact ownership. The main
|
|
105
105
|
Genex asset and runtime lanes are:
|
|
106
106
|
|
|
107
|
-
- `npx genex model "<prompt>"`—a
|
|
107
|
+
- `npx genex model "<prompt>"`—a generated GLB (also `--image` from a
|
|
108
|
+
reference picture, `model segment` into named parts, `model rig` +
|
|
109
|
+
`model animate` for non-biped bodies) → `$genex-ai-model`
|
|
108
110
|
- `npx genex texture "<prompt>"`—a generated surface → `$genex-ai-texture`
|
|
109
111
|
- sky, horizon, time of day, weather mood—built in code, never generated; no
|
|
110
112
|
command and no skill owns it, so pick what this game needs
|
|
@@ -125,7 +127,8 @@ Genex asset and runtime lanes are:
|
|
|
125
127
|
these → `$genex-threejs-procedural-assets`
|
|
126
128
|
|
|
127
129
|
For “make this image 3D,” ask **one** route question only when both results
|
|
128
|
-
honestly fit: a generated
|
|
130
|
+
honestly fit: a generated GLB built from the picture itself
|
|
131
|
+
(`npx genex model --image <path>`), or editable parameterized Three.js code.
|
|
129
132
|
If the request says procedural, parametric, code-built, reusable variations,
|
|
130
133
|
or names a GLB, start the corresponding route directly. An image alone never
|
|
131
134
|
auto-triggers the procedural lane. Player bodies, rigged characters/creatures,
|
|
@@ -40,7 +40,7 @@ copy demo architecture.
|
|
|
40
40
|
| the game's own generated character—the player's body wherever a human body appears—or Meshy animation coverage beyond the stock pack: reference-informed A-pose concepts, exact action IDs, same-rig adapter | `$genex-ai-character` + `$genex-threejs-character-controller` |
|
|
41
41
|
| a character/enemy needs motion the catalog lacks—a signature move, boss telegraph, death, full 8-way set, or the player's footage; free plan before spend | `$genex-ai-character` motion section + `references/motion-generation.md` |
|
|
42
42
|
| remote player bodies in multiplayer—never hand-built primitives: the game's generated character when it has one, otherwise the player's `p.avatarUrl` VRM | `$genex-threejs-multiplayer` + `$genex-threejs-character-controller` |
|
|
43
|
-
| enemies, NPCs, or creatures: rigged bipeds via `npx genex creature`; static plus procedural motion for
|
|
43
|
+
| enemies, NPCs, or creatures: rigged bipeds via `npx genex creature`; non-biped body plans (quadruped, flier, serpent, aquatic, multi-leg) via `npx genex model rig` + `model animate`; static plus procedural motion only for shapes with no body plan; collider, facing, hit reaction, death | `$genex-threejs-creatures` |
|
|
44
44
|
| cars, drones, vehicle physics, gearbox, character↔vehicle enter/exit | `$genex-threejs-vehicle-controllers` |
|
|
45
45
|
| playable on phones: joystick, virtual buttons, drag zones, genre touch recipes, rotate-device overlay | `$genex-threejs-touch-controls` |
|
|
46
46
|
| phone-survivable rendering: device tiers, DPR/shadow/post budgets, runtime governor, generated-asset rungs, Quality picker, dispose-on-swap | `$genex-threejs-adaptive-quality` |
|
|
@@ -52,7 +52,7 @@ copy demo architecture.
|
|
|
52
52
|
| stable large-world shadows, cascades, clipmaps, cached updates | `$genex-threejs-shadow-systems` |
|
|
53
53
|
| eye adaptation, tone mapping, output color, LUT grading, and proven static grain | `$genex-threejs-exposure-color-grading` |
|
|
54
54
|
| fixed-view screenshots, input direction, facing, temporal and budget evidence | `$genex-threejs-visual-validation` |
|
|
55
|
-
| a
|
|
55
|
+
| a generated GLB for a concrete prop, vehicle, building, or object — from text or a reference image (`--image`); split into named parts (`model segment`); rig + animate any mesh (`model rig` / `model animate`) | `$genex-ai-model` |
|
|
56
56
|
| generated surface or terrain texture with real-world UV scale | `$genex-ai-texture` |
|
|
57
57
|
| sky, skybox, horizon, time of day, weather mood, night or space backdrop | build it in code in the scene—there is no sky command and no owning skill, so pick the technique this game needs |
|
|
58
58
|
| poster, sign, sprite, decal, reference sheet, or other 2D art | `$genex-ai-image` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: genex-threejs-creatures
|
|
3
|
-
description: Build enemies and creatures that hold up in play — rigged Meshy bipeds via `npx genex creature` or static models with procedural motion, plus the mechanical floor every enemy owes the player regardless of rigging - a physics collider (no walking through bodies), verified facing, hit reactions, and a death moment. Load whenever the game has enemies, NPCs, or creatures.
|
|
3
|
+
description: Build enemies and creatures that hold up in play — rigged Meshy bipeds via `npx genex creature`, non-biped bodies (quadrupeds, fliers, serpents) rigged via `npx genex model rig`, or static models with procedural motion, plus the mechanical floor every enemy owes the player regardless of rigging - a physics collider (no walking through bodies), verified facing, hit reactions, and a death moment. Load whenever the game has enemies, NPCs, or creatures.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Genex Three.js · Creatures & Enemies
|
|
@@ -21,10 +21,18 @@ the rig). Route by silhouette:
|
|
|
21
21
|
- **Biped-shaped** (werewolf, orc, skeleton, gargoyle, zombie, knight — two
|
|
22
22
|
legs, two arms, upright): the **rigged lane** below. Real skeleton, real
|
|
23
23
|
library animations. This is the DEFAULT for every enemy that fits it.
|
|
24
|
-
- **
|
|
25
|
-
|
|
24
|
+
- **Non-biped body plans** (true quadrupeds, fliers, serpents, fish,
|
|
25
|
+
multi-legged things): the **model-rig route** — generate the body with
|
|
26
|
+
`npx genex model`, then `npx genex model rig <id>` (7 body plans:
|
|
27
|
+
quadruped/hexapod/octopod/avian/serpentine/aquatic and biped too) and
|
|
28
|
+
`npx genex model animate <rig-id> --preset walk`. A real skeleton and real
|
|
29
|
+
locomotion clips for exactly the shapes Meshy refuses — see
|
|
30
|
+
`$genex-ai-model` for the full flow, presets, and honest limits (avian rigs
|
|
31
|
+
have no preset clips; drive those bones in code).
|
|
32
|
+
- **Everything outside both** (swarms, blobs, amorphous things — no body plan
|
|
33
|
+
to rig): the **static + procedural lane** — `npx genex model` for the body,
|
|
26
34
|
motion authored in code. Say it honestly in the Assets table:
|
|
27
|
-
`
|
|
35
|
+
`slime: static + procedural — no riggable body plan`. Never pretend a
|
|
28
36
|
procedural creature is rigged.
|
|
29
37
|
|
|
30
38
|
## The rigged lane — `npx genex creature`
|
|
@@ -213,9 +221,10 @@ object's state field, never a per-frame broadcast.
|
|
|
213
221
|
- **"Email not verified" (`email_verification_required`)** — hand over the
|
|
214
222
|
verify link the CLI printed, wait, re-run.
|
|
215
223
|
- **The creature came back standing when you wanted four legs** — that is the
|
|
216
|
-
documented
|
|
217
|
-
produce a rigged quadruped. Switch that creature to the
|
|
218
|
-
|
|
224
|
+
documented Meshy limit, not a bad roll: re-rolling the prompt will not
|
|
225
|
+
produce a rigged quadruped there. Switch that creature to the model-rig
|
|
226
|
+
route (`npx genex model` → `model rig --type quadruped` →
|
|
227
|
+
`model animate --preset walk`) and say so in the Assets table.
|
|
219
228
|
- **Clips look wrong on the body** (arms clip the torso on a bulky model) —
|
|
220
229
|
pick a different library action id (`animations search`); never patch limbs
|
|
221
230
|
post-mixer.
|