canvasengine 2.0.0-beta.6 → 2.0.0-beta.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DebugRenderer-DkjTAc48.js +1384 -0
- package/dist/DebugRenderer-DkjTAc48.js.map +1 -0
- package/dist/components/Button.d.ts +185 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Canvas.d.ts +17 -0
- package/dist/components/Canvas.d.ts.map +1 -0
- package/dist/components/DOMElement.d.ts +54 -0
- package/dist/components/DOMElement.d.ts.map +1 -0
- package/dist/components/DOMSprite.d.ts +127 -0
- package/dist/components/DOMSprite.d.ts.map +1 -0
- package/dist/components/FocusContainer.d.ts +129 -0
- package/dist/components/FocusContainer.d.ts.map +1 -0
- package/dist/components/Graphic.d.ts +64 -0
- package/dist/components/Graphic.d.ts.map +1 -0
- package/dist/components/Joystick.d.ts +36 -0
- package/dist/components/Joystick.d.ts.map +1 -0
- package/dist/components/NineSliceSprite.d.ts +16 -0
- package/dist/components/NineSliceSprite.d.ts.map +1 -0
- package/dist/components/ParticleEmitter.d.ts +4 -0
- package/dist/components/ParticleEmitter.d.ts.map +1 -0
- package/dist/components/Scene.d.ts +2 -0
- package/dist/components/Scene.d.ts.map +1 -0
- package/dist/components/Text.d.ts +24 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/TilingSprite.d.ts +17 -0
- package/dist/components/TilingSprite.d.ts.map +1 -0
- package/dist/components/Video.d.ts +14 -0
- package/dist/components/Video.d.ts.map +1 -0
- package/dist/components/index.d.ts +20 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/types/DisplayObject.d.ts +118 -0
- package/dist/components/types/DisplayObject.d.ts.map +1 -0
- package/dist/components/types/MouseEvent.d.ts +4 -0
- package/dist/components/types/MouseEvent.d.ts.map +1 -0
- package/dist/components/types/Spritesheet.d.ts +248 -0
- package/dist/components/types/Spritesheet.d.ts.map +1 -0
- package/dist/components/types/index.d.ts +4 -0
- package/dist/components/types/index.d.ts.map +1 -0
- package/dist/directives/Controls.d.ts +112 -0
- package/dist/directives/Controls.d.ts.map +1 -0
- package/dist/directives/ControlsBase.d.ts +199 -0
- package/dist/directives/ControlsBase.d.ts.map +1 -0
- package/dist/directives/Drag.d.ts +69 -0
- package/dist/directives/Drag.d.ts.map +1 -0
- package/dist/directives/Flash.d.ts +116 -0
- package/dist/directives/Flash.d.ts.map +1 -0
- package/dist/directives/FocusNavigation.d.ts +52 -0
- package/dist/directives/FocusNavigation.d.ts.map +1 -0
- package/dist/directives/FogVisibility.d.ts +47 -0
- package/dist/directives/FogVisibility.d.ts.map +1 -0
- package/dist/directives/GamepadControls.d.ts +224 -0
- package/dist/directives/GamepadControls.d.ts.map +1 -0
- package/dist/directives/JoystickControls.d.ts +171 -0
- package/dist/directives/JoystickControls.d.ts.map +1 -0
- package/dist/directives/KeyboardControls.d.ts +219 -0
- package/dist/directives/KeyboardControls.d.ts.map +1 -0
- package/dist/directives/Scheduler.d.ts +36 -0
- package/dist/directives/Scheduler.d.ts.map +1 -0
- package/dist/directives/Shake.d.ts +98 -0
- package/dist/directives/Shake.d.ts.map +1 -0
- package/dist/directives/Sound.d.ts +25 -0
- package/dist/directives/Sound.d.ts.map +1 -0
- package/dist/directives/Transition.d.ts +10 -0
- package/dist/directives/Transition.d.ts.map +1 -0
- package/dist/directives/ViewportCull.d.ts +11 -0
- package/dist/directives/ViewportCull.d.ts.map +1 -0
- package/dist/directives/ViewportFollow.d.ts +18 -0
- package/dist/directives/ViewportFollow.d.ts.map +1 -0
- package/dist/directives/index.d.ts +14 -0
- package/dist/directives/index.d.ts.map +1 -0
- package/dist/dist-BOOc43Qm.js +778 -0
- package/dist/dist-BOOc43Qm.js.map +1 -0
- package/dist/engine/FocusManager.d.ts +174 -0
- package/dist/engine/FocusManager.d.ts.map +1 -0
- package/dist/engine/animation.d.ts +72 -0
- package/dist/engine/animation.d.ts.map +1 -0
- package/dist/engine/bootstrap.d.ts +52 -0
- package/dist/engine/bootstrap.d.ts.map +1 -0
- package/dist/engine/directive.d.ts +13 -0
- package/dist/engine/directive.d.ts.map +1 -0
- package/dist/engine/reactive.d.ts +135 -0
- package/dist/engine/reactive.d.ts.map +1 -0
- package/dist/engine/signal.d.ts +73 -0
- package/dist/engine/signal.d.ts.map +1 -0
- package/dist/engine/trigger.d.ts +54 -0
- package/dist/engine/trigger.d.ts.map +1 -0
- package/dist/engine/utils.d.ts +89 -0
- package/dist/engine/utils.d.ts.map +1 -0
- package/dist/hooks/addContext.d.ts +2 -0
- package/dist/hooks/addContext.d.ts.map +1 -0
- package/dist/hooks/useFocus.d.ts +60 -0
- package/dist/hooks/useFocus.d.ts.map +1 -0
- package/dist/hooks/useProps.d.ts +42 -0
- package/dist/hooks/useProps.d.ts.map +1 -0
- package/dist/hooks/useRef.d.ts +4 -0
- package/dist/hooks/useRef.d.ts.map +1 -0
- package/dist/index.d.ts +19 -1107
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +8 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +14708 -3135
- package/dist/index.js.map +1 -1
- package/dist/utils/Ease.d.ts +17 -0
- package/dist/utils/Ease.d.ts.map +1 -0
- package/dist/utils/GlobalAssetLoader.d.ts +141 -0
- package/dist/utils/GlobalAssetLoader.d.ts.map +1 -0
- package/dist/utils/RadialGradient.d.ts +57 -0
- package/dist/utils/RadialGradient.d.ts.map +1 -0
- package/dist/utils/functions.d.ts +2 -0
- package/dist/utils/functions.d.ts.map +1 -0
- package/dist/utils/tabindex.d.ts +16 -0
- package/dist/utils/tabindex.d.ts.map +1 -0
- package/package.json +16 -9
- package/src/components/Button.ts +399 -0
- package/src/components/Canvas.ts +82 -51
- package/src/components/Container.ts +21 -2
- package/src/components/DOMContainer.ts +379 -0
- package/src/components/DOMElement.ts +556 -0
- package/src/components/DOMSprite.ts +1040 -0
- package/src/components/DisplayObject.ts +422 -201
- package/src/components/FocusContainer.ts +368 -0
- package/src/components/Graphic.ts +239 -73
- package/src/components/Joystick.ts +363 -0
- package/src/components/Mesh.ts +222 -0
- package/src/components/NineSliceSprite.ts +4 -1
- package/src/components/ParticleEmitter.ts +12 -8
- package/src/components/Sprite.ts +418 -52
- package/src/components/Text.ts +270 -26
- package/src/components/Viewport.ts +122 -63
- package/src/components/index.ts +9 -2
- package/src/components/types/DisplayObject.ts +53 -5
- package/src/components/types/Spritesheet.ts +0 -118
- package/src/directives/Controls.ts +254 -0
- package/src/directives/ControlsBase.ts +267 -0
- package/src/directives/Drag.ts +357 -52
- package/src/directives/Flash.ts +419 -0
- package/src/directives/FocusNavigation.ts +113 -0
- package/src/directives/FogVisibility.ts +273 -0
- package/src/directives/GamepadControls.ts +537 -0
- package/src/directives/JoystickControls.ts +396 -0
- package/src/directives/KeyboardControls.ts +85 -430
- package/src/directives/Scheduler.ts +21 -5
- package/src/directives/Shake.ts +298 -0
- package/src/directives/Sound.ts +94 -31
- package/src/directives/ViewportFollow.ts +40 -9
- package/src/directives/index.ts +13 -6
- package/src/engine/FocusManager.ts +510 -0
- package/src/engine/animation.ts +175 -21
- package/src/engine/bootstrap.ts +140 -6
- package/src/engine/directive.ts +4 -4
- package/src/engine/reactive.ts +980 -177
- package/src/engine/signal.ts +241 -47
- package/src/engine/trigger.ts +34 -7
- package/src/engine/utils.ts +19 -3
- package/src/hooks/useFocus.ts +91 -0
- package/src/hooks/useProps.ts +1 -1
- package/src/index.ts +8 -2
- package/src/types/pixi-cull.d.ts +7 -0
- package/src/utils/GlobalAssetLoader.ts +257 -0
- package/src/utils/functions.ts +7 -0
- package/src/utils/tabindex.ts +70 -0
- package/testing/index.ts +35 -4
- package/tsconfig.json +18 -0
- package/vite.config.ts +39 -0
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import * as PIXI from "pixi.js";
|
|
2
2
|
import { SignalOrPrimitive } from ".";
|
|
3
|
+
import { DragProps } from "../../directives/Drag";
|
|
4
|
+
import { ViewportFollowProps } from "../../directives/ViewportFollow";
|
|
5
|
+
import { ShakeProps } from "../../directives/Shake";
|
|
6
|
+
import { FlashProps } from "../../directives/Flash";
|
|
7
|
+
import { FogVisibilityProps } from "../../directives/FogVisibility";
|
|
3
8
|
|
|
4
9
|
export type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
5
10
|
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
6
11
|
export type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';
|
|
7
12
|
export type Size = number | `${number}%`
|
|
8
13
|
export type EdgeSize = SignalOrPrimitive<Size | [Size, Size] | [Size, Size, Size, Size]>
|
|
14
|
+
export type ObjectFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
|
|
15
|
+
export type ObjectPosition = string;
|
|
16
|
+
export type TransformOrigin = string;
|
|
17
|
+
export type PositionType = 'relative' | 'absolute' | 'static';
|
|
18
|
+
|
|
19
|
+
export type ObservablePointSignal = [number, number] | SignalOrPrimitive<[number, number]> | { x: number, y: number } | SignalOrPrimitive<{ x: number, y: number }>;
|
|
9
20
|
|
|
10
21
|
export interface DisplayObjectProps {
|
|
11
22
|
attach?: any;
|
|
@@ -14,6 +25,24 @@ export interface DisplayObjectProps {
|
|
|
14
25
|
y?: SignalOrPrimitive<number>;
|
|
15
26
|
width?: SignalOrPrimitive<Size>;
|
|
16
27
|
height?: SignalOrPrimitive<Size>;
|
|
28
|
+
minWidth?: SignalOrPrimitive<Size>;
|
|
29
|
+
minHeight?: SignalOrPrimitive<Size>;
|
|
30
|
+
maxWidth?: SignalOrPrimitive<Size>;
|
|
31
|
+
maxHeight?: SignalOrPrimitive<Size>;
|
|
32
|
+
aspectRatio?: SignalOrPrimitive<number>;
|
|
33
|
+
flexGrow?: SignalOrPrimitive<number>;
|
|
34
|
+
flexShrink?: SignalOrPrimitive<number>;
|
|
35
|
+
flexBasis?: SignalOrPrimitive<Size>;
|
|
36
|
+
rowGap?: SignalOrPrimitive<number>;
|
|
37
|
+
columnGap?: SignalOrPrimitive<number>;
|
|
38
|
+
positionType?: PositionType;
|
|
39
|
+
top?: SignalOrPrimitive<Size>;
|
|
40
|
+
right?: SignalOrPrimitive<Size>;
|
|
41
|
+
bottom?: SignalOrPrimitive<Size>;
|
|
42
|
+
left?: SignalOrPrimitive<Size>;
|
|
43
|
+
objectFit?: ObjectFit;
|
|
44
|
+
objectPosition?: ObjectPosition;
|
|
45
|
+
transformOrigin?: TransformOrigin;
|
|
17
46
|
children?: any[];
|
|
18
47
|
flexDirection?: FlexDirection;
|
|
19
48
|
justifyContent?: JustifyContent;
|
|
@@ -22,9 +51,9 @@ export interface DisplayObjectProps {
|
|
|
22
51
|
padding?: EdgeSize;
|
|
23
52
|
border?: EdgeSize;
|
|
24
53
|
absolute?: SignalOrPrimitive<boolean>;
|
|
25
|
-
scale?:
|
|
26
|
-
anchor?:
|
|
27
|
-
skew?:
|
|
54
|
+
scale?: ObservablePointSignal | number;
|
|
55
|
+
anchor?: ObservablePointSignal;
|
|
56
|
+
skew?: ObservablePointSignal;
|
|
28
57
|
tint?: SignalOrPrimitive<number>;
|
|
29
58
|
rotation?: SignalOrPrimitive<number>;
|
|
30
59
|
angle?: SignalOrPrimitive<number>;
|
|
@@ -32,11 +61,29 @@ export interface DisplayObjectProps {
|
|
|
32
61
|
roundPixels?: SignalOrPrimitive<boolean>;
|
|
33
62
|
cursor?: SignalOrPrimitive<string>;
|
|
34
63
|
visible?: SignalOrPrimitive<boolean>;
|
|
35
|
-
pivot?:
|
|
64
|
+
pivot?: ObservablePointSignal;
|
|
36
65
|
filters?: any[];
|
|
37
66
|
blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;
|
|
38
67
|
blur?: SignalOrPrimitive<number>;
|
|
68
|
+
/**
|
|
69
|
+
* Optional metadata used by presets (for example `SpriteShadows`)
|
|
70
|
+
* to mark this display object as a shadow caster.
|
|
71
|
+
*/
|
|
72
|
+
shadowCaster?: any;
|
|
73
|
+
/**
|
|
74
|
+
* Optional metadata used by presets (for example `Footprints`)
|
|
75
|
+
* to mark this display object as a footprint caster.
|
|
76
|
+
*/
|
|
77
|
+
footprintCaster?: any;
|
|
78
|
+
|
|
79
|
+
// Directives
|
|
80
|
+
drag?: DragProps;
|
|
81
|
+
viewportFollow?: ViewportFollowProps;
|
|
82
|
+
shake?: ShakeProps;
|
|
83
|
+
flash?: FlashProps;
|
|
84
|
+
fogVisibility?: FogVisibilityProps;
|
|
39
85
|
|
|
86
|
+
// Events
|
|
40
87
|
click?: PIXI.FederatedEventHandler;
|
|
41
88
|
mousedown?: PIXI.FederatedEventHandler;
|
|
42
89
|
mouseenter?: PIXI.FederatedEventHandler;
|
|
@@ -67,4 +114,5 @@ export interface DisplayObjectProps {
|
|
|
67
114
|
touchmove?: PIXI.FederatedEventHandler;
|
|
68
115
|
touchstart?: PIXI.FederatedEventHandler;
|
|
69
116
|
wheel?: PIXI.FederatedEventHandler<PIXI.FederatedWheelEvent>;
|
|
70
|
-
|
|
117
|
+
tabindex?: SignalOrPrimitive<number>;
|
|
118
|
+
}
|
|
@@ -208,124 +208,6 @@ export interface TexturesOptions extends TextureOptions, TransformOptions {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
export interface SpritesheetOptions extends TransformOptions, TextureOptions {
|
|
211
|
-
/**
|
|
212
|
-
* Object containing all animations.
|
|
213
|
-
* The key to the object is the name of the animation. The value is a two-dimensional array
|
|
214
|
-
*
|
|
215
|
-
* ```ts
|
|
216
|
-
* textures: {
|
|
217
|
-
* myanim: {
|
|
218
|
-
* animations: [
|
|
219
|
-
* [ { time: 0, frameX: 0, frameY: 0 } ]
|
|
220
|
-
* ]
|
|
221
|
-
* }
|
|
222
|
-
* }
|
|
223
|
-
* ```
|
|
224
|
-
*
|
|
225
|
-
* The first array represents an animation group. You can put several of them together to create an animation cluster. For example, several explosions with the same spritesheet
|
|
226
|
-
* The second array represents the animation itself which will animate over time. The object indicates, over a period of time (in frame), which part of the spritesheet will be taken (`frameX`, `frameY`)
|
|
227
|
-
*
|
|
228
|
-
* Here are the properties:
|
|
229
|
-
*
|
|
230
|
-
* * `time`: Time in frame
|
|
231
|
-
* * `frameX`: Retrieve a frame from the spritesheet on the X-axis
|
|
232
|
-
* * `frameY`: Retrieve a frame from the spritesheet on the Y-axis
|
|
233
|
-
* * `opacity`
|
|
234
|
-
* * `pivot`
|
|
235
|
-
* * `anchor`
|
|
236
|
-
* * `rotation`
|
|
237
|
-
* * `angle`
|
|
238
|
-
* * `scale`
|
|
239
|
-
* * `skew`
|
|
240
|
-
* * `x`
|
|
241
|
-
* * `y`
|
|
242
|
-
* * `visible`
|
|
243
|
-
* * `sound`: The sound that will be played during the frame
|
|
244
|
-
*
|
|
245
|
-
* ---
|
|
246
|
-
* **Extract Animation of Spritesheet**
|
|
247
|
-
*
|
|
248
|
-
* Sometimes the animation is part of the image
|
|
249
|
-
*
|
|
250
|
-
* ```ts
|
|
251
|
-
* textures: {
|
|
252
|
-
* myanim: {
|
|
253
|
-
* rectWidth: 64,
|
|
254
|
-
* rectHeight: 64,
|
|
255
|
-
* framesWidth: 10,
|
|
256
|
-
* framesHeight: 2,
|
|
257
|
-
* offset: {x: 0, y: 230},
|
|
258
|
-
* sound: 'my-sound-id', // You can put a sound just for the animation
|
|
259
|
-
* animations: [
|
|
260
|
-
* [ { time: 0, frameX: 0, frameY: 0 } ]
|
|
261
|
-
* ]
|
|
262
|
-
* }
|
|
263
|
-
* }
|
|
264
|
-
* ```
|
|
265
|
-
*
|
|
266
|
-
* Above, we can specify which part we want to recover
|
|
267
|
-
*
|
|
268
|
-
* 1. We go to the position {0, 230} of the image (`offset`)
|
|
269
|
-
* 2. We recover cells of 64px (`rectWidth` and `rectHeight`)
|
|
270
|
-
* 3. And we get 20 cells (10 on the width, 2 on the height) (`frameX` and `frameY`)
|
|
271
|
-
*
|
|
272
|
-
* ---
|
|
273
|
-
*
|
|
274
|
-
* **Advanced**
|
|
275
|
-
*
|
|
276
|
-
* You can create an animation that will be linked to a data. For example, different animation according to a direction of the character.
|
|
277
|
-
*
|
|
278
|
-
* Full example:
|
|
279
|
-
*
|
|
280
|
-
* ```ts
|
|
281
|
-
* import { Spritesheet, Animation, Direction } from '@rpgjs/client'
|
|
282
|
-
*
|
|
283
|
-
* @Spritesheet({
|
|
284
|
-
* id: 'chest',
|
|
285
|
-
* image: require('./assets/chest.png'),
|
|
286
|
-
* width: 124,
|
|
287
|
-
* height: 61,
|
|
288
|
-
* framesHeight: 2,
|
|
289
|
-
* framesWidth: 4,
|
|
290
|
-
* textures: {
|
|
291
|
-
* [Animation.Stand]: {
|
|
292
|
-
* animations: direction => [[ {time: 0, frameX: 3, frameY: direction == Direction.Up ? 0 : 1 } ]]
|
|
293
|
-
* }
|
|
294
|
-
* })
|
|
295
|
-
* })
|
|
296
|
-
* export class Chest { }
|
|
297
|
-
* ```
|
|
298
|
-
*
|
|
299
|
-
* > It is important to know that `Animation.Stand` animation is called if it exists. it only works in the case of an event that doesn't move. The direction is then sent
|
|
300
|
-
*
|
|
301
|
-
* As you can see, the property contains a function that returns the array for the animation. Here, it is the direction but the parameters depend on the call of the animation. Example:
|
|
302
|
-
*
|
|
303
|
-
* ```ts
|
|
304
|
-
* import { Spritesheet, Animation, Direction, RpgSprite, ISpriteCharacter } from '@rpgjs/client'
|
|
305
|
-
*
|
|
306
|
-
* @Spritesheet({
|
|
307
|
-
* id: 'chest',
|
|
308
|
-
* image: require('./assets/chest.png'),
|
|
309
|
-
* width: 124,
|
|
310
|
-
* height: 61,
|
|
311
|
-
* framesHeight: 2,
|
|
312
|
-
* framesWidth: 4,
|
|
313
|
-
* textures: {
|
|
314
|
-
* [Animation.Stand]: {
|
|
315
|
-
* animations: str => [[ {time: 0, frameX: 3, frameY: str == 'hello' ? 0 : 1 } ]]
|
|
316
|
-
* }
|
|
317
|
-
* }
|
|
318
|
-
* })
|
|
319
|
-
* export class Chest implements ISpriteCharacter {
|
|
320
|
-
* onCharacterStand(sprite: RpgSprite) {
|
|
321
|
-
* sprite.animation.play(Animation.Stand, ['hello'])
|
|
322
|
-
* }
|
|
323
|
-
* }
|
|
324
|
-
* ```
|
|
325
|
-
*
|
|
326
|
-
* @prop { { [animName: string]: { animations: Array<Array<FrameOptions>> | Function, ...other } } } [textures]
|
|
327
|
-
* @memberof Spritesheet
|
|
328
|
-
* */
|
|
329
211
|
textures?: {
|
|
330
212
|
[animationName: string]: Partial<TexturesOptions> & Pick<TexturesOptions, 'animations'>
|
|
331
213
|
}
|
|
@@ -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<any>) {
|
|
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 as any).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<any>) { }
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Update controls configuration
|
|
91
|
+
* Updates both keyboard and gamepad controls
|
|
92
|
+
*/
|
|
93
|
+
onUpdate(props: any, element: Element<any>) {
|
|
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<any>) {
|
|
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);
|