@pixi-ui-editor/runtime-pixi 0.11.0 → 0.13.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.
@@ -2,6 +2,7 @@ import { type PageGroupNode } from "@pixi-ui-editor/schema";
2
2
  import { Container, Texture } from "pixi.js";
3
3
  import { PageItemContainer } from "../pageGroup.js";
4
4
  import { NodeView } from "./NodeView.js";
5
+ import type { PaginationArrow } from "./PaginationNodeView.js";
5
6
  export type { PageGroupNode };
6
7
  /**
7
8
  * Shows exactly one direct child ("page") at a time and hides the rest; each page fills the group's
@@ -38,5 +39,18 @@ export declare class PageGroupNodeView extends NodeView {
38
39
  get page(): number;
39
40
  /** External sync from game code (or the pagination widget's `onPageChange`): switches the visible page. */
40
41
  set page(value: number);
42
+ /**
43
+ * Подключает опциональные авторские кнопки-стрелки `pageUpButtonNodeId`/`pageDownButtonNodeId` —
44
+ * тот же приём, что `PaginationNodeView.setArrows` даёт пагинатору (ADR 0043): кнопки остаются
45
+ * обычными нодами сцены, виджет только подписывается на `onPress`. В отличие от пагинатора, здесь
46
+ * нет края диапазона, который гасил бы стрелку: это карусель — "up" с последней страницы
47
+ * возвращается на первую, "down" с первой уходит на последнюю, поэтому обе стрелки всегда активны.
48
+ */
49
+ setArrows(arrows: {
50
+ up?: PaginationArrow;
51
+ down?: PaginationArrow;
52
+ }): void;
53
+ /** Moves by `delta` pages, wrapping around both ends of the range — a carousel, not a clamp. */
54
+ private step;
41
55
  }
42
56
  //# sourceMappingURL=PageGroupNodeView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageGroupNodeView.d.ts","sourceRoot":"","sources":["../../src/views/PageGroupNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,WAAW,CAAS;IAE5B,YAAY,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAGlF;IAED,mHAAmH;IACnH,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAKzC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAU/B;IAED,SAAS,CAAC,WAAW,IAAI,IAAI,CAE5B;IAED,OAAO,CAAC,eAAe;IAIvB,IAAI,SAAS,IAAI,MAAM,CAA8B;IAErD,IAAI,IAAI,IAAI,MAAM,CAA6B;IAE/C,2GAA2G;IAC3G,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAMrB;CACF"}
1
+ {"version":3,"file":"PageGroupNodeView.d.ts","sourceRoot":"","sources":["../../src/views/PageGroupNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,YAAY,EAAE,aAAa,EAAE,CAAC;AAE9B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,WAAW,CAAS;IAE5B,YAAY,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAGlF;IAED,mHAAmH;IACnH,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAKzC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAU/B;IAED,SAAS,CAAC,WAAW,IAAI,IAAI,CAE5B;IAED,OAAO,CAAC,eAAe;IAIvB,IAAI,SAAS,IAAI,MAAM,CAA8B;IAErD,IAAI,IAAI,IAAI,MAAM,CAA6B;IAE/C,2GAA2G;IAC3G,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAMrB;IAED;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE;QAAE,EAAE,CAAC,EAAE,eAAe,CAAC;QAAC,IAAI,CAAC,EAAE,eAAe,CAAA;KAAE,GAAG,IAAI,CAGxE;IAED,gGAAgG;IAChG,OAAO,CAAC,IAAI;CAKb"}
@@ -68,5 +68,23 @@ export class PageGroupNodeView extends NodeView {
68
68
  this.currentPage = next;
69
69
  this.applyVisibility();
70
70
  }
71
+ /**
72
+ * Подключает опциональные авторские кнопки-стрелки `pageUpButtonNodeId`/`pageDownButtonNodeId` —
73
+ * тот же приём, что `PaginationNodeView.setArrows` даёт пагинатору (ADR 0043): кнопки остаются
74
+ * обычными нодами сцены, виджет только подписывается на `onPress`. В отличие от пагинатора, здесь
75
+ * нет края диапазона, который гасил бы стрелку: это карусель — "up" с последней страницы
76
+ * возвращается на первую, "down" с первой уходит на последнюю, поэтому обе стрелки всегда активны.
77
+ */
78
+ setArrows(arrows) {
79
+ arrows.up?.onPress.connect(() => this.step(1));
80
+ arrows.down?.onPress.connect(() => this.step(-1));
81
+ }
82
+ /** Moves by `delta` pages, wrapping around both ends of the range — a carousel, not a clamp. */
83
+ step(delta) {
84
+ if (this.items.length === 0)
85
+ return;
86
+ const count = this.items.length;
87
+ this.page = (this.currentPage + delta + count) % count;
88
+ }
71
89
  }
72
90
  //# sourceMappingURL=PageGroupNodeView.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageGroupNodeView.js","sourceRoot":"","sources":["../../src/views/PageGroupNodeView.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;IAC5B,KAAK,GAAgB,EAAE,CAAC;IACjC,WAAW,CAAS;IAE5B,YAAY,IAAmB,EAAE,QAAkD;QACjF,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,mHAAmH;IACnH,WAAW,CAAC,IAAuB;QACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC;IAC5C,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,IAAe;QACrB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC;QAC/C,MAAM,SAAS,GAAG,IAA8E,CAAC;QACjG,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,UAAU;YAAE,SAAS,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;aAC3E,CAAC;YAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAAC,CAAC;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IAES,WAAW;QACnB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAEO,eAAe;QACrB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,IAAI,SAAS,KAAa,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAErD,IAAI,IAAI,KAAa,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IAE/C,2GAA2G;IAC3G,IAAI,IAAI,CAAC,KAAa;QACpB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW;YAAE,OAAO;QACtC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;CACF","sourcesContent":["import { type PageGroupNode, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Texture } from \"pixi.js\";\r\nimport { PageItemContainer } from \"../pageGroup.js\";\r\nimport { NodeView } from \"./NodeView.js\";\r\n\r\nexport type { PageGroupNode };\r\n\r\n/**\r\n * Shows exactly one direct child (\"page\") at a time and hides the rest; each page fills the group's\r\n * full resolved rectangle (`PageItemContainer`/`scene.ts`, the same \"children don't own their own\r\n * position\" contract a layout group or scroll-view has). Page order is simply hierarchy child order,\r\n * followed by any pages appended at runtime through `addPage`.\r\n *\r\n * This view never decides on its own when to switch pages — it is driven one-way by `setPageGroupPage`\r\n * from game code, or from the standalone `pagination` widget's `onPageChange` — the same relationship\r\n * `PaginationNodeView` has with the value it displays. No built-in swipe gesture or transition.\r\n *\r\n * Pages are ordinarily authored (one per document child), but the count is not required to be known at\r\n * authoring time: a growing dataset (e.g. a spin history list appended to during play) can start with\r\n * zero or a few authored pages and grow through `addPage` — the same \"the document is a starting point,\r\n * not a ceiling\" contract `ScrollViewNodeView.addScrollItem` already gives scroll-view content.\r\n */\r\nexport class PageGroupNodeView extends NodeView {\r\n private readonly items: Container[] = [];\r\n private currentPage: number;\r\n\r\n constructor(node: PageGroupNode, textures: ReadonlyMap<string, Texture> | undefined) {\r\n super(textures);\r\n this.currentPage = Math.max(0, Math.round(node.defaultPage));\r\n }\r\n\r\n /** Registers a direct child's wrapper in hierarchy order — called once per child while the scene tree is built. */\r\n addPageItem(item: PageItemContainer): void {\r\n this.addChild(item);\r\n const index = this.items.length;\r\n this.items.push(item);\r\n item.visible = index === this.currentPage;\r\n }\r\n\r\n /**\r\n * Appends a page built at runtime (e.g. via `buildPrefabView`/`loadPrefabView`, or any hand-built\r\n * `Container`) after the last one and fits it to the group's current resolved rectangle — a\r\n * `SceneViewport` root is resized through its own `resize(...)` (the same fit contract Preview and\r\n * export already rely on); anything else falls back to `Container.width`/`height`. Hidden until\r\n * switched to via `page`/`setPageGroupViewPage`. Returns the new page's index.\r\n */\r\n addPage(view: Container): number {\r\n const { width, height } = this.layoutRectangle;\r\n const resizable = view as Partial<{ resize: (size: { width: number; height: number }) => void }>;\r\n if (typeof resizable.resize === \"function\") resizable.resize({ width, height });\r\n else { view.width = width; view.height = height; }\r\n const index = this.items.length;\r\n this.items.push(view);\r\n view.visible = index === this.currentPage;\r\n this.addChild(view);\r\n return index;\r\n }\r\n\r\n protected syncContent(): void {\r\n this.applyVisibility();\r\n }\r\n\r\n private applyVisibility(): void {\r\n this.items.forEach((item, index) => { item.visible = index === this.currentPage; });\r\n }\r\n\r\n get pageCount(): number { return this.items.length; }\r\n\r\n get page(): number { return this.currentPage; }\r\n\r\n /** External sync from game code (or the pagination widget's `onPageChange`): switches the visible page. */\r\n set page(value: number) {\r\n if (this.items.length === 0) return;\r\n const next = Math.min(Math.max(0, Math.round(value)), this.items.length - 1);\r\n if (next === this.currentPage) return;\r\n this.currentPage = next;\r\n this.applyVisibility();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"PageGroupNodeView.js","sourceRoot":"","sources":["../../src/views/PageGroupNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { type PageGroupNode, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Texture } from \"pixi.js\";\r\nimport { PageItemContainer } from \"../pageGroup.js\";\r\nimport { NodeView } from \"./NodeView.js\";\r\nimport type { PaginationArrow } from \"./PaginationNodeView.js\";\r\n\r\nexport type { PageGroupNode };\r\n\r\n/**\r\n * Shows exactly one direct child (\"page\") at a time and hides the rest; each page fills the group's\r\n * full resolved rectangle (`PageItemContainer`/`scene.ts`, the same \"children don't own their own\r\n * position\" contract a layout group or scroll-view has). Page order is simply hierarchy child order,\r\n * followed by any pages appended at runtime through `addPage`.\r\n *\r\n * This view never decides on its own when to switch pages — it is driven one-way by `setPageGroupPage`\r\n * from game code, or from the standalone `pagination` widget's `onPageChange` — the same relationship\r\n * `PaginationNodeView` has with the value it displays. No built-in swipe gesture or transition.\r\n *\r\n * Pages are ordinarily authored (one per document child), but the count is not required to be known at\r\n * authoring time: a growing dataset (e.g. a spin history list appended to during play) can start with\r\n * zero or a few authored pages and grow through `addPage` — the same \"the document is a starting point,\r\n * not a ceiling\" contract `ScrollViewNodeView.addScrollItem` already gives scroll-view content.\r\n */\r\nexport class PageGroupNodeView extends NodeView {\r\n private readonly items: Container[] = [];\r\n private currentPage: number;\r\n\r\n constructor(node: PageGroupNode, textures: ReadonlyMap<string, Texture> | undefined) {\r\n super(textures);\r\n this.currentPage = Math.max(0, Math.round(node.defaultPage));\r\n }\r\n\r\n /** Registers a direct child's wrapper in hierarchy order — called once per child while the scene tree is built. */\r\n addPageItem(item: PageItemContainer): void {\r\n this.addChild(item);\r\n const index = this.items.length;\r\n this.items.push(item);\r\n item.visible = index === this.currentPage;\r\n }\r\n\r\n /**\r\n * Appends a page built at runtime (e.g. via `buildPrefabView`/`loadPrefabView`, or any hand-built\r\n * `Container`) after the last one and fits it to the group's current resolved rectangle — a\r\n * `SceneViewport` root is resized through its own `resize(...)` (the same fit contract Preview and\r\n * export already rely on); anything else falls back to `Container.width`/`height`. Hidden until\r\n * switched to via `page`/`setPageGroupViewPage`. Returns the new page's index.\r\n */\r\n addPage(view: Container): number {\r\n const { width, height } = this.layoutRectangle;\r\n const resizable = view as Partial<{ resize: (size: { width: number; height: number }) => void }>;\r\n if (typeof resizable.resize === \"function\") resizable.resize({ width, height });\r\n else { view.width = width; view.height = height; }\r\n const index = this.items.length;\r\n this.items.push(view);\r\n view.visible = index === this.currentPage;\r\n this.addChild(view);\r\n return index;\r\n }\r\n\r\n protected syncContent(): void {\r\n this.applyVisibility();\r\n }\r\n\r\n private applyVisibility(): void {\r\n this.items.forEach((item, index) => { item.visible = index === this.currentPage; });\r\n }\r\n\r\n get pageCount(): number { return this.items.length; }\r\n\r\n get page(): number { return this.currentPage; }\r\n\r\n /** External sync from game code (or the pagination widget's `onPageChange`): switches the visible page. */\r\n set page(value: number) {\r\n if (this.items.length === 0) return;\r\n const next = Math.min(Math.max(0, Math.round(value)), this.items.length - 1);\r\n if (next === this.currentPage) return;\r\n this.currentPage = next;\r\n this.applyVisibility();\r\n }\r\n\r\n /**\r\n * Подключает опциональные авторские кнопки-стрелки `pageUpButtonNodeId`/`pageDownButtonNodeId` —\r\n * тот же приём, что `PaginationNodeView.setArrows` даёт пагинатору (ADR 0043): кнопки остаются\r\n * обычными нодами сцены, виджет только подписывается на `onPress`. В отличие от пагинатора, здесь\r\n * нет края диапазона, который гасил бы стрелку: это карусель — \"up\" с последней страницы\r\n * возвращается на первую, \"down\" с первой уходит на последнюю, поэтому обе стрелки всегда активны.\r\n */\r\n setArrows(arrows: { up?: PaginationArrow; down?: PaginationArrow }): void {\r\n arrows.up?.onPress.connect(() => this.step(1));\r\n arrows.down?.onPress.connect(() => this.step(-1));\r\n }\r\n\r\n /** Moves by `delta` pages, wrapping around both ends of the range — a carousel, not a clamp. */\r\n private step(delta: number): void {\r\n if (this.items.length === 0) return;\r\n const count = this.items.length;\r\n this.page = (this.currentPage + delta + count) % count;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SpineNodeView.d.ts","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACvH,OAAO,EAA2C,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACnK,OAAO,EAAE,SAAS,EAAoB,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,KAAK,gBAAgB,GAAG,cAAc,GAAG;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC;AAC/D,KAAK,uBAAuB,GAAG,gBAAgB,GAAG,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAqB9I,qBAAa,aAAc,SAAQ,QAAQ;IACzC,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IACjD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,oBAAoB,CAAS;IACrC,8FAA8F;IAC9F,OAAO,CAAC,aAAa,CAA8B;IAEnD,YAAY,YAAY,EAAE,YAAY,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,EAsBlO;IAED,gGAAgG;IAChG,IAAI,oBAAoB,IAAI,OAAO,CAElC;IAED,IAAI,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAEvC;IAED,0FAA0F;IAC1F,iBAAiB,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,GAAG,IAAI,CAKpE;IAED,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAwC7C;IAED,8EAA8E;IAC9E,qBAAqB,IAAI,IAAI,CAkD5B;IAED,OAAO,CAAC,uBAAuB;IAiB/B,iBAAiB,CAAC,cAAc,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI,CAEvE;IAED;;;;;OAKG;IACH,SAAS,CAAC,wBAAwB,IAAI,IAAI,CAEzC;IAED,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CA2BlG;CACF"}
1
+ {"version":3,"file":"SpineNodeView.d.ts","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACvH,OAAO,EAA2C,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACnK,OAAO,EAAE,SAAS,EAAoB,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,KAAK,gBAAgB,GAAG,cAAc,GAAG;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC;AAC/D,KAAK,uBAAuB,GAAG,gBAAgB,GAAG,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAqB9I,qBAAa,aAAc,SAAQ,QAAQ;IACzC,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;IACjD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,oBAAoB,CAAS;IACrC,8FAA8F;IAC9F,OAAO,CAAC,aAAa,CAA8B;IAEnD,YAAY,YAAY,EAAE,YAAY,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,EA6BlO;IAED,gGAAgG;IAChG,IAAI,oBAAoB,IAAI,OAAO,CAElC;IAED,IAAI,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAEvC;IAED,0FAA0F;IAC1F,iBAAiB,CAAC,QAAQ,EAAE,SAAS,uBAAuB,EAAE,GAAG,IAAI,CAKpE;IAED,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAwC7C;IAED,8EAA8E;IAC9E,qBAAqB,IAAI,IAAI,CAkD5B;IAED,OAAO,CAAC,uBAAuB;IAiB/B,iBAAiB,CAAC,cAAc,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI,CAEvE;IAED;;;;;OAKG;IACH,SAAS,CAAC,wBAAwB,IAAI,IAAI,CAEzC;IAED,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAgClG;CACF"}
@@ -32,14 +32,20 @@ export class SpineNodeView extends NodeView {
32
32
  //
33
33
  // An authoring view starts at the node's own autoplay setting, so a scene full of paused
34
34
  // skeletons subscribes to no ticker at all — the editor toggles `autoUpdate` from there.
35
- // A runtime view always keeps it on: it carries no track until game code starts an animation,
36
- // and that animation must then advance without the game touching `autoUpdate` itself.
35
+ // A runtime view always keeps it on: an animation game code starts later must advance without
36
+ // the game touching `autoUpdate` itself.
37
37
  const spine = new Spine({ skeletonData, autoUpdate: initializeForAuthoring ? autoplay : true, ...(ticker === undefined ? {} : { ticker }) });
38
38
  spine.afterUpdateWorldTransforms = () => this.refreshConnectorBones();
39
- // Runtime leaves a disabled animation without a track, ready for game code to start on an event.
40
- // Authoring still creates the track so its frame scrubber can inspect either initial state.
41
- if ((autoplay || initializeForAuthoring) && animation !== undefined && skeletonData.findAnimation(animation) !== null)
42
- spine.state.setAnimation(0, animation, loop).timeScale = animationSpeed;
39
+ // A configured animation always gets a track, posed to its own first frame a skeleton left
40
+ // without one instead renders Spine's setup/bind pose, which is almost never the intended "static"
41
+ // look and was reported as a visibly broken/twitching pose (still-running physics/IK constraints
42
+ // have nothing to settle against without a driving animation). When not autoplaying, `timeScale`
43
+ // is frozen at 0 so the track holds frame 0 forever without playing; game code starting a real
44
+ // animation later just calls `state.setAnimation(...)` itself, same as before.
45
+ if (animation !== undefined && skeletonData.findAnimation(animation) !== null) {
46
+ const playing = autoplay || initializeForAuthoring;
47
+ spine.state.setAnimation(0, animation, loop).timeScale = playing ? animationSpeed : 0;
48
+ }
43
49
  this.setContent(spine);
44
50
  }
45
51
  /** Runtime switch used by game code; authored connector definitions are inactive by default. */
@@ -187,15 +193,20 @@ export class SpineNodeView extends NodeView {
187
193
  const track = this.content.state.tracks[0];
188
194
  const animationChanged = track?.animation?.name !== settings.animation;
189
195
  const loopChanged = track !== null && track !== undefined && track.loop !== settings.loop;
190
- if (settings.animation === undefined || (!settings.autoplay && !this.initializeForAuthoring)) {
196
+ // Same "always a track, frozen at frame 0 unless actually playing" contract as the constructor:
197
+ // a static (non-autoplay) skeleton stays posed to its configured animation's first frame,
198
+ // never Spine's setup/bind pose.
199
+ const playing = settings.autoplay || this.initializeForAuthoring;
200
+ const desiredTimeScale = playing ? settings.animationSpeed : 0;
201
+ if (settings.animation === undefined) {
191
202
  if (track !== null && track !== undefined)
192
203
  this.content.state.clearTrack(0);
193
204
  }
194
205
  else if ((animationChanged || loopChanged) && this.content.skeleton.data.findAnimation(settings.animation) !== null) {
195
- this.content.state.setAnimation(0, settings.animation, settings.loop).timeScale = settings.animationSpeed;
206
+ this.content.state.setAnimation(0, settings.animation, settings.loop).timeScale = desiredTimeScale;
196
207
  }
197
208
  else if (track !== null && track !== undefined) {
198
- track.timeScale = settings.animationSpeed;
209
+ track.timeScale = desiredTimeScale;
199
210
  }
200
211
  }
201
212
  const fit = fitSpineToTransform(this.content.skeleton.data, transform, this.referenceFrame);
@@ -1 +1 @@
1
- {"version":3,"file":"SpineNodeView.js","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { PointAttachment, RegionAttachment, Spine, Vector2, type SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { resolveSpineConnectorPositionMultiplier, type LayoutProfileId, type SpineConnector, type SpineReferenceFrame, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Graphics, Matrix, type Ticker } from \"pixi.js\";\r\nimport { fitSpineToTransform, resolveSpineSettings } from \"../layout.js\";\r\nimport { NodeView } from \"./NodeView.js\";\r\n\r\ntype ConnectorBinding = SpineConnector & { target: Container };\r\ntype RuntimeConnectorBinding = ConnectorBinding | ({ boneName: string; targetNodeId: string; target: Container } & Partial<ConnectorBinding>);\r\ntype ConnectorSnapshot = {\r\n target: Container;\r\n parent: Container;\r\n index: number;\r\n position: { x: number; y: number };\r\n scale: { x: number; y: number };\r\n skew: { x: number; y: number };\r\n pivot: { x: number; y: number };\r\n rotation: number;\r\n};\r\ntype ActiveConnector = ConnectorSnapshot & Pick<SpineConnector, \"partType\" | \"partName\" | \"positionMultiplier\" | \"positionMultiplierOverrides\"> & { host: Container };\n\nfunction resolveConnectorPart(binding: RuntimeConnectorBinding): Pick<SpineConnector, \"partType\" | \"partName\"> | undefined {\n if ((binding.partType === \"bone\" || binding.partType === \"slot\") && typeof binding.partName === \"string\" && binding.partName.length > 0) {\n return { partType: binding.partType, partName: binding.partName };\n }\n const boneName = \"boneName\" in binding ? binding.boneName : undefined;\n return typeof boneName === \"string\" && boneName.length > 0 ? { partType: \"bone\", partName: boneName } : undefined;\n}\n\nexport class SpineNodeView extends NodeView {\n private referenceFrame: SpineReferenceFrame | undefined;\n private readonly initializeForAuthoring: boolean;\n private connectorBindings: RuntimeConnectorBinding[] = [];\r\n private activeConnectors: ActiveConnector[] = [];\r\n private connectorBonesActive = false;\r\n /** Layout profile the view was last synced with; connector multipliers resolve against it. */\r\n private activeProfile: LayoutProfileId = \"desktop\";\n\r\n constructor(skeletonData: SkeletonData | undefined, animation: string | undefined, autoplay: boolean, loop: boolean, animationSpeed: number, initializeForAuthoring: boolean, referenceFrame?: SpineReferenceFrame, ticker?: Ticker) {\r\n super();\n this.referenceFrame = referenceFrame;\n this.initializeForAuthoring = initializeForAuthoring;\n if (skeletonData === undefined) {\r\n this.setContent(new Graphics());\r\n return;\r\n }\r\n // The host's own Application ticker, when it passed one: a Spine left on the default\r\n // `Ticker.shared` advances its skeleton in a second rAF loop, out of band with the renderer\r\n // that actually draws it.\r\n //\r\n // An authoring view starts at the node's own autoplay setting, so a scene full of paused\r\n // skeletons subscribes to no ticker at all — the editor toggles `autoUpdate` from there.\r\n // A runtime view always keeps it on: it carries no track until game code starts an animation,\r\n // and that animation must then advance without the game touching `autoUpdate` itself.\r\n const spine = new Spine({ skeletonData, autoUpdate: initializeForAuthoring ? autoplay : true, ...(ticker === undefined ? {} : { ticker }) });\n spine.afterUpdateWorldTransforms = () => this.refreshConnectorBones();\n // Runtime leaves a disabled animation without a track, ready for game code to start on an event.\r\n // Authoring still creates the track so its frame scrubber can inspect either initial state.\r\n if ((autoplay || initializeForAuthoring) && animation !== undefined && skeletonData.findAnimation(animation) !== null) spine.state.setAnimation(0, animation, loop).timeScale = animationSpeed;\r\n this.setContent(spine);\n }\n\n /** Runtime switch used by game code; authored connector definitions are inactive by default. */\n get activeConnectorBones(): boolean {\n return this.connectorBonesActive;\n }\n\n set activeConnectorBones(active: boolean) {\n this.setConnectorBonesActive(active);\n }\n\n /** Replaces the scene-resolved connector targets, preserving the current active state. */\n setConnectorBones(bindings: readonly RuntimeConnectorBinding[]): void {\n const wasActive = this.connectorBonesActive;\n if (wasActive) this.setConnectorBonesActive(false);\n this.connectorBindings = [...bindings];\n if (wasActive) this.setConnectorBonesActive(true);\n }\n\n setConnectorBonesActive(active: boolean): void {\n if (active === this.connectorBonesActive) return;\n this.connectorBonesActive = active;\n if (!active) {\n this.restoreConnectorTargets();\n return;\n }\n\n const spine = this.getSpine();\n if (spine === undefined) return;\n for (const binding of this.connectorBindings) {\n const part = resolveConnectorPart(binding);\n if (part === undefined) continue;\n if (part.partType === \"bone\" ? spine.skeleton.findBone(part.partName) === null : spine.skeleton.findSlot(part.partName) === null) continue;\n const parent = binding.target.parent;\n if (parent === null || parent.destroyed) continue;\n const host = new Container();\n const snapshot: ActiveConnector = {\r\n partType: part.partType,\r\n partName: part.partName,\r\n positionMultiplier: binding.positionMultiplier,\r\n positionMultiplierOverrides: binding.positionMultiplierOverrides,\r\n target: binding.target,\r\n parent,\r\n index: parent.getChildIndex(binding.target),\r\n position: { x: binding.target.position.x, y: binding.target.position.y },\r\n scale: { x: binding.target.scale.x, y: binding.target.scale.y },\r\n skew: { x: binding.target.skew.x, y: binding.target.skew.y },\r\n pivot: { x: binding.target.pivot.x, y: binding.target.pivot.y },\r\n rotation: binding.target.rotation,\r\n host,\r\n };\n // The host genuinely belongs to the Spine view, so the authored skeleton offset inherits the\n // visual Spine fit. refreshConnectorBones compensates the host's linear transform only, so the\n // target keeps its original UI size/orientation.\n spine.addChild(host);\n host.addChild(binding.target);\n this.activeConnectors.push(snapshot);\n }\n this.refreshConnectorBones();\n }\n\n /** Reapplies bone matrices and the target's required zero local transform. */\n refreshConnectorBones(): void {\n const spine = this.getSpine();\n if (spine === undefined) return;\n for (const connector of this.activeConnectors) {\n const slot = connector.partType === \"slot\" ? spine.skeleton.findSlot(connector.partName) : null;\n const bone = connector.partType === \"bone\" ? spine.skeleton.findBone(connector.partName) : slot?.bone;\n if (bone === null || bone === undefined || connector.parent.destroyed) continue;\n // A slot itself has no transform beyond its bone, but a region attachment does: Spine stores\n // its authored Point offset in attachment.x/y. Project that attachment origin, otherwise\n // changing Point from e.g. -650 to -850 moves the visual attachment but not the UI connector.\n const attachment = slot?.attachment;\n let spineX = bone.worldX;\n let spineY = bone.worldY;\n if (attachment instanceof PointAttachment) {\n const point = attachment.computeWorldPosition(bone, new Vector2());\n spineX = point.x;\n spineY = point.y;\n } else if (attachment instanceof RegionAttachment) {\n spineX += attachment.x * bone.a + attachment.y * bone.b;\n spineY += attachment.x * bone.c + attachment.y * bone.d;\n }\n const spineWorld = spine.getGlobalTransform();\r\n const parentWorld = connector.parent.getGlobalTransform();\r\n const determinant = spineWorld.a * spineWorld.d - spineWorld.b * spineWorld.c;\r\n if (!Number.isFinite(determinant) || Math.abs(determinant) < 1e-8) continue;\r\n\r\n // Authored per-axis position multiplier (default 1): scales the projected part position from\r\n // the Spine node's origin before the parent transform compensation, so the target keeps its\r\n // own size/orientation and only its offset is multiplied.\r\n const multiplier = resolveSpineConnectorPositionMultiplier(connector, this.activeProfile);\r\n\r\n // The attachment position remains in original Spine source units and therefore inherits the\r\n // fitted Spine scale. For example, y=-650 at a 1/3 fit becomes roughly -217 on the UI scene.\r\n // Only the host's linear transform is compensated, so the target itself does not shrink.\r\n const hostA = (spineWorld.d * parentWorld.a - spineWorld.c * parentWorld.b) / determinant;\r\n const hostB = (-spineWorld.b * parentWorld.a + spineWorld.a * parentWorld.b) / determinant;\r\n const hostC = (spineWorld.d * parentWorld.c - spineWorld.c * parentWorld.d) / determinant;\r\n const hostD = (-spineWorld.b * parentWorld.c + spineWorld.a * parentWorld.d) / determinant;\r\n connector.host.setFromMatrix(new Matrix(\r\n hostA,\r\n hostB,\r\n hostC,\r\n hostD,\r\n spineX * multiplier.x,\r\n spineY * multiplier.y,\r\n ));\n connector.host.visible = slot === null\n || (spine.skeleton.drawOrder.includes(slot) && slot.attachment !== null && spine.alpha > 0 && spine.skeleton.color.a * slot.color.a > 0);\n connector.target.position.set(0, 0);\n }\n }\n\n private restoreConnectorTargets(): void {\n for (const connector of this.activeConnectors) {\n const { target, parent } = connector;\n if (!target.destroyed && !parent.destroyed) {\n const index = Math.min(connector.index, parent.children.length);\n parent.addChildAt(target, index);\n target.position.set(connector.position.x, connector.position.y);\n target.scale.set(connector.scale.x, connector.scale.y);\n target.skew.set(connector.skew.x, connector.skew.y);\n target.pivot.set(connector.pivot.x, connector.pivot.y);\n target.rotation = connector.rotation;\n }\n connector.host.destroy({ children: false });\n }\n this.activeConnectors = [];\n }\n\r\n setReferenceFrame(referenceFrame: SpineReferenceFrame | undefined): void {\r\n this.referenceFrame = referenceFrame;\r\n }\r\n\r\n /**\r\n * Every transform application (editor gesture previews, document commits, layout updates, anchor\r\n * resizes) recomputes active connector hosts immediately. The host's local matrix depends on the\r\n * spine's world transform — including the fitted width/height scale — so a resize of the spine\r\n * node must move its targets in the same pass, not on the next ticker frame or document commit.\r\n */\r\n protected onLayoutTransformApplied(): void {\r\n if (this.connectorBonesActive) this.refreshConnectorBones();\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"], profile: LayoutProfileId): void {\r\n this.activeProfile = profile;\r\n if (this.content instanceof Spine) {\n if (node.type === \"spine\") {\n const settings = resolveSpineSettings(node, profile);\n const track = this.content.state.tracks[0];\n const animationChanged = track?.animation?.name !== settings.animation;\n const loopChanged = track !== null && track !== undefined && track.loop !== settings.loop;\n if (settings.animation === undefined || (!settings.autoplay && !this.initializeForAuthoring)) {\n if (track !== null && track !== undefined) this.content.state.clearTrack(0);\n } else if ((animationChanged || loopChanged) && this.content.skeleton.data.findAnimation(settings.animation) !== null) {\n this.content.state.setAnimation(0, settings.animation, settings.loop).timeScale = settings.animationSpeed;\n } else if (track !== null && track !== undefined) {\n track.timeScale = settings.animationSpeed;\n }\n }\n const fit = fitSpineToTransform(this.content.skeleton.data, transform, this.referenceFrame);\r\n if (fit !== undefined) {\r\n this.content.scale.set(fit.scaleX, fit.scaleY);\r\n this.content.position.set(fit.x, fit.y);\r\n }\r\n // A paused Spine does not receive a ticker update. Refresh its world transforms after a\r\n // layout/viewport change so its displayed pose immediately matches the new fitted bounds.\r\n this.content.update(0);\r\n } else if (this.content instanceof Graphics) {\r\n this.content.clear().rect(0, 0, transform.width, transform.height).fill(0xff00ff);\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"SpineNodeView.js","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { PointAttachment, RegionAttachment, Spine, Vector2, type SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { resolveSpineConnectorPositionMultiplier, type LayoutProfileId, type SpineConnector, type SpineReferenceFrame, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Graphics, Matrix, type Ticker } from \"pixi.js\";\r\nimport { fitSpineToTransform, resolveSpineSettings } from \"../layout.js\";\r\nimport { NodeView } from \"./NodeView.js\";\r\n\r\ntype ConnectorBinding = SpineConnector & { target: Container };\r\ntype RuntimeConnectorBinding = ConnectorBinding | ({ boneName: string; targetNodeId: string; target: Container } & Partial<ConnectorBinding>);\r\ntype ConnectorSnapshot = {\r\n target: Container;\r\n parent: Container;\r\n index: number;\r\n position: { x: number; y: number };\r\n scale: { x: number; y: number };\r\n skew: { x: number; y: number };\r\n pivot: { x: number; y: number };\r\n rotation: number;\r\n};\r\ntype ActiveConnector = ConnectorSnapshot & Pick<SpineConnector, \"partType\" | \"partName\" | \"positionMultiplier\" | \"positionMultiplierOverrides\"> & { host: Container };\r\n\r\nfunction resolveConnectorPart(binding: RuntimeConnectorBinding): Pick<SpineConnector, \"partType\" | \"partName\"> | undefined {\r\n if ((binding.partType === \"bone\" || binding.partType === \"slot\") && typeof binding.partName === \"string\" && binding.partName.length > 0) {\r\n return { partType: binding.partType, partName: binding.partName };\r\n }\r\n const boneName = \"boneName\" in binding ? binding.boneName : undefined;\r\n return typeof boneName === \"string\" && boneName.length > 0 ? { partType: \"bone\", partName: boneName } : undefined;\r\n}\r\n\r\nexport class SpineNodeView extends NodeView {\r\n private referenceFrame: SpineReferenceFrame | undefined;\r\n private readonly initializeForAuthoring: boolean;\r\n private connectorBindings: RuntimeConnectorBinding[] = [];\r\n private activeConnectors: ActiveConnector[] = [];\r\n private connectorBonesActive = false;\r\n /** Layout profile the view was last synced with; connector multipliers resolve against it. */\r\n private activeProfile: LayoutProfileId = \"desktop\";\r\n\r\n constructor(skeletonData: SkeletonData | undefined, animation: string | undefined, autoplay: boolean, loop: boolean, animationSpeed: number, initializeForAuthoring: boolean, referenceFrame?: SpineReferenceFrame, ticker?: Ticker) {\r\n super();\r\n this.referenceFrame = referenceFrame;\r\n this.initializeForAuthoring = initializeForAuthoring;\r\n if (skeletonData === undefined) {\r\n this.setContent(new Graphics());\r\n return;\r\n }\r\n // The host's own Application ticker, when it passed one: a Spine left on the default\r\n // `Ticker.shared` advances its skeleton in a second rAF loop, out of band with the renderer\r\n // that actually draws it.\r\n //\r\n // An authoring view starts at the node's own autoplay setting, so a scene full of paused\r\n // skeletons subscribes to no ticker at all — the editor toggles `autoUpdate` from there.\r\n // A runtime view always keeps it on: an animation game code starts later must advance without\r\n // the game touching `autoUpdate` itself.\r\n const spine = new Spine({ skeletonData, autoUpdate: initializeForAuthoring ? autoplay : true, ...(ticker === undefined ? {} : { ticker }) });\r\n spine.afterUpdateWorldTransforms = () => this.refreshConnectorBones();\r\n // A configured animation always gets a track, posed to its own first frame — a skeleton left\r\n // without one instead renders Spine's setup/bind pose, which is almost never the intended \"static\"\r\n // look and was reported as a visibly broken/twitching pose (still-running physics/IK constraints\r\n // have nothing to settle against without a driving animation). When not autoplaying, `timeScale`\r\n // is frozen at 0 so the track holds frame 0 forever without playing; game code starting a real\r\n // animation later just calls `state.setAnimation(...)` itself, same as before.\r\n if (animation !== undefined && skeletonData.findAnimation(animation) !== null) {\r\n const playing = autoplay || initializeForAuthoring;\r\n spine.state.setAnimation(0, animation, loop).timeScale = playing ? animationSpeed : 0;\r\n }\r\n this.setContent(spine);\r\n }\r\n\r\n /** Runtime switch used by game code; authored connector definitions are inactive by default. */\r\n get activeConnectorBones(): boolean {\r\n return this.connectorBonesActive;\r\n }\r\n\r\n set activeConnectorBones(active: boolean) {\r\n this.setConnectorBonesActive(active);\r\n }\r\n\r\n /** Replaces the scene-resolved connector targets, preserving the current active state. */\r\n setConnectorBones(bindings: readonly RuntimeConnectorBinding[]): void {\r\n const wasActive = this.connectorBonesActive;\r\n if (wasActive) this.setConnectorBonesActive(false);\r\n this.connectorBindings = [...bindings];\r\n if (wasActive) this.setConnectorBonesActive(true);\r\n }\r\n\r\n setConnectorBonesActive(active: boolean): void {\r\n if (active === this.connectorBonesActive) return;\r\n this.connectorBonesActive = active;\r\n if (!active) {\r\n this.restoreConnectorTargets();\r\n return;\r\n }\r\n\r\n const spine = this.getSpine();\r\n if (spine === undefined) return;\r\n for (const binding of this.connectorBindings) {\r\n const part = resolveConnectorPart(binding);\r\n if (part === undefined) continue;\r\n if (part.partType === \"bone\" ? spine.skeleton.findBone(part.partName) === null : spine.skeleton.findSlot(part.partName) === null) continue;\r\n const parent = binding.target.parent;\r\n if (parent === null || parent.destroyed) continue;\r\n const host = new Container();\r\n const snapshot: ActiveConnector = {\r\n partType: part.partType,\r\n partName: part.partName,\r\n positionMultiplier: binding.positionMultiplier,\r\n positionMultiplierOverrides: binding.positionMultiplierOverrides,\r\n target: binding.target,\r\n parent,\r\n index: parent.getChildIndex(binding.target),\r\n position: { x: binding.target.position.x, y: binding.target.position.y },\r\n scale: { x: binding.target.scale.x, y: binding.target.scale.y },\r\n skew: { x: binding.target.skew.x, y: binding.target.skew.y },\r\n pivot: { x: binding.target.pivot.x, y: binding.target.pivot.y },\r\n rotation: binding.target.rotation,\r\n host,\r\n };\r\n // The host genuinely belongs to the Spine view, so the authored skeleton offset inherits the\r\n // visual Spine fit. refreshConnectorBones compensates the host's linear transform only, so the\r\n // target keeps its original UI size/orientation.\r\n spine.addChild(host);\r\n host.addChild(binding.target);\r\n this.activeConnectors.push(snapshot);\r\n }\r\n this.refreshConnectorBones();\r\n }\r\n\r\n /** Reapplies bone matrices and the target's required zero local transform. */\r\n refreshConnectorBones(): void {\r\n const spine = this.getSpine();\r\n if (spine === undefined) return;\r\n for (const connector of this.activeConnectors) {\r\n const slot = connector.partType === \"slot\" ? spine.skeleton.findSlot(connector.partName) : null;\r\n const bone = connector.partType === \"bone\" ? spine.skeleton.findBone(connector.partName) : slot?.bone;\r\n if (bone === null || bone === undefined || connector.parent.destroyed) continue;\r\n // A slot itself has no transform beyond its bone, but a region attachment does: Spine stores\r\n // its authored Point offset in attachment.x/y. Project that attachment origin, otherwise\r\n // changing Point from e.g. -650 to -850 moves the visual attachment but not the UI connector.\r\n const attachment = slot?.attachment;\r\n let spineX = bone.worldX;\r\n let spineY = bone.worldY;\r\n if (attachment instanceof PointAttachment) {\r\n const point = attachment.computeWorldPosition(bone, new Vector2());\r\n spineX = point.x;\r\n spineY = point.y;\r\n } else if (attachment instanceof RegionAttachment) {\r\n spineX += attachment.x * bone.a + attachment.y * bone.b;\r\n spineY += attachment.x * bone.c + attachment.y * bone.d;\r\n }\r\n const spineWorld = spine.getGlobalTransform();\r\n const parentWorld = connector.parent.getGlobalTransform();\r\n const determinant = spineWorld.a * spineWorld.d - spineWorld.b * spineWorld.c;\r\n if (!Number.isFinite(determinant) || Math.abs(determinant) < 1e-8) continue;\r\n\r\n // Authored per-axis position multiplier (default 1): scales the projected part position from\r\n // the Spine node's origin before the parent transform compensation, so the target keeps its\r\n // own size/orientation and only its offset is multiplied.\r\n const multiplier = resolveSpineConnectorPositionMultiplier(connector, this.activeProfile);\r\n\r\n // The attachment position remains in original Spine source units and therefore inherits the\r\n // fitted Spine scale. For example, y=-650 at a 1/3 fit becomes roughly -217 on the UI scene.\r\n // Only the host's linear transform is compensated, so the target itself does not shrink.\r\n const hostA = (spineWorld.d * parentWorld.a - spineWorld.c * parentWorld.b) / determinant;\r\n const hostB = (-spineWorld.b * parentWorld.a + spineWorld.a * parentWorld.b) / determinant;\r\n const hostC = (spineWorld.d * parentWorld.c - spineWorld.c * parentWorld.d) / determinant;\r\n const hostD = (-spineWorld.b * parentWorld.c + spineWorld.a * parentWorld.d) / determinant;\r\n connector.host.setFromMatrix(new Matrix(\r\n hostA,\r\n hostB,\r\n hostC,\r\n hostD,\r\n spineX * multiplier.x,\r\n spineY * multiplier.y,\r\n ));\r\n connector.host.visible = slot === null\r\n || (spine.skeleton.drawOrder.includes(slot) && slot.attachment !== null && spine.alpha > 0 && spine.skeleton.color.a * slot.color.a > 0);\r\n connector.target.position.set(0, 0);\r\n }\r\n }\r\n\r\n private restoreConnectorTargets(): void {\r\n for (const connector of this.activeConnectors) {\r\n const { target, parent } = connector;\r\n if (!target.destroyed && !parent.destroyed) {\r\n const index = Math.min(connector.index, parent.children.length);\r\n parent.addChildAt(target, index);\r\n target.position.set(connector.position.x, connector.position.y);\r\n target.scale.set(connector.scale.x, connector.scale.y);\r\n target.skew.set(connector.skew.x, connector.skew.y);\r\n target.pivot.set(connector.pivot.x, connector.pivot.y);\r\n target.rotation = connector.rotation;\r\n }\r\n connector.host.destroy({ children: false });\r\n }\r\n this.activeConnectors = [];\r\n }\r\n\r\n setReferenceFrame(referenceFrame: SpineReferenceFrame | undefined): void {\r\n this.referenceFrame = referenceFrame;\r\n }\r\n\r\n /**\r\n * Every transform application (editor gesture previews, document commits, layout updates, anchor\r\n * resizes) recomputes active connector hosts immediately. The host's local matrix depends on the\r\n * spine's world transform — including the fitted width/height scale — so a resize of the spine\r\n * node must move its targets in the same pass, not on the next ticker frame or document commit.\r\n */\r\n protected onLayoutTransformApplied(): void {\r\n if (this.connectorBonesActive) this.refreshConnectorBones();\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"], profile: LayoutProfileId): void {\r\n this.activeProfile = profile;\r\n if (this.content instanceof Spine) {\r\n if (node.type === \"spine\") {\r\n const settings = resolveSpineSettings(node, profile);\r\n const track = this.content.state.tracks[0];\r\n const animationChanged = track?.animation?.name !== settings.animation;\r\n const loopChanged = track !== null && track !== undefined && track.loop !== settings.loop;\r\n // Same \"always a track, frozen at frame 0 unless actually playing\" contract as the constructor:\r\n // a static (non-autoplay) skeleton stays posed to its configured animation's first frame,\r\n // never Spine's setup/bind pose.\r\n const playing = settings.autoplay || this.initializeForAuthoring;\r\n const desiredTimeScale = playing ? settings.animationSpeed : 0;\r\n if (settings.animation === undefined) {\r\n if (track !== null && track !== undefined) this.content.state.clearTrack(0);\r\n } else if ((animationChanged || loopChanged) && this.content.skeleton.data.findAnimation(settings.animation) !== null) {\r\n this.content.state.setAnimation(0, settings.animation, settings.loop).timeScale = desiredTimeScale;\r\n } else if (track !== null && track !== undefined) {\r\n track.timeScale = desiredTimeScale;\r\n }\r\n }\r\n const fit = fitSpineToTransform(this.content.skeleton.data, transform, this.referenceFrame);\r\n if (fit !== undefined) {\r\n this.content.scale.set(fit.scaleX, fit.scaleY);\r\n this.content.position.set(fit.x, fit.y);\r\n }\r\n // A paused Spine does not receive a ticker update. Refresh its world transforms after a\r\n // layout/viewport change so its displayed pose immediately matches the new fitted bounds.\r\n this.content.update(0);\r\n } else if (this.content instanceof Graphics) {\r\n this.content.clear().rect(0, 0, transform.width, transform.height).fill(0xff00ff);\r\n }\r\n }\r\n}\r\n"]}
@@ -51,6 +51,7 @@ export declare class StagedButtonNodeView extends NodeView {
51
51
  */
52
52
  private static paintPlaceholder;
53
53
  private static createStateView;
54
+ private static applyStateAppearance;
54
55
  /**
55
56
  * (Re)builds `FancyButton` and its four state views for the current stage. `size`, when provided,
56
57
  * sizes the freshly built views immediately — needed because a stage change may happen well outside
@@ -1 +1 @@
1
- {"version":3,"file":"StagedButtonNodeView.d.ts","sourceRoot":"","sources":["../../src/views/StagedButtonNodeView.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StagedButtonNodeView.d.ts","sourceRoot":"","sources":["../../src/views/StagedButtonNodeView.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,10 @@ export class StagedButtonNodeView extends NodeView {
74
74
  ? new Sprite(texture)
75
75
  : new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });
76
76
  }
77
+ static applyStateAppearance(view, stage, state) {
78
+ view.tint = stage.states[`${state}Tint`] ?? "#ffffff";
79
+ view.alpha = stage.states[`${state}Opacity`] ?? 1;
80
+ }
77
81
  /**
78
82
  * (Re)builds `FancyButton` and its four state views for the current stage. `size`, when provided,
79
83
  * sizes the freshly built views immediately — needed because a stage change may happen well outside
@@ -90,6 +94,7 @@ export class StagedButtonNodeView extends NodeView {
90
94
  const viewFor = (state, assetId) => {
91
95
  const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;
92
96
  const view = StagedButtonNodeView.createStateView(texture, this.nineSlice, resolvedSize);
97
+ StagedButtonNodeView.applyStateAppearance(view, stage, state);
93
98
  stateViews[state] = view;
94
99
  return view;
95
100
  };
@@ -193,6 +198,7 @@ export class StagedButtonNodeView extends NodeView {
193
198
  if (texture !== undefined && view.texture !== texture)
194
199
  view.texture = texture;
195
200
  }
201
+ StagedButtonNodeView.applyStateAppearance(view, stage, state);
196
202
  }
197
203
  this.applySizes(width, height);
198
204
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StagedButtonNodeView.js","sourceRoot":"","sources":["../../src/views/StagedButtonNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { BUTTON_STATE_KEYS, type ButtonStateKey, type LayoutPadding, type StagedButtonNode, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { FancyButton } from \"@pixi/ui\";\r\nimport type { Sound } from \"@pixi/sound\";\r\nimport { Container, Graphics, NineSliceSprite, Sprite, Texture } from \"pixi.js\";\r\nimport { Signal } from \"typed-signals\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\n\r\nexport type { StagedButtonNode };\r\ntype StagedButtonStage = StagedButtonNode[\"stages\"][number];\r\ntype FancyButtonEventHandler = Parameters<FancyButton[\"onPress\"][\"connect\"]>[0];\r\n\r\nconst FANCY_STATE_BY_KEY = { normal: \"default\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\n\r\n/**\r\n * Adapts a staged-button node to `@pixi/ui`'s `FancyButton`, exactly like `ButtonNodeView` does for a\r\n * plain button — this class never reimplements its pointer state machine either. It is a deliberately\r\n * separate component (see TASK-057): it does not extend or share behavior with `ButtonNodeView`.\r\n *\r\n * A click at runtime advances the current stage (`next()`), which respects `wrap`. Four state views\r\n * are created once and reused across stages: changing stage only reassigns their textures/size, never\r\n * replacing the view type — a full `FancyButton` rebuild only happens when a view's required *type*\r\n * changes (nine-slice toggled, or a texture just finished loading), because `FancyButton` gives no way\r\n * to swap a view after construction.\r\n */\r\nexport class StagedButtonNodeView extends NodeView {\r\n private button!: FancyButton;\r\n private stateViews!: Record<ButtonStateKey, Container>;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly sounds: ReadonlyMap<string, Sound> | undefined;\r\n private soundAssetIds: StagedButtonNode[\"sounds\"];\r\n private nineSlice: LayoutPadding | undefined;\r\n private stagesData: StagedButtonStage[];\r\n private currentStageId: string;\r\n private defaultStageId: string;\r\n private wrapState: boolean;\r\n private enabledState: boolean;\r\n /** Последнее editor-only визуальное состояние из `setState`: переживает пересборку `FancyButton`. */\r\n private forcedState: ButtonStateKey | undefined;\r\n\r\n /** Stable public signals: subscriptions survive an internal `FancyButton` rebuild. */\r\n readonly onPress: FancyButton[\"onPress\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onDown: FancyButton[\"onDown\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onUp: FancyButton[\"onUp\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onHover: FancyButton[\"onHover\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onOut: FancyButton[\"onOut\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onStageChange = new Signal<(stage: { index: number; value: string }) => void>();\r\n\r\n constructor(node: StagedButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.sounds = sounds;\r\n this.soundAssetIds = node.sounds;\r\n this.nineSlice = node.nineSlice;\r\n this.stagesData = node.stages;\r\n this.wrapState = node.wrap;\r\n this.defaultStageId = node.defaultStageId;\r\n this.currentStageId = node.stages.some((stage) => stage.id === node.defaultStageId) ? node.defaultStageId : node.stages[0]!.id;\r\n this.enabledState = node.enabled;\r\n // Explicit size, not the `this.layoutRectangle` default `buildButton()` would otherwise fall back\r\n // to: no layout pass has run yet at construction time, so that getter still reads `{0, 0}`.\r\n this.buildButton({ width: node.transform.width, height: node.transform.height });\r\n }\r\n\r\n private currentStage(): StagedButtonStage {\r\n return this.stagesData.find((stage) => stage.id === this.currentStageId) ?? this.stagesData[0]!;\r\n }\r\n\r\n /**\r\n * Invisible (alpha 0) but still hit-testable: Pixi's `containsPoint` hit-tests the fill's geometry\r\n * regardless of its alpha. Painted with a real size *before* the view ever reaches `FancyButton`:\r\n * `FancyButton` reads `defaultView`'s bounds exactly once, synchronously during construction, to\r\n * freeze its own `hitArea` — it never re-reads them afterwards. A `Graphics` still at its default\r\n * (0, 0) size at that moment would freeze a zero-size, permanently unclickable hit area.\r\n */\r\n private static paintPlaceholder(graphics: Graphics, width: number, height: number): void {\r\n graphics.clear().rect(0, 0, width, height).fill({ color: 0x000000, alpha: 0 });\r\n }\r\n\r\n private static createStateView(texture: Texture | undefined, nineSlice: LayoutPadding | undefined, size: { width: number; height: number }): Container {\r\n if (texture === undefined) {\r\n const graphics = new Graphics();\r\n StagedButtonNodeView.paintPlaceholder(graphics, size.width, size.height);\r\n return graphics;\r\n }\r\n return nineSlice === undefined\r\n ? new Sprite(texture)\r\n : new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });\r\n }\r\n\r\n /**\r\n * (Re)builds `FancyButton` and its four state views for the current stage. `size`, when provided,\r\n * sizes the freshly built views immediately — needed because a stage change may happen well outside\r\n * a `syncContent` pass (e.g. a runtime click), where nothing else would resize them afterwards. The\r\n * constructor also always passes it explicitly: `this.layoutRectangle` is still `{0, 0}` before the\r\n * first layout pass, and an initial placeholder painted at that size would freeze a zero-size,\r\n * permanently unclickable `hitArea` on `FancyButton` (see `paintPlaceholder`).\r\n */\r\n private buildButton(size?: { width: number; height: number }): void {\r\n const stage = this.currentStage();\r\n const normalTexture = this.textureFor(stage.states.normalAssetId);\r\n const resolvedSize = size ?? this.layoutRectangle;\r\n const stateViews = {} as Record<ButtonStateKey, Container>;\r\n const viewFor = (state: ButtonStateKey, assetId: string | undefined): Container => {\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = StagedButtonNodeView.createStateView(texture, this.nineSlice, resolvedSize);\r\n stateViews[state] = view;\r\n return view;\r\n };\r\n\r\n const button = new FancyButton({\r\n defaultView: viewFor(\"normal\", stage.states.normalAssetId),\r\n hoverView: viewFor(\"hover\", stage.states.hoverAssetId),\r\n pressedView: viewFor(\"pressed\", stage.states.pressedAssetId),\r\n disabledView: viewFor(\"disabled\", stage.states.disabledAssetId),\r\n });\r\n // Authoring-сцена инертна, как и у обычной кнопки: клики не должны крутить стадию, а попадание по\r\n // ноде остаётся ответственностью NodeView.containsPoint.\r\n if (this.interaction === \"authoring\") button.eventMode = \"none\";\r\n else {\r\n button.onPress.connect((source, event) => {\r\n this.next();\r\n const result = this.soundAssetIds?.pressAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.pressAssetId)?.play();\r\n if (result instanceof Promise) void result.catch(() => undefined);\r\n this.onPress.emit(source, event);\r\n });\r\n button.onDown.connect((source, event) => this.onDown.emit(source, event));\r\n button.onUp.connect((source, event) => this.onUp.emit(source, event));\r\n button.onHover.connect((source, event) => {\r\n const result = this.soundAssetIds?.hoverAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.hoverAssetId)?.play();\r\n if (result instanceof Promise) void result.catch(() => undefined);\r\n this.onHover.emit(source, event);\r\n });\r\n button.onOut.connect((source, event) => this.onOut.emit(source, event));\r\n }\r\n this.button = button;\r\n this.stateViews = stateViews;\r\n this.setContent(button);\r\n\r\n this.applySizes(resolvedSize.width, resolvedSize.height);\r\n\r\n // Пересборка — деталь реализации `FancyButton`, а не действие пользователя: transient enabled и\r\n // визуальное состояние восстанавливаются на новом инстансе, иначе переключение nine-slice или\r\n // догрузка текстуры сбрасывали бы их.\r\n this.applyEnabled(this.enabledState);\r\n if (this.forcedState !== undefined) this.button.setState(FANCY_STATE_BY_KEY[this.forcedState]);\r\n }\r\n\r\n /**\r\n * Sizes the four state views to the resolved layout rectangle without touching their textures.\r\n *\r\n * `NineSliceSprite` проверяется отдельно: в PixiJS 8 он наследуется от `ViewContainer`, а не от\r\n * `Sprite`, поэтому одна ветка `instanceof Sprite` его молча пропускает.\r\n */\r\n private applySizes(width: number, height: number): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (view instanceof NineSliceSprite) view.setSize(width, height);\r\n else if (view instanceof Sprite) view.setSize(width, height);\r\n else if (view instanceof Graphics) StagedButtonNodeView.paintPlaceholder(view, width, height);\r\n }\r\n }\r\n\r\n /**\r\n * Applies the current stage's textures/border to the existing state views (or rebuilds them if a\r\n * view's required type no longer matches, the same rule `ButtonNodeView.syncContent` follows).\r\n */\r\n private refreshStateViews(width: number, height: number): void {\r\n const stage = this.currentStage();\r\n const normalTexture = this.textureFor(stage.states.normalAssetId);\r\n\r\n let needsRebuild = false;\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const assetId = stage.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = this.stateViews[state];\r\n const wantsNineSlice = texture !== undefined && this.nineSlice !== undefined;\r\n // `NineSliceSprite` не наследуется от `Sprite` в PixiJS 8, поэтому ветки не пересекаются.\r\n const matches = texture === undefined ? view instanceof Graphics : wantsNineSlice ? view instanceof NineSliceSprite : view instanceof Sprite;\r\n if (!matches) { needsRebuild = true; break; }\r\n }\r\n\r\n if (needsRebuild) {\r\n this.buildButton({ width, height });\r\n return;\r\n }\r\n\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n const assetId = stage.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n // Set the texture before the layout size: Sprite/NineSliceSprite preserve scale when their\r\n // texture changes, so sizing first would shift visual bounds for a differently-sized source.\r\n if (view instanceof NineSliceSprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n if (this.nineSlice !== undefined) {\r\n view.leftWidth = this.nineSlice.left;\r\n view.topHeight = this.nineSlice.top;\r\n view.rightWidth = this.nineSlice.right;\r\n view.bottomHeight = this.nineSlice.bottom;\r\n }\r\n } else if (view instanceof Sprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n }\r\n }\r\n this.applySizes(width, height);\r\n }\r\n\r\n private applyStage(stageId: string): void {\r\n this.currentStageId = stageId;\r\n const { width, height } = this.layoutRectangle;\r\n this.refreshStateViews(width, height);\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive the visuals: `FancyButton` couples it to `eventMode`. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"runtime\") this.button.enabled = enabled;\r\n else this.button.setState(enabled ? \"default\" : \"disabled\");\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"staged-button\") return;\r\n this.soundAssetIds = node.sounds;\r\n this.nineSlice = node.nineSlice;\r\n this.wrapState = node.wrap;\r\n this.defaultStageId = node.defaultStageId;\r\n\r\n // Сохраняет текущую стадию, если она ещё существует после изменения документа; если стадию\r\n // удалили — переходит на ближайшую валидную по прежнему индексу.\r\n const previousIndex = this.stagesData.findIndex((stage) => stage.id === this.currentStageId);\r\n this.stagesData = node.stages;\r\n if (!node.stages.some((stage) => stage.id === this.currentStageId)) {\r\n const clampedIndex = Math.min(Math.max(previousIndex, 0), node.stages.length - 1);\r\n this.currentStageId = node.stages[clampedIndex]!.id;\r\n }\r\n\r\n this.refreshStateViews(transform.width, transform.height);\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n /** Editor-only live preview of nine-slice border edits while dragging the canvas gizmo. */\r\n previewNineSlice(nineSlice: LayoutPadding): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (!(view instanceof NineSliceSprite)) continue;\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get stage(): number {\r\n const index = this.stagesData.findIndex((stage) => stage.id === this.currentStageId);\r\n return index === -1 ? 0 : index;\r\n }\r\n\r\n get value(): string {\r\n return this.currentStage().value;\r\n }\r\n\r\n get stageCount(): number {\r\n return this.stagesData.length;\r\n }\r\n\r\n /** Moves to the stage at `index` and emits `onStageChange`; an out-of-range index is a no-op. */\r\n setStage(index: number): void {\r\n const target = this.stagesData[index];\r\n if (target === undefined) return;\r\n this.applyStage(target.id);\r\n this.onStageChange.emit({ index, value: target.value });\r\n }\r\n\r\n /** Moves to the stage at `index` without emitting — used by editor preview to avoid feedback loops. */\r\n forceStage(index: number): void {\r\n const target = this.stagesData[index];\r\n if (target === undefined) return;\r\n this.applyStage(target.id);\r\n }\r\n\r\n /** Moves to the first stage whose `value` matches; an unknown value is ignored. */\r\n setValue(value: string): void {\r\n const index = this.stagesData.findIndex((stage) => stage.value === value);\r\n if (index === -1) return;\r\n this.setStage(index);\r\n }\r\n\r\n /** Advances one stage, as a click does; respects `wrap` at the last stage. */\r\n next(): void {\r\n const nextIndex = this.stage + 1;\r\n if (nextIndex >= this.stagesData.length) {\r\n if (!this.wrapState) return;\r\n this.setStage(0);\r\n return;\r\n }\r\n this.setStage(nextIndex);\r\n }\r\n\r\n /** Returns to `defaultStageId`, emitting `onStageChange`. */\r\n reset(): void {\r\n const index = this.stagesData.findIndex((stage) => stage.id === this.defaultStageId);\r\n this.setStage(index === -1 ? 0 : index);\r\n }\r\n\r\n /** Forces an editor-only visual state without changing `enabled`, mirroring `ButtonNodeView.setState`. */\r\n setState(state: ButtonStateKey): void {\r\n this.forcedState = state;\r\n this.button.setState(FANCY_STATE_BY_KEY[state]);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"StagedButtonNodeView.js","sourceRoot":"","sources":["../../src/views/StagedButtonNodeView.ts"],"names":[],"mappings":"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","sourcesContent":["import { BUTTON_STATE_KEYS, type ButtonStateKey, type LayoutPadding, type StagedButtonNode, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { FancyButton } from \"@pixi/ui\";\r\nimport type { Sound } from \"@pixi/sound\";\r\nimport { Container, Graphics, NineSliceSprite, Sprite, Texture } from \"pixi.js\";\r\nimport { Signal } from \"typed-signals\";\r\nimport { NodeView, type SceneInteractionMode } from \"./NodeView.js\";\r\n\r\nexport type { StagedButtonNode };\r\ntype StagedButtonStage = StagedButtonNode[\"stages\"][number];\r\ntype FancyButtonEventHandler = Parameters<FancyButton[\"onPress\"][\"connect\"]>[0];\r\n\r\nconst FANCY_STATE_BY_KEY = { normal: \"default\", hover: \"hover\", pressed: \"pressed\", disabled: \"disabled\" } as const;\r\n\r\n/**\r\n * Adapts a staged-button node to `@pixi/ui`'s `FancyButton`, exactly like `ButtonNodeView` does for a\r\n * plain button — this class never reimplements its pointer state machine either. It is a deliberately\r\n * separate component (see TASK-057): it does not extend or share behavior with `ButtonNodeView`.\r\n *\r\n * A click at runtime advances the current stage (`next()`), which respects `wrap`. Four state views\r\n * are created once and reused across stages: changing stage only reassigns their textures/size, never\r\n * replacing the view type — a full `FancyButton` rebuild only happens when a view's required *type*\r\n * changes (nine-slice toggled, or a texture just finished loading), because `FancyButton` gives no way\r\n * to swap a view after construction.\r\n */\r\nexport class StagedButtonNodeView extends NodeView {\r\n private button!: FancyButton;\r\n private stateViews!: Record<ButtonStateKey, Container>;\r\n private readonly interaction: SceneInteractionMode;\r\n private readonly sounds: ReadonlyMap<string, Sound> | undefined;\r\n private soundAssetIds: StagedButtonNode[\"sounds\"];\r\n private nineSlice: LayoutPadding | undefined;\r\n private stagesData: StagedButtonStage[];\r\n private currentStageId: string;\r\n private defaultStageId: string;\r\n private wrapState: boolean;\r\n private enabledState: boolean;\r\n /** Последнее editor-only визуальное состояние из `setState`: переживает пересборку `FancyButton`. */\r\n private forcedState: ButtonStateKey | undefined;\r\n\r\n /** Stable public signals: subscriptions survive an internal `FancyButton` rebuild. */\r\n readonly onPress: FancyButton[\"onPress\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onDown: FancyButton[\"onDown\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onUp: FancyButton[\"onUp\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onHover: FancyButton[\"onHover\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onOut: FancyButton[\"onOut\"] = new Signal<FancyButtonEventHandler>();\r\n readonly onStageChange = new Signal<(stage: { index: number; value: string }) => void>();\r\n\r\n constructor(node: StagedButtonNode, textures: ReadonlyMap<string, Texture> | undefined, interaction: SceneInteractionMode, sounds?: ReadonlyMap<string, Sound>) {\r\n super(textures);\r\n this.interaction = interaction;\r\n this.sounds = sounds;\r\n this.soundAssetIds = node.sounds;\r\n this.nineSlice = node.nineSlice;\r\n this.stagesData = node.stages;\r\n this.wrapState = node.wrap;\r\n this.defaultStageId = node.defaultStageId;\r\n this.currentStageId = node.stages.some((stage) => stage.id === node.defaultStageId) ? node.defaultStageId : node.stages[0]!.id;\r\n this.enabledState = node.enabled;\r\n // Explicit size, not the `this.layoutRectangle` default `buildButton()` would otherwise fall back\r\n // to: no layout pass has run yet at construction time, so that getter still reads `{0, 0}`.\r\n this.buildButton({ width: node.transform.width, height: node.transform.height });\r\n }\r\n\r\n private currentStage(): StagedButtonStage {\r\n return this.stagesData.find((stage) => stage.id === this.currentStageId) ?? this.stagesData[0]!;\r\n }\r\n\r\n /**\r\n * Invisible (alpha 0) but still hit-testable: Pixi's `containsPoint` hit-tests the fill's geometry\r\n * regardless of its alpha. Painted with a real size *before* the view ever reaches `FancyButton`:\r\n * `FancyButton` reads `defaultView`'s bounds exactly once, synchronously during construction, to\r\n * freeze its own `hitArea` — it never re-reads them afterwards. A `Graphics` still at its default\r\n * (0, 0) size at that moment would freeze a zero-size, permanently unclickable hit area.\r\n */\r\n private static paintPlaceholder(graphics: Graphics, width: number, height: number): void {\r\n graphics.clear().rect(0, 0, width, height).fill({ color: 0x000000, alpha: 0 });\r\n }\r\n\r\n private static createStateView(texture: Texture | undefined, nineSlice: LayoutPadding | undefined, size: { width: number; height: number }): Container {\n if (texture === undefined) {\r\n const graphics = new Graphics();\r\n StagedButtonNodeView.paintPlaceholder(graphics, size.width, size.height);\r\n return graphics;\r\n }\r\n return nineSlice === undefined\r\n ? new Sprite(texture)\r\n : new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });\r\n }\n\n private static applyStateAppearance(view: Container, stage: StagedButtonStage, state: ButtonStateKey): void {\n view.tint = stage.states[`${state}Tint`] ?? \"#ffffff\";\n view.alpha = stage.states[`${state}Opacity`] ?? 1;\n }\n\r\n /**\r\n * (Re)builds `FancyButton` and its four state views for the current stage. `size`, when provided,\r\n * sizes the freshly built views immediately — needed because a stage change may happen well outside\r\n * a `syncContent` pass (e.g. a runtime click), where nothing else would resize them afterwards. The\r\n * constructor also always passes it explicitly: `this.layoutRectangle` is still `{0, 0}` before the\r\n * first layout pass, and an initial placeholder painted at that size would freeze a zero-size,\r\n * permanently unclickable `hitArea` on `FancyButton` (see `paintPlaceholder`).\r\n */\r\n private buildButton(size?: { width: number; height: number }): void {\r\n const stage = this.currentStage();\r\n const normalTexture = this.textureFor(stage.states.normalAssetId);\r\n const resolvedSize = size ?? this.layoutRectangle;\r\n const stateViews = {} as Record<ButtonStateKey, Container>;\r\n const viewFor = (state: ButtonStateKey, assetId: string | undefined): Container => {\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\n const view = StagedButtonNodeView.createStateView(texture, this.nineSlice, resolvedSize);\n StagedButtonNodeView.applyStateAppearance(view, stage, state);\n stateViews[state] = view;\r\n return view;\r\n };\r\n\r\n const button = new FancyButton({\r\n defaultView: viewFor(\"normal\", stage.states.normalAssetId),\r\n hoverView: viewFor(\"hover\", stage.states.hoverAssetId),\r\n pressedView: viewFor(\"pressed\", stage.states.pressedAssetId),\r\n disabledView: viewFor(\"disabled\", stage.states.disabledAssetId),\r\n });\r\n // Authoring-сцена инертна, как и у обычной кнопки: клики не должны крутить стадию, а попадание по\r\n // ноде остаётся ответственностью NodeView.containsPoint.\r\n if (this.interaction === \"authoring\") button.eventMode = \"none\";\r\n else {\r\n button.onPress.connect((source, event) => {\r\n this.next();\r\n const result = this.soundAssetIds?.pressAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.pressAssetId)?.play();\r\n if (result instanceof Promise) void result.catch(() => undefined);\r\n this.onPress.emit(source, event);\r\n });\r\n button.onDown.connect((source, event) => this.onDown.emit(source, event));\r\n button.onUp.connect((source, event) => this.onUp.emit(source, event));\r\n button.onHover.connect((source, event) => {\r\n const result = this.soundAssetIds?.hoverAssetId === undefined ? undefined : this.sounds?.get(this.soundAssetIds.hoverAssetId)?.play();\r\n if (result instanceof Promise) void result.catch(() => undefined);\r\n this.onHover.emit(source, event);\r\n });\r\n button.onOut.connect((source, event) => this.onOut.emit(source, event));\r\n }\r\n this.button = button;\r\n this.stateViews = stateViews;\r\n this.setContent(button);\r\n\r\n this.applySizes(resolvedSize.width, resolvedSize.height);\r\n\r\n // Пересборка — деталь реализации `FancyButton`, а не действие пользователя: transient enabled и\r\n // визуальное состояние восстанавливаются на новом инстансе, иначе переключение nine-slice или\r\n // догрузка текстуры сбрасывали бы их.\r\n this.applyEnabled(this.enabledState);\r\n if (this.forcedState !== undefined) this.button.setState(FANCY_STATE_BY_KEY[this.forcedState]);\r\n }\r\n\r\n /**\r\n * Sizes the four state views to the resolved layout rectangle without touching their textures.\r\n *\r\n * `NineSliceSprite` проверяется отдельно: в PixiJS 8 он наследуется от `ViewContainer`, а не от\r\n * `Sprite`, поэтому одна ветка `instanceof Sprite` его молча пропускает.\r\n */\r\n private applySizes(width: number, height: number): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (view instanceof NineSliceSprite) view.setSize(width, height);\r\n else if (view instanceof Sprite) view.setSize(width, height);\r\n else if (view instanceof Graphics) StagedButtonNodeView.paintPlaceholder(view, width, height);\r\n }\r\n }\r\n\r\n /**\r\n * Applies the current stage's textures/border to the existing state views (or rebuilds them if a\r\n * view's required type no longer matches, the same rule `ButtonNodeView.syncContent` follows).\r\n */\r\n private refreshStateViews(width: number, height: number): void {\r\n const stage = this.currentStage();\r\n const normalTexture = this.textureFor(stage.states.normalAssetId);\r\n\r\n let needsRebuild = false;\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const assetId = stage.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n const view = this.stateViews[state];\r\n const wantsNineSlice = texture !== undefined && this.nineSlice !== undefined;\r\n // `NineSliceSprite` не наследуется от `Sprite` в PixiJS 8, поэтому ветки не пересекаются.\r\n const matches = texture === undefined ? view instanceof Graphics : wantsNineSlice ? view instanceof NineSliceSprite : view instanceof Sprite;\r\n if (!matches) { needsRebuild = true; break; }\r\n }\r\n\r\n if (needsRebuild) {\r\n this.buildButton({ width, height });\r\n return;\r\n }\r\n\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n const assetId = stage.states[`${state}AssetId`];\r\n const texture = (assetId === undefined ? undefined : this.textureFor(assetId)) ?? normalTexture;\r\n // Set the texture before the layout size: Sprite/NineSliceSprite preserve scale when their\r\n // texture changes, so sizing first would shift visual bounds for a differently-sized source.\r\n if (view instanceof NineSliceSprite) {\r\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\r\n if (this.nineSlice !== undefined) {\r\n view.leftWidth = this.nineSlice.left;\r\n view.topHeight = this.nineSlice.top;\r\n view.rightWidth = this.nineSlice.right;\r\n view.bottomHeight = this.nineSlice.bottom;\r\n }\r\n } else if (view instanceof Sprite) {\n if (texture !== undefined && view.texture !== texture) view.texture = texture;\n }\n StagedButtonNodeView.applyStateAppearance(view, stage, state);\n }\n this.applySizes(width, height);\r\n }\r\n\r\n private applyStage(stageId: string): void {\r\n this.currentStageId = stageId;\r\n const { width, height } = this.layoutRectangle;\r\n this.refreshStateViews(width, height);\r\n }\r\n\r\n /** In authoring mode `enabled` may only drive the visuals: `FancyButton` couples it to `eventMode`. */\r\n private applyEnabled(enabled: boolean): void {\r\n this.enabledState = enabled;\r\n if (this.interaction === \"runtime\") this.button.enabled = enabled;\r\n else this.button.setState(enabled ? \"default\" : \"disabled\");\r\n }\r\n\r\n protected syncContent(node: UINode, transform: UINode[\"transform\"]): void {\r\n if (node.type !== \"staged-button\") return;\r\n this.soundAssetIds = node.sounds;\r\n this.nineSlice = node.nineSlice;\r\n this.wrapState = node.wrap;\r\n this.defaultStageId = node.defaultStageId;\r\n\r\n // Сохраняет текущую стадию, если она ещё существует после изменения документа; если стадию\r\n // удалили — переходит на ближайшую валидную по прежнему индексу.\r\n const previousIndex = this.stagesData.findIndex((stage) => stage.id === this.currentStageId);\r\n this.stagesData = node.stages;\r\n if (!node.stages.some((stage) => stage.id === this.currentStageId)) {\r\n const clampedIndex = Math.min(Math.max(previousIndex, 0), node.stages.length - 1);\r\n this.currentStageId = node.stages[clampedIndex]!.id;\r\n }\r\n\r\n this.refreshStateViews(transform.width, transform.height);\r\n\r\n // Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.\r\n if (node.enabled !== this.enabledState) this.applyEnabled(node.enabled);\r\n }\r\n\r\n /** Editor-only live preview of nine-slice border edits while dragging the canvas gizmo. */\r\n previewNineSlice(nineSlice: LayoutPadding): void {\r\n for (const state of BUTTON_STATE_KEYS) {\r\n const view = this.stateViews[state];\r\n if (!(view instanceof NineSliceSprite)) continue;\r\n view.leftWidth = nineSlice.left;\r\n view.topHeight = nineSlice.top;\r\n view.rightWidth = nineSlice.right;\r\n view.bottomHeight = nineSlice.bottom;\r\n }\r\n }\r\n\r\n get enabled(): boolean {\r\n return this.enabledState;\r\n }\r\n\r\n set enabled(value: boolean) {\r\n this.applyEnabled(value);\r\n }\r\n\r\n get stage(): number {\r\n const index = this.stagesData.findIndex((stage) => stage.id === this.currentStageId);\r\n return index === -1 ? 0 : index;\r\n }\r\n\r\n get value(): string {\r\n return this.currentStage().value;\r\n }\r\n\r\n get stageCount(): number {\r\n return this.stagesData.length;\r\n }\r\n\r\n /** Moves to the stage at `index` and emits `onStageChange`; an out-of-range index is a no-op. */\r\n setStage(index: number): void {\r\n const target = this.stagesData[index];\r\n if (target === undefined) return;\r\n this.applyStage(target.id);\r\n this.onStageChange.emit({ index, value: target.value });\r\n }\r\n\r\n /** Moves to the stage at `index` without emitting — used by editor preview to avoid feedback loops. */\r\n forceStage(index: number): void {\r\n const target = this.stagesData[index];\r\n if (target === undefined) return;\r\n this.applyStage(target.id);\r\n }\r\n\r\n /** Moves to the first stage whose `value` matches; an unknown value is ignored. */\r\n setValue(value: string): void {\r\n const index = this.stagesData.findIndex((stage) => stage.value === value);\r\n if (index === -1) return;\r\n this.setStage(index);\r\n }\r\n\r\n /** Advances one stage, as a click does; respects `wrap` at the last stage. */\r\n next(): void {\r\n const nextIndex = this.stage + 1;\r\n if (nextIndex >= this.stagesData.length) {\r\n if (!this.wrapState) return;\r\n this.setStage(0);\r\n return;\r\n }\r\n this.setStage(nextIndex);\r\n }\r\n\r\n /** Returns to `defaultStageId`, emitting `onStageChange`. */\r\n reset(): void {\r\n const index = this.stagesData.findIndex((stage) => stage.id === this.defaultStageId);\r\n this.setStage(index === -1 ? 0 : index);\r\n }\r\n\r\n /** Forces an editor-only visual state without changing `enabled`, mirroring `ButtonNodeView.setState`. */\r\n setState(state: ButtonStateKey): void {\r\n this.forcedState = state;\r\n this.button.setState(FANCY_STATE_BY_KEY[state]);\r\n }\r\n}\r\n"]}
@@ -74,6 +74,8 @@ export declare class TextNodeView extends NodeView {
74
74
  /** Последний применённый прямоугольник и стиль — их же переиспользует инкрементальный `setText`. */
75
75
  private lastTransform?;
76
76
  private lastStyle?;
77
+ /** `Text.textCase` from the last synced node — `setText`'s incremental path re-applies it without waiting for a full `syncContent`. */
78
+ private textCase?;
77
79
  constructor(text: string, fonts?: ReadonlyMap<string, string> | undefined);
78
80
  protected syncContent(node: UINode, transform: UINode["transform"], profile: LayoutProfileId): void;
79
81
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/views/basic.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/views/basic.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { applyTextCase } from "@pixi-ui-editor/schema";
1
2
  import { BitmapText, Container, Graphics, NineSliceSprite, Sprite, Text } from "pixi.js";
2
3
  import { NodeView } from "./NodeView.js";
3
4
  import { resolveTextStyle } from "../layout.js";
@@ -187,6 +188,8 @@ export class TextNodeView extends NodeView {
187
188
  /** Последний применённый прямоугольник и стиль — их же переиспользует инкрементальный `setText`. */
188
189
  lastTransform;
189
190
  lastStyle;
191
+ /** `Text.textCase` from the last synced node — `setText`'s incremental path re-applies it without waiting for a full `syncContent`. */
192
+ textCase;
190
193
  constructor(text, fonts) {
191
194
  super();
192
195
  this.fonts = fonts;
@@ -195,7 +198,8 @@ export class TextNodeView extends NodeView {
195
198
  syncContent(node, transform, profile) {
196
199
  if (node.type !== "text" || !(this.content instanceof Text))
197
200
  return;
198
- const text = this.localizedText ?? node.text;
201
+ this.textCase = node.textCase;
202
+ const text = applyTextCase(this.localizedText ?? node.text, this.textCase);
199
203
  if (this.content.text !== text)
200
204
  this.content.text = text;
201
205
  const style = resolveTextStyle(node, profile);
@@ -255,9 +259,12 @@ export class TextNodeView extends NodeView {
255
259
  * сохраняет identity, поэтому смена локали не трогает ни сцену, ни GPU-ресурсы стиля.
256
260
  */
257
261
  setText(text) {
258
- if (!(this.content instanceof Text) || this.content.text === text)
262
+ if (!(this.content instanceof Text))
259
263
  return;
260
- this.content.text = text;
264
+ const cased = applyTextCase(text, this.textCase);
265
+ if (this.content.text === cased)
266
+ return;
267
+ this.content.text = cased;
261
268
  this.align();
262
269
  }
263
270
  /** `undefined` возвращает ноду к авторской строке при следующей синхронизации документа. */