@pixi-ui-editor/runtime-pixi 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,11 +4,30 @@ PixiJS runtime that loads and renders scene documents produced by [Pixi UI Edito
4
4
 
5
5
  Consumes documents validated against [`@pixi-ui-editor/schema`](https://www.npmjs.com/package/@pixi-ui-editor/schema).
6
6
 
7
- ## Install
7
+ ## Install
8
8
 
9
9
  ```bash
10
- pnpm add @pixi-ui-editor/runtime-pixi
11
- ```
10
+ pnpm add @pixi-ui-editor/runtime-pixi
11
+ ```
12
+
13
+ ## Reparent live views
14
+
15
+ Use `reparentPreservingWorld` for a live Pixi `Container` created by game code or taken from a
16
+ mounted scene. It recalculates the ancestor chain instead of reading Pixi's render-pass cache, so the
17
+ view does not jump even before the first frame:
18
+
19
+ ```ts
20
+ import { reparentPreservingWorld } from "@pixi-ui-editor/runtime-pixi";
21
+
22
+ if (!reparentPreservingWorld(symbolView, bonusLayer, 0)) {
23
+ // The destination parent has a singular transform, for example scale.x === 0.
24
+ }
25
+ ```
26
+
27
+ `containerWorldMatrix`, `applyWorldTransform`, and `matchWorldTransform` expose the same live-view
28
+ layer for lower-level use. A singular parent returns `false` without writing a non-finite transform.
29
+ Use `NodeTransformSpace` instead when moving serialized document nodes: it additionally resolves
30
+ layout profiles, anchors, Canvas scaling, and layout-managed rectangles.
12
31
 
13
32
  ## Spawn a preset
14
33
 
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from "./layout.js";
5
5
  export { SceneViewport } from "./SceneViewport.js";
6
6
  export * from "./layoutGroups.js";
7
7
  export * from "./transformSpace.js";
8
+ export * from "./liveTransform.js";
8
9
  export * from "./scrollView.js";
9
10
  export * from "./pageGroup.js";
10
11
  export * from "./views/NodeView.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACpE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvH,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzL,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AACpE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACvH,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzL,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./layout.js";
3
3
  export { SceneViewport } from "./SceneViewport.js";
4
4
  export * from "./layoutGroups.js";
5
5
  export * from "./transformSpace.js";
6
+ export * from "./liveTransform.js";
6
7
  export * from "./scrollView.js";
7
8
  export * from "./pageGroup.js";
8
9
  export * from "./views/NodeView.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvH,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzL,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC","sourcesContent":["export type { SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nexport type { Sound } from \"@pixi/sound\";\r\nexport * from \"./document.js\";\r\nexport * from \"./layout.js\";\r\nexport { SceneViewport } from \"./SceneViewport.js\";\r\nexport * from \"./layoutGroups.js\";\r\nexport * from \"./transformSpace.js\";\r\nexport * from \"./scrollView.js\";\r\nexport * from \"./pageGroup.js\";\r\nexport * from \"./views/NodeView.js\";\r\nexport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\r\nexport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\r\nexport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nexport { InputNodeView } from \"./views/InputNodeView.js\";\r\nexport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\r\nexport { SpineNodeView } from \"./views/SpineNodeView.js\";\r\nexport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\r\nexport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\r\nexport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\r\nexport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nexport { ParticleEmitterNodeView } from \"./views/ParticleEmitterNodeView.js\";\r\nexport * from \"./particles.js\";\r\nexport { collectNodeAssetIds } from \"./views/createNodeView.js\";\r\nexport { SceneLocalization } from \"./localization.js\";\r\nexport type { SceneLocalizationOptions } from \"./localization.js\";\r\nexport { BitmapTextNodeView, ImageNodeView, MaskNodeView, OpacityGroupNodeView, TextNodeView } from \"./views/basic.js\";\r\nexport type { BuildSceneViewOptions, PrefabViewConfiguration, SceneViewResult } from \"./scene.js\";\r\nexport { applyProfile, buildPrefabView, buildSceneView, collectRenderedNodes, loadPrefabView, previewNodeView, updateNodeView, updateParticleEmitters, loadSceneView } from \"./scene.js\";\nexport * from \"./controls.js\";\r\nexport { createSceneAssetCache } from \"./assets/cache.js\";\r\nexport type { SceneAssetCache } from \"./assets/cache.js\";\r\nexport * from \"./assets/textures.js\";\r\nexport * from \"./assets/spine.js\";\r\nexport * from \"./assets/fonts.js\";\r\nexport * from \"./assets/bitmapFonts.js\";\r\nexport * from \"./assets/sounds.js\";\r\nexport * from \"./audio/bus.js\";\r\nexport * from \"./audio/director.js\";\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvH,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzL,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC","sourcesContent":["export type { SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nexport type { Sound } from \"@pixi/sound\";\r\nexport * from \"./document.js\";\r\nexport * from \"./layout.js\";\r\nexport { SceneViewport } from \"./SceneViewport.js\";\r\nexport * from \"./layoutGroups.js\";\r\nexport * from \"./transformSpace.js\";\nexport * from \"./liveTransform.js\";\nexport * from \"./scrollView.js\";\nexport * from \"./pageGroup.js\";\r\nexport * from \"./views/NodeView.js\";\r\nexport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\r\nexport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\r\nexport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nexport { InputNodeView } from \"./views/InputNodeView.js\";\r\nexport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\r\nexport { SpineNodeView } from \"./views/SpineNodeView.js\";\r\nexport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\r\nexport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\r\nexport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\r\nexport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nexport { ParticleEmitterNodeView } from \"./views/ParticleEmitterNodeView.js\";\r\nexport * from \"./particles.js\";\r\nexport { collectNodeAssetIds } from \"./views/createNodeView.js\";\r\nexport { SceneLocalization } from \"./localization.js\";\r\nexport type { SceneLocalizationOptions } from \"./localization.js\";\r\nexport { BitmapTextNodeView, ImageNodeView, MaskNodeView, OpacityGroupNodeView, TextNodeView } from \"./views/basic.js\";\r\nexport type { BuildSceneViewOptions, PrefabViewConfiguration, SceneViewResult } from \"./scene.js\";\r\nexport { applyProfile, buildPrefabView, buildSceneView, collectRenderedNodes, loadPrefabView, previewNodeView, updateNodeView, updateParticleEmitters, loadSceneView } from \"./scene.js\";\nexport * from \"./controls.js\";\r\nexport { createSceneAssetCache } from \"./assets/cache.js\";\r\nexport type { SceneAssetCache } from \"./assets/cache.js\";\r\nexport * from \"./assets/textures.js\";\r\nexport * from \"./assets/spine.js\";\r\nexport * from \"./assets/fonts.js\";\r\nexport * from \"./assets/bitmapFonts.js\";\r\nexport * from \"./assets/sounds.js\";\r\nexport * from \"./audio/bus.js\";\r\nexport * from \"./audio/director.js\";\r\n"]}
@@ -0,0 +1,22 @@
1
+ import { Container, Matrix } from "pixi.js";
2
+ /**
3
+ * Мировая матрица узла, пересчитанная обходом предков.
4
+ * Не опирается на кэш `worldTransform`, который Pixi обновляет только в рендер-проходе, — поэтому
5
+ * корректна и до первого тика.
6
+ */
7
+ export declare function containerWorldMatrix(view: Container): Matrix;
8
+ /**
9
+ * Ставит локальный transform `view` так, чтобы его мировой transform стал равен `world`,
10
+ * в системе координат текущего родителя `view`.
11
+ * `false` — родитель необратим (нулевой масштаб), transform не изменён.
12
+ */
13
+ export declare function applyWorldTransform(view: Container, world: Matrix): boolean;
14
+ /**
15
+ * Переносит `view` под `newParent` (опционально на позицию `index` среди его детей),
16
+ * не двигая `view` на экране. Перенос в дереве выполняется всегда; `false` — мировой transform
17
+ * сохранить не удалось.
18
+ */
19
+ export declare function reparentPreservingWorld(view: Container, newParent: Container, index?: number): boolean;
20
+ /** Оставляет `view` под текущим родителем, но совмещает его мировой transform с `source`. */
21
+ export declare function matchWorldTransform(view: Container, source: Container): boolean;
22
+ //# sourceMappingURL=liveTransform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveTransform.d.ts","sourceRoot":"","sources":["../src/liveTransform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAiB5C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAW5D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CA8B3E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAStG;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAE/E"}
@@ -0,0 +1,81 @@
1
+ import { Matrix } from "pixi.js";
2
+ import { IDENTITY_TRANSFORM, invertAffine, multiplyAffine, transformRelativeToParent, } from "./transformSpace.js";
3
+ function affineFromMatrix(matrix) {
4
+ return { a: matrix.a, b: matrix.b, c: matrix.c, d: matrix.d, tx: matrix.tx, ty: matrix.ty };
5
+ }
6
+ function matrixFromAffine(matrix) {
7
+ return new Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
8
+ }
9
+ /**
10
+ * Мировая матрица узла, пересчитанная обходом предков.
11
+ * Не опирается на кэш `worldTransform`, который Pixi обновляет только в рендер-проходе, — поэтому
12
+ * корректна и до первого тика.
13
+ */
14
+ export function containerWorldMatrix(view) {
15
+ const chain = [];
16
+ for (let current = view; current !== null; current = current.parent)
17
+ chain.push(current);
18
+ let world = IDENTITY_TRANSFORM;
19
+ for (let index = chain.length - 1; index >= 0; index -= 1) {
20
+ const current = chain[index];
21
+ current.updateLocalTransform();
22
+ world = multiplyAffine(world, affineFromMatrix(current.localTransform));
23
+ }
24
+ return matrixFromAffine(world);
25
+ }
26
+ /**
27
+ * Ставит локальный transform `view` так, чтобы его мировой transform стал равен `world`,
28
+ * в системе координат текущего родителя `view`.
29
+ * `false` — родитель необратим (нулевой масштаб), transform не изменён.
30
+ */
31
+ export function applyWorldTransform(view, world) {
32
+ const parentWorld = view.parent === null ? undefined : affineFromMatrix(containerWorldMatrix(view.parent));
33
+ const source = {
34
+ x: view.position.x,
35
+ y: view.position.y,
36
+ width: 1,
37
+ height: 1,
38
+ scaleX: view.scale.x,
39
+ scaleY: view.scale.y,
40
+ rotation: view.rotation,
41
+ // Schema pivots are normalized and multiplied by width/height in the shared kernel. Using a
42
+ // unit rectangle bridges Pixi's pixel pivot without exposing fake dimensions to callers.
43
+ pivotX: view.pivot.x,
44
+ pivotY: view.pivot.y,
45
+ };
46
+ const preserved = transformRelativeToParent(affineFromMatrix(world), parentWorld, source);
47
+ if (preserved !== undefined) {
48
+ view.position.set(preserved.x, preserved.y);
49
+ view.scale.set(preserved.scaleX, preserved.scaleY);
50
+ view.rotation = preserved.rotation;
51
+ return true;
52
+ }
53
+ const inverseParent = parentWorld === undefined ? IDENTITY_TRANSFORM : invertAffine(parentWorld);
54
+ if (inverseParent === undefined)
55
+ return false;
56
+ // The shared schema decomposition rejected an otherwise valid affine transform because it needs
57
+ // skew. Pixi can represent that final branch, so let its own decomposition retain it exactly.
58
+ view.setFromMatrix(matrixFromAffine(multiplyAffine(inverseParent, affineFromMatrix(world))));
59
+ return true;
60
+ }
61
+ /**
62
+ * Переносит `view` под `newParent` (опционально на позицию `index` среди его детей),
63
+ * не двигая `view` на экране. Перенос в дереве выполняется всегда; `false` — мировой transform
64
+ * сохранить не удалось.
65
+ */
66
+ export function reparentPreservingWorld(view, newParent, index) {
67
+ const world = containerWorldMatrix(view);
68
+ view.parent?.removeChild(view);
69
+ if (index === undefined) {
70
+ newParent.addChild(view);
71
+ }
72
+ else {
73
+ newParent.addChildAt(view, Math.min(newParent.children.length, Math.max(0, index)));
74
+ }
75
+ return applyWorldTransform(view, world);
76
+ }
77
+ /** Оставляет `view` под текущим родителем, но совмещает его мировой transform с `source`. */
78
+ export function matchWorldTransform(view, source) {
79
+ return applyWorldTransform(view, containerWorldMatrix(source));
80
+ }
81
+ //# sourceMappingURL=liveTransform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liveTransform.js","sourceRoot":"","sources":["../src/liveTransform.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, Matrix } from \"pixi.js\";\nimport {\n IDENTITY_TRANSFORM,\n invertAffine,\n multiplyAffine,\n transformRelativeToParent,\n type AffineTransform,\n} from \"./transformSpace.js\";\n\nfunction affineFromMatrix(matrix: Matrix): AffineTransform {\n return { a: matrix.a, b: matrix.b, c: matrix.c, d: matrix.d, tx: matrix.tx, ty: matrix.ty };\n}\n\nfunction matrixFromAffine(matrix: AffineTransform): Matrix {\n return new Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);\n}\n\n/**\n * Мировая матрица узла, пересчитанная обходом предков.\n * Не опирается на кэш `worldTransform`, который Pixi обновляет только в рендер-проходе, — поэтому\n * корректна и до первого тика.\n */\nexport function containerWorldMatrix(view: Container): Matrix {\n const chain: Container[] = [];\n for (let current: Container | null = view; current !== null; current = current.parent) chain.push(current);\n\n let world = IDENTITY_TRANSFORM;\n for (let index = chain.length - 1; index >= 0; index -= 1) {\n const current = chain[index]!;\n current.updateLocalTransform();\n world = multiplyAffine(world, affineFromMatrix(current.localTransform));\n }\n return matrixFromAffine(world);\n}\n\n/**\n * Ставит локальный transform `view` так, чтобы его мировой transform стал равен `world`,\n * в системе координат текущего родителя `view`.\n * `false` — родитель необратим (нулевой масштаб), transform не изменён.\n */\nexport function applyWorldTransform(view: Container, world: Matrix): boolean {\n const parentWorld = view.parent === null ? undefined : affineFromMatrix(containerWorldMatrix(view.parent));\n const source = {\n x: view.position.x,\n y: view.position.y,\n width: 1,\n height: 1,\n scaleX: view.scale.x,\n scaleY: view.scale.y,\n rotation: view.rotation,\n // Schema pivots are normalized and multiplied by width/height in the shared kernel. Using a\n // unit rectangle bridges Pixi's pixel pivot without exposing fake dimensions to callers.\n pivotX: view.pivot.x,\n pivotY: view.pivot.y,\n };\n const preserved = transformRelativeToParent(affineFromMatrix(world), parentWorld, source);\n if (preserved !== undefined) {\n view.position.set(preserved.x, preserved.y);\n view.scale.set(preserved.scaleX, preserved.scaleY);\n view.rotation = preserved.rotation;\n return true;\n }\n\n const inverseParent = parentWorld === undefined ? IDENTITY_TRANSFORM : invertAffine(parentWorld);\n if (inverseParent === undefined) return false;\n\n // The shared schema decomposition rejected an otherwise valid affine transform because it needs\n // skew. Pixi can represent that final branch, so let its own decomposition retain it exactly.\n view.setFromMatrix(matrixFromAffine(multiplyAffine(inverseParent, affineFromMatrix(world))));\n return true;\n}\n\n/**\n * Переносит `view` под `newParent` (опционально на позицию `index` среди его детей),\n * не двигая `view` на экране. Перенос в дереве выполняется всегда; `false` — мировой transform\n * сохранить не удалось.\n */\nexport function reparentPreservingWorld(view: Container, newParent: Container, index?: number): boolean {\n const world = containerWorldMatrix(view);\n view.parent?.removeChild(view);\n if (index === undefined) {\n newParent.addChild(view);\n } else {\n newParent.addChildAt(view, Math.min(newParent.children.length, Math.max(0, index)));\n }\n return applyWorldTransform(view, world);\n}\n\n/** Оставляет `view` под текущим родителем, но совмещает его мировой transform с `source`. */\nexport function matchWorldTransform(view: Container, source: Container): boolean {\n return applyWorldTransform(view, containerWorldMatrix(source));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixi-ui-editor/runtime-pixi",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "PixiJS runtime that renders Pixi UI Editor scene documents in a game.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -30,7 +30,7 @@
30
30
  "pixi.js": "^8.19.0",
31
31
  "typed-signals": "^2.5.0",
32
32
  "yoga-layout": "^3.2.1",
33
- "@pixi-ui-editor/schema": "0.16.0"
33
+ "@pixi-ui-editor/schema": "0.17.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^26.2.0"