pixelkiln 0.89.6 → 0.90.0
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/cli.js +53 -16
- package/dist/cli.js.map +1 -1
- package/dist/client/gallery.css +1 -0
- package/dist/client/gallery.js +54 -17
- package/dist/index.cjs +53 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -13
- package/dist/index.d.ts +36 -13
- package/dist/index.js +53 -16
- package/dist/index.js.map +1 -1
- package/docs/CHARACTERS.md +43 -3
- package/docs/ENDPOINTS.md +5 -1
- package/docs/MANIFEST.md +2 -2
- package/docs/REVISIONS.md +8 -5
- package/package.json +1 -1
- package/schema/manifest.schema.json +1 -1
- package/skills/pixelkiln/references/pixellab-roadmap.md +17 -13
- package/skills/pixelkiln/references/pixellab.md +8 -0
package/dist/cli.js
CHANGED
|
@@ -1238,16 +1238,21 @@ var CharacterAnimationSchema = z.object({
|
|
|
1238
1238
|
* `src/loop-directions.ts`.
|
|
1239
1239
|
*/
|
|
1240
1240
|
directions: z.array(CharacterDirectionSchema).min(1).optional(),
|
|
1241
|
-
/**
|
|
1242
|
-
|
|
1241
|
+
/**
|
|
1242
|
+
* Frames to generate without a template. A v3 loop takes an even 4 to 16;
|
|
1243
|
+
* a sentence loop (`mode: "skeleton-v3"` with no `template`) takes 3 to 15.
|
|
1244
|
+
*/
|
|
1245
|
+
frames: z.number().int().min(3).max(16).optional(),
|
|
1243
1246
|
/** Playback rate recorded with the frames; PixelLab does not store one. */
|
|
1244
1247
|
fps: z.number().int().min(1).max(60).default(8),
|
|
1245
1248
|
/** v3 only: keep the resting pose as frame 0, so `frames` generated frames land as `frames + 1` files. */
|
|
1246
1249
|
keepFirstFrame: z.boolean().default(true),
|
|
1247
1250
|
/**
|
|
1248
1251
|
* `template` when a template is named, otherwise `v3`; `skeleton-v3`
|
|
1249
|
-
* poses a template with PixelLab's skeleton model instead
|
|
1250
|
-
*
|
|
1252
|
+
* poses a template with PixelLab's skeleton model instead, or, with no
|
|
1253
|
+
* template, animates the asset's prompt as a sentence written into one 3D
|
|
1254
|
+
* motion (a v3 base; 3-15 `frames`); `pro` for the sequential
|
|
1255
|
+
* high-quality engine.
|
|
1251
1256
|
*/
|
|
1252
1257
|
mode: CharacterAnimationModeSchema.optional(),
|
|
1253
1258
|
/**
|
|
@@ -1277,15 +1282,23 @@ var CharacterAnimationSchema = z.object({
|
|
|
1277
1282
|
path: ["directions"]
|
|
1278
1283
|
});
|
|
1279
1284
|
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1285
|
+
const sentence = animation.mode === "skeleton-v3" && !animation.template;
|
|
1286
|
+
if (animation.frames !== void 0 && !sentence) {
|
|
1287
|
+
if (animation.frames % 2 !== 0) {
|
|
1288
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "frames must be even", path: ["frames"] });
|
|
1289
|
+
} else if (animation.frames < 4) {
|
|
1290
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "frames must be 4 to 16", path: ["frames"] });
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
if (animation.frames !== void 0 && sentence && animation.frames > 15) {
|
|
1294
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "a skeleton-v3 loop from a sentence takes 3 to 15 frames", path: ["frames"] });
|
|
1282
1295
|
}
|
|
1283
1296
|
const mode2 = animation.mode ?? (animation.template ? "template" : "v3");
|
|
1284
1297
|
for (const key of ["startFrame", "endFrame", "enhancePrompt"]) {
|
|
1285
1298
|
if (animation[key] !== void 0 && mode2 !== "v3") {
|
|
1286
1299
|
context.addIssue({
|
|
1287
1300
|
code: z.ZodIssueCode.custom,
|
|
1288
|
-
message: `${key} is for v3 loops; a ${mode2} loop ${mode2 === "template" || mode2 === "skeleton-v3" ?
|
|
1301
|
+
message: `${key} is for v3 loops; a ${mode2} loop ${mode2 === "template" || mode2 === "skeleton-v3" ? `starts from the character's rotation and ${animation.template ? "follows its template" : "animates its sentence"}` : "takes neither"}`,
|
|
1289
1302
|
path: [key]
|
|
1290
1303
|
});
|
|
1291
1304
|
}
|
|
@@ -1309,8 +1322,11 @@ var CharacterAnimationSchema = z.object({
|
|
|
1309
1322
|
path: ["frames"]
|
|
1310
1323
|
});
|
|
1311
1324
|
}
|
|
1312
|
-
if (!animation.template &&
|
|
1313
|
-
context.addIssue({ code: z.ZodIssueCode.custom, message:
|
|
1325
|
+
if (!animation.template && animation.mode === "template") {
|
|
1326
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "template mode needs a template", path: ["template"] });
|
|
1327
|
+
}
|
|
1328
|
+
if (sentence && animation.subject !== void 0) {
|
|
1329
|
+
context.addIssue({ code: z.ZodIssueCode.custom, message: "subject does not apply to a skeleton-v3 loop from a sentence; describe the motion in the prompt", path: ["subject"] });
|
|
1314
1330
|
}
|
|
1315
1331
|
});
|
|
1316
1332
|
var RevisionDitheringSchema = z.enum(["none", "2x2", "4x4", "8x8"]);
|
|
@@ -7258,7 +7274,10 @@ var PixelLabClient = class {
|
|
|
7258
7274
|
* Every mode but skeleton-v3 goes to `/animate-character`, the path whose
|
|
7259
7275
|
* shapes were measured live. skeleton-v3 is documented only on
|
|
7260
7276
|
* `/characters/animations`, which takes the same request and answers with
|
|
7261
|
-
* the same job list (plus an `animation_group_id`).
|
|
7277
|
+
* the same job list (plus an `animation_group_id`). With no `template` it
|
|
7278
|
+
* animates `actionDescription` as a sentence, 3 to 15 `frameCount` frames
|
|
7279
|
+
* written into one 3D motion; measured on a v3 character (8 frames, 64px:
|
|
7280
|
+
* 3 generations, frames back at 96x96).
|
|
7262
7281
|
*/
|
|
7263
7282
|
async animateCharacter(args) {
|
|
7264
7283
|
const encode = (image) => ({ type: "base64", base64: image.base64, format: image.format });
|
|
@@ -7273,7 +7292,8 @@ var PixelLabClient = class {
|
|
|
7273
7292
|
...args.template ? { template_animation_id: args.template } : {},
|
|
7274
7293
|
...args.actionDescription ? { action_description: args.actionDescription } : {},
|
|
7275
7294
|
...args.description ? { description: args.description } : {},
|
|
7276
|
-
|
|
7295
|
+
// A template fixes its own frame count; v3 and a skeleton-v3 sentence take one.
|
|
7296
|
+
...(args.mode === "v3" || args.mode === "skeleton-v3" && !args.template) && args.frameCount ? { frame_count: args.frameCount } : {},
|
|
7277
7297
|
...args.mode === "v3" && args.keepFirstFrame === false ? { keep_first_frame: false } : {},
|
|
7278
7298
|
...args.mode === "v3" && args.startFrame ? { custom_start_frame: encode(args.startFrame) } : {},
|
|
7279
7299
|
...args.mode === "v3" && args.endFrame ? { end_frame: encode(args.endFrame) } : {},
|
|
@@ -9193,6 +9213,16 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
9193
9213
|
if (skeletonTemplate && !CHARACTER_TEMPLATES.includes(skeletonTemplate)) {
|
|
9194
9214
|
throw new Error(`PixelLab animate-skeleton template "${skeletonTemplate}" is not one of ${CHARACTER_TEMPLATES.join(", ")}`);
|
|
9195
9215
|
}
|
|
9216
|
+
if (!spec.revision.description?.trim()) {
|
|
9217
|
+
throw new Error(
|
|
9218
|
+
`${spec.styleId}/${spec.assetId}: an animate-skeleton revision needs revision.description, what the character looks like (for example "a knight in steel armour holding a sword"); PixelLab refuses the request without it`
|
|
9219
|
+
);
|
|
9220
|
+
}
|
|
9221
|
+
if (!spec.prompt.trim()) {
|
|
9222
|
+
throw new Error(
|
|
9223
|
+
`${spec.styleId}/${spec.assetId}: an animate-skeleton revision needs a prompt, a short motion label (for example "swinging the sword")`
|
|
9224
|
+
);
|
|
9225
|
+
}
|
|
9196
9226
|
}
|
|
9197
9227
|
if (spec.revision?.mode === "animate" || spec.revision?.mode === "animate-pixminimax") {
|
|
9198
9228
|
const { sourceWidth: width, sourceHeight: height, mode: mode2, frames, lastFrameWidth, lastFrameHeight } = spec.revision;
|
|
@@ -9596,12 +9626,18 @@ var PixelLabProvider = class _PixelLabProvider {
|
|
|
9596
9626
|
`${spec.styleId}/${spec.assetId} animates "${character.animation.direction}", but its character has ${character.directions} directions: ${allowed.join(", ")}`
|
|
9597
9627
|
);
|
|
9598
9628
|
}
|
|
9599
|
-
|
|
9600
|
-
|
|
9629
|
+
const sentence = character.animation.mode === "skeleton-v3" && !character.animation.template;
|
|
9630
|
+
if (character.animation.mode !== "template" && (character.animation.mode !== "skeleton-v3" || sentence) && !spec.prompt.trim()) {
|
|
9631
|
+
throw new Error(
|
|
9632
|
+
`${spec.styleId}/${spec.assetId} needs a prompt describing the motion, or a template` + (sentence ? ' (a skeleton-v3 loop with no template animates its prompt, e.g. "swinging a sword in a wide arc")' : "")
|
|
9633
|
+
);
|
|
9634
|
+
}
|
|
9635
|
+
if (sentence && (character.animation.frames < 3 || character.animation.frames > 15)) {
|
|
9636
|
+
throw new Error(`${spec.styleId}/${spec.assetId}: a skeleton-v3 loop from a sentence takes 3 to 15 frames; ${character.animation.frames} is out of range`);
|
|
9601
9637
|
}
|
|
9602
9638
|
if (character.animation.mode === "skeleton-v3" && character.mode === "standard") {
|
|
9603
9639
|
throw new Error(
|
|
9604
|
-
`${spec.styleId}/${spec.assetId}: skeleton-v3 poses a template onto a 3D skeleton, which a ${character.mode} character has none of; use a v3 base (style mode: "v3"), or mode: "template" for this loop`
|
|
9640
|
+
sentence ? `${spec.styleId}/${spec.assetId}: a skeleton-v3 loop from a sentence writes the motion onto a 3D skeleton, which a ${character.mode} character has none of; use a v3 base (style mode: "v3"), or mode: "template" with a template for this loop` : `${spec.styleId}/${spec.assetId}: skeleton-v3 poses a template onto a 3D skeleton, which a ${character.mode} character has none of; use a v3 base (style mode: "v3"), or mode: "template" for this loop`
|
|
9605
9641
|
);
|
|
9606
9642
|
}
|
|
9607
9643
|
}
|
|
@@ -17029,7 +17065,8 @@ var SkeletonAnimationRequestSchema = z10.object({
|
|
|
17029
17065
|
/** The motion, sent as PixelLab's `action`. */
|
|
17030
17066
|
prompt: z10.string().min(1),
|
|
17031
17067
|
direction: CharacterDirectionSchema,
|
|
17032
|
-
|
|
17068
|
+
/** What the character looks like; PixelLab refuses the request without it. */
|
|
17069
|
+
description: z10.string().min(1),
|
|
17033
17070
|
skeletonTemplate: z10.string().min(1).optional(),
|
|
17034
17071
|
/** Manifest-relative JSON path inside the project. */
|
|
17035
17072
|
keypointsFile: z10.string().min(1),
|
|
@@ -17136,7 +17173,7 @@ async function createSkeletonAnimation(manifestPath, request) {
|
|
|
17136
17173
|
from: request.from,
|
|
17137
17174
|
keypointsFile: relative.split(path31.sep).join("/"),
|
|
17138
17175
|
direction: request.direction,
|
|
17139
|
-
|
|
17176
|
+
description: request.description,
|
|
17140
17177
|
...request.skeletonTemplate ? { skeletonTemplate: request.skeletonTemplate } : {}
|
|
17141
17178
|
}
|
|
17142
17179
|
}
|