canvasengine 2.0.0-beta.4 → 2.0.0-beta.41

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-BxfW34YG.js +172 -0
  2. package/dist/DebugRenderer-BxfW34YG.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 +54 -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-BnuKipxl.js +12568 -0
  84. package/dist/index-BnuKipxl.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 +363 -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 +419 -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 +295 -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 +34 -7
  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,254 @@
1
+ import { Directive, registerDirective } from "../engine/directive";
2
+ import { Element, isElementFrozen } from "../engine/reactive";
3
+ import { ControlsBase, Controls } from "./ControlsBase";
4
+ import { KeyboardControls } from "./KeyboardControls";
5
+ import { GamepadControls, GamepadConfig } from "./GamepadControls";
6
+ import { JoystickControls, JoystickConfig } from "./JoystickControls";
7
+ import { Signal, isSignal } from "@signe/reactive";
8
+ import { Subscription } from "rxjs";
9
+
10
+ /**
11
+ * Controls directive that coordinates keyboard, gamepad, and joystick input systems
12
+ *
13
+ * This directive automatically activates keyboard, gamepad, and joystick controls when available.
14
+ * The gamepad is automatically enabled if joypad.js is detected in the environment.
15
+ *
16
+ * All systems share the same control configuration and can work simultaneously.
17
+ *
18
+ * @example
19
+ * ```html
20
+ * <Sprite
21
+ * image="path/to/image.png"
22
+ * controls={controlsConfig}
23
+ * x={x}
24
+ * y={y}
25
+ * />
26
+ * ```
27
+ */
28
+ export class ControlsDirective extends Directive {
29
+ private keyboardControls: KeyboardControls | null = null;
30
+ private gamepadControls: GamepadControls | null = null;
31
+ private joystickControls: JoystickControls | null = null;
32
+ private freezeSubscription: Subscription | null = null;
33
+ private element: Element | null = null;
34
+
35
+ /**
36
+ * Initialize the controls directive
37
+ * Sets up keyboard, gamepad, and joystick controls if available
38
+ */
39
+ onInit(element: Element) {
40
+ this.element = element;
41
+ const value = element.props.controls?.value ?? element.props.controls;
42
+ if (!value) return;
43
+
44
+ // Initialize keyboard controls (always available)
45
+ this.keyboardControls = new KeyboardControls();
46
+ this.keyboardControls.setInputs(value as Controls);
47
+ this.keyboardControls.start();
48
+
49
+ // Initialize gamepad controls if gamepad config is present
50
+ // GamepadControls will handle joypad.js availability internally
51
+ const gamepadConfig = (value as Controls & { gamepad?: GamepadConfig }).gamepad;
52
+ if (gamepadConfig !== undefined && gamepadConfig.enabled !== false) {
53
+ this.gamepadControls = new GamepadControls();
54
+ this.gamepadControls.setInputs(value as Controls & { gamepad?: GamepadConfig });
55
+ this.gamepadControls.start();
56
+ }
57
+
58
+ // Initialize joystick controls if joystick config is present
59
+ const joystickConfig = (value as Controls & { joystick?: JoystickConfig }).joystick;
60
+ if (joystickConfig !== undefined && joystickConfig.enabled !== false) {
61
+ this.joystickControls = new JoystickControls();
62
+ this.joystickControls.setInputs(value as Controls & { joystick?: JoystickConfig });
63
+ this.joystickControls.start();
64
+ }
65
+
66
+ // Check initial freeze state
67
+ if (isElementFrozen(element)) {
68
+ this.stopInputs();
69
+ }
70
+
71
+ // Subscribe to freeze prop if it's a signal
72
+ const freezeProp = element.propObservables?.freeze ?? element.props?.freeze;
73
+ if (isSignal(freezeProp)) {
74
+ this.freezeSubscription = (freezeProp as Signal<boolean>).observable.subscribe((isFrozen) => {
75
+ if (isFrozen) {
76
+ this.stopInputs();
77
+ } else {
78
+ this.listenInputs();
79
+ }
80
+ });
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Mount hook (no specific action needed)
86
+ */
87
+ onMount(element: Element) {}
88
+
89
+ /**
90
+ * Update controls configuration
91
+ * Updates both keyboard and gamepad controls
92
+ */
93
+ onUpdate(props: any, element: Element) {
94
+ const value = props.controls?.value ?? props.controls;
95
+ if (value) {
96
+ if (this.keyboardControls) {
97
+ this.keyboardControls.setInputs(value as Controls);
98
+ }
99
+
100
+ if (this.gamepadControls) {
101
+ this.gamepadControls.setInputs(value as Controls & { gamepad?: GamepadConfig });
102
+ }
103
+ }
104
+
105
+ // Handle freeze prop update
106
+ if (props.freeze !== undefined && this.element) {
107
+ if (isElementFrozen(this.element)) {
108
+ this.stopInputs();
109
+ } else {
110
+ this.listenInputs();
111
+ }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Cleanup and destroy all control systems
117
+ */
118
+ onDestroy(element: Element) {
119
+ if (this.freezeSubscription) {
120
+ this.freezeSubscription.unsubscribe();
121
+ this.freezeSubscription = null;
122
+ }
123
+
124
+ if (this.keyboardControls) {
125
+ this.keyboardControls.destroy();
126
+ this.keyboardControls = null;
127
+ }
128
+
129
+ if (this.gamepadControls) {
130
+ this.gamepadControls.destroy();
131
+ this.gamepadControls = null;
132
+ }
133
+
134
+ if (this.joystickControls) {
135
+ this.joystickControls.destroy();
136
+ this.joystickControls = null;
137
+ }
138
+
139
+ this.element = null;
140
+ }
141
+
142
+ /**
143
+ * Get a control by input name
144
+ * Delegates to keyboard controls (primary system)
145
+ *
146
+ * @param inputName - Name of the input/key
147
+ * @returns BoundKey if found, undefined otherwise
148
+ */
149
+ getControl(inputName: string) {
150
+ return this.keyboardControls?.getControl(inputName);
151
+ }
152
+
153
+ /**
154
+ * Get all bound controls
155
+ * Delegates to keyboard controls (primary system)
156
+ *
157
+ * @returns Object mapping input names to BoundKey objects
158
+ */
159
+ getControls() {
160
+ return this.keyboardControls?.getControls() || {};
161
+ }
162
+
163
+ /**
164
+ * Apply a control action programmatically
165
+ * Applies to both keyboard and gamepad if available
166
+ *
167
+ * @param controlName - Name of the control
168
+ * @param isDown - Whether the control is pressed (true) or released (false)
169
+ * @param payload - Optional payload to pass to keyDown/keyUp callbacks (e.g., { power: 0.8 })
170
+ * @returns Promise that resolves when the action is complete
171
+ */
172
+ async applyControl(controlName: string | number, isDown?: boolean, payload?: any): Promise<void> {
173
+ if (this.keyboardControls) {
174
+ await this.keyboardControls.applyControl(controlName, isDown);
175
+ }
176
+ if (this.gamepadControls) {
177
+ await this.gamepadControls.applyControl(controlName, isDown, payload);
178
+ }
179
+ if (this.joystickControls) {
180
+ await this.joystickControls.applyControl(controlName, isDown, payload);
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Stop listening to inputs
186
+ * Stops keyboard, gamepad, and joystick input processing
187
+ */
188
+ stopInputs() {
189
+ if (this.keyboardControls) {
190
+ this.keyboardControls.stopInputs();
191
+ }
192
+ if (this.gamepadControls) {
193
+ this.gamepadControls.stopInputs();
194
+ }
195
+ if (this.joystickControls) {
196
+ this.joystickControls.stopInputs();
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Resume listening to inputs
202
+ * Resumes keyboard, gamepad, and joystick input processing
203
+ */
204
+ listenInputs() {
205
+ if (this.keyboardControls) {
206
+ this.keyboardControls.listenInputs();
207
+ }
208
+ if (this.gamepadControls) {
209
+ this.gamepadControls.listenInputs();
210
+ }
211
+ if (this.joystickControls) {
212
+ this.joystickControls.listenInputs();
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Get the current controls configuration
218
+ * Returns keyboard controls options (both systems share the same config)
219
+ *
220
+ * @returns The controls options object
221
+ */
222
+ get options(): Controls {
223
+ return this.keyboardControls?.options || {};
224
+ }
225
+
226
+ /**
227
+ * Get the keyboard controls instance
228
+ *
229
+ * @returns KeyboardControls instance or null
230
+ */
231
+ get keyboard(): KeyboardControls | null {
232
+ return this.keyboardControls;
233
+ }
234
+
235
+ /**
236
+ * Get the gamepad controls instance
237
+ *
238
+ * @returns GamepadControls instance or null
239
+ */
240
+ get gamepad(): GamepadControls | null {
241
+ return this.gamepadControls;
242
+ }
243
+
244
+ /**
245
+ * Get the joystick controls instance
246
+ *
247
+ * @returns JoystickControls instance or null
248
+ */
249
+ get joystick(): JoystickControls | null {
250
+ return this.joystickControls;
251
+ }
252
+ }
253
+
254
+ registerDirective('controls', ControlsDirective);
@@ -0,0 +1,266 @@
1
+ import { fps2ms } from "../engine/utils";
2
+
3
+ export interface ControlOptions {
4
+ repeat?: boolean;
5
+ bind: string | string[];
6
+ keyUp?: Function;
7
+ keyDown?: Function;
8
+ delay?: number | {
9
+ duration: number;
10
+ otherControls?: (string)[];
11
+ };
12
+ }
13
+
14
+ export interface Controls {
15
+ [controlName: string]: ControlOptions;
16
+ }
17
+
18
+ export type BoundKey = { actionName: string, options: ControlOptions, parameters?: any };
19
+
20
+ /**
21
+ * Abstract base class for control systems (keyboard, gamepad, etc.)
22
+ *
23
+ * This class provides common functionality shared across all control implementations:
24
+ * - Input binding and management
25
+ * - Control configuration
26
+ * - Input state management
27
+ * - Common methods for querying and triggering controls
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * class MyControls extends ControlsBase {
32
+ * protected setupListeners() {
33
+ * // Setup specific input listeners
34
+ * }
35
+ *
36
+ * protected cleanup() {
37
+ * // Cleanup specific resources
38
+ * }
39
+ *
40
+ * protected preStep() {
41
+ * // Process inputs each frame
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export abstract class ControlsBase {
47
+ protected boundKeys: {
48
+ [keyName: string]: BoundKey
49
+ } = {}
50
+ protected stop: boolean = false
51
+ protected _controlsOptions: Controls = {}
52
+ protected interval: any
53
+ protected serverFps: number = 60
54
+
55
+ /**
56
+ * Setup input listeners specific to this control implementation
57
+ * Must be implemented by subclasses
58
+ */
59
+ protected abstract setupListeners(): void;
60
+
61
+ /**
62
+ * Cleanup resources specific to this control implementation
63
+ * Must be implemented by subclasses
64
+ */
65
+ protected abstract cleanup(): void;
66
+
67
+ /**
68
+ * Process inputs each step/frame
69
+ * Must be implemented by subclasses
70
+ */
71
+ protected abstract preStep(): void;
72
+
73
+ /**
74
+ * Start the control processing loop
75
+ * Initializes listeners and starts the interval
76
+ */
77
+ start() {
78
+ this.setupListeners();
79
+ this.interval = setInterval(() => {
80
+ this.preStep()
81
+ }, fps2ms(this.serverFps ?? 60))
82
+ }
83
+
84
+ /**
85
+ * Stop the control processing and cleanup resources
86
+ */
87
+ destroy() {
88
+ if (this.interval) {
89
+ clearInterval(this.interval)
90
+ }
91
+ this.cleanup();
92
+ }
93
+
94
+ /**
95
+ * Bind a key/input to a control action
96
+ *
97
+ * @param keys - Single key or array of keys to bind
98
+ * @param actionName - Name of the control action
99
+ * @param options - Control options (repeat, keyDown, keyUp, etc.)
100
+ * @param parameters - Optional parameters to pass to the control callbacks
101
+ */
102
+ protected bindKey(keys: string | string[], actionName: string, options: ControlOptions, parameters?: object) {
103
+ if (!Array.isArray(keys)) keys = [keys]
104
+ const keyOptions = Object.assign({
105
+ repeat: false
106
+ }, options);
107
+ keys.forEach(keyName => {
108
+ this.boundKeys[keyName] = { actionName, options: keyOptions, parameters }
109
+ })
110
+ }
111
+
112
+ /**
113
+ * Apply an input action for a bound key
114
+ * Can be overridden by subclasses for custom behavior
115
+ *
116
+ * @param keyName - Name of the key/input to process
117
+ */
118
+ protected applyInput(keyName: string) {
119
+ const boundKey = this.boundKeys[keyName];
120
+ if (!boundKey) return;
121
+
122
+ const { repeat, keyDown } = boundKey.options;
123
+ // Default implementation - subclasses may override for state tracking
124
+ if (keyDown) {
125
+ let parameters = boundKey.parameters;
126
+ if (typeof parameters === "function") {
127
+ parameters = parameters();
128
+ }
129
+ keyDown(boundKey);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Get a control by input name
135
+ *
136
+ * @param inputName - Name of the input/key
137
+ * @returns BoundKey if found, undefined otherwise
138
+ * @example
139
+ * ```ts
140
+ * const control = controls.getControl('up');
141
+ * if (control) {
142
+ * console.log(control.actionName); // 'up'
143
+ * }
144
+ * ```
145
+ */
146
+ getControl(inputName: string): BoundKey | undefined {
147
+ return this.boundKeys[inputName]
148
+ }
149
+
150
+ /**
151
+ * Get all bound controls
152
+ *
153
+ * @returns Object mapping input names to BoundKey objects
154
+ * @example
155
+ * ```ts
156
+ * const allControls = controls.getControls();
157
+ * console.log(Object.keys(allControls)); // ['up', 'down', 'left', 'right', ...]
158
+ * ```
159
+ */
160
+ getControls(): { [key: string]: BoundKey } {
161
+ return this.boundKeys
162
+ }
163
+
164
+ /**
165
+ * Apply a control action programmatically
166
+ *
167
+ * Must be implemented by subclasses to provide input-specific behavior
168
+ *
169
+ * @param controlName - Name or identifier of the control
170
+ * @param isDown - Whether the control is pressed down (true) or released (false)
171
+ * @returns Promise that resolves when the control action is complete
172
+ * @example
173
+ * ```ts
174
+ * // Press a control
175
+ * await controls.applyControl('action', true);
176
+ *
177
+ * // Release a control
178
+ * await controls.applyControl('action', false);
179
+ *
180
+ * // Press and release (default)
181
+ * await controls.applyControl('action');
182
+ * ```
183
+ */
184
+ abstract applyControl(controlName: string | number, isDown?: boolean): Promise<void>;
185
+
186
+ /**
187
+ * Stop listening to inputs
188
+ * Input events will be ignored until listenInputs() is called
189
+ *
190
+ * @example
191
+ * ```ts
192
+ * controls.stopInputs();
193
+ * // ... later
194
+ * controls.listenInputs();
195
+ * ```
196
+ */
197
+ stopInputs() {
198
+ this.stop = true
199
+ }
200
+
201
+ /**
202
+ * Resume listening to inputs after stopInputs() was called
203
+ *
204
+ * @example
205
+ * ```ts
206
+ * controls.stopInputs();
207
+ * // ... later
208
+ * controls.listenInputs();
209
+ * ```
210
+ */
211
+ listenInputs() {
212
+ this.stop = false
213
+ }
214
+
215
+ /**
216
+ * Configure controls with input mappings
217
+ *
218
+ * This method sets up the binding between input keys/buttons and control actions.
219
+ * It clears existing bindings and creates new ones based on the provided configuration.
220
+ *
221
+ * @param inputs - Control configuration object
222
+ * @example
223
+ * ```ts
224
+ * controls.setInputs({
225
+ * up: {
226
+ * repeat: true,
227
+ * bind: 'up',
228
+ * keyDown() {
229
+ * console.log('Up pressed');
230
+ * }
231
+ * },
232
+ * action: {
233
+ * bind: ['space', 'enter'],
234
+ * keyDown() {
235
+ * console.log('Action triggered');
236
+ * }
237
+ * }
238
+ * });
239
+ * ```
240
+ */
241
+ setInputs(inputs: Controls) {
242
+ if (!inputs) return
243
+ this.boundKeys = {}
244
+ for (let control in inputs) {
245
+ const option = inputs[control]
246
+ const { bind } = option
247
+ let inputsKey: any = bind
248
+ if (!Array.isArray(inputsKey)) {
249
+ inputsKey = [bind]
250
+ }
251
+ for (let input of inputsKey) {
252
+ this.bindKey(input, control, option)
253
+ }
254
+ }
255
+ this._controlsOptions = inputs
256
+ }
257
+
258
+ /**
259
+ * Get the current controls configuration
260
+ *
261
+ * @returns The controls options object
262
+ */
263
+ get options(): Controls {
264
+ return this._controlsOptions
265
+ }
266
+ }