@pixi-ui-editor/runtime-pixi 0.2.0 → 0.4.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 +81 -2
- package/dist/SceneViewport.d.ts +17 -0
- package/dist/SceneViewport.d.ts.map +1 -0
- package/dist/SceneViewport.js +35 -0
- package/dist/SceneViewport.js.map +1 -0
- package/dist/assets/cache.d.ts +27 -0
- package/dist/assets/cache.d.ts.map +1 -0
- package/dist/assets/cache.js +17 -0
- package/dist/assets/cache.js.map +1 -0
- package/dist/assets/fonts.d.ts +1 -1
- package/dist/assets/fonts.d.ts.map +1 -1
- package/dist/assets/fonts.js +2 -2
- package/dist/assets/fonts.js.map +1 -1
- package/dist/assets/spine.test.d.ts +2 -0
- package/dist/assets/spine.test.d.ts.map +1 -0
- package/dist/assets/spine.test.js +42 -0
- package/dist/assets/spine.test.js.map +1 -0
- package/dist/controls.d.ts +5 -1
- package/dist/controls.d.ts.map +1 -1
- package/dist/controls.js +12 -0
- package/dist/controls.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +113 -3
- package/dist/index.test.js.map +1 -1
- package/dist/layout.d.ts +25 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +34 -0
- package/dist/layout.js.map +1 -1
- package/dist/localization.d.ts +42 -0
- package/dist/localization.d.ts.map +1 -0
- package/dist/localization.js +73 -0
- package/dist/localization.js.map +1 -0
- package/dist/scene.d.ts +23 -13
- package/dist/scene.d.ts.map +1 -1
- package/dist/scene.js +62 -12
- package/dist/scene.js.map +1 -1
- package/dist/views/ButtonNodeView.d.ts +16 -3
- package/dist/views/ButtonNodeView.d.ts.map +1 -1
- package/dist/views/ButtonNodeView.js +94 -27
- package/dist/views/ButtonNodeView.js.map +1 -1
- package/dist/views/CheckboxNodeView.d.ts +47 -0
- package/dist/views/CheckboxNodeView.d.ts.map +1 -0
- package/dist/views/CheckboxNodeView.js +127 -0
- package/dist/views/CheckboxNodeView.js.map +1 -0
- package/dist/views/NodeView.d.ts +3 -2
- package/dist/views/NodeView.d.ts.map +1 -1
- package/dist/views/NodeView.js +11 -6
- package/dist/views/NodeView.js.map +1 -1
- package/dist/views/SpineNodeView.d.ts +3 -2
- package/dist/views/SpineNodeView.d.ts.map +1 -1
- package/dist/views/SpineNodeView.js +20 -5
- package/dist/views/SpineNodeView.js.map +1 -1
- package/dist/views/basic.d.ts +50 -3
- package/dist/views/basic.d.ts.map +1 -1
- package/dist/views/basic.js +145 -17
- package/dist/views/basic.js.map +1 -1
- package/dist/views/createNodeView.d.ts.map +1 -1
- package/dist/views/createNodeView.js +22 -4
- package/dist/views/createNodeView.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { CHECKBOX_STATE_KEYS } from "@pixi-ui-editor/schema";
|
|
2
|
+
import { CheckBox } from "@pixi/ui";
|
|
3
|
+
import { Sprite, Texture } from "pixi.js";
|
|
4
|
+
import { NodeView } from "./NodeView.js";
|
|
5
|
+
/**
|
|
6
|
+
* Adapts a checkbox node to `@pixi/ui`'s `CheckBox`, which owns the checked/unchecked switching —
|
|
7
|
+
* this class never reimplements it. `group`-based radio exclusivity is wired one layer up, in
|
|
8
|
+
* `wireCheckboxGroups` (see scene.ts): this view only exposes `forceCheck` so that wiring can flip
|
|
9
|
+
* a sibling without re-emitting `onCheck` and recursing back into itself.
|
|
10
|
+
*
|
|
11
|
+
* Hover is layered on top of `CheckBox` by hand: unlike `FancyButton`, `CheckBox`/`Switcher` only
|
|
12
|
+
* switches between its checked/unchecked views and has no hover state slot of its own. Both of its
|
|
13
|
+
* internal Sprites always carry the texture matching the current hover flag — whichever one is
|
|
14
|
+
* `visible` at any moment is Switcher's concern, not ours.
|
|
15
|
+
*/
|
|
16
|
+
export class CheckboxNodeView extends NodeView {
|
|
17
|
+
checkbox;
|
|
18
|
+
interaction;
|
|
19
|
+
sounds;
|
|
20
|
+
soundAssetIds;
|
|
21
|
+
uncheckedTexture;
|
|
22
|
+
checkedTexture;
|
|
23
|
+
uncheckedHoverTexture;
|
|
24
|
+
checkedHoverTexture;
|
|
25
|
+
enabledState;
|
|
26
|
+
hovering = false;
|
|
27
|
+
constructor(node, textures, interaction, sounds) {
|
|
28
|
+
super(textures);
|
|
29
|
+
this.interaction = interaction;
|
|
30
|
+
this.sounds = sounds;
|
|
31
|
+
this.soundAssetIds = node.sounds;
|
|
32
|
+
const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;
|
|
33
|
+
const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;
|
|
34
|
+
this.uncheckedTexture = unchecked;
|
|
35
|
+
this.checkedTexture = checked;
|
|
36
|
+
this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);
|
|
37
|
+
this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);
|
|
38
|
+
this.checkbox = new CheckBox({
|
|
39
|
+
checked: node.defaultChecked,
|
|
40
|
+
style: { unchecked, checked },
|
|
41
|
+
});
|
|
42
|
+
// Authoring-сцена инертна, как и у button: eventMode "none" на верхнем контейнере отключает
|
|
43
|
+
// hit-testing всего поддерева, включая `innerView`, который Switcher сам сделал "static" — а
|
|
44
|
+
// значит и hover в authoring никогда не наступает, так что его незачем отдельно отключать.
|
|
45
|
+
if (interaction === "authoring")
|
|
46
|
+
this.checkbox.eventMode = "none";
|
|
47
|
+
else {
|
|
48
|
+
this.checkbox.innerView.on("pointerover", () => { this.hovering = true; this.applyTextures(); });
|
|
49
|
+
this.checkbox.innerView.on("pointerout", () => { this.hovering = false; this.applyTextures(); });
|
|
50
|
+
if (sounds !== undefined) {
|
|
51
|
+
this.checkbox.onCheck.connect((checkedState) => {
|
|
52
|
+
const assetId = checkedState ? this.soundAssetIds?.checkAssetId : this.soundAssetIds?.uncheckAssetId;
|
|
53
|
+
const result = assetId === undefined ? undefined : this.sounds?.get(assetId)?.play();
|
|
54
|
+
if (result instanceof Promise)
|
|
55
|
+
void result.catch(() => undefined);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
this.enabledState = node.enabled;
|
|
60
|
+
this.applyEnabled(node.enabled);
|
|
61
|
+
this.setContent(this.checkbox);
|
|
62
|
+
}
|
|
63
|
+
hoverTextureFor(assetId, fallback) {
|
|
64
|
+
return (assetId === undefined ? undefined : this.textureFor(assetId)) ?? fallback;
|
|
65
|
+
}
|
|
66
|
+
/** Puts the current hover/non-hover texture on both internal Sprites; switching visibility is Switcher's job. */
|
|
67
|
+
applyTextures() {
|
|
68
|
+
const [uncheckedView, checkedView] = this.checkbox.views;
|
|
69
|
+
if (uncheckedView instanceof Sprite)
|
|
70
|
+
uncheckedView.texture = this.hovering ? this.uncheckedHoverTexture : this.uncheckedTexture;
|
|
71
|
+
if (checkedView instanceof Sprite)
|
|
72
|
+
checkedView.texture = this.hovering ? this.checkedHoverTexture : this.checkedTexture;
|
|
73
|
+
}
|
|
74
|
+
/** In authoring mode `enabled` may only drive selectability elsewhere: this view stays inert either way. */
|
|
75
|
+
applyEnabled(enabled) {
|
|
76
|
+
this.enabledState = enabled;
|
|
77
|
+
if (this.interaction === "authoring")
|
|
78
|
+
return;
|
|
79
|
+
this.checkbox.eventMode = enabled ? "static" : "none";
|
|
80
|
+
}
|
|
81
|
+
syncContent(node, transform) {
|
|
82
|
+
if (node.type !== "checkbox")
|
|
83
|
+
return;
|
|
84
|
+
this.soundAssetIds = node.sounds;
|
|
85
|
+
const unchecked = this.textureFor(node.states.uncheckedAssetId) ?? Texture.WHITE;
|
|
86
|
+
const checked = this.textureFor(node.states.checkedAssetId) ?? Texture.WHITE;
|
|
87
|
+
// `style` rebuilds both internal views, so it's only reassigned when a base texture actually
|
|
88
|
+
// changed — same rule ButtonNodeView follows for its state Sprites. A fresh pair of Sprites
|
|
89
|
+
// starts out holding the plain (non-hover) textures `style` was given, so `applyTextures` always
|
|
90
|
+
// runs afterwards to restore the current hover look.
|
|
91
|
+
if (unchecked !== this.uncheckedTexture || checked !== this.checkedTexture) {
|
|
92
|
+
this.uncheckedTexture = unchecked;
|
|
93
|
+
this.checkedTexture = checked;
|
|
94
|
+
this.checkbox.style = { unchecked, checked };
|
|
95
|
+
}
|
|
96
|
+
this.uncheckedHoverTexture = this.hoverTextureFor(node.states.uncheckedHoverAssetId, unchecked);
|
|
97
|
+
this.checkedHoverTexture = this.hoverTextureFor(node.states.checkedHoverAssetId, checked);
|
|
98
|
+
this.applyTextures();
|
|
99
|
+
for (const view of this.checkbox.views)
|
|
100
|
+
if (view instanceof Sprite)
|
|
101
|
+
view.setSize(transform.width, transform.height);
|
|
102
|
+
// Только на изменение документа: иначе любой пересчёт layout сбрасывал бы transient preview state.
|
|
103
|
+
if (node.enabled !== this.enabledState)
|
|
104
|
+
this.applyEnabled(node.enabled);
|
|
105
|
+
}
|
|
106
|
+
get enabled() {
|
|
107
|
+
return this.enabledState;
|
|
108
|
+
}
|
|
109
|
+
set enabled(value) {
|
|
110
|
+
this.applyEnabled(value);
|
|
111
|
+
}
|
|
112
|
+
get checked() {
|
|
113
|
+
return this.checkbox.checked;
|
|
114
|
+
}
|
|
115
|
+
set checked(value) {
|
|
116
|
+
this.checkbox.checked = value;
|
|
117
|
+
}
|
|
118
|
+
/** Sets checked state without emitting `onCheck` — used by radio-group wiring to avoid re-entrancy. */
|
|
119
|
+
forceCheck(checked) {
|
|
120
|
+
this.checkbox.forceCheck(checked);
|
|
121
|
+
}
|
|
122
|
+
get state() {
|
|
123
|
+
return this.checkbox.checked ? CHECKBOX_STATE_KEYS[1] : CHECKBOX_STATE_KEYS[0];
|
|
124
|
+
}
|
|
125
|
+
get onCheck() { return this.checkbox.onCheck; }
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=CheckboxNodeView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CheckboxNodeView.js","sourceRoot":"","sources":["../../src/views/CheckboxNodeView.ts"],"names":[],"mappings":"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"}
|
package/dist/views/NodeView.d.ts
CHANGED
|
@@ -38,13 +38,14 @@ export declare abstract class NodeView extends Container {
|
|
|
38
38
|
* children — they are hit-tested first and independently, so a child always stays grabbable.
|
|
39
39
|
*/
|
|
40
40
|
containsPoint(point: PointData): boolean;
|
|
41
|
+
/** Заменяет содержимое ноды: прежнее снимается со сцены и уничтожается, чтобы не копить сироты. */
|
|
41
42
|
protected setContent(content: Container): void;
|
|
42
43
|
/** Syncs type-specific content to the resolved layout rectangle; layout math itself is shared. */
|
|
43
|
-
protected abstract syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
44
|
+
protected abstract syncContent(node: UINode, transform: UINode["transform"], profile: LayoutProfileId): void;
|
|
44
45
|
private applyResolvedTransform;
|
|
45
46
|
update(node: UINode, profile: LayoutProfileId, parentSize?: LayoutSize): void;
|
|
46
47
|
/** Applies a transient editor rectangle without deriving it from content-dependent Pixi bounds. */
|
|
47
|
-
preview(node: UINode, transform: UINode["transform"], visible?: boolean): void;
|
|
48
|
+
preview(node: UINode, transform: UINode["transform"], visible?: boolean, profile?: LayoutProfileId): void;
|
|
48
49
|
/** Applies the rectangle owned by a direct parent's layout solver. */
|
|
49
50
|
updateManaged(node: UINode, profile: LayoutProfileId, size: LayoutSize): void;
|
|
50
51
|
get layoutRectangle(): LayoutSize;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeView.d.ts","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAa,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAqD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAElG;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,8BAAsB,QAAS,SAAQ,SAAS;IAC9C,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC9B,4FAA4F;IAC5F,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,yGAAyG;IACzG,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;gBAEb,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAKnD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI1D;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAIxC,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"NodeView.d.ts","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAa,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAqD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAElG;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,8BAAsB,QAAS,SAAQ,SAAS;IAC9C,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC9B,4FAA4F;IAC5F,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,yGAAyG;IACzG,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;gBAEb,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAKnD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI1D;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAIxC,mGAAmG;IACnG,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAM9C,kGAAkG;IAClG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAE5G,OAAO,CAAC,sBAAsB;IAuB9B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI;IAK7E,mGAAmG;IACnG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,UAAO,EAAE,OAAO,GAAE,eAA2B,GAAG,IAAI;IAIjH,sEAAsE;IACtE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAK7E,IAAI,eAAe,IAAI,UAAU,CAEhC;IAED,QAAQ,IAAI,KAAK,GAAG,SAAS;CAG9B"}
|
package/dist/views/NodeView.js
CHANGED
|
@@ -38,12 +38,17 @@ export class NodeView extends Container {
|
|
|
38
38
|
containsPoint(point) {
|
|
39
39
|
return this.grabRect.contains(point.x, point.y);
|
|
40
40
|
}
|
|
41
|
+
/** Заменяет содержимое ноды: прежнее снимается со сцены и уничтожается, чтобы не копить сироты. */
|
|
41
42
|
setContent(content) {
|
|
43
|
+
if (this.content !== undefined) {
|
|
44
|
+
this.removeChild(this.content);
|
|
45
|
+
this.content.destroy();
|
|
46
|
+
}
|
|
42
47
|
this.content = content;
|
|
43
48
|
this.addChild(content);
|
|
44
49
|
}
|
|
45
|
-
applyResolvedTransform(node, transform, visible, managedByLayout) {
|
|
46
|
-
this.syncContent(node, transform);
|
|
50
|
+
applyResolvedTransform(node, transform, visible, managedByLayout, profile) {
|
|
51
|
+
this.syncContent(node, transform, profile);
|
|
47
52
|
const pivotX = (transform.pivotX ?? 0) * transform.width;
|
|
48
53
|
const pivotY = (transform.pivotY ?? 0) * transform.height;
|
|
49
54
|
this.pivot.set(pivotX, pivotY);
|
|
@@ -65,16 +70,16 @@ export class NodeView extends Container {
|
|
|
65
70
|
}
|
|
66
71
|
update(node, profile, parentSize) {
|
|
67
72
|
const resolved = resolveProfileTransform(node, profile);
|
|
68
|
-
this.applyResolvedTransform(node, resolveAnchoredTransform(resolved.transform, parentSize), resolved.visible, false);
|
|
73
|
+
this.applyResolvedTransform(node, resolveAnchoredTransform(resolved.transform, parentSize), resolved.visible, false, profile);
|
|
69
74
|
}
|
|
70
75
|
/** Applies a transient editor rectangle without deriving it from content-dependent Pixi bounds. */
|
|
71
|
-
preview(node, transform, visible = true) {
|
|
72
|
-
this.applyResolvedTransform(node, transform, visible, false);
|
|
76
|
+
preview(node, transform, visible = true, profile = "desktop") {
|
|
77
|
+
this.applyResolvedTransform(node, transform, visible, false, profile);
|
|
73
78
|
}
|
|
74
79
|
/** Applies the rectangle owned by a direct parent's layout solver. */
|
|
75
80
|
updateManaged(node, profile, size) {
|
|
76
81
|
const resolved = resolveProfileTransform(node, profile);
|
|
77
|
-
this.applyResolvedTransform(node, { ...resolved.transform, x: 0, y: 0, width: size.width, height: size.height }, resolved.visible, true);
|
|
82
|
+
this.applyResolvedTransform(node, { ...resolved.transform, x: 0, y: 0, width: size.width, height: size.height }, resolved.visible, true, profile);
|
|
78
83
|
}
|
|
79
84
|
get layoutRectangle() {
|
|
80
85
|
return { width: this.layoutWidth, height: this.layoutHeight };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeView.js","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,SAAS,EAA2B,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAmB,MAAM,cAAc,CAAC;AASlG;;;;GAIG;AACH,MAAM,OAAgB,QAAS,SAAQ,SAAS;IACpC,OAAO,CAAa;IAC9B,4FAA4F;IACzE,QAAQ,CAA2C;IACtE,6FAA6F;IAC5E,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAC;IAC5C,yGAAyG;IACjG,WAAW,GAAG,CAAC,CAAC;IAChB,YAAY,GAAG,CAAC,CAAC;IAEzB,YAAY,QAAuC;QACjD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAES,UAAU,CAAC,OAAe;QAClC,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAgB;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;
|
|
1
|
+
{"version":3,"file":"NodeView.js","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type SkeletonData } from "@esotericsoftware/spine-pixi-v8";
|
|
2
|
-
import { type SpineReferenceFrame, type UINode } from "@pixi-ui-editor/schema";
|
|
2
|
+
import { type LayoutProfileId, type SpineReferenceFrame, type UINode } from "@pixi-ui-editor/schema";
|
|
3
3
|
import { type Ticker } from "pixi.js";
|
|
4
4
|
import { NodeView } from "./NodeView.js";
|
|
5
5
|
export declare class SpineNodeView extends NodeView {
|
|
6
6
|
private referenceFrame;
|
|
7
|
+
private readonly initializeForAuthoring;
|
|
7
8
|
constructor(skeletonData: SkeletonData | undefined, animation: string | undefined, autoplay: boolean, loop: boolean, animationSpeed: number, initializeForAuthoring: boolean, referenceFrame?: SpineReferenceFrame, ticker?: Ticker);
|
|
8
9
|
setReferenceFrame(referenceFrame: SpineReferenceFrame | undefined): void;
|
|
9
|
-
protected syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
10
|
+
protected syncContent(node: UINode, transform: UINode["transform"], profile: LayoutProfileId): void;
|
|
10
11
|
}
|
|
11
12
|
//# sourceMappingURL=SpineNodeView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpineNodeView.d.ts","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"SpineNodeView.d.ts","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,qBAAa,aAAc,SAAQ,QAAQ;IACzC,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;gBAErC,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;IAuBnO,iBAAiB,CAAC,cAAc,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI;IAIxE,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;CA2BpG"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Spine } from "@esotericsoftware/spine-pixi-v8";
|
|
2
2
|
import { Graphics } from "pixi.js";
|
|
3
|
-
import { fitSpineToTransform } from "../layout.js";
|
|
3
|
+
import { fitSpineToTransform, resolveSpineSettings } from "../layout.js";
|
|
4
4
|
import { NodeView } from "./NodeView.js";
|
|
5
5
|
export class SpineNodeView extends NodeView {
|
|
6
6
|
referenceFrame;
|
|
7
|
+
initializeForAuthoring;
|
|
7
8
|
constructor(skeletonData, animation, autoplay, loop, animationSpeed, initializeForAuthoring, referenceFrame, ticker) {
|
|
8
9
|
super();
|
|
9
10
|
this.referenceFrame = referenceFrame;
|
|
11
|
+
this.initializeForAuthoring = initializeForAuthoring;
|
|
10
12
|
if (skeletonData === undefined) {
|
|
11
13
|
this.setContent(new Graphics());
|
|
12
14
|
return;
|
|
@@ -29,11 +31,24 @@ export class SpineNodeView extends NodeView {
|
|
|
29
31
|
setReferenceFrame(referenceFrame) {
|
|
30
32
|
this.referenceFrame = referenceFrame;
|
|
31
33
|
}
|
|
32
|
-
syncContent(node, transform) {
|
|
34
|
+
syncContent(node, transform, profile) {
|
|
33
35
|
if (this.content instanceof Spine) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
track
|
|
36
|
+
if (node.type === "spine") {
|
|
37
|
+
const settings = resolveSpineSettings(node, profile);
|
|
38
|
+
const track = this.content.state.tracks[0];
|
|
39
|
+
const animationChanged = track?.animation?.name !== settings.animation;
|
|
40
|
+
const loopChanged = track !== null && track !== undefined && track.loop !== settings.loop;
|
|
41
|
+
if (settings.animation === undefined || (!settings.autoplay && !this.initializeForAuthoring)) {
|
|
42
|
+
if (track !== null && track !== undefined)
|
|
43
|
+
this.content.state.clearTrack(0);
|
|
44
|
+
}
|
|
45
|
+
else if ((animationChanged || loopChanged) && this.content.skeleton.data.findAnimation(settings.animation) !== null) {
|
|
46
|
+
this.content.state.setAnimation(0, settings.animation, settings.loop).timeScale = settings.animationSpeed;
|
|
47
|
+
}
|
|
48
|
+
else if (track !== null && track !== undefined) {
|
|
49
|
+
track.timeScale = settings.animationSpeed;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
37
52
|
const fit = fitSpineToTransform(this.content.skeleton.data, transform, this.referenceFrame);
|
|
38
53
|
if (fit !== undefined) {
|
|
39
54
|
this.content.scale.set(fit.scaleX, fit.scaleY);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpineNodeView.js","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,iCAAiC,CAAC;AAE3E,OAAO,EAAE,QAAQ,EAAe,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"SpineNodeView.js","sourceRoot":"","sources":["../../src/views/SpineNodeView.ts"],"names":[],"mappings":"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"}
|
package/dist/views/basic.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { type UINode } from "@pixi-ui-editor/schema";
|
|
1
|
+
import { type LayoutPadding, type LayoutProfileId, type UINode } from "@pixi-ui-editor/schema";
|
|
2
2
|
import { Container, Texture } from "pixi.js";
|
|
3
3
|
import { NodeView } from "./NodeView.js";
|
|
4
4
|
export declare class ContainerNodeView extends NodeView {
|
|
5
5
|
protected syncContent(): void;
|
|
6
6
|
}
|
|
7
|
+
/** Clips every authored child to the node's resolved rectangular layout area. */
|
|
8
|
+
export declare class MaskNodeView extends NodeView {
|
|
9
|
+
private readonly maskShape;
|
|
10
|
+
constructor();
|
|
11
|
+
protected syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
12
|
+
}
|
|
7
13
|
/** Layout groups may optionally paint one image behind their managed children. No asset means no content/view at all. */
|
|
8
14
|
export declare class LayoutGroupNodeView extends NodeView {
|
|
9
15
|
private readonly layoutContent;
|
|
@@ -13,14 +19,55 @@ export declare class LayoutGroupNodeView extends NodeView {
|
|
|
13
19
|
addLayoutChild<T extends Container[]>(...children: T): T[0];
|
|
14
20
|
protected syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
15
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Ноде-картинке источник не обязателен: без `assetId` она рисует белый прямоугольник своего размера,
|
|
24
|
+
* а серо-синяя заглушка остаётся признаком того, что назначенный ассет не загрузился.
|
|
25
|
+
*
|
|
26
|
+
* `nineSlice` переключает контент на `NineSliceSprite`: углы источника остаются нерастянутыми, а
|
|
27
|
+
* растягиваются только края/середина — то же 9-slice, что уже использует Slider/ProgressBar через
|
|
28
|
+
* `@pixi/ui`'s `fillPaddings`, только здесь это применяется напрямую к содержимому Image-ноды.
|
|
29
|
+
*/
|
|
16
30
|
export declare class ImageNodeView extends NodeView {
|
|
17
|
-
constructor(assetId: string, textures: ReadonlyMap<string, Texture> | undefined);
|
|
31
|
+
constructor(assetId: string | undefined, textures: ReadonlyMap<string, Texture> | undefined, nineSlice?: LayoutPadding);
|
|
32
|
+
private static createSpriteContent;
|
|
18
33
|
protected syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
34
|
+
/**
|
|
35
|
+
* Editor-only live preview of border edits while dragging the canvas nine-slice gizmo; the
|
|
36
|
+
* document is only written once, on drag release. A no-op without a `NineSliceSprite` content —
|
|
37
|
+
* e.g. mid-drag right after the asset was cleared, before the next document sync catches up.
|
|
38
|
+
*/
|
|
39
|
+
previewNineSlice(nineSlice: LayoutPadding): void;
|
|
19
40
|
}
|
|
20
41
|
export declare class TextNodeView extends NodeView {
|
|
21
42
|
private readonly fonts?;
|
|
43
|
+
/**
|
|
44
|
+
* Строка, применённая локализацией поверх авторской. Она переживает `updateNodeView`: без неё
|
|
45
|
+
* любая синхронизация документа возвращала бы fallback `node.text` вместо текущего перевода.
|
|
46
|
+
*/
|
|
47
|
+
private localizedText?;
|
|
48
|
+
/** Последний применённый прямоугольник и стиль — их же переиспользует инкрементальный `setText`. */
|
|
49
|
+
private lastTransform?;
|
|
50
|
+
private lastStyle?;
|
|
22
51
|
constructor(text: string, fonts?: ReadonlyMap<string, string> | undefined);
|
|
23
|
-
protected syncContent(node: UINode, transform: UINode["transform"]): void;
|
|
52
|
+
protected syncContent(node: UINode, transform: UINode["transform"], profile: LayoutProfileId): void;
|
|
53
|
+
/**
|
|
54
|
+
* Инкрементальная смена строки: та же строка не делает работы вообще, новая — только переизмеряет
|
|
55
|
+
* и выравнивает текст в текущем authored rectangle. `TextStyle` не пересоздаётся, а сам view
|
|
56
|
+
* сохраняет identity, поэтому смена локали не трогает ни сцену, ни GPU-ресурсы стиля.
|
|
57
|
+
*/
|
|
58
|
+
setText(text: string): void;
|
|
59
|
+
/** `undefined` возвращает ноду к авторской строке при следующей синхронизации документа. */
|
|
60
|
+
setLocalizedText(text: string | undefined): void;
|
|
61
|
+
/**
|
|
62
|
+
* Вылезает ли фактически отрисованный текст за логический прямоугольник ноды.
|
|
63
|
+
*
|
|
64
|
+
* Меряется уже готовый `Text`, а не длина строки: перенос по словам, шрифт и обводка известны
|
|
65
|
+
* только рендеру. Без `wordWrap` переполнение возможно по ширине, с ним — по высоте, потому что
|
|
66
|
+
* перенос сам удерживает ширину в пределах `wordWrapWidth`. Диагностика transient: она ничего не
|
|
67
|
+
* пишет ни в документ, ни в view.
|
|
68
|
+
*/
|
|
69
|
+
measureOverflow(): boolean;
|
|
70
|
+
private align;
|
|
24
71
|
}
|
|
25
72
|
/**
|
|
26
73
|
* Содержимое инстанса приходит обычными детьми из общего резолвера иерархии. Собственный контент
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/views/basic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/views/basic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAA4B,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACzH,OAAO,EAAE,SAAS,EAA2C,OAAO,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,SAAS,CAAC,WAAW,IAAI,IAAI;CAC9B;AAED,iFAAiF;AACjF,qBAAa,YAAa,SAAQ,QAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;;IAU5C,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI;CAI1E;AAED,yHAAyH;AACzH,qBAAa,mBAAoB,SAAQ,QAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,UAAU,CAAC,CAAS;gBAEhB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAO9D,IAAI,YAAY,IAAI,SAAS,CAA+B;IAE5D,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAI3D,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI;CAW1E;AAED;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,SAAS,CAAC,EAAE,aAAa;IAMtH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAOlC,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI;IAgCzE;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,IAAI;CAOjD;AAED,qBAAa,YAAa,SAAQ,QAAQ;IAUd,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IATjD;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,oGAAoG;IACpG,OAAO,CAAC,aAAa,CAAC,CAAsB;IAC5C,OAAO,CAAC,SAAS,CAAC,CAAsB;gBAE5B,IAAI,EAAE,MAAM,EAAmB,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA;IAK9E,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAYnG;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM3B,4FAA4F;IAC5F,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKhD;;;;;;;OAOG;IACH,eAAe,IAAI,OAAO;IAU1B,OAAO,CAAC,KAAK;CAUd;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,QAAQ;gBACtC,QAAQ,EAAE,OAAO;IAK7B,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,IAAI;CAG3E"}
|
package/dist/views/basic.js
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
|
-
import { Container, Graphics, Sprite, Text } from "pixi.js";
|
|
1
|
+
import { Container, Graphics, NineSliceSprite, Sprite, Text } from "pixi.js";
|
|
2
2
|
import { NodeView } from "./NodeView.js";
|
|
3
|
+
import { resolveTextStyle } from "../layout.js";
|
|
3
4
|
export class ContainerNodeView extends NodeView {
|
|
4
5
|
syncContent() { }
|
|
5
6
|
}
|
|
7
|
+
/** Clips every authored child to the node's resolved rectangular layout area. */
|
|
8
|
+
export class MaskNodeView extends NodeView {
|
|
9
|
+
maskShape = new Graphics();
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.addChild(this.maskShape);
|
|
13
|
+
// A Graphics mask keeps the shape GPU-native and avoids the offscreen texture pass of alpha masks.
|
|
14
|
+
// Pixi's regular mask contract also preserves correct clipping through rotation and transformed parents.
|
|
15
|
+
this.mask = this.maskShape;
|
|
16
|
+
}
|
|
17
|
+
syncContent(node, transform) {
|
|
18
|
+
if (node.type !== "mask")
|
|
19
|
+
return;
|
|
20
|
+
this.maskShape.clear().rect(0, 0, transform.width, transform.height).fill(0xffffff);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
6
23
|
/** Layout groups may optionally paint one image behind their managed children. No asset means no content/view at all. */
|
|
7
24
|
export class LayoutGroupNodeView extends NodeView {
|
|
8
25
|
layoutContent = new Container();
|
|
@@ -38,40 +55,151 @@ export class LayoutGroupNodeView extends NodeView {
|
|
|
38
55
|
this.background.setSize(transform.width, transform.height);
|
|
39
56
|
}
|
|
40
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Ноде-картинке источник не обязателен: без `assetId` она рисует белый прямоугольник своего размера,
|
|
60
|
+
* а серо-синяя заглушка остаётся признаком того, что назначенный ассет не загрузился.
|
|
61
|
+
*
|
|
62
|
+
* `nineSlice` переключает контент на `NineSliceSprite`: углы источника остаются нерастянутыми, а
|
|
63
|
+
* растягиваются только края/середина — то же 9-slice, что уже использует Slider/ProgressBar через
|
|
64
|
+
* `@pixi/ui`'s `fillPaddings`, только здесь это применяется напрямую к содержимому Image-ноды.
|
|
65
|
+
*/
|
|
41
66
|
export class ImageNodeView extends NodeView {
|
|
42
|
-
constructor(assetId, textures) {
|
|
67
|
+
constructor(assetId, textures, nineSlice) {
|
|
43
68
|
super(textures);
|
|
44
|
-
const texture = this.textureFor(assetId);
|
|
45
|
-
this.setContent(
|
|
69
|
+
const texture = assetId === undefined ? undefined : this.textureFor(assetId);
|
|
70
|
+
this.setContent(ImageNodeView.createSpriteContent(texture, nineSlice));
|
|
71
|
+
}
|
|
72
|
+
static createSpriteContent(texture, nineSlice) {
|
|
73
|
+
if (texture === undefined)
|
|
74
|
+
return new Graphics();
|
|
75
|
+
return nineSlice === undefined
|
|
76
|
+
? new Sprite(texture)
|
|
77
|
+
: new NineSliceSprite({ texture, leftWidth: nineSlice.left, topHeight: nineSlice.top, rightWidth: nineSlice.right, bottomHeight: nineSlice.bottom });
|
|
46
78
|
}
|
|
47
79
|
syncContent(node, transform) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.content
|
|
56
|
-
|
|
57
|
-
|
|
80
|
+
if (node.type !== "image")
|
|
81
|
+
return;
|
|
82
|
+
const texture = node.assetId === undefined ? undefined : this.textureFor(node.assetId);
|
|
83
|
+
const nineSlice = node.nineSlice;
|
|
84
|
+
// Sprite ↔ NineSliceSprite ↔ Graphics меняются местами прямо здесь: структурный ключ сцены не
|
|
85
|
+
// включает assetId/nineSlice, поэтому переключение (в том числе на None) не пересобирает сцену.
|
|
86
|
+
if (texture !== undefined && nineSlice !== undefined) {
|
|
87
|
+
if (!(this.content instanceof NineSliceSprite))
|
|
88
|
+
this.setContent(ImageNodeView.createSpriteContent(texture, nineSlice));
|
|
89
|
+
const sprite = this.content;
|
|
90
|
+
// Keep the NineSliceSprite and its layout rectangle stable when its image asset/borders change.
|
|
91
|
+
if (sprite.texture !== texture)
|
|
92
|
+
sprite.texture = texture;
|
|
93
|
+
sprite.leftWidth = nineSlice.left;
|
|
94
|
+
sprite.topHeight = nineSlice.top;
|
|
95
|
+
sprite.rightWidth = nineSlice.right;
|
|
96
|
+
sprite.bottomHeight = nineSlice.bottom;
|
|
97
|
+
sprite.setSize(transform.width, transform.height);
|
|
98
|
+
}
|
|
99
|
+
else if (texture !== undefined) {
|
|
100
|
+
// `NineSliceSprite` is a Sprite sibling, not a subclass, so this rebuilds when switching back from it.
|
|
101
|
+
if (!(this.content instanceof Sprite))
|
|
102
|
+
this.setContent(new Sprite(texture));
|
|
103
|
+
const sprite = this.content;
|
|
104
|
+
// Keep the Sprite and its layout rectangle stable when its image asset changes.
|
|
105
|
+
if (sprite.texture !== texture)
|
|
106
|
+
sprite.texture = texture;
|
|
107
|
+
sprite.setSize(transform.width, transform.height);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
if (!(this.content instanceof Graphics))
|
|
111
|
+
this.setContent(new Graphics());
|
|
112
|
+
const graphics = this.content.clear().rect(0, 0, transform.width, transform.height);
|
|
113
|
+
if (node.assetId === undefined)
|
|
114
|
+
graphics.fill(0xffffff);
|
|
115
|
+
else
|
|
116
|
+
graphics.fill(0x4a5568).stroke({ width: 1, color: 0x94a3b8 });
|
|
117
|
+
}
|
|
118
|
+
this.content.alpha = node.opacity ?? 1;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Editor-only live preview of border edits while dragging the canvas nine-slice gizmo; the
|
|
122
|
+
* document is only written once, on drag release. A no-op without a `NineSliceSprite` content —
|
|
123
|
+
* e.g. mid-drag right after the asset was cleared, before the next document sync catches up.
|
|
124
|
+
*/
|
|
125
|
+
previewNineSlice(nineSlice) {
|
|
126
|
+
if (!(this.content instanceof NineSliceSprite))
|
|
127
|
+
return;
|
|
128
|
+
this.content.leftWidth = nineSlice.left;
|
|
129
|
+
this.content.topHeight = nineSlice.top;
|
|
130
|
+
this.content.rightWidth = nineSlice.right;
|
|
131
|
+
this.content.bottomHeight = nineSlice.bottom;
|
|
58
132
|
}
|
|
59
133
|
}
|
|
60
134
|
export class TextNodeView extends NodeView {
|
|
61
135
|
fonts;
|
|
136
|
+
/**
|
|
137
|
+
* Строка, применённая локализацией поверх авторской. Она переживает `updateNodeView`: без неё
|
|
138
|
+
* любая синхронизация документа возвращала бы fallback `node.text` вместо текущего перевода.
|
|
139
|
+
*/
|
|
140
|
+
localizedText;
|
|
141
|
+
/** Последний применённый прямоугольник и стиль — их же переиспользует инкрементальный `setText`. */
|
|
142
|
+
lastTransform;
|
|
143
|
+
lastStyle;
|
|
62
144
|
constructor(text, fonts) {
|
|
63
145
|
super();
|
|
64
146
|
this.fonts = fonts;
|
|
65
147
|
this.setContent(new Text({ text, style: { fontFamily: "Arial", fontSize: 24, fill: 0xffffff } }));
|
|
66
148
|
}
|
|
67
|
-
syncContent(node, transform) {
|
|
149
|
+
syncContent(node, transform, profile) {
|
|
68
150
|
if (node.type !== "text" || !(this.content instanceof Text))
|
|
69
151
|
return;
|
|
70
|
-
|
|
71
|
-
|
|
152
|
+
const text = this.localizedText ?? node.text;
|
|
153
|
+
if (this.content.text !== text)
|
|
154
|
+
this.content.text = text;
|
|
155
|
+
const style = resolveTextStyle(node, profile);
|
|
156
|
+
this.lastTransform = transform;
|
|
157
|
+
this.lastStyle = style;
|
|
72
158
|
if (style === undefined)
|
|
73
159
|
return;
|
|
74
160
|
this.content.style = { fontFamily: style.fontAssetId === undefined ? style.fontFamily : this.fonts?.get(style.fontAssetId) ?? style.fontFamily, fontSize: style.fontSize, fontWeight: style.fontWeight, fontStyle: style.fontStyle, fill: style.fill, align: style.align, wordWrap: style.wordWrap, breakWords: style.breakWords, wordWrapWidth: transform.width, lineHeight: style.lineHeight, letterSpacing: style.letterSpacing, stroke: style.stroke === undefined ? undefined : { color: style.stroke.color, width: style.stroke.width } };
|
|
161
|
+
this.align();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Инкрементальная смена строки: та же строка не делает работы вообще, новая — только переизмеряет
|
|
165
|
+
* и выравнивает текст в текущем authored rectangle. `TextStyle` не пересоздаётся, а сам view
|
|
166
|
+
* сохраняет identity, поэтому смена локали не трогает ни сцену, ни GPU-ресурсы стиля.
|
|
167
|
+
*/
|
|
168
|
+
setText(text) {
|
|
169
|
+
if (!(this.content instanceof Text) || this.content.text === text)
|
|
170
|
+
return;
|
|
171
|
+
this.content.text = text;
|
|
172
|
+
this.align();
|
|
173
|
+
}
|
|
174
|
+
/** `undefined` возвращает ноду к авторской строке при следующей синхронизации документа. */
|
|
175
|
+
setLocalizedText(text) {
|
|
176
|
+
this.localizedText = text;
|
|
177
|
+
if (text !== undefined)
|
|
178
|
+
this.setText(text);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Вылезает ли фактически отрисованный текст за логический прямоугольник ноды.
|
|
182
|
+
*
|
|
183
|
+
* Меряется уже готовый `Text`, а не длина строки: перенос по словам, шрифт и обводка известны
|
|
184
|
+
* только рендеру. Без `wordWrap` переполнение возможно по ширине, с ним — по высоте, потому что
|
|
185
|
+
* перенос сам удерживает ширину в пределах `wordWrapWidth`. Диагностика transient: она ничего не
|
|
186
|
+
* пишет ни в документ, ни в view.
|
|
187
|
+
*/
|
|
188
|
+
measureOverflow() {
|
|
189
|
+
const transform = this.lastTransform;
|
|
190
|
+
if (!(this.content instanceof Text) || transform === undefined || typeof globalThis.document === "undefined")
|
|
191
|
+
return false;
|
|
192
|
+
const bounds = this.content.getLocalBounds();
|
|
193
|
+
const tolerance = 0.5;
|
|
194
|
+
return this.lastStyle?.wordWrap === true
|
|
195
|
+
? bounds.height > transform.height + tolerance
|
|
196
|
+
: bounds.width > transform.width + tolerance || bounds.height > transform.height + tolerance;
|
|
197
|
+
}
|
|
198
|
+
align() {
|
|
199
|
+
const transform = this.lastTransform;
|
|
200
|
+
const style = this.lastStyle;
|
|
201
|
+
if (!(this.content instanceof Text) || transform === undefined || style === undefined)
|
|
202
|
+
return;
|
|
75
203
|
// Headless loaders and schema tests intentionally have no browser canvas. In that boundary
|
|
76
204
|
// text still owns its authored rectangle; browser rendering keeps the precise measurement.
|
|
77
205
|
const bounds = typeof globalThis.document === "undefined" ? { x: 0, y: 0, width: 0, height: 0 } : this.content.getLocalBounds();
|