canvasengine 2.0.0-beta.6 → 2.0.0-beta.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DebugRenderer-DkjTAc48.js +1384 -0
- package/dist/DebugRenderer-DkjTAc48.js.map +1 -0
- package/dist/components/Button.d.ts +185 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Canvas.d.ts +17 -0
- package/dist/components/Canvas.d.ts.map +1 -0
- package/dist/components/DOMElement.d.ts +54 -0
- package/dist/components/DOMElement.d.ts.map +1 -0
- package/dist/components/DOMSprite.d.ts +127 -0
- package/dist/components/DOMSprite.d.ts.map +1 -0
- package/dist/components/FocusContainer.d.ts +129 -0
- package/dist/components/FocusContainer.d.ts.map +1 -0
- package/dist/components/Graphic.d.ts +64 -0
- package/dist/components/Graphic.d.ts.map +1 -0
- package/dist/components/Joystick.d.ts +36 -0
- package/dist/components/Joystick.d.ts.map +1 -0
- package/dist/components/NineSliceSprite.d.ts +16 -0
- package/dist/components/NineSliceSprite.d.ts.map +1 -0
- package/dist/components/ParticleEmitter.d.ts +4 -0
- package/dist/components/ParticleEmitter.d.ts.map +1 -0
- package/dist/components/Scene.d.ts +2 -0
- package/dist/components/Scene.d.ts.map +1 -0
- package/dist/components/Text.d.ts +24 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/TilingSprite.d.ts +17 -0
- package/dist/components/TilingSprite.d.ts.map +1 -0
- package/dist/components/Video.d.ts +14 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/index.d.ts +20 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/types/DisplayObject.d.ts +118 -0
- package/dist/components/types/DisplayObject.d.ts.map +1 -0
- package/dist/components/types/MouseEvent.d.ts +4 -0
- package/dist/components/types/MouseEvent.d.ts.map +1 -0
- package/dist/components/types/Spritesheet.d.ts +248 -0
- package/dist/components/types/Spritesheet.d.ts.map +1 -0
- package/dist/components/types/index.d.ts +4 -0
- package/dist/components/types/index.d.ts.map +1 -0
- package/dist/directives/Controls.d.ts +112 -0
- package/dist/directives/Controls.d.ts.map +1 -0
- package/dist/directives/ControlsBase.d.ts +199 -0
- package/dist/directives/ControlsBase.d.ts.map +1 -0
- package/dist/directives/Drag.d.ts +69 -0
- package/dist/directives/Drag.d.ts.map +1 -0
- package/dist/directives/Flash.d.ts +116 -0
- package/dist/directives/Flash.d.ts.map +1 -0
- package/dist/directives/FocusNavigation.d.ts +52 -0
- package/dist/directives/FocusNavigation.d.ts.map +1 -0
- package/dist/directives/FogVisibility.d.ts +47 -0
- package/dist/directives/FogVisibility.d.ts.map +1 -0
- package/dist/directives/GamepadControls.d.ts +224 -0
- package/dist/directives/GamepadControls.d.ts.map +1 -0
- package/dist/directives/JoystickControls.d.ts +171 -0
- package/dist/directives/JoystickControls.d.ts.map +1 -0
- package/dist/directives/KeyboardControls.d.ts +219 -0
- package/dist/directives/KeyboardControls.d.ts.map +1 -0
- package/dist/directives/Scheduler.d.ts +36 -0
- package/dist/directives/Scheduler.d.ts.map +1 -0
- package/dist/directives/Shake.d.ts +98 -0
- package/dist/directives/Shake.d.ts.map +1 -0
- package/dist/directives/Sound.d.ts +25 -0
- package/dist/directives/Sound.d.ts.map +1 -0
- package/dist/directives/Transition.d.ts +10 -0
- package/dist/directives/Transition.d.ts.map +1 -0
- package/dist/directives/ViewportCull.d.ts +11 -0
- package/dist/directives/ViewportCull.d.ts.map +1 -0
- package/dist/directives/ViewportFollow.d.ts +18 -0
- package/dist/directives/ViewportFollow.d.ts.map +1 -0
- package/dist/directives/index.d.ts +14 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/dist-BOOc43Qm.js +778 -0
- package/dist/dist-BOOc43Qm.js.map +1 -0
- package/dist/engine/FocusManager.d.ts +174 -0
- package/dist/engine/FocusManager.d.ts.map +1 -0
- package/dist/engine/animation.d.ts +72 -0
- package/dist/engine/animation.d.ts.map +1 -0
- package/dist/engine/bootstrap.d.ts +52 -0
- package/dist/engine/bootstrap.d.ts.map +1 -0
- package/dist/engine/directive.d.ts +13 -0
- package/dist/engine/directive.d.ts.map +1 -0
- package/dist/engine/reactive.d.ts +135 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +73 -0
- package/dist/engine/signal.d.ts.map +1 -0
- package/dist/engine/trigger.d.ts +54 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +89 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/hooks/addContext.d.ts +2 -0
- package/dist/hooks/addContext.d.ts.map +1 -0
- package/dist/hooks/useFocus.d.ts +60 -0
- package/dist/hooks/useFocus.d.ts.map +1 -0
- package/dist/hooks/useProps.d.ts +42 -0
- package/dist/hooks/useProps.d.ts.map +1 -0
- package/dist/hooks/useRef.d.ts +4 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/index.d.ts +19 -1107
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +8 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +14708 -3135
- package/dist/index.js.map +1 -1
- package/dist/utils/Ease.d.ts +17 -0
- package/dist/utils/Ease.d.ts.map +1 -0
- package/dist/utils/GlobalAssetLoader.d.ts +141 -0
- package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
- package/dist/utils/RadialGradient.d.ts +57 -0
- package/dist/utils/RadialGradient.d.ts.map +1 -0
- package/dist/utils/functions.d.ts +2 -0
- package/dist/utils/functions.d.ts.map +1 -0
- package/dist/utils/tabindex.d.ts +16 -0
- package/dist/utils/tabindex.d.ts.map +1 -0
- package/package.json +16 -9
- package/src/components/Button.ts +399 -0
- package/src/components/Canvas.ts +82 -51
- package/src/components/Container.ts +21 -2
- package/src/components/DOMContainer.ts +379 -0
- package/src/components/DOMElement.ts +556 -0
- package/src/components/DOMSprite.ts +1040 -0
- package/src/components/DisplayObject.ts +422 -201
- package/src/components/FocusContainer.ts +368 -0
- package/src/components/Graphic.ts +239 -73
- package/src/components/Joystick.ts +363 -0
- package/src/components/Mesh.ts +222 -0
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +418 -52
- package/src/components/Text.ts +270 -26
- package/src/components/Viewport.ts +122 -63
- package/src/components/index.ts +9 -2
- package/src/components/types/DisplayObject.ts +53 -5
- package/src/components/types/Spritesheet.ts +0 -118
- package/src/directives/Controls.ts +254 -0
- package/src/directives/ControlsBase.ts +267 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/Flash.ts +419 -0
- package/src/directives/FocusNavigation.ts +113 -0
- package/src/directives/FogVisibility.ts +273 -0
- package/src/directives/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +85 -430
- package/src/directives/Scheduler.ts +21 -5
- package/src/directives/Shake.ts +298 -0
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +40 -9
- package/src/directives/index.ts +13 -6
- package/src/engine/FocusManager.ts +510 -0
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +140 -6
- package/src/engine/directive.ts +4 -4
- package/src/engine/reactive.ts +980 -177
- package/src/engine/signal.ts +241 -47
- package/src/engine/trigger.ts +34 -7
- package/src/engine/utils.ts +19 -3
- package/src/hooks/useFocus.ts +91 -0
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +8 -2
- package/src/types/pixi-cull.d.ts +7 -0
- package/src/utils/GlobalAssetLoader.ts +257 -0
- package/src/utils/functions.ts +7 -0
- package/src/utils/tabindex.ts +70 -0
- package/testing/index.ts +35 -4
- package/tsconfig.json +18 -0
- package/vite.config.ts +39 -0
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Element, isElement, Props } from "../engine/reactive";
|
|
1
|
+
import { Element, isElement, Props, isElementFrozen } from "../engine/reactive";
|
|
3
2
|
import { setObservablePoint } from "../engine/utils";
|
|
4
3
|
import type {
|
|
5
4
|
AlignContent,
|
|
6
5
|
EdgeSize,
|
|
7
6
|
FlexDirection,
|
|
8
|
-
|
|
7
|
+
ObjectFit,
|
|
8
|
+
ObjectPosition,
|
|
9
|
+
TransformOrigin,
|
|
9
10
|
} from "./types/DisplayObject";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
11
|
+
import { signal } from "@signe/reactive";
|
|
12
|
+
import { BlurFilter, ObservablePoint, type Point, type Rectangle } from "pixi.js";
|
|
13
|
+
import * as FILTERS from "pixi-filters";
|
|
14
|
+
import { isPercent } from "../utils/functions";
|
|
15
|
+
import { BehaviorSubject, filter, Subject } from "rxjs";
|
|
13
16
|
|
|
14
17
|
export interface ComponentInstance extends PixiMixins.ContainerOptions {
|
|
15
18
|
id?: string;
|
|
16
19
|
children?: ComponentInstance[];
|
|
17
20
|
onInit?(props: Props): void;
|
|
18
21
|
onUpdate?(props: Props): void;
|
|
19
|
-
onDestroy?(parent: Element): void;
|
|
20
|
-
onMount?(context: Element
|
|
22
|
+
onDestroy?(parent: Element, afterDestroy: () => void): void;
|
|
23
|
+
onMount?(context: Element<any>, index?: number): void;
|
|
21
24
|
setWidth(width: number): void;
|
|
22
25
|
setHeight(height: number): void;
|
|
26
|
+
getLocalBounds?(): Rectangle;
|
|
27
|
+
getGlobalPosition?(): Point;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export const EVENTS = [
|
|
@@ -93,6 +98,8 @@ export const EVENTS = [
|
|
|
93
98
|
"wheelcapture",
|
|
94
99
|
];
|
|
95
100
|
|
|
101
|
+
export type OnHook = (() => void) | (() => Promise<void> | void);
|
|
102
|
+
|
|
96
103
|
export function DisplayObject(extendClass) {
|
|
97
104
|
return class DisplayObject extends extendClass {
|
|
98
105
|
#canvasContext: {
|
|
@@ -101,117 +108,162 @@ export function DisplayObject(extendClass) {
|
|
|
101
108
|
isFlex: boolean = false;
|
|
102
109
|
fullProps: Props = {};
|
|
103
110
|
isMounted: boolean = false;
|
|
104
|
-
_anchorPoints = new ObservablePoint(
|
|
105
|
-
{ _onUpdate: () => {} },
|
|
106
|
-
0,
|
|
107
|
-
0
|
|
108
|
-
);
|
|
111
|
+
_anchorPoints = new ObservablePoint({ _onUpdate: () => {} }, 0, 0);
|
|
109
112
|
isCustomAnchor: boolean = false;
|
|
110
113
|
displayWidth = signal(0);
|
|
111
114
|
displayHeight = signal(0);
|
|
112
115
|
overrideProps: string[] = [];
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
layout = null;
|
|
117
|
+
onBeforeDestroy: OnHook | null = null;
|
|
118
|
+
onAfterMount: OnHook | null = null;
|
|
119
|
+
subjectInit = new BehaviorSubject(null);
|
|
120
|
+
disableLayout: boolean = false;
|
|
121
|
+
// Store registered event listeners for cleanup
|
|
122
|
+
#registeredEvents: Map<string, Function> = new Map();
|
|
123
|
+
// Store computed layout box dimensions
|
|
124
|
+
#computedLayoutBox: { width?: number; height?: number } | null = null;
|
|
125
|
+
// Store reference to element for freeze checking
|
|
126
|
+
#element: Element<any> | null = null;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get the element reference for freeze checking
|
|
130
|
+
* @returns The element reference or null
|
|
131
|
+
*/
|
|
132
|
+
getElement(): Element<any> | null {
|
|
133
|
+
return this.#element;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
onLayoutComputed(_event: any) {}
|
|
118
137
|
|
|
119
138
|
get deltaRatio() {
|
|
120
139
|
return this.#canvasContext?.scheduler?.tick.value.deltaRatio;
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
|
|
142
|
+
get parentIsFlex() {
|
|
143
|
+
if (this.disableLayout) return false;
|
|
144
|
+
return this.parent?.isFlex;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
onInit(props: Props) {
|
|
148
|
+
// Ensure layout setter from @pixi/layout is used when available.
|
|
149
|
+
if (Object.prototype.hasOwnProperty.call(this, "layout")) {
|
|
150
|
+
delete (this as any).layout;
|
|
151
|
+
}
|
|
124
152
|
this._id = props.id;
|
|
125
153
|
for (let event of EVENTS) {
|
|
126
154
|
if (props[event] && !this.overrideProps.includes(event)) {
|
|
127
155
|
this.eventMode = "static";
|
|
128
|
-
|
|
156
|
+
const originalEventHandler = props[event];
|
|
157
|
+
|
|
158
|
+
// Wrap event handler to check freeze state
|
|
159
|
+
const wrappedHandler = (...args: any[]) => {
|
|
160
|
+
// Check if element is frozen before executing handler
|
|
161
|
+
if (this.#element && isElementFrozen(this.#element)) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
return originalEventHandler(...args);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// Store the wrapped event handler for cleanup
|
|
168
|
+
if (event === 'click') {
|
|
169
|
+
this.on('pointertap', wrappedHandler);
|
|
170
|
+
this.#registeredEvents.set('pointertap', wrappedHandler);
|
|
171
|
+
} else {
|
|
172
|
+
this.on(event, wrappedHandler);
|
|
173
|
+
this.#registeredEvents.set(event, wrappedHandler);
|
|
174
|
+
}
|
|
129
175
|
}
|
|
130
176
|
}
|
|
177
|
+
if (props.onBeforeDestroy || props['on-before-destroy']) {
|
|
178
|
+
this.onBeforeDestroy = props.onBeforeDestroy || props['on-before-destroy'];
|
|
179
|
+
}
|
|
180
|
+
if (props.onAfterMount || props['on-after-mount']) {
|
|
181
|
+
this.onAfterMount = props.onAfterMount || props['on-after-mount'];
|
|
182
|
+
}
|
|
183
|
+
if (
|
|
184
|
+
props.justifyContent ||
|
|
185
|
+
props.alignItems ||
|
|
186
|
+
props.flexDirection ||
|
|
187
|
+
props.flexWrap ||
|
|
188
|
+
props.alignContent ||
|
|
189
|
+
props.display == "flex" ||
|
|
190
|
+
isPercent(props.width) ||
|
|
191
|
+
isPercent(props.height) ||
|
|
192
|
+
props.isRoot
|
|
193
|
+
) {
|
|
194
|
+
this.layout = {};
|
|
195
|
+
this.isFlex = true;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
this.subjectInit.next(this);
|
|
131
199
|
}
|
|
132
200
|
|
|
133
|
-
onMount(
|
|
134
|
-
this
|
|
135
|
-
this
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
201
|
+
async onMount(element: Element<any>, index?: number) {
|
|
202
|
+
if (this.destroyed) return
|
|
203
|
+
this.#element = element;
|
|
204
|
+
this.#canvasContext = element.props.context;
|
|
205
|
+
if (element.parent) {
|
|
206
|
+
let parentElement = element.parent;
|
|
207
|
+
let instance = parentElement.componentInstance as DisplayObject;
|
|
208
|
+
if (typeof (instance as any)?.addChild !== "function") {
|
|
209
|
+
let search = parentElement.parent;
|
|
210
|
+
while (search && typeof (search.componentInstance as any)?.addChild !== "function") {
|
|
211
|
+
search = search.parent;
|
|
212
|
+
}
|
|
213
|
+
if (search && typeof (search.componentInstance as any)?.addChild === "function") {
|
|
214
|
+
parentElement = search;
|
|
215
|
+
instance = parentElement.componentInstance as DisplayObject;
|
|
216
|
+
} else {
|
|
217
|
+
console.warn("DisplayObject mount skipped: parent has no addChild", {
|
|
218
|
+
child: element.tag,
|
|
219
|
+
parent: element.parent?.tag,
|
|
220
|
+
});
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (instance.isFlex && !this.layout && !this.disableLayout) {
|
|
225
|
+
try {
|
|
226
|
+
this.layout = {};
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.warn('Failed to set layout:', error);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (index === undefined || parentElement !== element.parent || typeof (instance as any)?.addChildAt !== "function") {
|
|
139
232
|
instance.addChild(this);
|
|
140
233
|
} else {
|
|
141
234
|
instance.addChildAt(this, index);
|
|
142
235
|
}
|
|
143
|
-
if (instance.layer) this.parentLayer = instance.layer;
|
|
144
236
|
this.isMounted = true;
|
|
145
|
-
this.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const { left, top } = child.getComputedLayout();
|
|
155
|
-
child.x = left;
|
|
156
|
-
child.y = top;
|
|
237
|
+
this.onUpdate(element.props);
|
|
238
|
+
|
|
239
|
+
// Listen to layout events to store computed layout dimensions
|
|
240
|
+
const layoutHandler = (event: any) => {
|
|
241
|
+
if (event.computedLayout) {
|
|
242
|
+
this.#computedLayoutBox = {
|
|
243
|
+
width: event.computedLayout.width,
|
|
244
|
+
height: event.computedLayout.height,
|
|
245
|
+
};
|
|
157
246
|
}
|
|
247
|
+
this.onLayoutComputed(event);
|
|
248
|
+
};
|
|
249
|
+
this.on('layout', layoutHandler);
|
|
250
|
+
this.#registeredEvents.set('layout', layoutHandler);
|
|
251
|
+
|
|
252
|
+
if (this.onAfterMount) {
|
|
253
|
+
await this.onAfterMount();
|
|
158
254
|
}
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
effectSize(width: Size, height: Size) {
|
|
164
|
-
const handleSize = (
|
|
165
|
-
size: Size,
|
|
166
|
-
setter: (value: number) => void,
|
|
167
|
-
parentSize: Signal<number>
|
|
168
|
-
) => {
|
|
169
|
-
if (typeof size === "string" && size.endsWith("%")) {
|
|
170
|
-
effect(() => {
|
|
171
|
-
setter(parentSize() * (parseInt(size) / 100));
|
|
172
|
-
if (this.isFlex) {
|
|
173
|
-
this.#applyFlexLayout();
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
} else {
|
|
177
|
-
setter(+size);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
if (width != undefined)
|
|
182
|
-
handleSize(width, this.setWidth.bind(this), this.parent.displayWidth);
|
|
183
|
-
if (height != undefined)
|
|
184
|
-
handleSize(
|
|
185
|
-
height,
|
|
186
|
-
this.setHeight.bind(this),
|
|
187
|
-
this.parent.displayHeight
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
#applyFlexLayout() {
|
|
192
|
-
this.calculateLayout();
|
|
193
|
-
for (let child of this.children) {
|
|
194
|
-
const { left, top } = child.node.getComputedLayout();
|
|
195
|
-
child.x = left;
|
|
196
|
-
child.y = top;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
#flexRender(props) {
|
|
201
|
-
if (!this.parent) return;
|
|
202
|
-
if (props.flexDirection || props.justifyContent) {
|
|
203
|
-
this.isFlex = true;
|
|
204
|
-
this.#applyFlexLayout();
|
|
205
255
|
}
|
|
206
256
|
}
|
|
207
257
|
|
|
208
|
-
onUpdate(props) {
|
|
258
|
+
onUpdate(props: Props) {
|
|
209
259
|
this.fullProps = {
|
|
210
260
|
...this.fullProps,
|
|
211
261
|
...props,
|
|
212
262
|
};
|
|
213
263
|
|
|
264
|
+
if (this.destroyed) return
|
|
214
265
|
if (!this.#canvasContext || !this.parent) return;
|
|
266
|
+
|
|
215
267
|
if (props.x !== undefined) this.setX(props.x);
|
|
216
268
|
if (props.y !== undefined) this.setY(props.y);
|
|
217
269
|
if (props.scale !== undefined)
|
|
@@ -219,6 +271,28 @@ export function DisplayObject(extendClass) {
|
|
|
219
271
|
if (props.anchor !== undefined && !this.isCustomAnchor) {
|
|
220
272
|
setObservablePoint(this.anchor, props.anchor);
|
|
221
273
|
}
|
|
274
|
+
if (props.width !== undefined) this.setWidth(props.width);
|
|
275
|
+
if (props.height !== undefined) this.setHeight(props.height);
|
|
276
|
+
if (props.minWidth !== undefined) this.setMinWidth(props.minWidth);
|
|
277
|
+
if (props.minHeight !== undefined) this.setMinHeight(props.minHeight);
|
|
278
|
+
if (props.maxWidth !== undefined) this.setMaxWidth(props.maxWidth);
|
|
279
|
+
if (props.maxHeight !== undefined) this.setMaxHeight(props.maxHeight);
|
|
280
|
+
if (props.aspectRatio !== undefined)
|
|
281
|
+
this.setAspectRatio(props.aspectRatio);
|
|
282
|
+
if (props.flexGrow !== undefined) this.setFlexGrow(props.flexGrow);
|
|
283
|
+
if (props.flexShrink !== undefined) this.setFlexShrink(props.flexShrink);
|
|
284
|
+
if (props.flexBasis !== undefined) this.setFlexBasis(props.flexBasis);
|
|
285
|
+
if (props.rowGap !== undefined) this.setRowGap(props.rowGap);
|
|
286
|
+
if (props.columnGap !== undefined) this.setColumnGap(props.columnGap);
|
|
287
|
+
if (props.top !== undefined) this.setTop(props.top);
|
|
288
|
+
if (props.left !== undefined) this.setLeft(props.left);
|
|
289
|
+
if (props.right !== undefined) this.setRight(props.right);
|
|
290
|
+
if (props.bottom !== undefined) this.setBottom(props.bottom);
|
|
291
|
+
if (props.objectFit !== undefined) this.setObjectFit(props.objectFit);
|
|
292
|
+
if (props.objectPosition !== undefined)
|
|
293
|
+
this.setObjectPosition(props.objectPosition);
|
|
294
|
+
if (props.transformOrigin !== undefined)
|
|
295
|
+
this.setTransformOrigin(props.transformOrigin);
|
|
222
296
|
if (props.skew !== undefined) setObservablePoint(this.skew, props.skew);
|
|
223
297
|
if (props.tint) this.tint = props.tint;
|
|
224
298
|
if (props.rotation !== undefined) this.rotation = props.rotation;
|
|
@@ -243,23 +317,51 @@ export function DisplayObject(extendClass) {
|
|
|
243
317
|
if (props.filters) this.filters = props.filters;
|
|
244
318
|
if (props.maskOf) {
|
|
245
319
|
if (isElement(props.maskOf)) {
|
|
246
|
-
props.maskOf.componentInstance.mask = this;
|
|
320
|
+
props.maskOf.componentInstance.mask = this as any;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (props.shadowCaster !== undefined) {
|
|
324
|
+
const shadowCasterValue = (props.shadowCaster as any)?.value ?? props.shadowCaster;
|
|
325
|
+
if (
|
|
326
|
+
shadowCasterValue &&
|
|
327
|
+
typeof shadowCasterValue === "object" &&
|
|
328
|
+
!Array.isArray(shadowCasterValue)
|
|
329
|
+
) {
|
|
330
|
+
const current = ((this as any).shadowCaster ?? {}) as Record<string, unknown>;
|
|
331
|
+
(this as any).shadowCaster = { ...current, ...shadowCasterValue };
|
|
332
|
+
} else {
|
|
333
|
+
(this as any).shadowCaster = shadowCasterValue;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (props.footprintCaster !== undefined) {
|
|
337
|
+
const footprintCasterValue =
|
|
338
|
+
(props.footprintCaster as any)?.value ?? props.footprintCaster;
|
|
339
|
+
if (
|
|
340
|
+
footprintCasterValue &&
|
|
341
|
+
typeof footprintCasterValue === "object" &&
|
|
342
|
+
!Array.isArray(footprintCasterValue)
|
|
343
|
+
) {
|
|
344
|
+
const current = ((this as any).footprintCaster ?? {}) as Record<string, unknown>;
|
|
345
|
+
(this as any).footprintCaster = { ...current, ...footprintCasterValue };
|
|
346
|
+
} else {
|
|
347
|
+
(this as any).footprintCaster = footprintCasterValue;
|
|
247
348
|
}
|
|
248
349
|
}
|
|
249
350
|
if (props.blendMode) this.blendMode = props.blendMode;
|
|
250
351
|
if (props.filterArea) this.filterArea = props.filterArea;
|
|
251
352
|
const currentFilters = this.filters || [];
|
|
252
353
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
354
|
+
// TODO: Fix DropShadowFilter import issue
|
|
355
|
+
// if (props.shadow) {
|
|
356
|
+
// let dropShadowFilter = currentFilters.find(
|
|
357
|
+
// (filter) => filter instanceof FILTERS.DropShadowFilter
|
|
358
|
+
// );
|
|
359
|
+
// if (!dropShadowFilter) {
|
|
360
|
+
// dropShadowFilter = new FILTERS.DropShadowFilter();
|
|
361
|
+
// currentFilters.push(dropShadowFilter);
|
|
362
|
+
// }
|
|
363
|
+
// Object.assign(dropShadowFilter, props.shadow);
|
|
364
|
+
// }
|
|
263
365
|
|
|
264
366
|
if (props.blur) {
|
|
265
367
|
let blurFilter = currentFilters.find(
|
|
@@ -279,73 +381,44 @@ export function DisplayObject(extendClass) {
|
|
|
279
381
|
}
|
|
280
382
|
|
|
281
383
|
this.filters = currentFilters;
|
|
282
|
-
|
|
283
|
-
this.#flexRender(props);
|
|
284
384
|
}
|
|
285
385
|
|
|
286
|
-
onDestroy() {
|
|
287
|
-
|
|
288
|
-
this
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
applyComputedLayout() {
|
|
296
|
-
const layout = this.getComputedLayout();
|
|
297
|
-
this.x = layout.left;
|
|
298
|
-
this.y = layout.top;
|
|
299
|
-
}
|
|
386
|
+
async onDestroy(parent: Element, afterDestroy?: () => void) {
|
|
387
|
+
// Remove all registered event listeners
|
|
388
|
+
for (const [eventName, eventHandler] of this.#registeredEvents) {
|
|
389
|
+
this.off(eventName, eventHandler);
|
|
390
|
+
}
|
|
391
|
+
this.#registeredEvents.clear();
|
|
392
|
+
this.#element = null;
|
|
300
393
|
|
|
301
|
-
|
|
302
|
-
|
|
394
|
+
if (this.onBeforeDestroy) {
|
|
395
|
+
await this.onBeforeDestroy();
|
|
396
|
+
}
|
|
397
|
+
if (afterDestroy) afterDestroy();
|
|
398
|
+
if (this.parent && typeof this.parent.removeChild === "function") {
|
|
399
|
+
this.parent.removeChild(this);
|
|
400
|
+
}
|
|
401
|
+
super.destroy();
|
|
303
402
|
}
|
|
304
403
|
|
|
305
404
|
setFlexDirection(direction: FlexDirection) {
|
|
306
|
-
|
|
307
|
-
row: this.yoga.FLEX_DIRECTION_ROW,
|
|
308
|
-
column: this.yoga.FLEX_DIRECTION_COLUMN,
|
|
309
|
-
"row-reverse": this.yoga.FLEX_DIRECTION_ROW_REVERSE,
|
|
310
|
-
"column-reverse": this.yoga.FLEX_DIRECTION_COLUMN_REVERSE,
|
|
311
|
-
};
|
|
312
|
-
this.node.setFlexDirection(mapping[direction]);
|
|
405
|
+
this.layout = { flexDirection: direction };
|
|
313
406
|
}
|
|
314
407
|
|
|
315
408
|
setFlexWrap(wrap: "wrap" | "nowrap" | "wrap-reverse") {
|
|
316
|
-
|
|
317
|
-
wrap: this.yoga.WRAP_WRAP,
|
|
318
|
-
nowrap: this.yoga.WRAP_NO_WRAP,
|
|
319
|
-
"wrap-reverse": this.yoga.WRAP_WRAP_REVERSE,
|
|
320
|
-
};
|
|
321
|
-
this.node.setFlexWrap(mapping[wrap]);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
#setAlign(methodName: string, align: AlignContent) {
|
|
325
|
-
const mapping = {
|
|
326
|
-
auto: this.yoga.ALIGN_AUTO,
|
|
327
|
-
"flex-start": this.yoga.ALIGN_FLEX_START,
|
|
328
|
-
"flex-end": this.yoga.ALIGN_FLEX_END,
|
|
329
|
-
center: this.yoga.ALIGN_CENTER,
|
|
330
|
-
stretch: this.yoga.ALIGN_STRETCH,
|
|
331
|
-
baseline: this.yoga.ALIGN_BASELINE,
|
|
332
|
-
"space-between": this.yoga.ALIGN_SPACE_BETWEEN,
|
|
333
|
-
"space-around": this.yoga.ALIGN_SPACE_AROUND,
|
|
334
|
-
};
|
|
335
|
-
const method = (this.node as any)[methodName].bind(this.node);
|
|
336
|
-
method(mapping[align]);
|
|
409
|
+
this.layout = { flexWrap: wrap };
|
|
337
410
|
}
|
|
338
411
|
|
|
339
412
|
setAlignContent(align: AlignContent) {
|
|
340
|
-
this
|
|
413
|
+
this.layout = { alignContent: align };
|
|
341
414
|
}
|
|
342
415
|
|
|
343
416
|
setAlignSelf(align: AlignContent) {
|
|
344
|
-
this
|
|
417
|
+
this.layout = { alignSelf: align };
|
|
345
418
|
}
|
|
346
419
|
|
|
347
420
|
setAlignItems(align: AlignContent) {
|
|
348
|
-
this
|
|
421
|
+
this.layout = { alignItems: align };
|
|
349
422
|
}
|
|
350
423
|
|
|
351
424
|
setJustifyContent(
|
|
@@ -356,103 +429,251 @@ export function DisplayObject(extendClass) {
|
|
|
356
429
|
| "space-between"
|
|
357
430
|
| "space-around"
|
|
358
431
|
) {
|
|
359
|
-
|
|
360
|
-
"flex-start": this.yoga.JUSTIFY_FLEX_START,
|
|
361
|
-
"flex-end": this.yoga.JUSTIFY_FLEX_END,
|
|
362
|
-
center: this.yoga.JUSTIFY_CENTER,
|
|
363
|
-
"space-between": this.yoga.JUSTIFY_SPACE_BETWEEN,
|
|
364
|
-
"space-around": this.yoga.JUSTIFY_SPACE_AROUND,
|
|
365
|
-
};
|
|
366
|
-
this.node.setJustifyContent(mapping[justifyContent]);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
#setEdgeSize(methodName: string, size: EdgeSize) {
|
|
370
|
-
const method = (this.node as any)[methodName].bind(this.node);
|
|
371
|
-
if (size instanceof Array) {
|
|
372
|
-
if (size.length === 2) {
|
|
373
|
-
method(this.yoga.EDGE_VERTICAL, size[0]);
|
|
374
|
-
method(this.yoga.EDGE_HORIZONTAL, size[1]);
|
|
375
|
-
} else if (size.length === 4) {
|
|
376
|
-
method(this.yoga.EDGE_TOP, size[0]);
|
|
377
|
-
method(this.yoga.EDGE_RIGHT, size[1]);
|
|
378
|
-
method(this.yoga.EDGE_BOTTOM, size[2]);
|
|
379
|
-
method(this.yoga.EDGE_LEFT, size[3]);
|
|
380
|
-
}
|
|
381
|
-
} else {
|
|
382
|
-
method(this.yoga.EDGE_ALL, size);
|
|
383
|
-
}
|
|
432
|
+
this.layout = { justifyContent };
|
|
384
433
|
}
|
|
385
434
|
|
|
386
435
|
setPosition(position: EdgeSize) {
|
|
387
|
-
|
|
436
|
+
if (position instanceof Array) {
|
|
437
|
+
if (position.length === 2) {
|
|
438
|
+
this.layout = {
|
|
439
|
+
positionY: position[0],
|
|
440
|
+
positionX: position[1],
|
|
441
|
+
};
|
|
442
|
+
} else if (position.length === 4) {
|
|
443
|
+
this.layout = {
|
|
444
|
+
positionTop: position[0],
|
|
445
|
+
positionRight: position[1],
|
|
446
|
+
positionBottom: position[2],
|
|
447
|
+
positionLeft: position[3],
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
} else {
|
|
451
|
+
this.layout = { position };
|
|
452
|
+
}
|
|
388
453
|
}
|
|
389
454
|
|
|
390
455
|
setX(x: number) {
|
|
391
456
|
x = x + this.getWidth() * this._anchorPoints.x;
|
|
392
|
-
if (!this.
|
|
457
|
+
if (!this.parentIsFlex) {
|
|
458
|
+
this.x = x;
|
|
459
|
+
} else {
|
|
393
460
|
this.x = x;
|
|
461
|
+
this.layout = { x };
|
|
394
462
|
}
|
|
395
|
-
this.node.setPosition(this.yoga.EDGE_LEFT, x);
|
|
396
463
|
}
|
|
397
464
|
|
|
398
465
|
setY(y: number) {
|
|
399
466
|
y = y + this.getHeight() * this._anchorPoints.y;
|
|
400
|
-
if (!this.
|
|
467
|
+
if (!this.parentIsFlex) {
|
|
468
|
+
this.y = y;
|
|
469
|
+
} else {
|
|
401
470
|
this.y = y;
|
|
471
|
+
this.layout = { y };
|
|
402
472
|
}
|
|
403
|
-
this.node.setPosition(this.yoga.EDGE_TOP, y);
|
|
404
473
|
}
|
|
405
474
|
|
|
406
475
|
setPadding(padding: EdgeSize) {
|
|
407
|
-
|
|
476
|
+
if (padding instanceof Array) {
|
|
477
|
+
if (padding.length === 2) {
|
|
478
|
+
this.layout = {
|
|
479
|
+
paddingVertical: padding[0],
|
|
480
|
+
paddingHorizontal: padding[1],
|
|
481
|
+
};
|
|
482
|
+
} else if (padding.length === 4) {
|
|
483
|
+
this.layout = {
|
|
484
|
+
paddingTop: padding[0],
|
|
485
|
+
paddingRight: padding[1],
|
|
486
|
+
paddingBottom: padding[2],
|
|
487
|
+
paddingLeft: padding[3],
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
} else {
|
|
491
|
+
this.layout = { padding };
|
|
492
|
+
}
|
|
408
493
|
}
|
|
409
494
|
|
|
410
495
|
setMargin(margin: EdgeSize) {
|
|
411
|
-
|
|
496
|
+
if (margin instanceof Array) {
|
|
497
|
+
if (margin.length === 2) {
|
|
498
|
+
this.layout = {
|
|
499
|
+
marginVertical: margin[0],
|
|
500
|
+
marginHorizontal: margin[1],
|
|
501
|
+
};
|
|
502
|
+
} else if (margin.length === 4) {
|
|
503
|
+
this.layout = {
|
|
504
|
+
marginTop: margin[0],
|
|
505
|
+
marginRight: margin[1],
|
|
506
|
+
marginBottom: margin[2],
|
|
507
|
+
marginLeft: margin[3],
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
} else {
|
|
511
|
+
this.layout = { margin };
|
|
512
|
+
}
|
|
412
513
|
}
|
|
413
514
|
|
|
414
515
|
setGap(gap: EdgeSize) {
|
|
415
|
-
this.
|
|
516
|
+
this.layout = { gap };
|
|
416
517
|
}
|
|
417
518
|
|
|
418
519
|
setBorder(border: EdgeSize) {
|
|
419
|
-
|
|
520
|
+
if (border instanceof Array) {
|
|
521
|
+
if (border.length === 2) {
|
|
522
|
+
this.layout = {
|
|
523
|
+
borderVertical: border[0],
|
|
524
|
+
borderHorizontal: border[1],
|
|
525
|
+
};
|
|
526
|
+
} else if (border.length === 4) {
|
|
527
|
+
this.layout = {
|
|
528
|
+
borderTop: border[0],
|
|
529
|
+
borderRight: border[1],
|
|
530
|
+
borderBottom: border[2],
|
|
531
|
+
borderLeft: border[3],
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
this.layout = { border };
|
|
536
|
+
}
|
|
420
537
|
}
|
|
421
538
|
|
|
422
539
|
setPositionType(positionType: "relative" | "absolute") {
|
|
423
|
-
|
|
424
|
-
relative: this.yoga.POSITION_TYPE_RELATIVE,
|
|
425
|
-
absolute: this.yoga.POSITION_TYPE_ABSOLUTE,
|
|
426
|
-
};
|
|
427
|
-
this.node.setPositionType(mapping[positionType]);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
calculateBounds() {
|
|
431
|
-
super.calculateBounds();
|
|
432
|
-
if (!this._geometry) return;
|
|
433
|
-
const bounds = this._geometry.bounds;
|
|
434
|
-
const width = Math.abs(bounds.minX - bounds.maxX);
|
|
435
|
-
const height = Math.abs(bounds.minY - bounds.maxY);
|
|
436
|
-
// this.node.setWidth(width);
|
|
437
|
-
// this.node.setHeight(height);
|
|
540
|
+
this.layout = { position: positionType };
|
|
438
541
|
}
|
|
439
542
|
|
|
440
543
|
setWidth(width: number) {
|
|
441
544
|
this.displayWidth.set(width);
|
|
442
|
-
this.
|
|
545
|
+
if (!this.parentIsFlex) {
|
|
546
|
+
this.width = width;
|
|
547
|
+
} else {
|
|
548
|
+
this.layout = { width };
|
|
549
|
+
}
|
|
443
550
|
}
|
|
444
551
|
|
|
445
552
|
setHeight(height: number) {
|
|
446
553
|
this.displayHeight.set(height);
|
|
447
|
-
this.
|
|
554
|
+
if (!this.parentIsFlex) {
|
|
555
|
+
this.height = height;
|
|
556
|
+
} else {
|
|
557
|
+
this.layout = { height };
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
getWidth(): number {
|
|
562
|
+
// If width is a percentage, use computed layout box
|
|
563
|
+
if (isPercent(this.fullProps.width)) {
|
|
564
|
+
if (this.#computedLayoutBox?.width !== undefined) {
|
|
565
|
+
return this.#computedLayoutBox.width;
|
|
566
|
+
}
|
|
567
|
+
// Fallback to native width if layout not yet computed
|
|
568
|
+
return typeof this.width === 'number' ? this.width : 0;
|
|
569
|
+
}
|
|
570
|
+
// For static values, use native PixiJS width or displayWidth signal
|
|
571
|
+
const staticWidth = typeof this.width === 'number' && this.width > 0
|
|
572
|
+
? this.width
|
|
573
|
+
: (typeof this.displayWidth() === 'number' ? this.displayWidth() : 0);
|
|
574
|
+
return staticWidth;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
getHeight(): number {
|
|
578
|
+
// If height is a percentage, use computed layout box
|
|
579
|
+
if (isPercent(this.fullProps.height)) {
|
|
580
|
+
if (this.#computedLayoutBox?.height !== undefined) {
|
|
581
|
+
return this.#computedLayoutBox.height;
|
|
582
|
+
}
|
|
583
|
+
// Fallback to native height if layout not yet computed
|
|
584
|
+
return typeof this.height === 'number' ? this.height : 0;
|
|
585
|
+
}
|
|
586
|
+
// For static values, use native PixiJS height or displayHeight signal
|
|
587
|
+
const staticHeight = typeof this.height === 'number' && this.height > 0
|
|
588
|
+
? this.height
|
|
589
|
+
: (typeof this.displayHeight() === 'number' ? this.displayHeight() : 0);
|
|
590
|
+
return staticHeight;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Min/Max constraints
|
|
594
|
+
setMinWidth(minWidth: number | string) {
|
|
595
|
+
this.layout = { minWidth };
|
|
448
596
|
}
|
|
449
597
|
|
|
450
|
-
|
|
451
|
-
|
|
598
|
+
setMinHeight(minHeight: number | string) {
|
|
599
|
+
this.layout = { minHeight };
|
|
452
600
|
}
|
|
453
601
|
|
|
454
|
-
|
|
455
|
-
|
|
602
|
+
setMaxWidth(maxWidth: number | string) {
|
|
603
|
+
this.layout = { maxWidth };
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
setMaxHeight(maxHeight: number | string) {
|
|
607
|
+
this.layout = { maxHeight };
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Aspect ratio
|
|
611
|
+
setAspectRatio(aspectRatio: number) {
|
|
612
|
+
this.layout = { aspectRatio };
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Flex properties
|
|
616
|
+
setFlexGrow(flexGrow: number) {
|
|
617
|
+
this.layout = { flexGrow };
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
setFlexShrink(flexShrink: number) {
|
|
621
|
+
this.layout = { flexShrink };
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
setFlexBasis(flexBasis: number | string) {
|
|
625
|
+
this.layout = { flexBasis };
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Gap properties
|
|
629
|
+
setRowGap(rowGap: number) {
|
|
630
|
+
this.layout = { rowGap };
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
setColumnGap(columnGap: number) {
|
|
634
|
+
this.layout = { columnGap };
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Position insets
|
|
638
|
+
setTop(top: number | string) {
|
|
639
|
+
this.layout = { top };
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
setLeft(left: number | string) {
|
|
643
|
+
this.layout = { left };
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
setRight(right: number | string) {
|
|
647
|
+
this.layout = { right };
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
setBottom(bottom: number | string) {
|
|
651
|
+
this.layout = { bottom };
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Object properties
|
|
655
|
+
setObjectFit(objectFit: ObjectFit) {
|
|
656
|
+
try {
|
|
657
|
+
this.layout = { objectFit };
|
|
658
|
+
} catch (error) {
|
|
659
|
+
// Ignore layout errors in test environments or when yoga-layout is not available
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
setObjectPosition(objectPosition: ObjectPosition) {
|
|
664
|
+
try {
|
|
665
|
+
this.layout = { objectPosition };
|
|
666
|
+
} catch (error) {
|
|
667
|
+
// Ignore layout errors in test environments or when yoga-layout is not available
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
setTransformOrigin(transformOrigin: TransformOrigin) {
|
|
672
|
+
try {
|
|
673
|
+
this.layout = { transformOrigin };
|
|
674
|
+
} catch (error) {
|
|
675
|
+
// Ignore layout errors in test environments or when yoga-layout is not available
|
|
676
|
+
}
|
|
456
677
|
}
|
|
457
678
|
};
|
|
458
679
|
}
|