@vpmedia/phaser 1.122.0 → 1.124.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.
Files changed (207) hide show
  1. package/dist/index.js +341 -325
  2. package/dist/index.js.map +1 -1
  3. package/dist/phaser/core/animation.d.ts +3 -3
  4. package/dist/phaser/core/animation.d.ts.map +1 -1
  5. package/dist/phaser/core/animation_manager.d.ts.map +1 -1
  6. package/dist/phaser/core/animation_parser.d.ts +27 -2
  7. package/dist/phaser/core/animation_parser.d.ts.map +1 -1
  8. package/dist/phaser/core/array_set.d.ts +11 -11
  9. package/dist/phaser/core/array_set.d.ts.map +1 -1
  10. package/dist/phaser/core/cache.d.ts.map +1 -1
  11. package/dist/phaser/core/callback.d.ts.map +1 -1
  12. package/dist/phaser/core/dom.d.ts +125 -19
  13. package/dist/phaser/core/dom.d.ts.map +1 -1
  14. package/dist/phaser/core/factory.d.ts +3 -2
  15. package/dist/phaser/core/factory.d.ts.map +1 -1
  16. package/dist/phaser/core/input.d.ts +3 -2
  17. package/dist/phaser/core/input.d.ts.map +1 -1
  18. package/dist/phaser/core/input_handler.d.ts.map +1 -1
  19. package/dist/phaser/core/input_mouse.d.ts +5 -1
  20. package/dist/phaser/core/input_mouse.d.ts.map +1 -1
  21. package/dist/phaser/core/input_pointer.d.ts +3 -3
  22. package/dist/phaser/core/input_pointer.d.ts.map +1 -1
  23. package/dist/phaser/core/input_touch.d.ts +8 -8
  24. package/dist/phaser/core/input_touch.d.ts.map +1 -1
  25. package/dist/phaser/core/loader.d.ts +11 -2
  26. package/dist/phaser/core/loader.d.ts.map +1 -1
  27. package/dist/phaser/core/loader_parser.d.ts +14 -1
  28. package/dist/phaser/core/loader_parser.d.ts.map +1 -1
  29. package/dist/phaser/core/raf.d.ts +1 -1
  30. package/dist/phaser/core/raf.d.ts.map +1 -1
  31. package/dist/phaser/core/scale_manager.d.ts.map +1 -1
  32. package/dist/phaser/core/scene_manager.d.ts.map +1 -1
  33. package/dist/phaser/core/signal.d.ts.map +1 -1
  34. package/dist/phaser/core/sound.d.ts.map +1 -1
  35. package/dist/phaser/core/sound_manager.d.ts +1 -1
  36. package/dist/phaser/core/sound_manager.d.ts.map +1 -1
  37. package/dist/phaser/core/stage.d.ts +16 -6
  38. package/dist/phaser/core/stage.d.ts.map +1 -1
  39. package/dist/phaser/core/time.d.ts.map +1 -1
  40. package/dist/phaser/core/timer.d.ts +1 -1
  41. package/dist/phaser/core/timer.d.ts.map +1 -1
  42. package/dist/phaser/core/tween.d.ts +13 -5
  43. package/dist/phaser/core/tween.d.ts.map +1 -1
  44. package/dist/phaser/core/tween_data.d.ts +9 -7
  45. package/dist/phaser/core/tween_data.d.ts.map +1 -1
  46. package/dist/phaser/core/tween_manager.d.ts.map +1 -1
  47. package/dist/phaser/display/button.d.ts +6 -5
  48. package/dist/phaser/display/button.d.ts.map +1 -1
  49. package/dist/phaser/display/canvas/buffer.d.ts +1 -1
  50. package/dist/phaser/display/canvas/buffer.d.ts.map +1 -1
  51. package/dist/phaser/display/canvas/masker.d.ts +1 -1
  52. package/dist/phaser/display/canvas/masker.d.ts.map +1 -1
  53. package/dist/phaser/display/canvas/pool.d.ts +2 -2
  54. package/dist/phaser/display/canvas/pool.d.ts.map +1 -1
  55. package/dist/phaser/display/canvas/renderer.d.ts +9 -8
  56. package/dist/phaser/display/canvas/renderer.d.ts.map +1 -1
  57. package/dist/phaser/display/display_object.d.ts +3 -1
  58. package/dist/phaser/display/display_object.d.ts.map +1 -1
  59. package/dist/phaser/display/graphics.d.ts +1 -1
  60. package/dist/phaser/display/graphics.d.ts.map +1 -1
  61. package/dist/phaser/display/group.d.ts +1 -1
  62. package/dist/phaser/display/group.d.ts.map +1 -1
  63. package/dist/phaser/display/image.d.ts +6 -5
  64. package/dist/phaser/display/image.d.ts.map +1 -1
  65. package/dist/phaser/display/sprite_util.d.ts +3 -2
  66. package/dist/phaser/display/sprite_util.d.ts.map +1 -1
  67. package/dist/phaser/display/text.d.ts +2 -16
  68. package/dist/phaser/display/text.d.ts.map +1 -1
  69. package/dist/phaser/display/webgl/abstract_filter.d.ts +14 -8
  70. package/dist/phaser/display/webgl/abstract_filter.d.ts.map +1 -1
  71. package/dist/phaser/display/webgl/blend_manager.d.ts +2 -3
  72. package/dist/phaser/display/webgl/blend_manager.d.ts.map +1 -1
  73. package/dist/phaser/display/webgl/fast_sprite_batch.d.ts +11 -5
  74. package/dist/phaser/display/webgl/fast_sprite_batch.d.ts.map +1 -1
  75. package/dist/phaser/display/webgl/filter_manager.d.ts +6 -4
  76. package/dist/phaser/display/webgl/filter_manager.d.ts.map +1 -1
  77. package/dist/phaser/display/webgl/filter_texture.d.ts +4 -4
  78. package/dist/phaser/display/webgl/filter_texture.d.ts.map +1 -1
  79. package/dist/phaser/display/webgl/graphics.d.ts +2 -2
  80. package/dist/phaser/display/webgl/graphics.d.ts.map +1 -1
  81. package/dist/phaser/display/webgl/mask_manager.d.ts +3 -2
  82. package/dist/phaser/display/webgl/mask_manager.d.ts.map +1 -1
  83. package/dist/phaser/display/webgl/render_texture.d.ts +11 -8
  84. package/dist/phaser/display/webgl/render_texture.d.ts.map +1 -1
  85. package/dist/phaser/display/webgl/renderer.d.ts +8 -4
  86. package/dist/phaser/display/webgl/renderer.d.ts.map +1 -1
  87. package/dist/phaser/display/webgl/shader/normal.d.ts +28 -3
  88. package/dist/phaser/display/webgl/shader/normal.d.ts.map +1 -1
  89. package/dist/phaser/display/webgl/sprite_batch.d.ts +6 -5
  90. package/dist/phaser/display/webgl/sprite_batch.d.ts.map +1 -1
  91. package/dist/phaser/display/webgl/stencil_manager.d.ts +3 -3
  92. package/dist/phaser/display/webgl/stencil_manager.d.ts.map +1 -1
  93. package/dist/phaser/display/webgl/texture_util.d.ts +2 -2
  94. package/dist/phaser/display/webgl/texture_util.d.ts.map +1 -1
  95. package/dist/phaser/display/webgl/util.d.ts +1 -1
  96. package/dist/phaser/display/webgl/util.d.ts.map +1 -1
  97. package/dist/phaser/geom/circle.d.ts.map +1 -1
  98. package/dist/phaser/geom/line.d.ts +10 -1
  99. package/dist/phaser/geom/line.d.ts.map +1 -1
  100. package/dist/phaser/geom/rectangle.d.ts.map +1 -1
  101. package/dist/phaser/geom/util/circle.d.ts +2 -1
  102. package/dist/phaser/geom/util/circle.d.ts.map +1 -1
  103. package/dist/phaser/geom/util/point.d.ts +1 -1
  104. package/dist/phaser/geom/util/point.d.ts.map +1 -1
  105. package/dist/phaser/geom/util/rectangle.d.ts +1 -1
  106. package/dist/phaser/geom/util/rectangle.d.ts.map +1 -1
  107. package/dist/phaser/util/math.d.ts.map +1 -1
  108. package/package.json +1 -1
  109. package/src/phaser/core/animation.ts +4 -4
  110. package/src/phaser/core/animation_manager.ts +10 -10
  111. package/src/phaser/core/animation_parser.ts +30 -24
  112. package/src/phaser/core/array_set.ts +27 -27
  113. package/src/phaser/core/cache.test.ts +33 -33
  114. package/src/phaser/core/cache.ts +3 -3
  115. package/src/phaser/core/callback.ts +1 -0
  116. package/src/phaser/core/callback_context.test.ts +8 -8
  117. package/src/phaser/core/dom.ts +15 -5
  118. package/src/phaser/core/factory.ts +9 -2
  119. package/src/phaser/core/frame_data.test.ts +23 -23
  120. package/src/phaser/core/input.ts +9 -8
  121. package/src/phaser/core/input_handler.test.ts +18 -18
  122. package/src/phaser/core/input_handler.ts +1 -1
  123. package/src/phaser/core/input_mouse.ts +9 -8
  124. package/src/phaser/core/input_pointer.test.ts +26 -26
  125. package/src/phaser/core/input_pointer.ts +3 -3
  126. package/src/phaser/core/input_touch.ts +8 -8
  127. package/src/phaser/core/loader.test.ts +26 -26
  128. package/src/phaser/core/loader.ts +25 -25
  129. package/src/phaser/core/loader_parser.test.ts +16 -16
  130. package/src/phaser/core/loader_parser.ts +16 -6
  131. package/src/phaser/core/raf.ts +1 -1
  132. package/src/phaser/core/registry.test.ts +6 -6
  133. package/src/phaser/core/scale_manager.ts +2 -2
  134. package/src/phaser/core/scene_manager.test.ts +30 -30
  135. package/src/phaser/core/scene_manager.ts +1 -1
  136. package/src/phaser/core/signal.test.ts +8 -8
  137. package/src/phaser/core/signal.ts +1 -1
  138. package/src/phaser/core/signal_dispatch.test.ts +30 -30
  139. package/src/phaser/core/sound.ts +20 -8
  140. package/src/phaser/core/sound_manager.ts +6 -6
  141. package/src/phaser/core/stage.ts +19 -9
  142. package/src/phaser/core/time.ts +1 -1
  143. package/src/phaser/core/timer.test.ts +47 -47
  144. package/src/phaser/core/timer.ts +1 -1
  145. package/src/phaser/core/tween.ts +28 -25
  146. package/src/phaser/core/tween_data.test.ts +119 -0
  147. package/src/phaser/core/tween_data.ts +54 -39
  148. package/src/phaser/core/tween_easing.test.ts +5 -5
  149. package/src/phaser/core/tween_manager.ts +2 -2
  150. package/src/phaser/display/bitmap_text.test.ts +30 -30
  151. package/src/phaser/display/button.ts +8 -6
  152. package/src/phaser/display/canvas/buffer.ts +2 -2
  153. package/src/phaser/display/canvas/masker.ts +1 -1
  154. package/src/phaser/display/canvas/pool.test.ts +20 -20
  155. package/src/phaser/display/canvas/pool.ts +3 -3
  156. package/src/phaser/display/canvas/renderer.ts +12 -11
  157. package/src/phaser/display/canvas/util.test.ts +31 -24
  158. package/src/phaser/display/canvas/util.ts +2 -2
  159. package/src/phaser/display/display_object.ts +3 -1
  160. package/src/phaser/display/graphics.test.ts +70 -20
  161. package/src/phaser/display/graphics.ts +38 -32
  162. package/src/phaser/display/group.ts +4 -4
  163. package/src/phaser/display/image.ts +28 -25
  164. package/src/phaser/display/sprite_util.ts +3 -2
  165. package/src/phaser/display/text.test.ts +28 -25
  166. package/src/phaser/display/text.ts +21 -18
  167. package/src/phaser/display/webgl/abstract_filter.ts +20 -10
  168. package/src/phaser/display/webgl/blend_manager.ts +4 -5
  169. package/src/phaser/display/webgl/earcut.test.ts +20 -20
  170. package/src/phaser/display/webgl/fast_sprite_batch.ts +21 -16
  171. package/src/phaser/display/webgl/filter_manager.ts +7 -4
  172. package/src/phaser/display/webgl/filter_texture.ts +5 -5
  173. package/src/phaser/display/webgl/graphics.ts +2 -2
  174. package/src/phaser/display/webgl/mask_manager.ts +9 -14
  175. package/src/phaser/display/webgl/render_texture.ts +15 -14
  176. package/src/phaser/display/webgl/renderer.ts +7 -6
  177. package/src/phaser/display/webgl/shader/normal.ts +41 -31
  178. package/src/phaser/display/webgl/shader/shader.test.ts +24 -24
  179. package/src/phaser/display/webgl/shader_manager.test.ts +18 -18
  180. package/src/phaser/display/webgl/sprite_batch.ts +8 -8
  181. package/src/phaser/display/webgl/stencil_manager.ts +4 -4
  182. package/src/phaser/display/webgl/texture_util.ts +2 -2
  183. package/src/phaser/display/webgl/util.ts +1 -1
  184. package/src/phaser/geom/circle.test.ts +38 -38
  185. package/src/phaser/geom/circle.ts +7 -7
  186. package/src/phaser/geom/ellipse.test.ts +12 -12
  187. package/src/phaser/geom/line.test.ts +15 -15
  188. package/src/phaser/geom/line.ts +5 -2
  189. package/src/phaser/geom/matrix.test.ts +31 -31
  190. package/src/phaser/geom/point.test.ts +31 -31
  191. package/src/phaser/geom/polygon.test.ts +27 -27
  192. package/src/phaser/geom/rectangle.test.ts +87 -87
  193. package/src/phaser/geom/rectangle.ts +11 -11
  194. package/src/phaser/geom/rounded_rectangle.test.ts +9 -9
  195. package/src/phaser/geom/util/circle.test.ts +5 -5
  196. package/src/phaser/geom/util/circle.ts +2 -1
  197. package/src/phaser/geom/util/ellipse.test.ts +2 -2
  198. package/src/phaser/geom/util/line.test.ts +2 -2
  199. package/src/phaser/geom/util/matrix.test.ts +4 -4
  200. package/src/phaser/geom/util/point.test.ts +2 -2
  201. package/src/phaser/geom/util/point.ts +1 -1
  202. package/src/phaser/geom/util/polygon.test.ts +2 -2
  203. package/src/phaser/geom/util/rectangle.test.ts +2 -2
  204. package/src/phaser/geom/util/rectangle.ts +1 -1
  205. package/src/phaser/geom/util/rounded_rectangle.test.ts +2 -2
  206. package/src/phaser/util/math.test.ts +41 -41
  207. package/src/phaser/util/math.ts +5 -2
@@ -4,6 +4,7 @@ import { Signal } from '../core/signal.js';
4
4
  import { Image } from './image.js';
5
5
  import type { Game } from '../core/game.js';
6
6
  import type { SignalListener } from '../core/signal.js';
7
+ import type { Pointer } from '../core/input_pointer.js';
7
8
 
8
9
  const STATE_OVER = 'Over';
9
10
  const STATE_OUT = 'Out';
@@ -25,7 +26,7 @@ export class Button extends Image {
25
26
  public onOverMouseOnly!: boolean;
26
27
  public justReleasedPreventsOver!: number;
27
28
  public freezeFrames!: boolean;
28
- public forceOut!: any;
29
+ public forceOut!: boolean | number;
29
30
  public input!: InputHandler;
30
31
  /**
31
32
  * Creates a new Button instance.
@@ -208,7 +209,7 @@ export class Button extends Image {
208
209
  * @param {object} _sprite - The sprite that triggered the event.
209
210
  * @param {object} pointer - The pointer that triggered the event.
210
211
  */
211
- public onInputOverHandler(_sprite: any, pointer: any): void {
212
+ public onInputOverHandler(_sprite: Image, pointer: Pointer): void {
212
213
  if (pointer.justReleased() && (this.justReleasedPreventsOver & pointer.pointerMode) === pointer.pointerMode) {
213
214
  // If the Pointer was only just released then we don't fire an over event
214
215
  return;
@@ -227,7 +228,7 @@ export class Button extends Image {
227
228
  * @param {object} _sprite - The sprite that triggered the event.
228
229
  * @param {object} pointer - The pointer that triggered the event.
229
230
  */
230
- public onInputOutHandler(_sprite: any, pointer: any): void {
231
+ public onInputOutHandler(_sprite: Image, pointer: Pointer): void {
231
232
  this.changeStateFrame(STATE_OUT);
232
233
  if (this.onInputOut) {
233
234
  this.onInputOut.dispatch(this, pointer);
@@ -239,7 +240,7 @@ export class Button extends Image {
239
240
  * @param {object} _sprite - The sprite that triggered the event.
240
241
  * @param {object} pointer - The pointer that triggered the event.
241
242
  */
242
- public onInputDownHandler(_sprite: any, pointer: any): void {
243
+ public onInputDownHandler(_sprite: Image, pointer: Pointer): void {
243
244
  this.changeStateFrame(STATE_DOWN);
244
245
  if (this.onInputDown) {
245
246
  this.onInputDown.dispatch(this, pointer);
@@ -252,14 +253,15 @@ export class Button extends Image {
252
253
  * @param {object} pointer - The pointer that triggered the event.
253
254
  * @param {boolean} isOver - Whether the pointer is currently over the button (default: true).
254
255
  */
255
- public onInputUpHandler(_sprite: any, pointer: any, isOver: boolean): void {
256
+ public onInputUpHandler(_sprite: Image, pointer: Pointer, isOver: boolean): void {
256
257
  if (this.onInputUp) {
257
258
  this.onInputUp.dispatch(this, pointer, isOver);
258
259
  }
259
260
  if (this.freezeFrames) {
260
261
  return;
261
262
  }
262
- if (this.forceOut === true || (this.forceOut & pointer.pointerMode) === pointer.pointerMode) {
263
+ const forcedOutMode = typeof this.forceOut === 'number' ? this.forceOut : 0;
264
+ if (this.forceOut === true || (forcedOutMode & pointer.pointerMode) === pointer.pointerMode) {
263
265
  this.changeStateFrame(STATE_OUT);
264
266
  } else {
265
267
  const changedUp = this.changeStateFrame(STATE_UP);
@@ -3,7 +3,7 @@ import { create, removeByCanvas } from './pool.js';
3
3
  export class CanvasBuffer {
4
4
  public width!: number;
5
5
  public height!: number;
6
- public canvas!: any;
6
+ public canvas!: HTMLCanvasElement;
7
7
  public context!: CanvasRenderingContext2D;
8
8
  /**
9
9
  * Creates a new CanvasBuffer instance.
@@ -14,7 +14,7 @@ export class CanvasBuffer {
14
14
  this.width = width;
15
15
  this.height = height;
16
16
  this.canvas = create(this, this.width, this.height);
17
- this.context = this.canvas.getContext('2d', { willReadFrequently: false });
17
+ this.context = this.canvas.getContext('2d', { willReadFrequently: false })!;
18
18
  this.canvas.width = width;
19
19
  this.canvas.height = height;
20
20
  }
@@ -7,7 +7,7 @@ import type { Graphics } from '../graphics.js';
7
7
  * @param {object} maskData - The mask data to apply.
8
8
  * @param {object} renderSession - The rendering session object.
9
9
  */
10
- export const pushMask = (maskData: any, renderSession: RenderSession): void => {
10
+ export const pushMask = (maskData: Graphics, renderSession: RenderSession): void => {
11
11
  const { context } = renderSession;
12
12
  context.save();
13
13
  const cacheAlpha = maskData.alpha;
@@ -1,20 +1,20 @@
1
1
  import { beforeEach, describe, expect, it } from 'vitest';
2
2
  import { create, getFirst, getFree, getPool, getTotal, remove, removeByCanvas } from './pool.js';
3
3
 
4
- describe('canvas pool', () => {
5
- beforeEach(() => {
4
+ describe('canvas pool', (): void => {
5
+ beforeEach((): void => {
6
6
  getPool().length = 0;
7
7
  });
8
8
 
9
- describe('getPool', () => {
10
- it('lazily creates the backing array and returns the same one thereafter', () => {
9
+ describe('getPool', (): void => {
10
+ it('lazily creates the backing array and returns the same one thereafter', (): void => {
11
11
  expect(getPool()).toBe(getPool());
12
12
  expect(getPool()).toStrictEqual([]);
13
13
  });
14
14
  });
15
15
 
16
- describe('create', () => {
17
- it('adds a new entry when the pool is empty', () => {
16
+ describe('create', (): void => {
17
+ it('adds a new entry when the pool is empty', (): void => {
18
18
  const parent = { name: 'owner' };
19
19
  const canvas = create(parent);
20
20
  expect(getPool()).toHaveLength(1);
@@ -22,7 +22,7 @@ describe('canvas pool', () => {
22
22
  expect(getPool()[0]?.canvas).toBe(canvas);
23
23
  });
24
24
 
25
- it('reuses a free entry instead of growing the pool', () => {
25
+ it('reuses a free entry instead of growing the pool', (): void => {
26
26
  const first = { name: 'first' };
27
27
  const canvas = create(first);
28
28
  remove(first);
@@ -32,7 +32,7 @@ describe('canvas pool', () => {
32
32
  expect(getPool()[0]?.parent).toBe(second);
33
33
  });
34
34
 
35
- it('grows the pool when skipPool is set even if an entry is free', () => {
35
+ it('grows the pool when skipPool is set even if an entry is free', (): void => {
36
36
  const first = { name: 'first' };
37
37
  create(first);
38
38
  remove(first);
@@ -40,20 +40,20 @@ describe('canvas pool', () => {
40
40
  expect(getPool()).toHaveLength(2);
41
41
  });
42
42
 
43
- it('applies the requested dimensions', () => {
43
+ it('applies the requested dimensions', (): void => {
44
44
  const canvas = create({ name: 'sized' }, 64, 32);
45
45
  expect(canvas.width).toBe(64);
46
46
  expect(canvas.height).toBe(32);
47
47
  });
48
48
  });
49
49
 
50
- describe('getFirst', () => {
51
- it('reports -1 when every entry is claimed', () => {
50
+ describe('getFirst', (): void => {
51
+ it('reports -1 when every entry is claimed', (): void => {
52
52
  create({ name: 'owner' });
53
53
  expect(getFirst()).toBe(-1);
54
54
  });
55
55
 
56
- it('reports the index of the first free entry', () => {
56
+ it('reports the index of the first free entry', (): void => {
57
57
  create({ name: 'a' });
58
58
  const b = { name: 'b' };
59
59
  create(b);
@@ -63,8 +63,8 @@ describe('canvas pool', () => {
63
63
  });
64
64
  });
65
65
 
66
- describe('remove', () => {
67
- it('frees the entry and shrinks its canvas to 1x1', () => {
66
+ describe('remove', (): void => {
67
+ it('frees the entry and shrinks its canvas to 1x1', (): void => {
68
68
  const parent = { name: 'owner' };
69
69
  const canvas = create(parent, 100, 50);
70
70
  remove(parent);
@@ -73,17 +73,17 @@ describe('canvas pool', () => {
73
73
  expect(canvas.height).toBe(1);
74
74
  });
75
75
 
76
- it('ignores a parent that owns nothing', () => {
76
+ it('ignores a parent that owns nothing', (): void => {
77
77
  create({ name: 'owner' });
78
- expect(() => {
78
+ expect((): void => {
79
79
  remove({ name: 'stranger' });
80
80
  }).not.toThrow();
81
81
  expect(getPool()[0]?.parent).not.toBeNull();
82
82
  });
83
83
  });
84
84
 
85
- describe('removeByCanvas', () => {
86
- it('frees the entry holding that canvas', () => {
85
+ describe('removeByCanvas', (): void => {
86
+ it('frees the entry holding that canvas', (): void => {
87
87
  const canvas = create({ name: 'owner' }, 100, 50);
88
88
  removeByCanvas(canvas);
89
89
  expect(getPool()[0]?.parent).toBeNull();
@@ -91,8 +91,8 @@ describe('canvas pool', () => {
91
91
  });
92
92
  });
93
93
 
94
- describe('getTotal and getFree', () => {
95
- it('count claimed and unclaimed entries', () => {
94
+ describe('getTotal and getFree', (): void => {
95
+ it('count claimed and unclaimed entries', (): void => {
96
96
  const a = { name: 'a' };
97
97
  create(a);
98
98
  create({ name: 'b' });
@@ -27,7 +27,7 @@ export const getFirst = (): number => {
27
27
  * Adds a canvas to the pool with the specified parent.
28
28
  * @param {object} parent - The parent object for the canvas.
29
29
  */
30
- export const remove = (parent: any): void => {
30
+ export const remove = (parent: CanvasOwner): void => {
31
31
  const pool = getPool();
32
32
  for (const entry of pool) {
33
33
  if (entry.parent === parent) {
@@ -91,7 +91,7 @@ export const getFree = (): number => {
91
91
  * @param {boolean} skipPool - True to skip using the pool and create a new canvas.
92
92
  * @returns {HTMLCanvasElement} The canvas from the pool or a newly created one.
93
93
  */
94
- export const create = (parent: any, width?: any, height?: any, skipPool = false): HTMLCanvasElement => {
94
+ export const create = (parent: CanvasOwner, width?: number, height?: number, skipPool = false): HTMLCanvasElement => {
95
95
  if (parent === undefined) {
96
96
  console.warn('Created CanvasPool element with undefined parent.');
97
97
  }
@@ -111,7 +111,7 @@ export const create = (parent: any, width?: any, height?: any, skipPool = false)
111
111
  const { canvas } = entry;
112
112
  if (width !== undefined) {
113
113
  canvas.width = width;
114
- canvas.height = height;
114
+ canvas.height = height ?? 0;
115
115
  }
116
116
  return canvas;
117
117
  };
@@ -26,21 +26,22 @@ import { ENGINE_ERROR_CREATING_CANVAS_2D_CONTEXT } from '../../core/error_code.j
26
26
  import * as CanvasMaskManager from './masker.js';
27
27
  import { detectCapabilities } from './tinter.js';
28
28
  import { getSmoothingPrefix, setSmoothing } from './util.js';
29
+ import type { DisplayObject } from '../display_object.js';
29
30
  import type { RenderSession } from '../render_session.js';
30
31
 
31
32
  export class CanvasRenderer {
32
- public type!: any;
33
+ public type!: number;
33
34
  public resolution!: number;
34
- public clearBeforeRender!: any;
35
- public transparent!: any;
36
- public autoResize!: any;
37
- public contextLost!: any;
35
+ public clearBeforeRender!: boolean;
36
+ public transparent!: boolean;
37
+ public autoResize!: boolean;
38
+ public contextLost!: boolean;
38
39
  public width!: number;
39
40
  public height!: number;
40
41
  public view!: HTMLCanvasElement;
41
42
  public context!: CanvasRenderingContext2D;
42
- public refresh!: any;
43
- public count!: any;
43
+ public refresh!: boolean;
44
+ public count!: number;
44
45
  public renderSession!: RenderSession;
45
46
  /**
46
47
  * Creates a new CanvasRenderer instance.
@@ -52,7 +53,7 @@ export class CanvasRenderer {
52
53
  this.type = RENDER_CANVAS;
53
54
  this.resolution = game.config.resolution;
54
55
  this.clearBeforeRender = game.config.clearBeforeRender;
55
- this.transparent = game.config.transparent;
56
+ this.transparent = Boolean(game.config.transparent);
56
57
  this.autoResize = false;
57
58
  this.contextLost = false;
58
59
  this.width = game.width * this.resolution;
@@ -62,7 +63,7 @@ export class CanvasRenderer {
62
63
  this.context = this.view.getContext('2d', {
63
64
  willReadFrequently: false,
64
65
  alpha: this.transparent,
65
- }) as CanvasRenderingContext2D;
66
+ })!;
66
67
  if (!this.context) {
67
68
  throw new Error(ENGINE_ERROR_CREATING_CANVAS_2D_CONTEXT);
68
69
  }
@@ -140,10 +141,10 @@ export class CanvasRenderer {
140
141
  * @param {CanvasRenderingContext2D} context - The canvas rendering context.
141
142
  * @param {Matrix} matrix - The transformation matrix.
142
143
  */
143
- public renderDisplayObject(displayObject: any, context?: any, matrix?: any): void {
144
+ public renderDisplayObject(displayObject: DisplayObject, context?: CanvasRenderingContext2D): void {
144
145
  this.renderSession.context = context ?? this.context;
145
146
  this.renderSession.resolution = this.resolution;
146
- displayObject.renderCanvas(this.renderSession, matrix);
147
+ displayObject.renderCanvas(this.renderSession);
147
148
  }
148
149
 
149
150
  /**
@@ -3,36 +3,36 @@ import { addToDOM, create, removeFromDOM, setBackgroundColor, setTouchAction, se
3
3
 
4
4
  const createCanvas = (): HTMLCanvasElement => create(null, 32, 16, '', true);
5
5
 
6
- describe('canvas util', () => {
7
- afterEach(() => {
6
+ describe('canvas util', (): void => {
7
+ afterEach((): void => {
8
8
  document.body.innerHTML = '';
9
9
  });
10
10
 
11
- describe('create', () => {
12
- it('sizes the canvas as asked', () => {
11
+ describe('create', (): void => {
12
+ it('sizes the canvas as asked', (): void => {
13
13
  const canvas = createCanvas();
14
14
  expect(canvas.width).toBe(32);
15
15
  expect(canvas.height).toBe(16);
16
16
  });
17
17
 
18
- it('falls back to 256 square for a zero size', () => {
18
+ it('falls back to 256 square for a zero size', (): void => {
19
19
  const canvas = create(null, 0, 0, '', true);
20
20
  expect(canvas.width).toBe(256);
21
21
  expect(canvas.height).toBe(256);
22
22
  });
23
23
 
24
- it('assigns the id it is given and leaves an empty one off', () => {
24
+ it('assigns the id it is given and leaves an empty one off', (): void => {
25
25
  expect(create(null, 32, 16, 'stage', true).id).toBe('stage');
26
26
  expect(createCanvas().id).toBe('');
27
27
  });
28
28
 
29
- it('takes the canvas out of the flow', () => {
29
+ it('takes the canvas out of the flow', (): void => {
30
30
  expect(createCanvas().style.display).toBe('block');
31
31
  });
32
32
  });
33
33
 
34
- describe('addToDOM', () => {
35
- it('appends to the element with the given id', () => {
34
+ describe('addToDOM', (): void => {
35
+ it('appends to the element with the given id', (): void => {
36
36
  const host = document.createElement('div');
37
37
  host.id = 'host';
38
38
  document.body.append(host);
@@ -41,7 +41,7 @@ describe('canvas util', () => {
41
41
  expect(canvas.parentElement).toBe(host);
42
42
  });
43
43
 
44
- it('appends to an element passed directly', () => {
44
+ it('appends to an element passed directly', (): void => {
45
45
  const host = document.createElement('div');
46
46
  document.body.append(host);
47
47
  const canvas = createCanvas();
@@ -49,19 +49,26 @@ describe('canvas util', () => {
49
49
  expect(canvas.parentElement).toBe(host);
50
50
  });
51
51
 
52
- it('falls back to the body for an id nothing matches', () => {
52
+ it('falls back to the body for an id nothing matches', (): void => {
53
53
  const canvas = createCanvas();
54
54
  addToDOM(canvas, 'nothing-here');
55
55
  expect(canvas.parentElement).toBe(document.body);
56
56
  });
57
57
 
58
- it('falls back to the body when given no parent', () => {
58
+ it('falls back to the body when given no parent', (): void => {
59
59
  const canvas = createCanvas();
60
60
  addToDOM(canvas, null);
61
61
  expect(canvas.parentElement).toBe(document.body);
62
62
  });
63
63
 
64
- it('hides the parent overflow unless told not to', () => {
64
+ // An empty id used to build the selector `#`, which throws before the body fallback is reached.
65
+ it('falls back to the body for an empty id', (): void => {
66
+ const canvas = createCanvas();
67
+ addToDOM(canvas, '');
68
+ expect(canvas.parentElement).toBe(document.body);
69
+ });
70
+
71
+ it('hides the parent overflow unless told not to', (): void => {
65
72
  const host = document.createElement('div');
66
73
  document.body.append(host);
67
74
  addToDOM(createCanvas(), host);
@@ -72,7 +79,7 @@ describe('canvas util', () => {
72
79
  expect(other.style.overflow).toBe('');
73
80
  });
74
81
 
75
- it('survives an id that is not a valid bare selector', () => {
82
+ it('survives an id that is not a valid bare selector', (): void => {
76
83
  const host = document.createElement('div');
77
84
  host.id = 'game.container';
78
85
  document.body.append(host);
@@ -82,40 +89,40 @@ describe('canvas util', () => {
82
89
  });
83
90
  });
84
91
 
85
- describe('removeFromDOM', () => {
86
- it('detaches an attached canvas', () => {
92
+ describe('removeFromDOM', (): void => {
93
+ it('detaches an attached canvas', (): void => {
87
94
  const canvas = createCanvas();
88
95
  document.body.append(canvas);
89
96
  removeFromDOM(canvas);
90
97
  expect(canvas.parentElement).toBeNull();
91
98
  });
92
99
 
93
- it('leaves a detached canvas alone', () => {
100
+ it('leaves a detached canvas alone', (): void => {
94
101
  const canvas = createCanvas();
95
- expect(() => {
102
+ expect((): void => {
96
103
  removeFromDOM(canvas);
97
104
  }).not.toThrow();
98
105
  });
99
106
  });
100
107
 
101
- describe('style helpers', () => {
102
- it('sets the background colour', () => {
108
+ describe('style helpers', (): void => {
109
+ it('sets the background colour', (): void => {
103
110
  expect(setBackgroundColor(createCanvas(), 'rgb(255, 0, 0)').style.backgroundColor).toBe('rgb(255, 0, 0)');
104
111
  });
105
112
 
106
- it('disables touch actions', () => {
113
+ it('disables touch actions', (): void => {
107
114
  expect(setTouchAction(createCanvas()).style.getPropertyValue('touch-action')).toBe('none');
108
115
  });
109
116
 
110
- it('falls back to none for an empty touch action', () => {
117
+ it('falls back to none for an empty touch action', (): void => {
111
118
  expect(setTouchAction(createCanvas(), '').style.getPropertyValue('touch-action')).toBe('none');
112
119
  });
113
120
 
114
- it('disables user selection', () => {
121
+ it('disables user selection', (): void => {
115
122
  expect(setUserSelect(createCanvas()).style.getPropertyValue('user-select')).toBe('none');
116
123
  });
117
124
 
118
- it('falls back to none for an empty user selection', () => {
125
+ it('falls back to none for an empty user selection', (): void => {
119
126
  expect(setUserSelect(createCanvas(), '').style.getPropertyValue('user-select')).toBe('none');
120
127
  });
121
128
  });
@@ -83,10 +83,10 @@ export const addToDOM = (
83
83
  overflowHidden = true
84
84
  ): HTMLCanvasElement => {
85
85
  let target: HTMLElement | null = null;
86
- if (typeof parent === 'string') {
86
+ if (typeof parent === 'string' && parent !== '') {
87
87
  // hopefully an element ID
88
88
  target = document.querySelector<HTMLElement>(`#${CSS.escape(parent)}`);
89
- } else if (parent?.nodeType === 1) {
89
+ } else if (typeof parent === 'object' && parent?.nodeType === 1) {
90
90
  target = parent;
91
91
  }
92
92
  // Fallback, covers an invalid ID and a non HTMLelement object
@@ -123,8 +123,10 @@ export class DisplayObject {
123
123
 
124
124
  /**
125
125
  * Destroys this display object and cleans up resources.
126
+ * @param {boolean} _destroyChildren - Whether the subclass should destroy its children too.
127
+ * @param {boolean} _destroyTexture - Whether the subclass should destroy its texture too.
126
128
  */
127
- public destroy(): void {
129
+ public destroy(_destroyChildren = true, _destroyTexture = false): void {
128
130
  if (this.children) {
129
131
  let i = this.children.length;
130
132
  while (i) {
@@ -9,11 +9,11 @@ const createGame = (): Game => ({ renderer: { resolution: 1 } }) as unknown as G
9
9
 
10
10
  const createGraphics = (): Graphics => new Graphics(createGame());
11
11
 
12
- describe('Graphics', () => {
13
- describe('containsPoint', () => {
12
+ describe('Graphics', (): void => {
13
+ describe('containsPoint', (): void => {
14
14
  // The index never advanced here, so any filled shape that did not contain the point spun
15
15
  // forever. A vitest timeout is the only way a hang shows up as a failure.
16
- it('returns false for a point outside a filled shape instead of hanging', { timeout: 2000 }, () => {
16
+ it('returns false for a point outside a filled shape instead of hanging', { timeout: 2000 }, (): void => {
17
17
  const graphics = createGraphics();
18
18
  graphics.beginFill(0xff0000);
19
19
  graphics.drawRect(0, 0, 10, 10);
@@ -21,7 +21,7 @@ describe('Graphics', () => {
21
21
  expect(graphics.containsPoint(new Point(100, 100), new Point())).toBe(false);
22
22
  });
23
23
 
24
- it('returns true for a point inside a filled shape', { timeout: 2000 }, () => {
24
+ it('returns true for a point inside a filled shape', { timeout: 2000 }, (): void => {
25
25
  const graphics = createGraphics();
26
26
  graphics.beginFill(0xff0000);
27
27
  graphics.drawRect(0, 0, 10, 10);
@@ -29,7 +29,7 @@ describe('Graphics', () => {
29
29
  expect(graphics.containsPoint(new Point(5, 5), new Point())).toBe(true);
30
30
  });
31
31
 
32
- it('walks past a non-matching shape to a later matching one', { timeout: 2000 }, () => {
32
+ it('walks past a non-matching shape to a later matching one', { timeout: 2000 }, (): void => {
33
33
  const graphics = createGraphics();
34
34
  graphics.beginFill(0xff0000);
35
35
  graphics.drawRect(0, 0, 10, 10);
@@ -38,33 +38,33 @@ describe('Graphics', () => {
38
38
  expect(graphics.containsPoint(new Point(105, 105), new Point())).toBe(true);
39
39
  });
40
40
 
41
- it('ignores unfilled shapes', { timeout: 2000 }, () => {
41
+ it('ignores unfilled shapes', { timeout: 2000 }, (): void => {
42
42
  const graphics = createGraphics();
43
43
  graphics.lineStyle(1, 0x00ff00);
44
44
  graphics.drawRect(0, 0, 10, 10);
45
45
  expect(graphics.containsPoint(new Point(5, 5), new Point())).toBe(false);
46
46
  });
47
47
 
48
- it('returns false when nothing has been drawn', { timeout: 2000 }, () => {
48
+ it('returns false when nothing has been drawn', { timeout: 2000 }, (): void => {
49
49
  expect(createGraphics().containsPoint(new Point(0, 0), new Point())).toBe(false);
50
50
  });
51
51
  });
52
52
 
53
- describe('drawShape', () => {
54
- it('records a polygon as the current path', () => {
53
+ describe('drawShape', (): void => {
54
+ it('records a polygon as the current path', (): void => {
55
55
  const graphics = createGraphics();
56
56
  const data = graphics.drawShape(new Polygon([0, 0, 10, 0, 10, 10]));
57
57
  expect(graphics.currentPath).toBe(data);
58
58
  expect(data.shape).toBeInstanceOf(Polygon);
59
59
  });
60
60
 
61
- it('does not record a rectangle as the current path', () => {
61
+ it('does not record a rectangle as the current path', (): void => {
62
62
  const graphics = createGraphics();
63
63
  graphics.drawShape(new Rectangle(0, 0, 10, 10));
64
64
  expect(graphics.currentPath).toBeNull();
65
65
  });
66
66
 
67
- it('carries the current fill and line style onto the data', () => {
67
+ it('carries the current fill and line style onto the data', (): void => {
68
68
  const graphics = createGraphics();
69
69
  graphics.lineStyle(4, 0x00ff00, 0.5);
70
70
  graphics.beginFill(0xff0000, 0.25);
@@ -77,15 +77,15 @@ describe('Graphics', () => {
77
77
  expect(data.fill).toBe(true);
78
78
  });
79
79
 
80
- it('flattens a polygon so the builders see numbers', () => {
80
+ it('flattens a polygon so the builders see numbers', (): void => {
81
81
  const graphics = createGraphics();
82
82
  const data = graphics.drawShape(new Polygon([new Point(0, 0), new Point(10, 0), new Point(10, 10)]));
83
- expect((data.shape as Polygon)._points.every((value) => typeof value === 'number')).toBe(true);
83
+ expect((data.shape as Polygon)._points.every((value): boolean => typeof value === 'number')).toBe(true);
84
84
  });
85
85
  });
86
86
 
87
- describe('path building', () => {
88
- it('accumulates points through moveTo and lineTo', () => {
87
+ describe('path building', (): void => {
88
+ it('accumulates points through moveTo and lineTo', (): void => {
89
89
  const graphics = createGraphics();
90
90
  graphics.moveTo(0, 0);
91
91
  graphics.lineTo(10, 0);
@@ -93,15 +93,15 @@ describe('Graphics', () => {
93
93
  expect(graphics.currentPath?.shape.points).toStrictEqual([0, 0, 10, 0, 10, 10]);
94
94
  });
95
95
 
96
- it('starts a path at the origin when lineTo comes first', () => {
96
+ it('starts a path at the origin when lineTo comes first', (): void => {
97
97
  const graphics = createGraphics();
98
98
  graphics.lineTo(10, 10);
99
99
  expect(graphics.currentPath?.shape.points).toStrictEqual([0, 0, 10, 10]);
100
100
  });
101
101
  });
102
102
 
103
- describe('endFill', () => {
104
- it('stops filling subsequent shapes', () => {
103
+ describe('endFill', (): void => {
104
+ it('stops filling subsequent shapes', (): void => {
105
105
  const graphics = createGraphics();
106
106
  graphics.beginFill(0xff0000);
107
107
  graphics.endFill();
@@ -109,8 +109,58 @@ describe('Graphics', () => {
109
109
  });
110
110
  });
111
111
 
112
- describe('clear', () => {
113
- it('drops the recorded graphics data', () => {
112
+ describe('drawTriangle', (): void => {
113
+ it('records the triangle as a polygon', (): void => {
114
+ const graphics = createGraphics();
115
+ graphics.drawTriangle([new Point(0, 0), new Point(10, 0), new Point(0, 10)]);
116
+ expect(graphics.graphicsData).toHaveLength(1);
117
+ expect(graphics.graphicsData[0]?.shape).toBeInstanceOf(Polygon);
118
+ });
119
+
120
+ it('keeps a front-facing triangle when culling', (): void => {
121
+ const graphics = createGraphics();
122
+ graphics.drawTriangle([new Point(0, 0), new Point(10, 0), new Point(0, 10)], true);
123
+ graphics.drawTriangle([new Point(0, 0), new Point(0, 10), new Point(10, 0)], true);
124
+ expect(graphics.graphicsData).toHaveLength(1);
125
+ });
126
+
127
+ it('draws both windings when culling is off', (): void => {
128
+ const graphics = createGraphics();
129
+ graphics.drawTriangle([new Point(0, 0), new Point(10, 0), new Point(0, 10)]);
130
+ graphics.drawTriangle([new Point(0, 0), new Point(0, 10), new Point(10, 0)]);
131
+ expect(graphics.graphicsData).toHaveLength(2);
132
+ });
133
+ });
134
+
135
+ describe('drawTriangles', (): void => {
136
+ it('reads a flat coordinate list as triangles', (): void => {
137
+ const graphics = createGraphics();
138
+ graphics.drawTriangles([0, 0, 10, 0, 0, 10, 20, 20, 30, 20, 20, 30], null as unknown as number[]);
139
+ expect(graphics.graphicsData).toHaveLength(2);
140
+ });
141
+
142
+ it('reads a point list as triangles', (): void => {
143
+ const graphics = createGraphics();
144
+ graphics.drawTriangles([new Point(0, 0), new Point(10, 0), new Point(0, 10)], null as unknown as number[]);
145
+ expect(graphics.graphicsData).toHaveLength(1);
146
+ });
147
+
148
+ it('follows an index list over a flat coordinate list', (): void => {
149
+ const graphics = createGraphics();
150
+ graphics.drawTriangles([0, 0, 10, 0, 0, 10], [0, 1, 2]);
151
+ expect(graphics.graphicsData).toHaveLength(1);
152
+ expect((graphics.graphicsData[0]!.shape as Polygon).toNumberArray()).toStrictEqual([0, 0, 10, 0, 0, 10]);
153
+ });
154
+
155
+ it('follows an index list over a point list', (): void => {
156
+ const graphics = createGraphics();
157
+ graphics.drawTriangles([new Point(0, 0), new Point(10, 0), new Point(0, 10)], [0, 1, 2]);
158
+ expect(graphics.graphicsData).toHaveLength(1);
159
+ });
160
+ });
161
+
162
+ describe('clear', (): void => {
163
+ it('drops the recorded graphics data', (): void => {
114
164
  const graphics = createGraphics();
115
165
  graphics.beginFill(0xff0000);
116
166
  graphics.drawRect(0, 0, 10, 10);