@vpmedia/phaser 1.120.0 → 1.121.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 (153) hide show
  1. package/dist/index.js +499 -607
  2. package/dist/index.js.map +1 -1
  3. package/dist/phaser/core/animation.d.ts.map +1 -1
  4. package/dist/phaser/core/animation_manager.d.ts.map +1 -1
  5. package/dist/phaser/core/animation_parser.d.ts +1 -1
  6. package/dist/phaser/core/array_set.d.ts.map +1 -1
  7. package/dist/phaser/core/callback.d.ts +12 -0
  8. package/dist/phaser/core/callback.d.ts.map +1 -0
  9. package/dist/phaser/core/device.d.ts +1 -5
  10. package/dist/phaser/core/device.d.ts.map +1 -1
  11. package/dist/phaser/core/dom.d.ts.map +1 -1
  12. package/dist/phaser/core/factory.d.ts +2 -1
  13. package/dist/phaser/core/factory.d.ts.map +1 -1
  14. package/dist/phaser/core/game.d.ts +3 -0
  15. package/dist/phaser/core/game.d.ts.map +1 -1
  16. package/dist/phaser/core/input.d.ts +11 -9
  17. package/dist/phaser/core/input.d.ts.map +1 -1
  18. package/dist/phaser/core/input_event.d.ts +1 -1
  19. package/dist/phaser/core/input_event.d.ts.map +1 -1
  20. package/dist/phaser/core/input_handler.d.ts.map +1 -1
  21. package/dist/phaser/core/input_mouse.d.ts.map +1 -1
  22. package/dist/phaser/core/input_mspointer.d.ts.map +1 -1
  23. package/dist/phaser/core/input_pointer.d.ts +3 -2
  24. package/dist/phaser/core/input_pointer.d.ts.map +1 -1
  25. package/dist/phaser/core/input_touch.d.ts.map +1 -1
  26. package/dist/phaser/core/loader.d.ts +5 -4
  27. package/dist/phaser/core/loader.d.ts.map +1 -1
  28. package/dist/phaser/core/scale_manager.d.ts +5 -4
  29. package/dist/phaser/core/scale_manager.d.ts.map +1 -1
  30. package/dist/phaser/core/scene_manager.d.ts.map +1 -1
  31. package/dist/phaser/core/signal.d.ts +14 -7
  32. package/dist/phaser/core/signal.d.ts.map +1 -1
  33. package/dist/phaser/core/signal_binding.d.ts +10 -10
  34. package/dist/phaser/core/signal_binding.d.ts.map +1 -1
  35. package/dist/phaser/core/sound.d.ts +3 -3
  36. package/dist/phaser/core/sound.d.ts.map +1 -1
  37. package/dist/phaser/core/sound_manager.d.ts +9 -3
  38. package/dist/phaser/core/sound_manager.d.ts.map +1 -1
  39. package/dist/phaser/core/sound_sprite.d.ts +19 -7
  40. package/dist/phaser/core/sound_sprite.d.ts.map +1 -1
  41. package/dist/phaser/core/timer.d.ts +5 -4
  42. package/dist/phaser/core/timer.d.ts.map +1 -1
  43. package/dist/phaser/core/timer_event.d.ts +3 -2
  44. package/dist/phaser/core/timer_event.d.ts.map +1 -1
  45. package/dist/phaser/core/tween.d.ts +7 -6
  46. package/dist/phaser/core/tween.d.ts.map +1 -1
  47. package/dist/phaser/core/tween_data.d.ts +2 -1
  48. package/dist/phaser/core/tween_data.d.ts.map +1 -1
  49. package/dist/phaser/core/tween_easing.d.ts +31 -31
  50. package/dist/phaser/core/tween_manager.d.ts.map +1 -1
  51. package/dist/phaser/display/bitmap_text.d.ts.map +1 -1
  52. package/dist/phaser/display/button.d.ts +2 -1
  53. package/dist/phaser/display/button.d.ts.map +1 -1
  54. package/dist/phaser/display/canvas/pool.d.ts.map +1 -1
  55. package/dist/phaser/display/canvas/renderer.d.ts +1 -1
  56. package/dist/phaser/display/canvas/renderer.d.ts.map +1 -1
  57. package/dist/phaser/display/canvas/tinter.d.ts.map +1 -1
  58. package/dist/phaser/display/canvas/util.d.ts +2 -2
  59. package/dist/phaser/display/canvas/util.d.ts.map +1 -1
  60. package/dist/phaser/display/display_object.d.ts +8 -6
  61. package/dist/phaser/display/display_object.d.ts.map +1 -1
  62. package/dist/phaser/display/graphics.d.ts +7 -3
  63. package/dist/phaser/display/graphics.d.ts.map +1 -1
  64. package/dist/phaser/display/group.d.ts +1 -1
  65. package/dist/phaser/display/group.d.ts.map +1 -1
  66. package/dist/phaser/display/image.d.ts.map +1 -1
  67. package/dist/phaser/display/sprite_util.d.ts.map +1 -1
  68. package/dist/phaser/display/text.d.ts +5 -0
  69. package/dist/phaser/display/text.d.ts.map +1 -1
  70. package/dist/phaser/display/webgl/base_texture.d.ts.map +1 -1
  71. package/dist/phaser/display/webgl/earcut.d.ts.map +1 -1
  72. package/dist/phaser/display/webgl/fast_sprite_batch.d.ts.map +1 -1
  73. package/dist/phaser/display/webgl/filter_manager.d.ts.map +1 -1
  74. package/dist/phaser/display/webgl/graphics.d.ts.map +1 -1
  75. package/dist/phaser/display/webgl/graphics_data.d.ts.map +1 -1
  76. package/dist/phaser/display/webgl/render_texture.d.ts.map +1 -1
  77. package/dist/phaser/display/webgl/renderer.d.ts.map +1 -1
  78. package/dist/phaser/display/webgl/sprite_batch.d.ts.map +1 -1
  79. package/dist/phaser/display/webgl/texture.d.ts.map +1 -1
  80. package/dist/phaser/geom/polygon.d.ts +11 -5
  81. package/dist/phaser/geom/polygon.d.ts.map +1 -1
  82. package/dist/phaser/geom/rectangle.d.ts.map +1 -1
  83. package/dist/phaser/geom/rounded_rectangle.d.ts.map +1 -1
  84. package/dist/phaser/util/math.d.ts.map +1 -1
  85. package/package.json +1 -1
  86. package/src/phaser/core/animation.ts +1 -2
  87. package/src/phaser/core/animation_manager.ts +3 -11
  88. package/src/phaser/core/animation_parser.ts +2 -2
  89. package/src/phaser/core/array_set.ts +8 -10
  90. package/src/phaser/core/cache.ts +2 -2
  91. package/src/phaser/core/callback.ts +14 -0
  92. package/src/phaser/core/device.ts +24 -53
  93. package/src/phaser/core/device_util.ts +6 -6
  94. package/src/phaser/core/dom.ts +10 -7
  95. package/src/phaser/core/factory.ts +3 -2
  96. package/src/phaser/core/game.ts +4 -5
  97. package/src/phaser/core/input.ts +16 -12
  98. package/src/phaser/core/input_event.ts +1 -1
  99. package/src/phaser/core/input_handler.ts +21 -22
  100. package/src/phaser/core/input_mouse.ts +12 -17
  101. package/src/phaser/core/input_mspointer.ts +8 -11
  102. package/src/phaser/core/input_pointer.ts +22 -21
  103. package/src/phaser/core/input_touch.ts +16 -19
  104. package/src/phaser/core/loader.ts +75 -86
  105. package/src/phaser/core/loader_parser.ts +6 -6
  106. package/src/phaser/core/scale_manager.ts +34 -42
  107. package/src/phaser/core/scene_manager.ts +2 -1
  108. package/src/phaser/core/signal.ts +21 -13
  109. package/src/phaser/core/signal_binding.ts +20 -21
  110. package/src/phaser/core/sound.ts +9 -11
  111. package/src/phaser/core/sound_manager.ts +53 -47
  112. package/src/phaser/core/sound_sprite.ts +34 -21
  113. package/src/phaser/core/stage.ts +4 -4
  114. package/src/phaser/core/timer.ts +13 -30
  115. package/src/phaser/core/timer_event.ts +3 -2
  116. package/src/phaser/core/tween.ts +9 -8
  117. package/src/phaser/core/tween_data.ts +15 -41
  118. package/src/phaser/core/tween_easing.test.ts +35 -35
  119. package/src/phaser/core/tween_easing.ts +33 -33
  120. package/src/phaser/core/tween_manager.ts +77 -75
  121. package/src/phaser/display/bitmap_text.ts +7 -11
  122. package/src/phaser/display/button.ts +3 -2
  123. package/src/phaser/display/canvas/graphics.ts +7 -7
  124. package/src/phaser/display/canvas/pool.ts +5 -6
  125. package/src/phaser/display/canvas/renderer.ts +7 -4
  126. package/src/phaser/display/canvas/tinter.ts +9 -11
  127. package/src/phaser/display/canvas/util.test.ts +122 -0
  128. package/src/phaser/display/canvas/util.ts +34 -35
  129. package/src/phaser/display/display_object.ts +30 -43
  130. package/src/phaser/display/graphics.ts +30 -45
  131. package/src/phaser/display/group.ts +1 -1
  132. package/src/phaser/display/image.ts +9 -16
  133. package/src/phaser/display/sprite_util.ts +0 -1
  134. package/src/phaser/display/text.ts +27 -43
  135. package/src/phaser/display/webgl/base_texture.ts +3 -3
  136. package/src/phaser/display/webgl/earcut.ts +2 -3
  137. package/src/phaser/display/webgl/fast_sprite_batch.ts +1 -2
  138. package/src/phaser/display/webgl/filter_manager.ts +6 -18
  139. package/src/phaser/display/webgl/filter_texture.ts +3 -3
  140. package/src/phaser/display/webgl/graphics.ts +28 -38
  141. package/src/phaser/display/webgl/graphics_data.ts +0 -1
  142. package/src/phaser/display/webgl/render_texture.ts +4 -13
  143. package/src/phaser/display/webgl/renderer.ts +0 -1
  144. package/src/phaser/display/webgl/sprite_batch.ts +2 -9
  145. package/src/phaser/display/webgl/texture.ts +12 -15
  146. package/src/phaser/geom/point.ts +1 -1
  147. package/src/phaser/geom/polygon.test.ts +59 -0
  148. package/src/phaser/geom/polygon.ts +43 -45
  149. package/src/phaser/geom/rectangle.ts +3 -15
  150. package/src/phaser/geom/rounded_rectangle.ts +2 -4
  151. package/src/phaser/geom/util/point.ts +1 -1
  152. package/src/phaser/geom/util/rectangle.ts +2 -2
  153. package/src/phaser/util/math.ts +1 -5
@@ -0,0 +1,122 @@
1
+ import { afterEach, describe, expect, it } from 'vitest';
2
+ import { addToDOM, create, removeFromDOM, setBackgroundColor, setTouchAction, setUserSelect } from './util.js';
3
+
4
+ const createCanvas = (): HTMLCanvasElement => create(null, 32, 16, '', true);
5
+
6
+ describe('canvas util', () => {
7
+ afterEach(() => {
8
+ document.body.innerHTML = '';
9
+ });
10
+
11
+ describe('create', () => {
12
+ it('sizes the canvas as asked', () => {
13
+ const canvas = createCanvas();
14
+ expect(canvas.width).toBe(32);
15
+ expect(canvas.height).toBe(16);
16
+ });
17
+
18
+ it('falls back to 256 square for a zero size', () => {
19
+ const canvas = create(null, 0, 0, '', true);
20
+ expect(canvas.width).toBe(256);
21
+ expect(canvas.height).toBe(256);
22
+ });
23
+
24
+ it('assigns the id it is given and leaves an empty one off', () => {
25
+ expect(create(null, 32, 16, 'stage', true).id).toBe('stage');
26
+ expect(createCanvas().id).toBe('');
27
+ });
28
+
29
+ it('takes the canvas out of the flow', () => {
30
+ expect(createCanvas().style.display).toBe('block');
31
+ });
32
+ });
33
+
34
+ describe('addToDOM', () => {
35
+ it('appends to the element with the given id', () => {
36
+ const host = document.createElement('div');
37
+ host.id = 'host';
38
+ document.body.append(host);
39
+ const canvas = createCanvas();
40
+ addToDOM(canvas, 'host');
41
+ expect(canvas.parentElement).toBe(host);
42
+ });
43
+
44
+ it('appends to an element passed directly', () => {
45
+ const host = document.createElement('div');
46
+ document.body.append(host);
47
+ const canvas = createCanvas();
48
+ addToDOM(canvas, host);
49
+ expect(canvas.parentElement).toBe(host);
50
+ });
51
+
52
+ it('falls back to the body for an id nothing matches', () => {
53
+ const canvas = createCanvas();
54
+ addToDOM(canvas, 'nothing-here');
55
+ expect(canvas.parentElement).toBe(document.body);
56
+ });
57
+
58
+ it('falls back to the body when given no parent', () => {
59
+ const canvas = createCanvas();
60
+ addToDOM(canvas, null);
61
+ expect(canvas.parentElement).toBe(document.body);
62
+ });
63
+
64
+ it('hides the parent overflow unless told not to', () => {
65
+ const host = document.createElement('div');
66
+ document.body.append(host);
67
+ addToDOM(createCanvas(), host);
68
+ expect(host.style.overflow).toBe('hidden');
69
+ const other = document.createElement('div');
70
+ document.body.append(other);
71
+ addToDOM(createCanvas(), other, false);
72
+ expect(other.style.overflow).toBe('');
73
+ });
74
+
75
+ it('survives an id that is not a valid bare selector', () => {
76
+ const host = document.createElement('div');
77
+ host.id = 'game.container';
78
+ document.body.append(host);
79
+ const canvas = createCanvas();
80
+ addToDOM(canvas, 'game.container');
81
+ expect(canvas.parentElement).toBe(host);
82
+ });
83
+ });
84
+
85
+ describe('removeFromDOM', () => {
86
+ it('detaches an attached canvas', () => {
87
+ const canvas = createCanvas();
88
+ document.body.append(canvas);
89
+ removeFromDOM(canvas);
90
+ expect(canvas.parentElement).toBeNull();
91
+ });
92
+
93
+ it('leaves a detached canvas alone', () => {
94
+ const canvas = createCanvas();
95
+ expect(() => {
96
+ removeFromDOM(canvas);
97
+ }).not.toThrow();
98
+ });
99
+ });
100
+
101
+ describe('style helpers', () => {
102
+ it('sets the background colour', () => {
103
+ expect(setBackgroundColor(createCanvas(), 'rgb(255, 0, 0)').style.backgroundColor).toBe('rgb(255, 0, 0)');
104
+ });
105
+
106
+ it('disables touch actions', () => {
107
+ expect(setTouchAction(createCanvas()).style.getPropertyValue('touch-action')).toBe('none');
108
+ });
109
+
110
+ it('falls back to none for an empty touch action', () => {
111
+ expect(setTouchAction(createCanvas(), '').style.getPropertyValue('touch-action')).toBe('none');
112
+ });
113
+
114
+ it('disables user selection', () => {
115
+ expect(setUserSelect(createCanvas()).style.getPropertyValue('user-select')).toBe('none');
116
+ });
117
+
118
+ it('falls back to none for an empty user selection', () => {
119
+ expect(setUserSelect(createCanvas(), '').style.getPropertyValue('user-select')).toBe('none');
120
+ });
121
+ });
122
+ });
@@ -10,20 +10,20 @@ import { create as createCanvas } from './pool.js';
10
10
  * @returns {HTMLCanvasElement} The created HTML canvas element.
11
11
  */
12
12
  export const create = (
13
- parent: any,
13
+ parent: object | null,
14
14
  width: number,
15
15
  height: number,
16
16
  id: string,
17
17
  skipPool: boolean
18
18
  ): HTMLCanvasElement => {
19
- width = width || 256;
20
- height = height || 256;
21
- const canvas = skipPool ? document.createElement('canvas') : createCanvas(parent, width, height);
22
- if (typeof id === 'string' && id !== '') {
19
+ const canvasWidth = width || 256;
20
+ const canvasHeight = height || 256;
21
+ const canvas = skipPool ? document.createElement('canvas') : createCanvas(parent, canvasWidth, canvasHeight);
22
+ if (id !== '') {
23
23
  canvas.id = id;
24
24
  }
25
- canvas.width = width;
26
- canvas.height = height;
25
+ canvas.width = canvasWidth;
26
+ canvas.height = canvasHeight;
27
27
  canvas.style.display = 'block';
28
28
  return canvas;
29
29
  };
@@ -46,9 +46,9 @@ export const setBackgroundColor = (canvas: HTMLCanvasElement, color = 'rgb(0,0,0
46
46
  * @returns {HTMLCanvasElement} The modified canvas element.
47
47
  */
48
48
  export const setTouchAction = (canvas: HTMLCanvasElement, value = 'none'): HTMLCanvasElement => {
49
- value = value || 'none';
50
- canvas.style.setProperty('-ms-touch-action', value);
51
- canvas.style.setProperty('touch-action', value);
49
+ const touchAction = value || 'none';
50
+ canvas.style.setProperty('-ms-touch-action', touchAction);
51
+ canvas.style.setProperty('touch-action', touchAction);
52
52
  return canvas;
53
53
  };
54
54
 
@@ -59,13 +59,13 @@ export const setTouchAction = (canvas: HTMLCanvasElement, value = 'none'): HTMLC
59
59
  * @returns {HTMLCanvasElement} The modified canvas element.
60
60
  */
61
61
  export const setUserSelect = (canvas: HTMLCanvasElement, value = 'none'): HTMLCanvasElement => {
62
- value = value || 'none';
63
- canvas.style.setProperty('-webkit-touch-callout', value);
64
- canvas.style.setProperty('-webkit-user-select', value);
65
- canvas.style.setProperty('-khtml-user-select', value);
66
- canvas.style.setProperty('-moz-user-select', value);
67
- canvas.style.setProperty('-ms-user-select', value);
68
- canvas.style.setProperty('user-select', value);
62
+ const userSelect = value || 'none';
63
+ canvas.style.setProperty('-webkit-touch-callout', userSelect);
64
+ canvas.style.setProperty('-webkit-user-select', userSelect);
65
+ canvas.style.setProperty('-khtml-user-select', userSelect);
66
+ canvas.style.setProperty('-moz-user-select', userSelect);
67
+ canvas.style.setProperty('-ms-user-select', userSelect);
68
+ canvas.style.setProperty('user-select', userSelect);
69
69
  canvas.style.setProperty('-webkit-tap-highlight-color', 'rgba(0, 0, 0, 0)');
70
70
  return canvas;
71
71
  };
@@ -77,20 +77,21 @@ export const setUserSelect = (canvas: HTMLCanvasElement, value = 'none'): HTMLCa
77
77
  * @param {boolean} overflowHidden - Whether to set overflow hidden on the parent.
78
78
  * @returns {HTMLCanvasElement} The added canvas element.
79
79
  */
80
- export const addToDOM = (canvas: HTMLCanvasElement, parent: any, overflowHidden = true): HTMLCanvasElement => {
81
- let target;
82
- if (parent) {
83
- if (typeof parent === 'string') {
84
- // hopefully an element ID
85
- target = document.querySelector(`#${parent}`);
86
- } else if (typeof parent === 'object' && parent.nodeType === 1) {
87
- // quick test for a HTMLelement
88
- target = parent;
89
- }
80
+ export const addToDOM = (
81
+ canvas: HTMLCanvasElement,
82
+ parent: string | HTMLElement | null,
83
+ overflowHidden = true
84
+ ): HTMLCanvasElement => {
85
+ let target: HTMLElement | null = null;
86
+ if (typeof parent === 'string') {
87
+ // hopefully an element ID
88
+ target = document.querySelector<HTMLElement>(`#${CSS.escape(parent)}`);
89
+ } else if (parent?.nodeType === 1) {
90
+ target = parent;
90
91
  }
91
92
  // Fallback, covers an invalid ID and a non HTMLelement object
92
93
  target ??= document.body;
93
- if (overflowHidden && target.style) {
94
+ if (overflowHidden) {
94
95
  target.style.overflow = 'hidden';
95
96
  }
96
97
  target.append(canvas);
@@ -102,9 +103,7 @@ export const addToDOM = (canvas: HTMLCanvasElement, parent: any, overflowHidden
102
103
  * @param {HTMLCanvasElement} canvas - The canvas element to remove.
103
104
  */
104
105
  export const removeFromDOM = (canvas: HTMLCanvasElement): void => {
105
- if (canvas && canvas.parentNode) {
106
- canvas.parentNode.removeChild(canvas);
107
- }
106
+ canvas.remove();
108
107
  };
109
108
 
110
109
  /**
@@ -140,10 +139,10 @@ export const getSmoothingPrefix = (context: CanvasRenderingContext2D): string |
140
139
  const VENDORS = ['i', 'webkitI', 'msI', 'mozI', 'oI'];
141
140
  // the vendor-prefixed smoothing flags predate the standard property and are absent from lib.dom
142
141
  const smoothingFlags = context as unknown as Record<string, boolean | undefined>;
143
- for (let i = 0; i < VENDORS.length; i += 1) {
144
- const s = `${VENDORS[i]}mageSmoothingEnabled`;
145
- if (context && smoothingFlags[s]) {
146
- return s;
142
+ for (const vendor of VENDORS) {
143
+ const flag = `${vendor}mageSmoothingEnabled`;
144
+ if (smoothingFlags[flag]) {
145
+ return flag;
147
146
  }
148
147
  }
149
148
  return null;
@@ -6,6 +6,8 @@ import { PI_2 } from '../util/math.js';
6
6
  import { renderCanvas, renderWebGL } from './sprite_util.js';
7
7
  import type { Graphics } from './graphics.js';
8
8
  import type { Game } from '../core/game.js';
9
+ import type { EventManager } from '../core/event_manager.js';
10
+ import type { Image } from './image.js';
9
11
  import type { RenderSession } from './render_session.js';
10
12
 
11
13
  export class DisplayObject {
@@ -43,18 +45,18 @@ export class DisplayObject {
43
45
  /** @type {boolean} */
44
46
  public ignoreChildInput = false;
45
47
  public name: string | null = null;
46
- public data: any = null;
48
+ public data: object | null = null;
47
49
  public game!: Game;
48
50
  public type!: number;
49
- public _cachedSprite!: any;
51
+ public _cachedSprite!: Image | null;
50
52
  public rotationCache!: number;
51
53
  public worldRotation!: number;
52
- public transformCallback!: any;
53
- public transformCallbackContext!: any;
54
+ public transformCallback!: ((worldTransform: Matrix, parentTransform: Matrix) => void) | null;
55
+ public transformCallbackContext!: unknown;
54
56
  public _width!: number;
55
57
  public _height!: number;
56
58
  public z!: number;
57
- public events!: any;
59
+ public events!: EventManager;
58
60
  public renderOrderID!: number;
59
61
  /**
60
62
  * Creates a new DisplayObject instance.
@@ -111,9 +113,9 @@ export class DisplayObject {
111
113
  /** @type {boolean} */
112
114
  this.ignoreChildInput = false;
113
115
  /** @type {string | null } */
114
- this.name = this.name ?? null;
116
+ this.name ??= null;
115
117
  /** @type {object | null } */
116
- this.data = this.data ?? null;
118
+ this.data ??= null;
117
119
  /** @type {Game } */
118
120
  this.game = game;
119
121
  }
@@ -133,7 +135,7 @@ export class DisplayObject {
133
135
  this.exists = false;
134
136
  this.renderable = false;
135
137
  this.visible = false;
136
- // TODO: investigate how to clean up properly object references without breaking delayed tween cleanups.
138
+ // the geometry below is deliberately left alive: a delayed tween may still be reading it
137
139
  /*
138
140
  This.position = null;
139
141
  this.scale = null;
@@ -177,7 +179,7 @@ export class DisplayObject {
177
179
  this.children.splice(index, 0, child);
178
180
  return child;
179
181
  }
180
- throw new Error(`${child}addChildAt: The index ${index} supplied is out of bounds ${this.children.length}`);
182
+ throw new Error(`addChildAt: index ${index} is out of bounds for ${this.children.length} children`);
181
183
  }
182
184
 
183
185
  /**
@@ -362,10 +364,7 @@ export class DisplayObject {
362
364
  // Set the World values
363
365
  this.worldAlpha = this.alpha * p.worldAlpha;
364
366
  // This.worldPosition.setTo(wt.tx, wt.ty);
365
- this.worldScale.setTo(
366
- this.scale.x * Math.sqrt(wt.a * wt.a + wt.c * wt.c),
367
- this.scale.y * Math.sqrt(wt.b * wt.b + wt.d * wt.d)
368
- );
367
+ this.worldScale.setTo(this.scale.x * Math.hypot(wt.a, wt.c), this.scale.y * Math.hypot(wt.b, wt.d));
369
368
  this.worldRotation = Math.atan2(-wt.c, wt.d);
370
369
  // Reset the bounds each time this is called!
371
370
  this.currentBounds = null;
@@ -384,23 +383,22 @@ export class DisplayObject {
384
383
  * @param {DisplayObject} targetCoordinateSpace - The coordinate space to calculate bounds in.
385
384
  * @returns {Rectangle} The bounds rectangle of this display object.
386
385
  */
387
- public getBounds(targetCoordinateSpace?: any): Rectangle {
388
- const isTargetCoordinateSpaceDisplayObject = targetCoordinateSpace && targetCoordinateSpace.contains !== undefined;
386
+ public getBounds(targetCoordinateSpace?: unknown): Rectangle {
387
+ const candidate = targetCoordinateSpace as DisplayObject | undefined;
388
+ const isTargetCoordinateSpaceDisplayObject = Boolean(candidate?.contains);
389
+ let target = this as DisplayObject;
389
390
  let isTargetCoordinateSpaceThisOrParent = true;
390
- if (!isTargetCoordinateSpaceDisplayObject) {
391
- targetCoordinateSpace = this;
392
- } else if (targetCoordinateSpace.contains !== undefined) {
393
- isTargetCoordinateSpaceThisOrParent = targetCoordinateSpace.contains(this);
394
- } else {
395
- isTargetCoordinateSpaceThisOrParent = false;
391
+ if (isTargetCoordinateSpaceDisplayObject) {
392
+ target = candidate!;
393
+ isTargetCoordinateSpaceThisOrParent = target.contains(this);
396
394
  }
397
395
  let i;
398
396
  let matrixCache;
399
397
  if (isTargetCoordinateSpaceDisplayObject) {
400
- matrixCache = targetCoordinateSpace.worldTransform;
401
- targetCoordinateSpace.worldTransform = getIdentityMatrix();
402
- for (i = 0; i < targetCoordinateSpace.children.length; i += 1) {
403
- targetCoordinateSpace.children[i].updateTransform();
398
+ matrixCache = target.worldTransform;
399
+ target.worldTransform = getIdentityMatrix();
400
+ for (i = 0; i < target.children.length; i += 1) {
401
+ target.children[i]!.updateTransform();
404
402
  }
405
403
  }
406
404
  let minX = Infinity;
@@ -468,13 +466,13 @@ export class DisplayObject {
468
466
  bounds.width = maxX - minX;
469
467
  bounds.height = maxY - minY;
470
468
  if (isTargetCoordinateSpaceDisplayObject) {
471
- targetCoordinateSpace.worldTransform = matrixCache;
472
- for (i = 0; i < targetCoordinateSpace.children.length; i += 1) {
473
- targetCoordinateSpace.children[i].updateTransform();
469
+ target.worldTransform = matrixCache!;
470
+ for (i = 0; i < target.children.length; i += 1) {
471
+ target.children[i]!.updateTransform();
474
472
  }
475
473
  }
476
474
  if (!isTargetCoordinateSpaceThisOrParent) {
477
- const targetCoordinateSpaceBounds = targetCoordinateSpace.getBounds();
475
+ const targetCoordinateSpaceBounds = target.getBounds();
478
476
  bounds.x -= targetCoordinateSpaceBounds.x;
479
477
  bounds.y -= targetCoordinateSpaceBounds.y;
480
478
  }
@@ -587,7 +585,6 @@ export class DisplayObject {
587
585
  * @throws {Error} This method is not implemented yet.
588
586
  */
589
587
  public generateTexture(): void {
590
- // TODO
591
588
  throw new Error('display_object.generateTexture() is not implemented');
592
589
  }
593
590
 
@@ -634,9 +631,7 @@ export class DisplayObject {
634
631
  /**
635
632
  * Generates a cached sprite for this display object.
636
633
  */
637
- public generateCachedSprite(): void {
638
- // TODO
639
- }
634
+ public generateCachedSprite(): void {}
640
635
 
641
636
  /**
642
637
  * Destroys the cached sprite for this display object.
@@ -665,11 +660,7 @@ export class DisplayObject {
665
660
  */
666
661
  public set width(value: number) {
667
662
  const { width } = this.getLocalBounds();
668
- if (width !== 0) {
669
- this.scale.x = value / width;
670
- } else {
671
- this.scale.x = 1;
672
- }
663
+ this.scale.x = width === 0 ? 1 : value / width;
673
664
  this._width = value;
674
665
  }
675
666
 
@@ -687,11 +678,7 @@ export class DisplayObject {
687
678
  */
688
679
  public set height(value: number) {
689
680
  const { height } = this.getLocalBounds();
690
- if (height !== 0) {
691
- this.scale.y = value / height;
692
- } else {
693
- this.scale.y = 1;
694
- }
681
+ this.scale.y = height === 0 ? 1 : value / height;
695
682
  this._height = value;
696
683
  }
697
684
 
@@ -25,8 +25,11 @@ import type { IdentifiedWebGLRenderingContext } from './webgl/util.js';
25
25
  /** Graphics attaches the buffer it draws into onto its cached sprite. */
26
26
  export type CachedSprite = Image & { buffer: CanvasBuffer };
27
27
 
28
- /** drawShape only records a current path for polygon data, so its shape is always a Polygon. */
29
- export type PolygonPath = GraphicsData & { shape: Polygon };
28
+ /** A polygon whose vertices have been flattened to a bare x, y number list. */
29
+ export type FlatPolygon = Omit<Polygon, 'points'> & { points: number[] };
30
+
31
+ /** drawShape only records a current path for polygon data, and it flattens what it records. */
32
+ export type PolygonPath = Omit<GraphicsData, 'shape'> & { shape: FlatPolygon };
30
33
 
31
34
  /** Per-context WebGL state cached on a graphics object, keyed by gl context id. */
32
35
  export type GraphicsWebGLBucket = {
@@ -110,7 +113,6 @@ export class Graphics extends DisplayObject {
110
113
  * Destroys the graphics object and clears all data.
111
114
  */
112
115
  public override destroy(): void {
113
- // TODO
114
116
  this.clear();
115
117
  super.destroy();
116
118
  }
@@ -190,8 +192,8 @@ export class Graphics extends DisplayObject {
190
192
  if (points.length === 0) {
191
193
  this.moveTo(0, 0);
192
194
  }
193
- const fromX = points.at(-2);
194
- const fromY = points.at(-1);
195
+ const fromX = points.at(-2)!;
196
+ const fromY = points.at(-1)!;
195
197
  let j = 0;
196
198
  for (let i = 1; i <= n; i += 1) {
197
199
  j = i / n;
@@ -229,8 +231,8 @@ export class Graphics extends DisplayObject {
229
231
  let t2;
230
232
  let t3;
231
233
  const { points } = this.currentPath!.shape;
232
- const fromX = points.at(-2);
233
- const fromY = points.at(-1);
234
+ const fromX = points.at(-2)!;
235
+ const fromY = points.at(-1)!;
234
236
  let j = 0;
235
237
  for (let i = 1; i <= n; i += 1) {
236
238
  j = i / n;
@@ -267,8 +269,8 @@ export class Graphics extends DisplayObject {
267
269
  this.moveTo(x1, y1);
268
270
  }
269
271
  const { points } = this.currentPath!.shape;
270
- const fromX = points.at(-2);
271
- const fromY = points.at(-1);
272
+ const fromX = points.at(-2)!;
273
+ const fromY = points.at(-1)!;
272
274
  const a1 = fromY - y1;
273
275
  const b1 = fromX - x1;
274
276
  const a2 = y2 - y1;
@@ -373,12 +375,10 @@ export class Graphics extends DisplayObject {
373
375
  this.filling = true;
374
376
  this.fillColor = color || 0;
375
377
  this.fillAlpha = alpha ?? 1;
376
- if (this.currentPath) {
377
- if (this.currentPath.shape.points.length <= 2) {
378
- this.currentPath.fill = this.filling;
379
- this.currentPath.fillColor = this.fillColor;
380
- this.currentPath.fillAlpha = this.fillAlpha;
381
- }
378
+ if (this.currentPath && this.currentPath.shape.points.length <= 2) {
379
+ this.currentPath.fill = this.filling;
380
+ this.currentPath.fillColor = this.fillColor;
381
+ this.currentPath.fillAlpha = this.fillAlpha;
382
382
  }
383
383
  return this;
384
384
  }
@@ -452,13 +452,7 @@ export class Graphics extends DisplayObject {
452
452
  * @returns {Graphics} This Graphics object for chaining.
453
453
  */
454
454
  public drawPolygon(path: Polygon): this {
455
- let points;
456
- if (path instanceof Polygon) {
457
- points = path.points;
458
- } else {
459
- points = path;
460
- }
461
- // TODO
455
+ const points = path instanceof Polygon ? path.points : path;
462
456
  /*
463
457
  if (!Array.isArray(points)) {
464
458
  points = new Array(arguments.length);
@@ -490,7 +484,6 @@ export class Graphics extends DisplayObject {
490
484
  * Generates a texture from the graphics object (not implemented).
491
485
  */
492
486
  public override generateTexture(): void {
493
- // TODO
494
487
  this.game.logger.warn('graphics.generateTexture() is not implemented');
495
488
  }
496
489
 
@@ -700,10 +693,8 @@ export class Graphics extends DisplayObject {
700
693
  this.worldTransform.applyInverse(point, tempPoint);
701
694
  const { graphicsData } = this;
702
695
  for (const data of graphicsData) {
703
- if (data.fill && data.shape) {
704
- if (data.shape.contains(tempPoint.x, tempPoint.y)) {
705
- return true;
706
- }
696
+ if (data.fill && data.shape?.contains(tempPoint.x, tempPoint.y)) {
697
+ return true;
707
698
  }
708
699
  }
709
700
  return false;
@@ -718,15 +709,13 @@ export class Graphics extends DisplayObject {
718
709
  let minY = Infinity;
719
710
  let maxY = -Infinity;
720
711
  if (this.graphicsData.length > 0) {
721
- let shape;
722
712
  let points;
723
713
  let x;
724
714
  let y;
725
715
  let w;
726
716
  let h;
727
717
  for (const data of this.graphicsData) {
728
- const { lineWidth } = data;
729
- shape = data.shape;
718
+ const { lineWidth, shape } = data;
730
719
  if (shape instanceof Rectangle || shape instanceof RoundedRectangle) {
731
720
  x = shape.x - lineWidth / 2;
732
721
  y = shape.y - lineWidth / 2;
@@ -737,8 +726,7 @@ export class Graphics extends DisplayObject {
737
726
  minY = y < minY ? y : minY;
738
727
  maxY = y + h > maxY ? y + h : maxY;
739
728
  } else if (shape instanceof Circle) {
740
- x = shape.x;
741
- y = shape.y;
729
+ ({ x, y } = shape);
742
730
  w = shape.radius + lineWidth / 2;
743
731
  h = shape.radius + lineWidth / 2;
744
732
  minX = x - w < minX ? x - w : minX;
@@ -746,8 +734,7 @@ export class Graphics extends DisplayObject {
746
734
  minY = y - h < minY ? y - h : minY;
747
735
  maxY = y + h > maxY ? y + h : maxY;
748
736
  } else if (shape instanceof Ellipse) {
749
- x = shape.x;
750
- y = shape.y;
737
+ ({ x, y } = shape);
751
738
  w = shape.width + lineWidth / 2;
752
739
  h = shape.height + lineWidth / 2;
753
740
  minX = x - w < minX ? x - w : minX;
@@ -756,14 +743,14 @@ export class Graphics extends DisplayObject {
756
743
  maxY = y + h > maxY ? y + h : maxY;
757
744
  } else {
758
745
  // POLY - assumes points are sequential, not Point objects
759
- points = shape.points;
746
+ ({ points } = shape);
760
747
  for (let j = 0; j < points.length; j += 1) {
761
- if (points[j] instanceof Point) {
762
- x = points[j].x;
763
- y = points[j].y;
748
+ const vertex = points[j];
749
+ if (vertex instanceof Point) {
750
+ ({ x, y } = vertex);
764
751
  } else {
765
- x = points[j];
766
- y = points[j + 1];
752
+ x = vertex!;
753
+ y = points[j + 1] as number;
767
754
  if (j < points.length - 1) {
768
755
  j += 1;
769
756
  }
@@ -850,11 +837,9 @@ export class Graphics extends DisplayObject {
850
837
  * @returns {GraphicsData} The graphics data for the drawn shape.
851
838
  */
852
839
  public drawShape(shape: GraphicsShape): GraphicsData {
853
- if (this.currentPath) {
854
- // check current path!
855
- if (this.currentPath.shape.points.length <= 2) {
856
- this.graphicsData.pop();
857
- }
840
+ // check current path!
841
+ if (this.currentPath && this.currentPath.shape.points.length <= 2) {
842
+ this.graphicsData.pop();
858
843
  }
859
844
  this.currentPath = null;
860
845
  // Handle mixed-type polygons
@@ -11,7 +11,7 @@ export class Group extends DisplayObject {
11
11
  declare public z: number;
12
12
  public ignoreDestroy!: boolean;
13
13
  public pendingDestroy!: boolean;
14
- public classType!: Function;
14
+ public classType!: new (game: Game, ...args: never[]) => DisplayObject;
15
15
  public cursor!: DisplayObject | null;
16
16
  public inputEnableChildren!: boolean;
17
17
  public onChildInputDown!: Signal;
@@ -146,33 +146,26 @@ export class Image extends DisplayObject {
146
146
  frame: string | number | null = 0,
147
147
  stopAnimation = true
148
148
  ): void {
149
- if (key === PENDING_ATLAS) {
150
- key = frame ?? 0;
151
- frame = 0;
152
- } else {
153
- frame = frame ?? 0;
154
- }
149
+ const isPendingAtlas = key === PENDING_ATLAS;
150
+ const textureKey = isPendingAtlas ? (frame ?? 0) : key;
151
+ const textureFrame = isPendingAtlas ? 0 : (frame ?? 0);
155
152
  if (stopAnimation) {
156
153
  this.animations.stop();
157
154
  }
158
- this.key = key;
155
+ this.key = textureKey;
159
156
  this.customRender = false;
160
157
  const { cache } = this.game;
161
158
  const smoothed = !this.texture.baseTexture.scaleMode;
162
159
  let setFrame = true;
163
- if (key instanceof Texture) {
164
- this.setTexture(key);
160
+ if (textureKey instanceof Texture) {
161
+ this.setTexture(textureKey);
165
162
  } else {
166
- const img = cache.getImage(key ?? undefined, true);
163
+ const img = cache.getImage(textureKey ?? undefined, true);
167
164
  if (img) {
168
165
  this.key = img.key;
169
166
  this.setTexture(new Texture(img.base));
170
- if (key === '__default') {
171
- this.texture.baseTexture.skipRender = true;
172
- } else {
173
- this.texture.baseTexture.skipRender = false;
174
- }
175
- setFrame = !this.animations.loadFrameData(img.frameData, frame);
167
+ this.texture.baseTexture.skipRender = textureKey === '__default';
168
+ setFrame = !this.animations.loadFrameData(img.frameData, textureFrame);
176
169
  }
177
170
  }
178
171
  if (setFrame) {
@@ -30,7 +30,6 @@ export const setTexture = (target: Image, texture: Texture, destroyBase = false)
30
30
  * @returns {Rectangle} The bounds rectangle.
31
31
  */
32
32
  export const getBounds = (target: Image, matrix: Matrix | null = null) => {
33
- // TODO verify
34
33
  if (target.currentBounds) {
35
34
  return target.currentBounds;
36
35
  }