pixelkiln 0.44.0 → 0.46.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/index.js CHANGED
@@ -90,7 +90,7 @@ var MIRRORED_DIRECTION = {
90
90
  west: "east",
91
91
  "south-west": "south-east"
92
92
  };
93
- var CharacterModeSchema = z.enum(["standard", "v3", "pro"]);
93
+ var CharacterModeSchema = z.enum(["standard", "v3", "pro", "pro-flash"]);
94
94
  var CHARACTER_PROPORTION_PRESETS = ["default", "chibi", "cartoon", "stylized", "realistic_male", "realistic_female", "heroic"];
95
95
  var CharacterProportionsSchema = z.union([
96
96
  z.enum(CHARACTER_PROPORTION_PRESETS),
@@ -286,14 +286,27 @@ var StyleObjectSchema = z.object({
286
286
  /**
287
287
  * `character` only. `standard` draws from a skeleton template for 1
288
288
  * generation; `v3` is the highest quality at 2 to 9 by size; `pro` is a
289
- * reference-based engine at 20 to 40 by size. States inherit the
290
- * parent's engine; animations choose their own.
289
+ * reference-based engine at 20 to 40 by size; `pro-flash` draws a
290
+ * south sprite with PixelLab's newest image model and rotates it with
291
+ * v3, 6 to 17 by size, or the rotations alone (1 at 64px) from a
292
+ * `reference`. States inherit the parent's engine; animations choose
293
+ * their own.
291
294
  */
292
295
  mode: CharacterModeSchema.optional(),
293
- /** `character` only. Rotations per base or state. `v3` and `pro` always draw 8. */
296
+ /** `character` only. Rotations per base or state. Every engine but `standard` draws 8. */
294
297
  directions: z.union([z.literal(4), z.literal(8)]).optional(),
295
- /** `character` only. Body template: `mannequin` (default) or a quadruped (`bear`, `cat`, `dog`, `horse`, `lion`). */
298
+ /** `character` only. Body template: `mannequin` (default), a quadruped (`bear`, `cat`, `dog`, `horse`, `lion`), or `custom` for `pro-flash`. */
296
299
  template: z.string().min(1).optional(),
300
+ /**
301
+ * `character` only, `pro-flash` bases with a style image: which traits
302
+ * the style image lends. Each defaults to true.
303
+ */
304
+ styleTraits: z.object({
305
+ palette: z.boolean().optional(),
306
+ outline: z.boolean().optional(),
307
+ detail: z.boolean().optional(),
308
+ shading: z.boolean().optional()
309
+ }).strict().optional(),
297
310
  /** `character` only, `standard` humanoid bases. A preset or multipliers; an asset may override it. */
298
311
  proportions: CharacterProportionsSchema.optional(),
299
312
  /**
@@ -306,6 +319,12 @@ var StyleObjectSchema = z.object({
306
319
  isometric: z.boolean().optional(),
307
320
  /** `character` only, `v3` bases: let PixelLab expand the prompt into a fuller one before drawing. */
308
321
  enhancePrompt: z.boolean().optional(),
322
+ /**
323
+ * `character` only, `pro` bases: the asset id of a generated 8-direction
324
+ * character in this style whose look every base drawn from text or a
325
+ * concept follows. An asset may override it; the anchor itself ignores it.
326
+ */
327
+ styleCharacter: z.string().min(1).optional(),
309
328
  /** Fixed seed for reproducibility where the endpoint supports it. */
310
329
  seed: z.number().int().optional(),
311
330
  /**
@@ -478,6 +497,15 @@ var AssetSchema = z.object({
478
497
  * still guides the result.
479
498
  */
480
499
  reference: z.union([z.string().min(1), z.record(CharacterDirectionSchema, z.string().min(1))]).optional(),
500
+ /**
501
+ * `character` styles, `pro` bases only: a manifest-relative concept
502
+ * image (a painting, a photo, a sketch; up to 1024px) that seeds the
503
+ * design instead of the prompt alone. A style image or `styleCharacter`
504
+ * may still anchor the look.
505
+ */
506
+ concept: z.string().min(1).optional(),
507
+ /** `character` styles, `pro` bases: this base's style anchor, over the style's. */
508
+ styleCharacter: z.string().min(1).optional(),
481
509
  /**
482
510
  * Another asset of the same style flipped left to right, made locally
483
511
  * from that asset's downloaded files at no generation cost.
@@ -559,6 +587,20 @@ var AssetSchema = z.object({
559
587
  path: ["reference"]
560
588
  });
561
589
  }
590
+ if (asset.concept && (asset.state || asset.animation || asset.mirror)) {
591
+ context.addIssue({
592
+ code: z.ZodIssueCode.custom,
593
+ message: "a concept image belongs on a base; a state, animation, or mirror takes its look from its parent",
594
+ path: ["concept"]
595
+ });
596
+ }
597
+ if (asset.concept && asset.reference) {
598
+ context.addIssue({
599
+ code: z.ZodIssueCode.custom,
600
+ message: "concept and reference are mutually exclusive: a concept seeds a new design, a reference is the sprite to rotate",
601
+ path: ["concept"]
602
+ });
603
+ }
562
604
  if (typeof asset.reference === "object" && !Object.keys(asset.reference).length) {
563
605
  context.addIssue({ code: z.ZodIssueCode.custom, message: "a reference needs at least a south image", path: ["reference"] });
564
606
  }
@@ -1233,6 +1275,29 @@ var PixelLabClient = class {
1233
1275
  ...south ? { reference_image: encode(south) } : {},
1234
1276
  ...args.enhancePrompt ? { enhance_prompt: true } : {}
1235
1277
  };
1278
+ } else if (args.mode === "pro-flash") {
1279
+ path33 = "/create-character-pro-flash";
1280
+ const traits = args.styleTraits;
1281
+ body = {
1282
+ description: args.description,
1283
+ template_id: args.template,
1284
+ n_directions: 8,
1285
+ // The author's sprite sets the canvas; a size only applies to text creation.
1286
+ ...south ? { first_frame: encode(south) } : { image_size: imageSize },
1287
+ ...args.view ? { view: args.view } : {},
1288
+ ...args.seed != null ? { seed: args.seed } : {},
1289
+ ...args.styleReference && args.styleReferenceSize ? {
1290
+ style_image: { image: encode(args.styleReference), size: args.styleReferenceSize },
1291
+ ...traits ? {
1292
+ style_options: {
1293
+ ...traits.palette !== void 0 ? { color_palette: traits.palette } : {},
1294
+ ...traits.outline !== void 0 ? { outline: traits.outline } : {},
1295
+ ...traits.detail !== void 0 ? { detail: traits.detail } : {},
1296
+ ...traits.shading !== void 0 ? { shading: traits.shading } : {}
1297
+ }
1298
+ } : {}
1299
+ } : {}
1300
+ };
1236
1301
  } else if (args.mode === "pro") {
1237
1302
  path33 = "/create-character-pro";
1238
1303
  body = {
@@ -1240,10 +1305,12 @@ var PixelLabClient = class {
1240
1305
  image_size: imageSize,
1241
1306
  template_id: args.template,
1242
1307
  no_background: args.noBackground ?? true,
1243
- method: south ? "rotate_character" : "create_with_style",
1308
+ method: south ? "rotate_character" : args.concept ? "create_from_concept" : "create_with_style",
1244
1309
  ...args.view ? { view: args.view } : {},
1245
1310
  ...args.seed != null ? { seed: args.seed } : {},
1246
- ...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {}
1311
+ ...south ? { reference_image: encode(south) } : args.styleReference ? { reference_image: encode(args.styleReference) } : {},
1312
+ ...!south && args.concept ? { concept_image: encode(args.concept) } : {},
1313
+ ...!south && args.styleCharacterId ? { style_character_id: args.styleCharacterId } : {}
1247
1314
  };
1248
1315
  } else {
1249
1316
  path33 = args.directions === 4 ? "/create-character-with-4-directions" : "/create-character-with-8-directions";
@@ -2005,7 +2072,10 @@ function specHash(spec, styleImageHashes, providerOptionIdentity = spec.provider
2005
2072
  textGuidanceScale: spec.character.textGuidanceScale,
2006
2073
  isometric: spec.character.isometric,
2007
2074
  enhancePrompt: spec.character.enhancePrompt,
2008
- reference: spec.character.reference ? Object.fromEntries(Object.entries(spec.character.reference).map(([direction, image]) => [direction, image.sha256])) : void 0
2075
+ styleTraits: spec.character.styleTraits,
2076
+ reference: spec.character.reference ? Object.fromEntries(Object.entries(spec.character.reference).map(([direction, image]) => [direction, image.sha256])) : void 0,
2077
+ concept: spec.character.concept?.sha256,
2078
+ styleAnchor: spec.character.styleAnchor ? { of: spec.character.styleAnchor.assetId, sha256: spec.character.styleAnchor.sha256 } : void 0
2009
2079
  } : void 0,
2010
2080
  // A mirror's bytes come from its source's recorded outputs; the plan
2011
2081
  // compares those directly, so only the choice of source is identity.
@@ -2046,12 +2116,24 @@ function characterCost(spec) {
2046
2116
  if (character.kind === "state") return generationCost(spec.width, spec.height, "1dir");
2047
2117
  if (character.mode === "standard") return 1;
2048
2118
  if (character.mode === "v3") return 1 + Math.max(1, Math.ceil(px * 8 / 65536));
2119
+ if (character.mode === "pro-flash") {
2120
+ const south = character.reference?.south;
2121
+ return south ? proFlashCharacterCost(south.width, south.height, true) : proFlashCharacterCost(spec.width, spec.height, false);
2122
+ }
2049
2123
  return generationCost(spec.width, spec.height, "1dir");
2050
2124
  }
2125
+ function proFlashCharacterCost(width, height, fromReference) {
2126
+ const side = Math.max(32, Math.ceil(Math.max(width, height) / 4) * 4);
2127
+ const rotations = Math.max(1, Math.ceil(side * side * 8 / 65536));
2128
+ if (fromReference) return rotations;
2129
+ const image = side <= 96 ? 5 : side <= 208 ? 6 : 9;
2130
+ return image + rotations;
2131
+ }
2051
2132
  function characterAnimationName(spec) {
2052
2133
  return `pixelkiln:${spec.styleId}/${spec.assetId}`;
2053
2134
  }
2054
2135
  var CHARACTER_TEMPLATES = ["mannequin", "bear", "cat", "dog", "horse", "lion"];
2136
+ var PRO_FLASH_TEMPLATES = [...CHARACTER_TEMPLATES, "custom"];
2055
2137
  function encodeAnimationJob(job) {
2056
2138
  return `character-animation:${Buffer.from(JSON.stringify(job)).toString("base64url")}`;
2057
2139
  }
@@ -2192,12 +2274,25 @@ var PixelLabProvider = class _PixelLabProvider {
2192
2274
  }
2193
2275
  }
2194
2276
  }
2277
+ if (character.concept) {
2278
+ if (character.mode !== "pro") throw new Error(`${label}: a concept image is a pro input; the ${character.mode} engine draws from text or a reference`);
2279
+ if (character.concept.width > 1024 || character.concept.height > 1024) {
2280
+ throw new Error(`${label}: concept image is ${character.concept.width}x${character.concept.height}; PixelLab pro takes up to 1024px`);
2281
+ }
2282
+ }
2283
+ if (character.styleAnchor) {
2284
+ if (character.mode !== "pro") throw new Error(`${label}: styleCharacter is a pro input; the ${character.mode} engine has no style anchor`);
2285
+ if (character.reference) throw new Error(`${label}: a pro base rotating its own reference takes no styleCharacter`);
2286
+ if (character.styleAnchor.spec.character?.directions !== 8) {
2287
+ throw new Error(`${label}: styleCharacter ${character.styleAnchor.assetId} has ${character.styleAnchor.spec.character?.directions} directions; PixelLab wants an 8-direction anchor`);
2288
+ }
2289
+ }
2195
2290
  if (character.reference) {
2196
2291
  const given = Object.keys(character.reference);
2197
2292
  if (!character.reference.south) throw new Error(`${label}: a reference needs a south-facing sprite`);
2198
2293
  if (character.mode !== "standard") {
2199
2294
  if (given.length > 1) throw new Error(`${label}: PixelLab ${character.mode} rotates one south-facing reference; drop the other directions`);
2200
- const limit = character.mode === "v3" ? 256 : 168;
2295
+ const limit = character.mode === "pro" ? 168 : 256;
2201
2296
  const south = character.reference.south;
2202
2297
  if (south.width > limit || south.height > limit) {
2203
2298
  throw new Error(`${label}: reference is ${south.width}x${south.height}; PixelLab ${character.mode} takes up to ${limit}px`);
@@ -2221,26 +2316,39 @@ var PixelLabProvider = class _PixelLabProvider {
2221
2316
  }
2222
2317
  }
2223
2318
  if (styleImages.length) {
2224
- if (character.mode !== "pro") {
2319
+ if (character.mode !== "pro" && character.mode !== "pro-flash") {
2225
2320
  throw new Error(
2226
- `PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro for a style anchor`
2321
+ `PixelLab ${character.mode} characters take no style images; give a base its own sprite with \`reference\`, or use mode pro or pro-flash for a style anchor`
2227
2322
  );
2228
2323
  }
2229
- if (styleImages.length > 1) throw new Error("PixelLab pro characters take one style image");
2324
+ if (styleImages.length > 1) throw new Error(`PixelLab ${character.mode} characters take one style image`);
2230
2325
  if (character.kind === "base" && character.reference) {
2231
- throw new Error(`${label}: a pro base rotating its own reference takes no style image`);
2326
+ throw new Error(`${label}: a ${character.mode} base rotating its own reference takes no style image`);
2232
2327
  }
2233
2328
  const image = styleImages[0];
2234
- if (image.width > 168 || image.height > 168) {
2235
- throw new Error(`PixelLab pro character style image is ${image.width}x${image.height}; the limit is 168px`);
2329
+ const limit = character.mode === "pro" ? 168 : 256;
2330
+ if (image.width > limit || image.height > limit) {
2331
+ throw new Error(`PixelLab ${character.mode} character style image is ${image.width}x${image.height}; the limit is ${limit}px`);
2332
+ }
2333
+ if (character.mode === "pro-flash" && (image.width > spec.width || image.height > spec.height)) {
2334
+ throw new Error(
2335
+ `PixelLab pro-flash style image is ${image.width}x${image.height} but the character is ${spec.width}x${spec.height}; crop the image to its subject or raise the style's size`
2336
+ );
2236
2337
  }
2237
2338
  }
2238
- const maxSize = character.mode === "v3" ? 256 : 128;
2339
+ if (character.styleTraits && character.mode !== "pro-flash") {
2340
+ throw new Error(`${label}: styleTraits choose what a pro-flash style image lends; the ${character.mode} engine does not take them`);
2341
+ }
2342
+ const maxSize = character.mode === "v3" || character.mode === "pro-flash" ? 256 : 128;
2239
2343
  if (spec.width < 16 || spec.height < 16 || spec.width > maxSize || spec.height > maxSize) {
2240
2344
  throw new Error(`PixelLab ${character.mode} characters must be between 16 and ${maxSize} pixels`);
2241
2345
  }
2242
- if (!CHARACTER_TEMPLATES.includes(character.template)) {
2243
- throw new Error(`PixelLab character template must be one of: ${CHARACTER_TEMPLATES.join(", ")}`);
2346
+ if (character.mode === "pro-flash" && character.kind === "base" && (spec.width % 4 || spec.height % 4)) {
2347
+ throw new Error(`PixelLab pro-flash characters are sized in multiples of 4 pixels; ${spec.width}x${spec.height} is not`);
2348
+ }
2349
+ const templates = character.mode === "pro-flash" ? PRO_FLASH_TEMPLATES : CHARACTER_TEMPLATES;
2350
+ if (!templates.includes(character.template)) {
2351
+ throw new Error(`PixelLab ${character.mode} character template must be one of: ${templates.join(", ")}`);
2244
2352
  }
2245
2353
  const views = character.mode === "standard" ? ["low top-down", "high top-down", "side", "perspective", "oblique"] : ["low top-down", "high top-down", "side"];
2246
2354
  if (!views.includes(spec.view)) {
@@ -2293,7 +2401,11 @@ var PixelLabProvider = class _PixelLabProvider {
2293
2401
  isometric: character.isometric,
2294
2402
  reference: character.reference ? readReference(spec, character.reference) : void 0,
2295
2403
  styleReference: styleImage ? { base64: styleImage.base64, format: styleImage.format } : void 0,
2296
- enhancePrompt: character.enhancePrompt
2404
+ enhancePrompt: character.enhancePrompt,
2405
+ concept: character.concept ? readPose(spec, "concept image", character.concept) : void 0,
2406
+ styleCharacterId: character.styleAnchor ? requireStyleObjectId(spec, context) : void 0,
2407
+ styleReferenceSize: styleImage ? { width: styleImage.width, height: styleImage.height } : void 0,
2408
+ styleTraits: character.styleTraits
2297
2409
  });
2298
2410
  return { jobId: res2.character_id, metadata: { character: { kind: "base", characterId: res2.character_id, mode: character.mode, directions: character.directions, backgroundJobId: res2.background_job_id } } };
2299
2411
  }
@@ -2713,6 +2825,14 @@ function readReference(spec, reference) {
2713
2825
  }
2714
2826
  return images;
2715
2827
  }
2828
+ function requireStyleObjectId(spec, context) {
2829
+ if (!context?.styleObjectId) {
2830
+ throw new Error(
2831
+ `${spec.styleId}/${spec.assetId} anchors its style on ${spec.character.styleAnchor.assetId}, which has no PixelLab character id in the lockfile yet; generate the anchor first`
2832
+ );
2833
+ }
2834
+ return context.styleObjectId;
2835
+ }
2716
2836
  function readPose(spec, what, image) {
2717
2837
  const bytes = readFileSync(image.path);
2718
2838
  if (sha256(bytes) !== image.sha256) {
@@ -5412,6 +5532,18 @@ async function resolveSpecs(loaded, filter) {
5412
5532
  finalized.add(assetId);
5413
5533
  return resolved;
5414
5534
  }
5535
+ const anchorId = asset.styleCharacter ?? style.styleCharacter;
5536
+ if (resolved.character?.kind === "base" && anchorId && anchorId !== assetId) {
5537
+ const anchorSpec = await finalize(anchorId);
5538
+ if (!anchorSpec.character || anchorSpec.character.kind === "animation") {
5539
+ throw new Error(`assets.${assetId}: styleCharacter ${anchorId} is not a character base or state`);
5540
+ }
5541
+ const file = memberPath(anchorSpec.outFile, "south", 0, anchorSpec.character.directions, MediaType.PNG);
5542
+ resolved.character = {
5543
+ ...resolved.character,
5544
+ styleAnchor: { assetId: anchorId, spec: anchorSpec, file, sha256: existsSync4(file) ? await sha256File(file) : null }
5545
+ };
5546
+ }
5415
5547
  const characterParent = asset.state?.of ?? asset.animation?.of;
5416
5548
  if (resolved.character && characterParent) {
5417
5549
  const parentSpec = await finalize(characterParent);
@@ -5562,8 +5694,13 @@ async function resolveCharacterShape(asset, style, kind, files) {
5562
5694
  ...proportions !== void 0 ? { proportions } : {},
5563
5695
  ...style.textGuidanceScale !== void 0 ? { textGuidanceScale: style.textGuidanceScale } : {},
5564
5696
  ...style.isometric !== void 0 ? { isometric: style.isometric } : {},
5565
- ...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {}
5697
+ ...style.enhancePrompt !== void 0 ? { enhancePrompt: style.enhancePrompt } : {},
5698
+ ...style.styleTraits ? { styleTraits: style.styleTraits } : {}
5566
5699
  };
5700
+ if (asset.concept) {
5701
+ const image = await files.load(asset.concept, "Concept image");
5702
+ shape.concept = { path: path5.resolve(files.root, asset.concept), sha256: image.hash, width: image.width, height: image.height, format: image.format };
5703
+ }
5567
5704
  if (asset.reference) {
5568
5705
  const byDirection = typeof asset.reference === "string" ? { south: asset.reference } : asset.reference;
5569
5706
  shape.reference = {};
@@ -7083,9 +7220,24 @@ import path11 from "path";
7083
7220
  async function inspectRevisionReadiness(spec, lock) {
7084
7221
  if (spec.mirror) return inspectMirror(spec, lock, /* @__PURE__ */ new Set());
7085
7222
  if (spec.character?.parentSpec) return inspectCharacterParent(spec, lock, /* @__PURE__ */ new Set());
7223
+ if (spec.character?.styleAnchor) return inspectStyleAnchor(spec, lock, /* @__PURE__ */ new Set());
7086
7224
  if (!spec.revision) return null;
7087
7225
  return inspectRevision(spec, lock, /* @__PURE__ */ new Set());
7088
7226
  }
7227
+ async function inspectStyleAnchor(spec, lock, seen) {
7228
+ const anchor = spec.character.styleAnchor;
7229
+ const label = `style anchor ${spec.styleId}/${anchor.assetId}`;
7230
+ const dependency = await inspectParent(anchor.spec, lock, seen);
7231
+ if (!dependency.ready) return { ready: false, reason: `${label} is not ready: ${dependency.reason}` };
7232
+ if (!anchor.sha256 || !existsSync7(anchor.file)) return { ready: false, reason: `${label} has no generated south-facing file yet` };
7233
+ if (await sha256File(anchor.file) !== anchor.sha256) {
7234
+ return { ready: false, reason: `${label} changed after the manifest was resolved` };
7235
+ }
7236
+ if (!lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)]?.objectId) {
7237
+ return { ready: false, reason: `${label} has no PixelLab character id recorded` };
7238
+ }
7239
+ return { ready: true, reason: `${label} is current` };
7240
+ }
7089
7241
  async function inspectMirror(spec, lock, seen) {
7090
7242
  const source = spec.mirror.sourceSpec;
7091
7243
  const label = `mirror source ${spec.styleId}/${spec.mirror.sourceAssetId}`;
@@ -7157,6 +7309,10 @@ async function inspectParent(spec, lock, seen) {
7157
7309
  const inputs = await inspectCharacterParent(spec, lock, nextSeen);
7158
7310
  if (!inputs.ready) return inputs;
7159
7311
  }
7312
+ if (spec.character?.styleAnchor) {
7313
+ const inputs = await inspectStyleAnchor(spec, lock, nextSeen);
7314
+ if (!inputs.ready) return inputs;
7315
+ }
7160
7316
  if (spec.quality) {
7161
7317
  const quality = await inspectQualityProfile(spec, lock);
7162
7318
  return quality?.state === "approved" ? { ready: true, reason: "approved quality output is current" } : {
@@ -7196,6 +7352,14 @@ async function anyOutputModified(entry, spec) {
7196
7352
  }
7197
7353
  return false;
7198
7354
  }
7355
+ function dependencies(spec) {
7356
+ return [
7357
+ spec.mirror?.sourceSpec,
7358
+ spec.revision?.sourceSpec,
7359
+ spec.character?.parentSpec,
7360
+ spec.character?.styleAnchor?.spec
7361
+ ].filter((parent) => Boolean(parent));
7362
+ }
7199
7363
  function resumeCommandForStatus(status) {
7200
7364
  if (status === "pending" || status === "processing") return "poll";
7201
7365
  if (status === "review") return "pick";
@@ -7304,16 +7468,19 @@ async function buildPlan(specs, lock, opts = {}) {
7304
7468
  const stateOf = new Map(items.map((i) => [i.key, i.state]));
7305
7469
  for (const item of items) {
7306
7470
  if (!isActionable(item)) continue;
7307
- const parent = item.spec.mirror?.sourceSpec ?? item.spec.revision?.sourceSpec ?? item.spec.character?.parentSpec;
7308
- if (!parent) continue;
7309
- const parentKey = lockKey(parent.styleId, parent.assetId);
7310
- const parentState = stateOf.get(parentKey);
7311
- if (parentState && isActionable({ state: parentState })) {
7312
- item.state = "blocked";
7313
- item.reason = `parent ${parentKey} is being generated in this run; this follows in the next wave`;
7314
- } else if (item.spec.mirror && (parentState === "recoverable" || parentState === "in-flight")) {
7315
- item.state = "blocked";
7316
- item.reason = `mirror source ${parentKey} is ${parentState}; this follows in the next wave`;
7471
+ for (const parent of dependencies(item.spec)) {
7472
+ const parentKey = lockKey(parent.styleId, parent.assetId);
7473
+ const parentState = stateOf.get(parentKey);
7474
+ if (parentState && isActionable({ state: parentState })) {
7475
+ item.state = "blocked";
7476
+ item.reason = `parent ${parentKey} is being generated in this run; this follows in the next wave`;
7477
+ break;
7478
+ }
7479
+ if (item.spec.mirror && (parentState === "recoverable" || parentState === "in-flight")) {
7480
+ item.state = "blocked";
7481
+ item.reason = `mirror source ${parentKey} is ${parentState}; this follows in the next wave`;
7482
+ break;
7483
+ }
7317
7484
  }
7318
7485
  }
7319
7486
  const actionable = items.filter(isActionable);
@@ -9792,10 +9959,13 @@ async function submit(provider, loaded, items, lock, lockPath, opts = {}) {
9792
9959
  try {
9793
9960
  const refs = styleImages.get(spec.styleId) ?? [];
9794
9961
  const parentEntry = spec.character?.parentSpec ? lock.entries[lockKey(spec.character.parentSpec.styleId, spec.character.parentSpec.assetId)] : void 0;
9962
+ const anchor = spec.character?.styleAnchor;
9963
+ const anchorEntry = anchor ? lock.entries[lockKey(anchor.spec.styleId, anchor.spec.assetId)] : void 0;
9795
9964
  const replacedMetadata = previousEntry?.providerMetadata?.[provider.id];
9796
9965
  const { jobId, metadata } = await provider.submit(spec, refs, {
9797
9966
  ...previousJobId ? { previousJobId } : {},
9798
9967
  ...parentEntry?.objectId ? { parentObjectId: parentEntry.objectId } : {},
9968
+ ...anchorEntry?.objectId ? { styleObjectId: anchorEntry.objectId } : {},
9799
9969
  ...replacedMetadata ? { replacedMetadata } : {},
9800
9970
  ...previousMetadata ? { previousMetadata } : {},
9801
9971
  checkpoint: async (checkpoint) => {
@@ -12404,7 +12574,7 @@ var pin_default = {
12404
12574
  godot: "4.7.2",
12405
12575
  extensionsApi: 9,
12406
12576
  protocol: 4,
12407
- release: "editor-pixelorama-v1.2.2-pk.18",
12577
+ release: "editor-pixelorama-v1.2.2-pk.26",
12408
12578
  files: {
12409
12579
  "index.apple-touch-icon.png": {
12410
12580
  sha256: "ee5434873e0fed91e9a888c3ea5a8b79beac25999308be7a6eb41bf4ce640d27",
@@ -12419,7 +12589,7 @@ var pin_default = {
12419
12589
  bytes: 7298
12420
12590
  },
12421
12591
  "index.html": {
12422
- sha256: "d9adf06036660c4b76ef5386e872bc03dc0d5b0628fd6ac660d480893ee1f47a",
12592
+ sha256: "326101ab02bb4a29a7964214c9307c7dff26e9d66b8ebaaf6e7a3987e84a05b2",
12423
12593
  bytes: 5442
12424
12594
  },
12425
12595
  "index.icon.png": {
@@ -12431,8 +12601,8 @@ var pin_default = {
12431
12601
  bytes: 279815
12432
12602
  },
12433
12603
  "index.pck": {
12434
- sha256: "a41d9c3a39aa99ea5ee49ddcedfeb8b092006aa75c0de67139f13297c17f42e4",
12435
- bytes: 6431692
12604
+ sha256: "e26292650bb996965acd1ba70e74d2b4020b063d14f1276701312c1d34cb0a83",
12605
+ bytes: 6431932
12436
12606
  },
12437
12607
  "index.png": {
12438
12608
  sha256: "6e3ca3eb4a99e4c07bdd89ebc873b440ec0ffd66ce1955160da9e7ed80d538d7",