canvasengine 2.0.0-beta.5 → 2.0.0-beta.51
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/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/Container.d.ts +86 -0
- package/dist/components/Container.d.ts.map +1 -0
- package/dist/components/DOMContainer.d.ts +98 -0
- package/dist/components/DOMContainer.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/DisplayObject.d.ts +94 -0
- package/dist/components/DisplayObject.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/Mesh.d.ts +208 -0
- package/dist/components/Mesh.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/Sprite.d.ts +242 -0
- package/dist/components/Sprite.d.ts.map +1 -0
- package/dist/components/Text.d.ts +25 -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/Viewport.d.ts +121 -0
- package/dist/components/Viewport.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 +106 -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/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 +35 -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 +13 -0
- package/dist/directives/index.d.ts.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 +48 -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 +134 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +71 -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-DaGekQUW.js +2218 -0
- package/dist/index-DaGekQUW.js.map +1 -0
- package/dist/index.d.ts +19 -1099
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +5 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +11749 -2901
- 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 +13 -7
- package/src/components/Button.ts +399 -0
- package/src/components/Canvas.ts +62 -46
- 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 +392 -201
- package/src/components/FocusContainer.ts +368 -0
- package/src/components/Graphic.ts +227 -66
- 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 +297 -31
- package/src/components/Text.ts +125 -18
- package/src/components/Video.ts +2 -2
- package/src/components/Viewport.ts +118 -63
- package/src/components/index.ts +9 -2
- package/src/components/types/DisplayObject.ts +41 -4
- 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/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +85 -430
- package/src/directives/Scheduler.ts +12 -4
- 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 +12 -6
- package/src/engine/FocusManager.ts +510 -0
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +93 -3
- package/src/engine/directive.ts +4 -4
- package/src/engine/reactive.ts +901 -161
- package/src/engine/signal.ts +113 -25
- 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
package/src/components/Sprite.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Howl } from 'howler';
|
|
2
|
+
import { computed, effect, isSignal, Signal } from "@signe/reactive";
|
|
2
3
|
import {
|
|
4
|
+
Application,
|
|
3
5
|
Assets,
|
|
4
6
|
Container,
|
|
5
7
|
Sprite as PixiSprite,
|
|
@@ -10,7 +12,9 @@ import { Subscription } from "rxjs";
|
|
|
10
12
|
import {
|
|
11
13
|
Element,
|
|
12
14
|
createComponent,
|
|
15
|
+
isElement,
|
|
13
16
|
registerComponent,
|
|
17
|
+
isElementFrozen,
|
|
14
18
|
} from "../engine/reactive";
|
|
15
19
|
import { arrayEquals, isFunction } from "../engine/utils";
|
|
16
20
|
import { DisplayObject } from "./DisplayObject";
|
|
@@ -24,6 +28,8 @@ import {
|
|
|
24
28
|
import { ComponentFunction } from "../engine/signal";
|
|
25
29
|
import { DisplayObjectProps } from "./types/DisplayObject";
|
|
26
30
|
import { AnimatedSignal, isAnimatedSignal } from "../engine/animation";
|
|
31
|
+
import { Layout } from '@pixi/layout';
|
|
32
|
+
import { GlobalAssetLoader } from "../utils/GlobalAssetLoader";
|
|
27
33
|
|
|
28
34
|
const log = console.log;
|
|
29
35
|
|
|
@@ -73,15 +79,127 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
73
79
|
private subscriptionSheet: Subscription[] = [];
|
|
74
80
|
private sheetParams: any = {};
|
|
75
81
|
private sheetCurrentAnimation: string = StandardAnimation.Stand;
|
|
82
|
+
private app: Application | null = null;
|
|
76
83
|
onFinish: () => void;
|
|
84
|
+
private globalLoader: GlobalAssetLoader | null = null;
|
|
85
|
+
private trackedAssetIds: Set<string> = new Set();
|
|
86
|
+
|
|
87
|
+
get renderer() {
|
|
88
|
+
return this.app?.renderer;
|
|
89
|
+
}
|
|
77
90
|
|
|
78
91
|
private currentAnimationContainer: Container | null = null;
|
|
79
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Auto-detects image dimensions by loading the image and reading its natural size
|
|
95
|
+
* This is used when width/height are not explicitly provided in the spritesheet definition
|
|
96
|
+
*
|
|
97
|
+
* @param imagePath - Path to the image file
|
|
98
|
+
* @returns Object containing the detected width and height of the image
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const { width, height } = await sprite.detectImageDimensions('path/to/image.png');
|
|
103
|
+
* // width: 256, height: 128
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
private async detectImageDimensions(imagePath: string): Promise<{ width: number; height: number }> {
|
|
107
|
+
if (!imagePath || typeof imagePath !== 'string' || imagePath.trim() === '') {
|
|
108
|
+
throw new Error(`Invalid image path provided to detectImageDimensions: ${imagePath}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Register asset in global loader if available
|
|
112
|
+
let assetId: string | null = null;
|
|
113
|
+
if (this.globalLoader) {
|
|
114
|
+
assetId = this.globalLoader.registerAsset(imagePath);
|
|
115
|
+
this.trackedAssetIds.add(assetId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const texture = await Assets.load(imagePath, (progress) => {
|
|
119
|
+
if (this.globalLoader && assetId) {
|
|
120
|
+
this.globalLoader.updateProgress(assetId, progress);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Mark as complete
|
|
125
|
+
if (this.globalLoader && assetId) {
|
|
126
|
+
this.globalLoader.completeAsset(assetId);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
width: texture.width,
|
|
131
|
+
height: texture.height,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Creates textures from a spritesheet image by cutting it into frames
|
|
137
|
+
* Automatically detects image dimensions if width/height are not provided
|
|
138
|
+
*
|
|
139
|
+
* @param options - Texture options containing image path, dimensions, and frame configuration
|
|
140
|
+
* @returns A 2D array of textures organized by rows and columns
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // With explicit dimensions
|
|
145
|
+
* const textures = await sprite.createTextures({
|
|
146
|
+
* image: 'path/to/image.png',
|
|
147
|
+
* width: 256,
|
|
148
|
+
* height: 128,
|
|
149
|
+
* framesWidth: 4,
|
|
150
|
+
* framesHeight: 2,
|
|
151
|
+
* spriteWidth: 64,
|
|
152
|
+
* spriteHeight: 64
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* // Without dimensions (automatically detected)
|
|
156
|
+
* const textures = await sprite.createTextures({
|
|
157
|
+
* image: 'path/to/image.png',
|
|
158
|
+
* framesWidth: 4,
|
|
159
|
+
* framesHeight: 2,
|
|
160
|
+
* spriteWidth: 64,
|
|
161
|
+
* spriteHeight: 64
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
80
165
|
private async createTextures(
|
|
81
166
|
options: Required<TextureOptionsMerging>
|
|
82
167
|
): Promise<Texture[][]> {
|
|
83
|
-
|
|
84
|
-
|
|
168
|
+
let { width, height, framesHeight, framesWidth, image, offset } = options;
|
|
169
|
+
|
|
170
|
+
if (!image || typeof image !== 'string' || image.trim() === '') {
|
|
171
|
+
console.warn('Invalid image path provided to createTextures:', image);
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Register asset in global loader if available
|
|
176
|
+
let assetId: string | null = null;
|
|
177
|
+
if (this.globalLoader) {
|
|
178
|
+
assetId = this.globalLoader.registerAsset(image);
|
|
179
|
+
this.trackedAssetIds.add(assetId);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const texture = await Assets.load(image, (progress) => {
|
|
183
|
+
if (this.globalLoader && assetId) {
|
|
184
|
+
this.globalLoader.updateProgress(assetId, progress);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Mark as complete
|
|
189
|
+
if (this.globalLoader && assetId) {
|
|
190
|
+
this.globalLoader.completeAsset(assetId);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Auto-detect width and height from the image if not provided
|
|
194
|
+
if (!width || width <= 0) {
|
|
195
|
+
width = texture.width;
|
|
196
|
+
options.width = width;
|
|
197
|
+
}
|
|
198
|
+
if (!height || height <= 0) {
|
|
199
|
+
height = texture.height;
|
|
200
|
+
options.height = height;
|
|
201
|
+
}
|
|
202
|
+
|
|
85
203
|
const spriteWidth = options.spriteWidth;
|
|
86
204
|
const spriteHeight = options.spriteHeight;
|
|
87
205
|
const frames: Texture[][] = [];
|
|
@@ -140,12 +258,30 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
140
258
|
} as any;
|
|
141
259
|
const {
|
|
142
260
|
rectWidth,
|
|
143
|
-
width = 0,
|
|
261
|
+
width: widthOption = 0,
|
|
144
262
|
framesWidth = 1,
|
|
145
263
|
rectHeight,
|
|
146
|
-
height = 0,
|
|
264
|
+
height: heightOption = 0,
|
|
147
265
|
framesHeight = 1,
|
|
266
|
+
image,
|
|
148
267
|
} = optionsTextures;
|
|
268
|
+
|
|
269
|
+
// Auto-detect width and height from the image if not provided
|
|
270
|
+
let width = widthOption;
|
|
271
|
+
let height = heightOption;
|
|
272
|
+
|
|
273
|
+
if (image && ((!width || width <= 0) || (!height || height <= 0))) {
|
|
274
|
+
const dimensions = await this.detectImageDimensions(image);
|
|
275
|
+
if (!width || width <= 0) {
|
|
276
|
+
width = dimensions.width;
|
|
277
|
+
optionsTextures.width = width;
|
|
278
|
+
}
|
|
279
|
+
if (!height || height <= 0) {
|
|
280
|
+
height = dimensions.height;
|
|
281
|
+
optionsTextures.height = height;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
149
285
|
optionsTextures.spriteWidth = rectWidth ? rectWidth : width / framesWidth;
|
|
150
286
|
optionsTextures.spriteHeight = rectHeight
|
|
151
287
|
? rectHeight
|
|
@@ -163,20 +299,37 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
163
299
|
}
|
|
164
300
|
}
|
|
165
301
|
|
|
166
|
-
async onMount(params: Element<
|
|
302
|
+
async onMount(params: Element<any>) {
|
|
303
|
+
// Set #element manually for freeze checking before calling super.onMount
|
|
304
|
+
// We need to set it early so update() can check freeze state
|
|
305
|
+
(this as any)['#element'] = params;
|
|
306
|
+
|
|
167
307
|
const { props, propObservables } = params;
|
|
168
308
|
const tick: Signal = props.context.tick;
|
|
169
309
|
const sheet = props.sheet ?? {};
|
|
310
|
+
const definition = props.sheet?.definition ?? {};
|
|
311
|
+
this.app = props.context.app();
|
|
312
|
+
// Get global loader from context if available
|
|
313
|
+
this.globalLoader = props.context?.globalLoader || null;
|
|
170
314
|
if (sheet?.onFinish) {
|
|
171
315
|
this.onFinish = sheet.onFinish;
|
|
172
316
|
}
|
|
173
317
|
this.subscriptionTick = tick.observable.subscribe((value) => {
|
|
318
|
+
if (this.destroyed) return
|
|
174
319
|
this.update(value);
|
|
175
320
|
});
|
|
176
|
-
if (
|
|
177
|
-
|
|
321
|
+
if (definition) {
|
|
322
|
+
const resolvedDefinition = definition instanceof Promise ? await definition : definition;
|
|
323
|
+
this.spritesheet = resolvedDefinition.value ?? resolvedDefinition;
|
|
178
324
|
await this.createAnimations();
|
|
179
325
|
}
|
|
326
|
+
if (sheet?.params) {
|
|
327
|
+
this.sheetParams = sheet.params;
|
|
328
|
+
}
|
|
329
|
+
if (sheet?.playing && this.has(sheet.playing)) {
|
|
330
|
+
this.sheetCurrentAnimation = sheet.playing;
|
|
331
|
+
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
332
|
+
}
|
|
180
333
|
if (sheet.params) {
|
|
181
334
|
for (let key in propObservables?.sheet["params"]) {
|
|
182
335
|
const value = propObservables?.sheet["params"][key] as Signal;
|
|
@@ -184,11 +337,13 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
184
337
|
this.subscriptionSheet.push(
|
|
185
338
|
value.observable.subscribe((value) => {
|
|
186
339
|
if (this.animations.size == 0) return;
|
|
187
|
-
this.
|
|
340
|
+
if (!this.has(this.sheetCurrentAnimation)) return;
|
|
341
|
+
this.play(this.sheetCurrentAnimation, [{ ...this.sheetParams, [key]: value }]);
|
|
188
342
|
})
|
|
189
343
|
);
|
|
190
344
|
} else {
|
|
191
|
-
this.
|
|
345
|
+
if (!this.has(this.sheetCurrentAnimation)) continue;
|
|
346
|
+
this.play(this.sheetCurrentAnimation, [{ ...this.sheetParams, [key]: value }]);
|
|
192
347
|
}
|
|
193
348
|
}
|
|
194
349
|
}
|
|
@@ -218,20 +373,46 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
218
373
|
this.sheetCurrentAnimation = StandardAnimation.Stand;
|
|
219
374
|
}
|
|
220
375
|
|
|
221
|
-
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
376
|
+
if (this.spritesheet && this.has(this.sheetCurrentAnimation)) this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
222
377
|
});
|
|
223
|
-
|
|
224
378
|
super.onMount(params);
|
|
225
379
|
}
|
|
226
380
|
|
|
227
381
|
async onUpdate(props) {
|
|
382
|
+
if (this.destroyed) return
|
|
228
383
|
super.onUpdate(props);
|
|
229
384
|
|
|
385
|
+
// Initialize globalLoader from context if not already set
|
|
386
|
+
if (!this.globalLoader && props.context?.globalLoader) {
|
|
387
|
+
this.globalLoader = props.context.globalLoader;
|
|
388
|
+
}
|
|
389
|
+
|
|
230
390
|
const setTexture = async (image: string) => {
|
|
391
|
+
if (!image || typeof image !== 'string' || image.trim() === '') {
|
|
392
|
+
console.warn('Invalid image path provided to setTexture:', image);
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Register asset in global loader if available
|
|
397
|
+
let assetId: string | null = null;
|
|
398
|
+
if (this.globalLoader) {
|
|
399
|
+
assetId = this.globalLoader.registerAsset(image);
|
|
400
|
+
this.trackedAssetIds.add(assetId);
|
|
401
|
+
}
|
|
402
|
+
|
|
231
403
|
const onProgress = this.fullProps.loader?.onProgress;
|
|
232
404
|
const texture = await Assets.load(image, (progress) => {
|
|
405
|
+
// Update global loader progress
|
|
406
|
+
if (this.globalLoader && assetId) {
|
|
407
|
+
this.globalLoader.updateProgress(assetId, progress);
|
|
408
|
+
}
|
|
409
|
+
// Call local loader callback if provided
|
|
233
410
|
if (onProgress) onProgress(progress);
|
|
234
411
|
if (progress == 1) {
|
|
412
|
+
// Mark as complete in global loader
|
|
413
|
+
if (this.globalLoader && assetId) {
|
|
414
|
+
this.globalLoader.completeAsset(assetId);
|
|
415
|
+
}
|
|
235
416
|
const onComplete = this.fullProps.loader?.onComplete;
|
|
236
417
|
if (onComplete) {
|
|
237
418
|
// hack to memoize the texture
|
|
@@ -245,39 +426,71 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
245
426
|
return texture
|
|
246
427
|
}
|
|
247
428
|
|
|
248
|
-
const sheet = props.sheet
|
|
429
|
+
const sheet = props.sheet
|
|
430
|
+
const definition = props.sheet?.definition ?? {};
|
|
431
|
+
|
|
432
|
+
if (definition?.type === 'reset') {
|
|
433
|
+
const resolvedValue = definition.value instanceof Promise ? await definition.value : definition.value;
|
|
434
|
+
this.spritesheet = resolvedValue ?? definition;
|
|
435
|
+
await this.resetAnimations();
|
|
436
|
+
}
|
|
437
|
+
|
|
249
438
|
if (sheet?.params) this.sheetParams = sheet?.params;
|
|
250
439
|
|
|
251
|
-
if (sheet?.playing && this.isMounted) {
|
|
440
|
+
if (sheet?.playing && this.isMounted && this.spritesheet && this.animations.size > 0) {
|
|
252
441
|
this.sheetCurrentAnimation = sheet?.playing;
|
|
253
442
|
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
254
443
|
}
|
|
255
444
|
|
|
256
|
-
if (props.hitbox) this.hitbox = props.hitbox;
|
|
445
|
+
if (props.hitbox) this.hitbox = props.hitbox.value ?? props.hitbox;
|
|
257
446
|
|
|
258
447
|
if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;
|
|
259
448
|
else if (props.image && this.fullProps.rectangle === undefined) {
|
|
260
|
-
|
|
449
|
+
const texture = await setTexture(this.fullProps.image);
|
|
450
|
+
if (texture) {
|
|
451
|
+
this.texture = texture;
|
|
452
|
+
}
|
|
261
453
|
} else if (props.texture) {
|
|
262
|
-
|
|
454
|
+
if (isElement(props.texture)) {
|
|
455
|
+
const textureInstance = props.texture.componentInstance;
|
|
456
|
+
textureInstance.subjectInit
|
|
457
|
+
.subscribe()
|
|
458
|
+
this.texture = this.renderer?.generateTexture(props.texture.componentInstance);
|
|
459
|
+
} else {
|
|
460
|
+
this.texture = props.texture;
|
|
461
|
+
}
|
|
263
462
|
}
|
|
264
463
|
if (props.rectangle !== undefined) {
|
|
265
464
|
const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;
|
|
266
465
|
const texture = await setTexture(this.fullProps.image);
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
466
|
+
if (texture) {
|
|
467
|
+
this.texture = new Texture({
|
|
468
|
+
source: texture.source,
|
|
469
|
+
frame: new Rectangle(x, y, width, height),
|
|
470
|
+
});
|
|
471
|
+
}
|
|
271
472
|
}
|
|
272
473
|
}
|
|
273
474
|
|
|
274
|
-
onDestroy(): void {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
475
|
+
async onDestroy(parent: Element, afterDestroy: () => void): Promise<void> {
|
|
476
|
+
const _afterDestroy = async () => {
|
|
477
|
+
// Clean up tracked assets from global loader
|
|
478
|
+
if (this.globalLoader) {
|
|
479
|
+
this.trackedAssetIds.forEach((assetId) => {
|
|
480
|
+
this.globalLoader!.removeAsset(assetId);
|
|
481
|
+
});
|
|
482
|
+
this.trackedAssetIds.clear();
|
|
483
|
+
}
|
|
484
|
+
this.subscriptionSheet.forEach((sub) => sub.unsubscribe());
|
|
485
|
+
this.subscriptionTick.unsubscribe();
|
|
486
|
+
if (this.currentAnimationContainer && this.parent instanceof Container) {
|
|
487
|
+
this.parent.removeChild(this.currentAnimationContainer);
|
|
488
|
+
}
|
|
489
|
+
if (afterDestroy) {
|
|
490
|
+
afterDestroy();
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
await super.onDestroy(parent, _afterDestroy);
|
|
281
494
|
}
|
|
282
495
|
|
|
283
496
|
has(name: string): boolean {
|
|
@@ -296,7 +509,6 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
296
509
|
|
|
297
510
|
stop() {
|
|
298
511
|
this.currentAnimation = null;
|
|
299
|
-
this.destroy();
|
|
300
512
|
}
|
|
301
513
|
|
|
302
514
|
play(name: string, params: any[] = []) {
|
|
@@ -338,7 +550,12 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
338
550
|
const sound = this.currentAnimation.data.sound;
|
|
339
551
|
|
|
340
552
|
if (sound) {
|
|
341
|
-
|
|
553
|
+
new Howl({
|
|
554
|
+
src: sound,
|
|
555
|
+
autoplay: true,
|
|
556
|
+
loop: false,
|
|
557
|
+
volume: 1,
|
|
558
|
+
})
|
|
342
559
|
}
|
|
343
560
|
|
|
344
561
|
// Updates immediately to avoid flickering
|
|
@@ -347,7 +564,51 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
347
564
|
});
|
|
348
565
|
}
|
|
349
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Resets the sprite by destroying and recreating all animations
|
|
569
|
+
* This method clears the current animation state, destroys existing textures,
|
|
570
|
+
* and recreates all animations from the spritesheet
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```typescript
|
|
574
|
+
* // Reset all animations to their initial state
|
|
575
|
+
* sprite.resetAnimations();
|
|
576
|
+
*
|
|
577
|
+
* // Reset and then play a specific animation
|
|
578
|
+
* await sprite.resetAnimations();
|
|
579
|
+
* sprite.play('walk');
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
async resetAnimations(): Promise<void> {
|
|
583
|
+
// Stop current animation
|
|
584
|
+
this.stop();
|
|
585
|
+
|
|
586
|
+
// Clear all animations and textures
|
|
587
|
+
this.animations.clear();
|
|
588
|
+
|
|
589
|
+
// Reset animation state
|
|
590
|
+
this.currentAnimation = null;
|
|
591
|
+
this.currentAnimationContainer = null;
|
|
592
|
+
this.time = 0;
|
|
593
|
+
this.frameIndex = 0;
|
|
594
|
+
|
|
595
|
+
// Clear children
|
|
596
|
+
this.removeChildren();
|
|
597
|
+
|
|
598
|
+
// Recreate animations from spritesheet
|
|
599
|
+
if (this.spritesheet) {
|
|
600
|
+
await this.createAnimations();
|
|
601
|
+
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
350
605
|
update({ deltaRatio }) {
|
|
606
|
+
// Block animation update if element is frozen
|
|
607
|
+
const element = this.getElement();
|
|
608
|
+
if (element && isElementFrozen(element)) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
|
|
351
612
|
if (
|
|
352
613
|
!this.isPlaying() ||
|
|
353
614
|
!this.currentAnimation ||
|
|
@@ -413,6 +674,7 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
413
674
|
const widthOfSprite =
|
|
414
675
|
typeof realSize == "number" ? realSize : realSize?.width;
|
|
415
676
|
|
|
677
|
+
|
|
416
678
|
const applyAnchorBySize = () => {
|
|
417
679
|
if (heightOfSprite && this.hitbox) {
|
|
418
680
|
const { spriteWidth, spriteHeight } = data;
|
|
@@ -457,7 +719,9 @@ export class CanvasSprite extends DisplayObject(PixiSprite) {
|
|
|
457
719
|
}
|
|
458
720
|
}
|
|
459
721
|
|
|
460
|
-
export interface CanvasSprite extends PixiSprite {
|
|
722
|
+
export interface CanvasSprite extends PixiSprite {
|
|
723
|
+
layout: Layout | null;
|
|
724
|
+
}
|
|
461
725
|
|
|
462
726
|
registerComponent("Sprite", CanvasSprite);
|
|
463
727
|
|
|
@@ -510,5 +774,7 @@ export type SpritePropTypes = SpritePropsWithImage | SpritePropsWithSheet;
|
|
|
510
774
|
|
|
511
775
|
// Update the Sprite function to use the props interface
|
|
512
776
|
export const Sprite: ComponentFunction<SpritePropTypes> = (props) => {
|
|
777
|
+
// Ensure component is registered in test environments where module cache may differ
|
|
778
|
+
registerComponent("Sprite", CanvasSprite);
|
|
513
779
|
return createComponent("Sprite", props);
|
|
514
780
|
};
|