spine-rigc 1.9.0 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/cli.ts +48 -17
  2. package/docs/AUTHORING.md +2 -2
  3. package/package.json +1 -1
  4. package/src/assertions/bodies/a09.ts +82 -0
  5. package/src/assertions/bodies/a10.ts +116 -0
  6. package/src/assertions/bodies/a12.ts +30 -0
  7. package/src/assertions/bodies/a24.ts +68 -0
  8. package/src/assertions/bodies/a25.ts +39 -0
  9. package/src/assertions/bodies/a26.ts +61 -0
  10. package/src/assertions/bodies/a29.ts +34 -0
  11. package/src/assertions/bodies/a30.ts +50 -0
  12. package/src/assertions/bodies/a32.ts +44 -0
  13. package/src/assertions/bodies/a34.ts +133 -0
  14. package/src/assertions/bodies/a39.ts +303 -0
  15. package/src/assertions/bodies/a40.ts +128 -0
  16. package/src/assertions/bodies/a43.ts +181 -0
  17. package/src/assertions/bodies/a46.ts +224 -0
  18. package/src/assertions/facts/animation_durations.ts +37 -0
  19. package/src/assertions/facts/bone_timelines.ts +37 -0
  20. package/src/assertions/facts/constraint_targets.ts +56 -0
  21. package/src/assertions/facts/deform_survey.ts +27 -0
  22. package/src/assertions/facts/event_keys.ts +55 -0
  23. package/src/assertions/facts/sequences.ts +85 -0
  24. package/src/assertions/facts/skeleton_roster.ts +45 -0
  25. package/src/assertions/facts/slider_composition.ts +78 -0
  26. package/src/assertions/facts/stepped_poses.ts +74 -0
  27. package/src/assertions/facts/two_colour.ts +52 -0
  28. package/src/assertions/inward_advance.ts +58 -0
  29. package/src/assertions/model/animation_durations.ts +57 -0
  30. package/src/assertions/model/bone_timelines.ts +56 -0
  31. package/src/assertions/model/constraint_targets.ts +82 -0
  32. package/src/assertions/model/constraints.ts +34 -16
  33. package/src/assertions/model/deform_survey.ts +24 -0
  34. package/src/assertions/model/event_keys.ts +45 -0
  35. package/src/assertions/model/index.ts +83 -2
  36. package/src/assertions/model/linked_meshes.ts +2 -2
  37. package/src/assertions/model/mesh_attachments.ts +1 -1
  38. package/src/assertions/model/region_joins.ts +20 -12
  39. package/src/assertions/model/sequences.ts +157 -0
  40. package/src/assertions/model/skeleton_roster.ts +23 -0
  41. package/src/assertions/model/skin_entries.ts +18 -8
  42. package/src/assertions/model/skin_members.ts +5 -3
  43. package/src/assertions/model/skin_meshes.ts +1 -1
  44. package/src/assertions/model/slider_composition.ts +191 -0
  45. package/src/assertions/model/slot_colour.ts +5 -4
  46. package/src/assertions/model/stepped_poses.ts +89 -0
  47. package/src/assertions/model/two_colour.ts +61 -0
  48. package/src/assertions/model/vertex_polygons.ts +9 -8
  49. package/src/bonedist.ts +18 -6
  50. package/src/compile.ts +114 -14
  51. package/src/core/additive.ts +468 -0
  52. package/src/core/constraints.ts +12 -2
  53. package/src/core/constraints_physics.ts +31 -8
  54. package/src/core/raw.ts +77 -16
  55. package/src/core/walk.ts +202 -0
  56. package/src/deformmeasure.ts +35 -2270
  57. package/src/deformstructure.ts +60 -18
  58. package/src/deformsurvey.ts +2295 -0
  59. package/src/nonfinite.ts +54 -0
  60. package/src/render.ts +200 -59
  61. package/src/render_core.ts +5 -0
  62. package/src/validate.ts +791 -1558
@@ -52,9 +52,21 @@
52
52
  * was the file's on 14 of 19 rows. Since issue #1026 a `rigc-compiled/3`
53
53
  * document states that order (`editorOrder.animations`, computed by the
54
54
  * same function at compile time) and the survey reads it; a `/2` or `/1`
55
- * document is ordered by the comparator as before. Every other order the survey reads — a
56
- * skin's, an animation's deform timelines, the sliders — the file keeps from
57
- * the model.
55
+ * document's is derived by that function (`fileAnimationOrder`), which
56
+ * since issue #1034 returns the file's order — integer-like names first, as
57
+ * an object keys them, where the comparator alone put `-a` before `5`.
58
+ * - **An animation's deform timelines** are in the order the file keys them:
59
+ * the model's, with each of the three levels (skin, slot, attachment) put
60
+ * through `keyedOrder` (`attachmentTimelinesInFileOrder`, issue #1034) —
61
+ * the model's own order on every name that is not integer-like. The sliders
62
+ * the file keeps from the model.
63
+ * - **The skins** are in the file's order (`fileSkinOrder`, issue #1034): the
64
+ * order a `/3` document states, else the emitter's `editorSkinOrder`. This
65
+ * said, until #1034, that the file keeps a skin's order from the model; the
66
+ * emitter sorts the skins (`default` first, the rest by the editor's
67
+ * comparator), and a probe declaring `default, 5, 10, -a, 2b, 01` read
68
+ * `default, -a, 01, 2b, 5, 10` off spine-core and the declared order off the
69
+ * model — no row had carried a set the comparator moves.
58
70
  * - **A slider's duration** is the runtime's (`CoreAnimationTimelines.duration`:
59
71
  * the last key time of every timeline, float32), not the document's declared
60
72
  * one, which was the runtime's on 1 of 2.
@@ -77,7 +89,7 @@
77
89
  * reader, in `src/deformmeasure.ts`.
78
90
  */
79
91
  import { CompileError } from './errors.ts';
80
- import { editorAnimationOrder } from './compile.ts';
92
+ import { fileAnimationOrder, fileSkinOrder, keyedOrder, skinsInFileOrder } from './compile.ts';
81
93
  import { bezierPolyline } from './core/animation.ts';
82
94
  import { DEFORM_CURVE_END, heldArray, type CoreAttachmentTimeline, type CoreDeformKey } from './core/deform.ts';
83
95
  import type { DialBoneField } from './core/hooks.ts';
@@ -274,7 +286,7 @@ export function modelStructure(doc: CompiledDocument): SurveyStructure {
274
286
  };
275
287
  const animationOf = (a: CoreAnimation): SurveyAnimation => {
276
288
  const deforms: SurveyDeformTimeline[] = [];
277
- for (const t of a.timelines.attachments) if (t.deform !== null) deforms.push(deformOf(t, t.deform));
289
+ for (const t of attachmentTimelinesInFileOrder(a.timelines.attachments)) if (t.deform !== null) deforms.push(deformOf(t, t.deform));
278
290
  return {
279
291
  name: a.name,
280
292
  deforms,
@@ -294,18 +306,16 @@ export function modelStructure(doc: CompiledDocument): SurveyStructure {
294
306
  },
295
307
  };
296
308
  };
297
- // The order the Spine file lists the animations in: stated by a
298
- // `rigc-compiled/3` document (`editorOrder`, issue #1026), and derived for a
299
- // `/2` or `/1` one, which does not state it, by the emitter's own comparator.
309
+ // The order the Spine file lists the animations in (`fileAnimationOrder`,
310
+ // issue #1034): stated by a `rigc-compiled/3` document (`editorOrder`, issue
311
+ // #1026), and derived for a `/2` or `/1` one, which does not state it, by the
312
+ // emitter's own rule — integer-like names first, as the file keys them.
300
313
  let order: readonly string[];
301
- if (doc.stated !== null) order = doc.stated.editorOrder.animations;
302
- else {
303
- try {
304
- order = editorAnimationOrder(doc.animations.map((a) => a.name));
305
- } catch (err) {
306
- if (!(err instanceof CompileError)) throw err;
307
- throw new CoreInputError(`the animations' order in the Spine file is not settled by the model's names — ${err.message}`);
308
- }
314
+ try {
315
+ order = fileAnimationOrder(doc);
316
+ } catch (err) {
317
+ if (!(err instanceof CompileError)) throw err;
318
+ throw new CoreInputError(`the animations' order in the Spine file is not settled by the model's names — ${err.message}`);
309
319
  }
310
320
  const animations = order.map((name) => {
311
321
  const a = doc.animations.find((x) => x.name === name);
@@ -331,10 +341,19 @@ export function modelStructure(doc: CompiledDocument): SurveyStructure {
331
341
  loop: r.loop,
332
342
  });
333
343
  }
344
+ // The skins in the order the Spine file lists them (`fileSkinOrder`, issue #1034), as the runtime's structure lists its skins:
345
+ // stated by a `/3` document, derived for a `/2` or `/1` one by the emitter's rule, which a comparator-moved name set shows.
346
+ let skins: CompiledDocument['skins'];
347
+ try {
348
+ skins = skinsInFileOrder(doc.skins, fileSkinOrder(doc)).map((walk) => walk.skin);
349
+ } catch (err) {
350
+ if (!(err instanceof CompileError)) throw err;
351
+ throw new CoreInputError(`the skins' order in the Spine file is not settled by the model's names — ${err.message}`);
352
+ }
334
353
  return {
335
- skins: doc.skins.flatMap((k) => {
354
+ skins: skins.flatMap((k) => {
336
355
  const handle = skinOf(k.name);
337
- return handle === null || doc.skins.find((x) => x.name === k.name) !== k ? [] : [handle];
356
+ return handle === null || skins.find((x) => x.name === k.name) !== k ? [] : [handle];
338
357
  }),
339
358
  animations,
340
359
  sliders,
@@ -342,3 +361,26 @@ export function modelStructure(doc: CompiledDocument): SurveyStructure {
342
361
  skinsNamed: (name) => doc.skins.filter((k) => k.name === name).length,
343
362
  };
344
363
  }
364
+
365
+ /**
366
+ * An animation's attachment timelines in the order the Spine file keys them
367
+ * (issue #1034): the emitter writes `attachments` as three nested objects —
368
+ * skin, slot, attachment — each filled in the model's order, and an object
369
+ * lists an integer-like key first (`keyedOrder`). So the model's list is
370
+ * grouped skin by skin and slot by slot in the order each first appears, and
371
+ * each level put through `keyedOrder`. Measured on a build whose deform
372
+ * timelines are filed under slots `10`, `5`, `-a` in the model: the file and
373
+ * spine-core list `5, 10, -a`.
374
+ */
375
+ function attachmentTimelinesInFileOrder(timelines: readonly CoreAttachmentTimeline[]): CoreAttachmentTimeline[] {
376
+ const firsts = (names: readonly string[]): string[] => keyedOrder(names.filter((name, i) => names.indexOf(name) === i));
377
+ const out: CoreAttachmentTimeline[] = [];
378
+ for (const skin of firsts(timelines.map((t) => t.skin))) {
379
+ const inSkin = timelines.filter((t) => t.skin === skin);
380
+ for (const slot of firsts(inSkin.map((t) => t.slot))) {
381
+ const inSlot = inSkin.filter((t) => t.slot === slot);
382
+ for (const attachment of firsts(inSlot.map((t) => t.attachment))) out.push(...inSlot.filter((t) => t.attachment === attachment));
383
+ }
384
+ }
385
+ return out;
386
+ }