canvasengine 2.0.0-beta.4 → 2.0.0-beta.40

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.
Files changed (142) hide show
  1. package/dist/DebugRenderer-DgECR3yZ.js +172 -0
  2. package/dist/DebugRenderer-DgECR3yZ.js.map +1 -0
  3. package/dist/components/Button.d.ts +183 -0
  4. package/dist/components/Button.d.ts.map +1 -0
  5. package/dist/components/Canvas.d.ts +18 -0
  6. package/dist/components/Canvas.d.ts.map +1 -0
  7. package/dist/components/DOMElement.d.ts +44 -0
  8. package/dist/components/DOMElement.d.ts.map +1 -0
  9. package/dist/components/Graphic.d.ts +65 -0
  10. package/dist/components/Graphic.d.ts.map +1 -0
  11. package/dist/components/Joystick.d.ts +36 -0
  12. package/dist/components/Joystick.d.ts.map +1 -0
  13. package/dist/components/NineSliceSprite.d.ts +17 -0
  14. package/dist/components/NineSliceSprite.d.ts.map +1 -0
  15. package/dist/components/ParticleEmitter.d.ts +5 -0
  16. package/dist/components/ParticleEmitter.d.ts.map +1 -0
  17. package/dist/components/Scene.d.ts +2 -0
  18. package/dist/components/Scene.d.ts.map +1 -0
  19. package/dist/components/Text.d.ts +26 -0
  20. package/dist/components/Text.d.ts.map +1 -0
  21. package/dist/components/TilingSprite.d.ts +18 -0
  22. package/dist/components/TilingSprite.d.ts.map +1 -0
  23. package/dist/components/Video.d.ts +15 -0
  24. package/dist/components/Video.d.ts.map +1 -0
  25. package/dist/components/index.d.ts +18 -0
  26. package/dist/components/index.d.ts.map +1 -0
  27. package/dist/components/types/DisplayObject.d.ts +110 -0
  28. package/dist/components/types/DisplayObject.d.ts.map +1 -0
  29. package/dist/components/types/MouseEvent.d.ts +4 -0
  30. package/dist/components/types/MouseEvent.d.ts.map +1 -0
  31. package/dist/components/types/Spritesheet.d.ts +248 -0
  32. package/dist/components/types/Spritesheet.d.ts.map +1 -0
  33. package/dist/components/types/index.d.ts +5 -0
  34. package/dist/components/types/index.d.ts.map +1 -0
  35. package/dist/directives/Controls.d.ts +113 -0
  36. package/dist/directives/Controls.d.ts.map +1 -0
  37. package/dist/directives/ControlsBase.d.ts +198 -0
  38. package/dist/directives/ControlsBase.d.ts.map +1 -0
  39. package/dist/directives/Drag.d.ts +70 -0
  40. package/dist/directives/Drag.d.ts.map +1 -0
  41. package/dist/directives/Flash.d.ts +117 -0
  42. package/dist/directives/Flash.d.ts.map +1 -0
  43. package/dist/directives/GamepadControls.d.ts +225 -0
  44. package/dist/directives/GamepadControls.d.ts.map +1 -0
  45. package/dist/directives/JoystickControls.d.ts +172 -0
  46. package/dist/directives/JoystickControls.d.ts.map +1 -0
  47. package/dist/directives/KeyboardControls.d.ts +219 -0
  48. package/dist/directives/KeyboardControls.d.ts.map +1 -0
  49. package/dist/directives/Scheduler.d.ts +36 -0
  50. package/dist/directives/Scheduler.d.ts.map +1 -0
  51. package/dist/directives/Shake.d.ts +98 -0
  52. package/dist/directives/Shake.d.ts.map +1 -0
  53. package/dist/directives/Sound.d.ts +26 -0
  54. package/dist/directives/Sound.d.ts.map +1 -0
  55. package/dist/directives/Transition.d.ts +11 -0
  56. package/dist/directives/Transition.d.ts.map +1 -0
  57. package/dist/directives/ViewportCull.d.ts +12 -0
  58. package/dist/directives/ViewportCull.d.ts.map +1 -0
  59. package/dist/directives/ViewportFollow.d.ts +19 -0
  60. package/dist/directives/ViewportFollow.d.ts.map +1 -0
  61. package/dist/directives/index.d.ts +13 -0
  62. package/dist/directives/index.d.ts.map +1 -0
  63. package/dist/engine/animation.d.ts +73 -0
  64. package/dist/engine/animation.d.ts.map +1 -0
  65. package/dist/engine/bootstrap.d.ts +16 -0
  66. package/dist/engine/bootstrap.d.ts.map +1 -0
  67. package/dist/engine/directive.d.ts +14 -0
  68. package/dist/engine/directive.d.ts.map +1 -0
  69. package/dist/engine/reactive.d.ts +105 -0
  70. package/dist/engine/reactive.d.ts.map +1 -0
  71. package/dist/engine/signal.d.ts +72 -0
  72. package/dist/engine/signal.d.ts.map +1 -0
  73. package/dist/engine/trigger.d.ts +50 -0
  74. package/dist/engine/trigger.d.ts.map +1 -0
  75. package/dist/engine/utils.d.ts +90 -0
  76. package/dist/engine/utils.d.ts.map +1 -0
  77. package/dist/hooks/addContext.d.ts +2 -0
  78. package/dist/hooks/addContext.d.ts.map +1 -0
  79. package/dist/hooks/useProps.d.ts +42 -0
  80. package/dist/hooks/useProps.d.ts.map +1 -0
  81. package/dist/hooks/useRef.d.ts +5 -0
  82. package/dist/hooks/useRef.d.ts.map +1 -0
  83. package/dist/index-gb763Hyx.js +12560 -0
  84. package/dist/index-gb763Hyx.js.map +1 -0
  85. package/dist/index.d.ts +15 -1083
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.global.js +29 -0
  88. package/dist/index.global.js.map +1 -0
  89. package/dist/index.js +81 -3041
  90. package/dist/index.js.map +1 -1
  91. package/dist/utils/Ease.d.ts +17 -0
  92. package/dist/utils/Ease.d.ts.map +1 -0
  93. package/dist/utils/GlobalAssetLoader.d.ts +141 -0
  94. package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
  95. package/dist/utils/RadialGradient.d.ts +58 -0
  96. package/dist/utils/RadialGradient.d.ts.map +1 -0
  97. package/dist/utils/functions.d.ts +2 -0
  98. package/dist/utils/functions.d.ts.map +1 -0
  99. package/package.json +13 -7
  100. package/src/components/Button.ts +396 -0
  101. package/src/components/Canvas.ts +61 -45
  102. package/src/components/Container.ts +21 -2
  103. package/src/components/DOMContainer.ts +123 -0
  104. package/src/components/DOMElement.ts +421 -0
  105. package/src/components/DisplayObject.ts +350 -197
  106. package/src/components/Graphic.ts +200 -34
  107. package/src/components/Joystick.ts +361 -0
  108. package/src/components/Mesh.ts +222 -0
  109. package/src/components/NineSliceSprite.ts +4 -1
  110. package/src/components/ParticleEmitter.ts +12 -8
  111. package/src/components/Sprite.ts +306 -30
  112. package/src/components/Text.ts +125 -18
  113. package/src/components/Video.ts +110 -0
  114. package/src/components/Viewport.ts +59 -43
  115. package/src/components/index.ts +8 -2
  116. package/src/components/types/DisplayObject.ts +34 -0
  117. package/src/components/types/Spritesheet.ts +0 -118
  118. package/src/directives/Controls.ts +254 -0
  119. package/src/directives/ControlsBase.ts +266 -0
  120. package/src/directives/Drag.ts +357 -52
  121. package/src/directives/Flash.ts +409 -0
  122. package/src/directives/GamepadControls.ts +537 -0
  123. package/src/directives/JoystickControls.ts +396 -0
  124. package/src/directives/KeyboardControls.ts +66 -424
  125. package/src/directives/Shake.ts +282 -0
  126. package/src/directives/Sound.ts +94 -31
  127. package/src/directives/ViewportFollow.ts +35 -7
  128. package/src/directives/index.ts +12 -6
  129. package/src/engine/animation.ts +175 -21
  130. package/src/engine/bootstrap.ts +23 -3
  131. package/src/engine/directive.ts +2 -2
  132. package/src/engine/reactive.ts +780 -177
  133. package/src/engine/signal.ts +35 -4
  134. package/src/engine/trigger.ts +21 -4
  135. package/src/engine/utils.ts +19 -3
  136. package/src/hooks/useProps.ts +1 -1
  137. package/src/index.ts +4 -2
  138. package/src/utils/GlobalAssetLoader.ts +257 -0
  139. package/src/utils/functions.ts +7 -0
  140. package/testing/index.ts +12 -0
  141. package/tsconfig.json +17 -0
  142. package/vite.config.ts +39 -0
@@ -0,0 +1,409 @@
1
+ import { Container } from 'pixi.js';
2
+ import { Directive, registerDirective } from '../engine/directive';
3
+ import { Element } from '../engine/reactive';
4
+ import { effect, isSignal } from '@signe/reactive';
5
+ import { on, isTrigger, Trigger } from '../engine/trigger';
6
+ import { useProps } from '../hooks/useProps';
7
+ import { SignalOrPrimitive } from '../components/types';
8
+ import { animatedSignal, AnimatedSignal } from '../engine/animation';
9
+ import { Subscription } from 'rxjs';
10
+
11
+ export type FlashType = 'alpha' | 'tint' | 'both';
12
+
13
+ export type FlashProps = {
14
+ /**
15
+ * Trigger that activates the flash animation
16
+ * When the trigger is activated, the flash animation will start
17
+ */
18
+ trigger?: Trigger<any>;
19
+ /**
20
+ * Type of flash effect: 'alpha' (opacity), 'tint' (color), or 'both'
21
+ * @default 'alpha'
22
+ */
23
+ type?: SignalOrPrimitive<FlashType>;
24
+ /**
25
+ * Duration of the flash animation in milliseconds
26
+ * @default 300
27
+ */
28
+ duration?: SignalOrPrimitive<number>;
29
+ /**
30
+ * Number of flash cycles (flash on/off)
31
+ * @default 1
32
+ */
33
+ cycles?: SignalOrPrimitive<number>;
34
+ /**
35
+ * Alpha value when flashing (0 to 1)
36
+ * Only used when type is 'alpha' or 'both'
37
+ * @default 0.3
38
+ */
39
+ alpha?: SignalOrPrimitive<number>;
40
+ /**
41
+ * Tint color when flashing (hex color value)
42
+ * Only used when type is 'tint' or 'both'
43
+ * @default 0xffffff (white)
44
+ */
45
+ tint?: SignalOrPrimitive<number>;
46
+ /**
47
+ * Original alpha value to restore after flash
48
+ * If not provided, uses the current alpha value
49
+ */
50
+ originalAlpha?: number;
51
+ /**
52
+ * Original tint value to restore after flash
53
+ * If not provided, uses the current tint value
54
+ */
55
+ originalTint?: number;
56
+ /**
57
+ * Callback function called when flash starts
58
+ */
59
+ onStart?: () => void;
60
+ /**
61
+ * Callback function called when flash completes
62
+ */
63
+ onComplete?: () => void;
64
+ }
65
+
66
+ /**
67
+ * Flash directive that animates a display object's alpha and/or tint when a trigger is activated.
68
+ * Creates a flash effect by rapidly changing opacity or color.
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // Basic usage with trigger
73
+ * const flashTrigger = trigger();
74
+ *
75
+ * onMount(element) {
76
+ * // Element will flash when trigger is activated
77
+ * element.props.flash = { trigger: flashTrigger };
78
+ * }
79
+ *
80
+ * // Trigger the flash
81
+ * flashTrigger.start();
82
+ * ```
83
+ */
84
+ export class Flash extends Directive {
85
+ private elementRef: Element<Container> | null = null;
86
+ private progressSignal: AnimatedSignal<number> | null = null;
87
+ private flashSubscription: any = null;
88
+ private alphaEffect: Subscription | null = null;
89
+ private tintEffect: Subscription | null = null;
90
+ private originalAlpha: number = 1;
91
+ private originalTint: number = 0xffffff;
92
+ private currentFlashConfig: {
93
+ type: FlashType;
94
+ duration: number;
95
+ cycles: number;
96
+ flashAlpha: number;
97
+ flashTint: number;
98
+ } | null = null;
99
+
100
+ /**
101
+ * Initializes the flash directive
102
+ * @param element - The element to attach the flash effect to
103
+ */
104
+ onInit(element: Element<Container>) {
105
+ this.elementRef = element;
106
+ }
107
+
108
+ /**
109
+ * Mounts the flash directive and sets up trigger listener
110
+ * @param element - The element being mounted
111
+ */
112
+ onMount(element: Element<Container>) {
113
+ const instance = element.componentInstance;
114
+ if (!instance) return;
115
+
116
+ const flashProps = this.flashProps;
117
+
118
+ // Check if trigger is provided
119
+ if (!flashProps.trigger || !isTrigger(flashProps.trigger)) {
120
+ return;
121
+ }
122
+
123
+ // Store original values once at mount time
124
+ // Only set if not already stored (to preserve values from first mount)
125
+ if (this.originalAlpha === 1 && !flashProps.originalAlpha) {
126
+ this.originalAlpha = instance.alpha ?? 1;
127
+ } else if (flashProps.originalAlpha !== undefined) {
128
+ this.originalAlpha = flashProps.originalAlpha;
129
+ }
130
+
131
+ const currentTint = (instance as any).tint;
132
+ if (this.originalTint === 0xffffff && !flashProps.originalTint) {
133
+ this.originalTint = (isSignal(currentTint) ? currentTint() : currentTint) ?? 0xffffff;
134
+ } else if (flashProps.originalTint !== undefined) {
135
+ this.originalTint = flashProps.originalTint;
136
+ }
137
+
138
+ // Listen to trigger activation
139
+ this.flashSubscription = on(flashProps.trigger, async (data) => {
140
+ await this.performFlash(data);
141
+ });
142
+ }
143
+
144
+ /**
145
+ * Gets the flash props with default values
146
+ * @returns FlashProps with defaults applied
147
+ */
148
+ get flashProps(): FlashProps {
149
+ const flash = this.elementRef?.props.flash;
150
+ return useProps(flash?.value ?? flash, {
151
+ type: 'alpha',
152
+ duration: 300,
153
+ cycles: 1,
154
+ alpha: 0.3,
155
+ tint: 0xffffff,
156
+ });
157
+ }
158
+
159
+ /**
160
+ * Performs the flash animation using animatedSignal
161
+ * @param data - Optional data passed from the trigger that can override default options
162
+ */
163
+ private async performFlash(data?: any): Promise<void> {
164
+ if (!this.elementRef?.componentInstance) return;
165
+
166
+ const instance = this.elementRef.componentInstance;
167
+ const flashProps = this.flashProps;
168
+
169
+ // Use data from trigger to override defaults if provided
170
+ const type = data?.type ?? (typeof flashProps.type === 'function' ? flashProps.type() : flashProps.type);
171
+ const duration = data?.duration ?? (typeof flashProps.duration === 'function' ? flashProps.duration() : flashProps.duration);
172
+ const cycles = data?.cycles ?? (typeof flashProps.cycles === 'function' ? flashProps.cycles() : flashProps.cycles);
173
+ const flashAlpha = data?.alpha ?? (typeof flashProps.alpha === 'function' ? flashProps.alpha() : flashProps.alpha);
174
+ const flashTint = data?.tint ?? (typeof flashProps.tint === 'function' ? flashProps.tint() : flashProps.tint);
175
+
176
+ // Stop any existing animation first
177
+ if (this.progressSignal) {
178
+ // Stop the animation immediately
179
+ this.progressSignal.set(0, { duration: 0 });
180
+ }
181
+
182
+ // Clean up effects BEFORE restoring values
183
+ // This prevents effects from continuing to update values after we restore
184
+ if (this.alphaEffect) {
185
+ this.alphaEffect.unsubscribe();
186
+ this.alphaEffect = null;
187
+ }
188
+ if (this.tintEffect) {
189
+ this.tintEffect.unsubscribe();
190
+ this.tintEffect = null;
191
+ }
192
+
193
+ // Always restore to original values immediately after stopping effects
194
+ // This ensures that if a new flash starts before the previous one completes,
195
+ // we restore to the true original values, not the intermediate animation values
196
+ instance.alpha = this.originalAlpha;
197
+ const currentTint = (instance as any).tint;
198
+ if (currentTint !== undefined) {
199
+ // Ensure originalTint is a primitive value, not a signal
200
+ const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;
201
+ // Handle both signal and primitive tint
202
+ if (isSignal(currentTint)) {
203
+ currentTint.set(tintValue);
204
+ } else {
205
+ (instance as any).tint = tintValue;
206
+ }
207
+ }
208
+
209
+ // Call onStart callback
210
+ flashProps.onStart?.();
211
+
212
+ // Store current flash configuration for use in effect
213
+ this.currentFlashConfig = {
214
+ type,
215
+ duration,
216
+ cycles,
217
+ flashAlpha,
218
+ flashTint,
219
+ };
220
+
221
+ // Create or recreate progress signal for flash animation
222
+ // Note: We already stopped the previous animation above, so we can reuse the signal
223
+ if (!this.progressSignal) {
224
+ this.progressSignal = animatedSignal(0, {
225
+ duration: duration,
226
+ ease: (t) => t, // Linear ease
227
+ });
228
+ }
229
+ // Reset to 0 immediately without animation to start fresh
230
+ this.progressSignal.set(0, { duration: 0 });
231
+ // Wait a bit to ensure the reset is complete before starting new animation
232
+ await new Promise(resolve => setTimeout(resolve, 0));
233
+
234
+ // Create effect to update alpha based on progress
235
+ if (type === 'alpha' || type === 'both') {
236
+ this.alphaEffect = effect(() => {
237
+ if (!instance || !this.progressSignal || !this.currentFlashConfig) return;
238
+
239
+ const progress = this.progressSignal();
240
+ const config = this.currentFlashConfig;
241
+
242
+ // Calculate flash value based on cycles
243
+ // Each cycle goes from 0 to 1, so we use modulo to repeat
244
+ const cycleProgress = (progress * config.cycles) % 1;
245
+
246
+ // Create flash effect: fade to flashAlpha then back to original
247
+ // For each cycle, we flash twice (on/off)
248
+ const flashPhase = cycleProgress < 0.5
249
+ ? cycleProgress * 2 // Fade to flashAlpha (0 to 1)
250
+ : 1 - ((cycleProgress - 0.5) * 2); // Fade back to original (1 to 0)
251
+
252
+ // Interpolate between original and flash alpha
253
+ const currentAlpha = this.originalAlpha + (config.flashAlpha - this.originalAlpha) * flashPhase;
254
+ instance.alpha = currentAlpha;
255
+ }).subscription;
256
+ }
257
+
258
+ // Create effect to update tint based on progress
259
+ if (type === 'tint' || type === 'both') {
260
+ this.tintEffect = effect(() => {
261
+ if (!instance || !this.progressSignal || !this.currentFlashConfig) return;
262
+
263
+ // Get current tint value - handle both signal and primitive
264
+ const currentTint = (instance as any).tint;
265
+ if (currentTint === undefined) return;
266
+
267
+ // Check if tint is a signal
268
+ const tintIsSignal = isSignal(currentTint);
269
+
270
+ const progress = this.progressSignal();
271
+ const config = this.currentFlashConfig;
272
+
273
+ // Calculate flash value based on cycles
274
+ const cycleProgress = (progress * config.cycles) % 1;
275
+
276
+ // Create flash effect: change to flashTint then back to original
277
+ const flashPhase = cycleProgress < 0.5
278
+ ? cycleProgress * 2 // Change to flashTint (0 to 1)
279
+ : 1 - ((cycleProgress - 0.5) * 2); // Change back to original (1 to 0)
280
+
281
+ // Interpolate between original and flash tint
282
+ // Simple linear interpolation for RGB values
283
+ const r1 = (this.originalTint >> 16) & 0xff;
284
+ const g1 = (this.originalTint >> 8) & 0xff;
285
+ const b1 = this.originalTint & 0xff;
286
+
287
+ const r2 = (config.flashTint >> 16) & 0xff;
288
+ const g2 = (config.flashTint >> 8) & 0xff;
289
+ const b2 = config.flashTint & 0xff;
290
+
291
+ const r = Math.round(r1 + (r2 - r1) * flashPhase);
292
+ const g = Math.round(g1 + (g2 - g1) * flashPhase);
293
+ const b = Math.round(b1 + (b2 - b1) * flashPhase);
294
+
295
+ const newTintValue = (r << 16) | (g << 8) | b;
296
+
297
+ // Handle both signal and primitive tint
298
+ if (tintIsSignal) {
299
+ currentTint.set(newTintValue);
300
+ } else {
301
+ (instance as any).tint = newTintValue;
302
+ }
303
+ }).subscription;
304
+ }
305
+
306
+ // Start animation and wait for completion
307
+ await this.progressSignal.set(1, {
308
+ duration: duration,
309
+ });
310
+
311
+ // Animation completed - clean up and call callbacks
312
+ // Restore original values
313
+ if (instance) {
314
+ instance.alpha = this.originalAlpha;
315
+ const currentTint = (instance as any).tint;
316
+ if (currentTint !== undefined) {
317
+ // Ensure originalTint is a primitive value, not a signal
318
+ const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;
319
+ // Handle both signal and primitive tint
320
+ if (isSignal(currentTint)) {
321
+ currentTint.set(tintValue);
322
+ } else {
323
+ (instance as any).tint = tintValue;
324
+ }
325
+ }
326
+ }
327
+
328
+ // Clean up effects
329
+ if (this.alphaEffect) {
330
+ this.alphaEffect.unsubscribe();
331
+ this.alphaEffect = null;
332
+ }
333
+ if (this.tintEffect) {
334
+ this.tintEffect.unsubscribe();
335
+ this.tintEffect = null;
336
+ }
337
+
338
+ // Clear flash config
339
+ this.currentFlashConfig = null;
340
+
341
+ // Call onComplete callback
342
+ flashProps.onComplete?.();
343
+ }
344
+
345
+ /**
346
+ * Updates the flash directive when props change
347
+ * @param props - Updated props
348
+ */
349
+ onUpdate(props: any) {
350
+ // Re-mount if props change significantly
351
+ if (props.type && props.type === 'reset') {
352
+ this.onDestroy();
353
+ if (this.elementRef) {
354
+ this.onMount(this.elementRef);
355
+ }
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Cleans up the flash directive
361
+ */
362
+ onDestroy() {
363
+ // Stop any running animation by resetting progress
364
+ if (this.progressSignal) {
365
+ this.progressSignal.set(0, { duration: 0 });
366
+ this.progressSignal = null;
367
+ }
368
+
369
+ // Clean up effects
370
+ if (this.alphaEffect) {
371
+ this.alphaEffect.unsubscribe();
372
+ this.alphaEffect = null;
373
+ }
374
+ if (this.tintEffect) {
375
+ this.tintEffect.unsubscribe();
376
+ this.tintEffect = null;
377
+ }
378
+
379
+ // Clear flash config
380
+ this.currentFlashConfig = null;
381
+
382
+ // Restore original values
383
+ if (this.elementRef?.componentInstance) {
384
+ const instance = this.elementRef.componentInstance;
385
+ instance.alpha = this.originalAlpha;
386
+ const currentTint = (instance as any).tint;
387
+ if (currentTint !== undefined) {
388
+ // Ensure originalTint is a primitive value, not a signal
389
+ const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;
390
+ // Handle both signal and primitive tint
391
+ if (isSignal(currentTint)) {
392
+ currentTint.set(tintValue);
393
+ } else {
394
+ (instance as any).tint = tintValue;
395
+ }
396
+ }
397
+ }
398
+
399
+ // Clean up subscription
400
+ if (this.flashSubscription) {
401
+ this.flashSubscription = null;
402
+ }
403
+
404
+ this.elementRef = null;
405
+ }
406
+ }
407
+
408
+ registerDirective('flash', Flash);
409
+