@skewedaspect/sage 0.3.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.
- package/LICENSE +21 -0
- package/Readme.md +53 -0
- package/dist/classes/bindings/toggle.d.ts +122 -0
- package/dist/classes/bindings/trigger.d.ts +79 -0
- package/dist/classes/bindings/value.d.ts +104 -0
- package/dist/classes/entity.d.ts +83 -0
- package/dist/classes/eventBus.d.ts +94 -0
- package/dist/classes/gameEngine.d.ts +57 -0
- package/dist/classes/input/gamepad.d.ts +94 -0
- package/dist/classes/input/keyboard.d.ts +66 -0
- package/dist/classes/input/mouse.d.ts +80 -0
- package/dist/classes/input/readers/gamepad.d.ts +77 -0
- package/dist/classes/input/readers/keyboard.d.ts +60 -0
- package/dist/classes/input/readers/mouse.d.ts +45 -0
- package/dist/classes/loggers/consoleBackend.d.ts +29 -0
- package/dist/classes/loggers/nullBackend.d.ts +14 -0
- package/dist/engines/scene.d.ts +11 -0
- package/dist/interfaces/action.d.ts +20 -0
- package/dist/interfaces/binding.d.ts +144 -0
- package/dist/interfaces/entity.d.ts +9 -0
- package/dist/interfaces/game.d.ts +26 -0
- package/dist/interfaces/input.d.ts +181 -0
- package/dist/interfaces/logger.d.ts +88 -0
- package/dist/managers/binding.d.ts +185 -0
- package/dist/managers/entity.d.ts +70 -0
- package/dist/managers/game.d.ts +20 -0
- package/dist/managers/input.d.ts +56 -0
- package/dist/managers/level.d.ts +55 -0
- package/dist/sage.d.ts +20 -0
- package/dist/sage.es.js +2208 -0
- package/dist/sage.es.js.map +1 -0
- package/dist/sage.umd.js +2 -0
- package/dist/sage.umd.js.map +1 -0
- package/dist/utils/capabilities.d.ts +2 -0
- package/dist/utils/graphics.d.ts +10 -0
- package/dist/utils/logger.d.ts +66 -0
- package/dist/utils/physics.d.ts +2 -0
- package/dist/utils/version.d.ts +5 -0
- package/docs/architecture.md +129 -0
- package/docs/behaviors.md +706 -0
- package/docs/binding_system.md +820 -0
- package/docs/design/input.md +86 -0
- package/docs/entity_system.md +538 -0
- package/docs/eventbus.md +225 -0
- package/docs/getting_started.md +264 -0
- package/docs/images/sage_logo.png +0 -0
- package/docs/images/sage_logo_shape.png +0 -0
- package/docs/overview.md +38 -0
- package/docs/physics_system.md +686 -0
- package/docs/scene_system.md +513 -0
- package/package.json +69 -0
- package/src/classes/bindings/toggle.ts +261 -0
- package/src/classes/bindings/trigger.ts +211 -0
- package/src/classes/bindings/value.ts +227 -0
- package/src/classes/entity.ts +256 -0
- package/src/classes/eventBus.ts +259 -0
- package/src/classes/gameEngine.ts +125 -0
- package/src/classes/input/gamepad.ts +388 -0
- package/src/classes/input/keyboard.ts +189 -0
- package/src/classes/input/mouse.ts +276 -0
- package/src/classes/input/readers/gamepad.ts +179 -0
- package/src/classes/input/readers/keyboard.ts +123 -0
- package/src/classes/input/readers/mouse.ts +133 -0
- package/src/classes/loggers/consoleBackend.ts +135 -0
- package/src/classes/loggers/nullBackend.ts +51 -0
- package/src/engines/scene.ts +112 -0
- package/src/images/sage_logo.svg +172 -0
- package/src/images/sage_logo_shape.svg +146 -0
- package/src/interfaces/action.ts +30 -0
- package/src/interfaces/binding.ts +191 -0
- package/src/interfaces/entity.ts +21 -0
- package/src/interfaces/game.ts +44 -0
- package/src/interfaces/input.ts +221 -0
- package/src/interfaces/logger.ts +118 -0
- package/src/managers/binding.ts +729 -0
- package/src/managers/entity.ts +252 -0
- package/src/managers/game.ts +111 -0
- package/src/managers/input.ts +233 -0
- package/src/managers/level.ts +261 -0
- package/src/sage.ts +119 -0
- package/src/types/global.d.ts +11 -0
- package/src/utils/capabilities.ts +16 -0
- package/src/utils/graphics.ts +148 -0
- package/src/utils/logger.ts +225 -0
- package/src/utils/physics.ts +16 -0
- package/src/utils/version.ts +11 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Mouse Input Resource Access
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
// Interfaces
|
|
6
|
+
import type { ButtonState, MouseDevice, MouseInputState, Position } from '../../interfaces/input.ts';
|
|
7
|
+
|
|
8
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Callback type for mouse device connection events
|
|
12
|
+
*/
|
|
13
|
+
export type MouseDeviceCallback = (device : MouseDevice) => void;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Callback type for mouse input events
|
|
17
|
+
*/
|
|
18
|
+
export type MouseInputCallback = (device : MouseDevice, state : MouseInputState) => void;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Responsible for tracking mouse state and notifying subscribers of changes.
|
|
22
|
+
*/
|
|
23
|
+
export class MouseInputPlugin
|
|
24
|
+
{
|
|
25
|
+
private _targetElement : HTMLElement;
|
|
26
|
+
private _mouseDevice : MouseDevice;
|
|
27
|
+
private _buttonState : Record<string, ButtonState> = {};
|
|
28
|
+
private _axesState : Record<string, number> = {};
|
|
29
|
+
private _position : Position = {
|
|
30
|
+
absolute: { x: 0, y: 0 },
|
|
31
|
+
relative: { x: 0, y: 0 },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
private _wheelState = {
|
|
35
|
+
deltaX: 0,
|
|
36
|
+
deltaY: 0,
|
|
37
|
+
deltaZ: 0,
|
|
38
|
+
deltaMode: 0,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Callbacks
|
|
42
|
+
private _onDeviceConnected ?: MouseDeviceCallback;
|
|
43
|
+
private _onInputChanged ?: MouseInputCallback;
|
|
44
|
+
|
|
45
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create a new MouseResourceAccess
|
|
49
|
+
*
|
|
50
|
+
* @param targetElement - The DOM element to attach mouse listeners to (defaults to document.body)
|
|
51
|
+
*/
|
|
52
|
+
constructor(targetElement : HTMLElement = document.body)
|
|
53
|
+
{
|
|
54
|
+
this._targetElement = targetElement;
|
|
55
|
+
|
|
56
|
+
// Initialize mouse device
|
|
57
|
+
this._mouseDevice = {
|
|
58
|
+
id: 'mouse-0',
|
|
59
|
+
name: 'Mouse',
|
|
60
|
+
type: 'mouse',
|
|
61
|
+
connected: true,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Set up event listeners
|
|
65
|
+
this._setupMouseEvents();
|
|
66
|
+
|
|
67
|
+
// Initialize axes to zero
|
|
68
|
+
this._axesState['axis-x'] = 0;
|
|
69
|
+
this._axesState['axis-y'] = 0;
|
|
70
|
+
|
|
71
|
+
// Notify that device is connected (on next tick to allow callback registration)
|
|
72
|
+
setTimeout(() => this._notifyDeviceConnected(), 0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
76
|
+
// Public API
|
|
77
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register a callback for device connected events
|
|
81
|
+
*
|
|
82
|
+
* @param callback - The callback to register
|
|
83
|
+
*/
|
|
84
|
+
public onDeviceConnected(callback : MouseDeviceCallback) : void
|
|
85
|
+
{
|
|
86
|
+
this._onDeviceConnected = callback;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Register a callback for input changed events
|
|
91
|
+
*
|
|
92
|
+
* @param callback - The callback to register
|
|
93
|
+
*/
|
|
94
|
+
public onInputChanged(callback : MouseInputCallback) : void
|
|
95
|
+
{
|
|
96
|
+
this._onInputChanged = callback;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get the current mouse state
|
|
101
|
+
*/
|
|
102
|
+
public getState() : MouseInputState
|
|
103
|
+
{
|
|
104
|
+
return {
|
|
105
|
+
type: 'mouse',
|
|
106
|
+
buttons: { ...this._buttonState },
|
|
107
|
+
axes: { ...this._axesState },
|
|
108
|
+
position: {
|
|
109
|
+
absolute: { ...this._position.absolute },
|
|
110
|
+
relative: { ...this._position.relative },
|
|
111
|
+
},
|
|
112
|
+
wheel: { ...this._wheelState },
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the mouse device
|
|
118
|
+
*/
|
|
119
|
+
public getDevice() : MouseDevice
|
|
120
|
+
{
|
|
121
|
+
return { ...this._mouseDevice };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Destroy the mouse resource access and clean up event listeners
|
|
126
|
+
*/
|
|
127
|
+
public destroy() : void
|
|
128
|
+
{
|
|
129
|
+
// Remove mouse event listeners
|
|
130
|
+
this._targetElement.removeEventListener('mousedown', this._handleMouseDown);
|
|
131
|
+
this._targetElement.removeEventListener('mouseup', this._handleMouseUp);
|
|
132
|
+
this._targetElement.removeEventListener('mousemove', this._handleMouseMove);
|
|
133
|
+
this._targetElement.removeEventListener('wheel', this._handleMouseWheel);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
137
|
+
// Private Methods
|
|
138
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Set up mouse event listeners
|
|
142
|
+
*/
|
|
143
|
+
private _setupMouseEvents() : void
|
|
144
|
+
{
|
|
145
|
+
// Bind handlers to this instance
|
|
146
|
+
this._handleMouseDown = this._handleMouseDown.bind(this);
|
|
147
|
+
this._handleMouseUp = this._handleMouseUp.bind(this);
|
|
148
|
+
this._handleMouseMove = this._handleMouseMove.bind(this);
|
|
149
|
+
this._handleMouseWheel = this._handleMouseWheel.bind(this);
|
|
150
|
+
|
|
151
|
+
// Add event listeners
|
|
152
|
+
this._targetElement.addEventListener('mousedown', this._handleMouseDown);
|
|
153
|
+
this._targetElement.addEventListener('mouseup', this._handleMouseUp);
|
|
154
|
+
this._targetElement.addEventListener('mousemove', this._handleMouseMove);
|
|
155
|
+
this._targetElement.addEventListener('wheel', this._handleMouseWheel);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Handle mouse button down events
|
|
160
|
+
*/
|
|
161
|
+
private _handleMouseDown(event : MouseEvent) : void
|
|
162
|
+
{
|
|
163
|
+
const buttonKey = `button-${ event.button }`;
|
|
164
|
+
const buttonState : ButtonState = {
|
|
165
|
+
pressed: true,
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
this._buttonState[buttonKey] = buttonState;
|
|
169
|
+
|
|
170
|
+
this._notifyInputChanged({
|
|
171
|
+
type: 'mouse',
|
|
172
|
+
event,
|
|
173
|
+
buttons: { ...this._buttonState },
|
|
174
|
+
axes: { ...this._axesState },
|
|
175
|
+
position: { ...this._position },
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Handle mouse button up events
|
|
181
|
+
*/
|
|
182
|
+
private _handleMouseUp(event : MouseEvent) : void
|
|
183
|
+
{
|
|
184
|
+
const buttonKey = `button-${ event.button }`;
|
|
185
|
+
const buttonState : ButtonState = {
|
|
186
|
+
pressed: false,
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
this._buttonState[buttonKey] = buttonState;
|
|
190
|
+
|
|
191
|
+
this._notifyInputChanged({
|
|
192
|
+
type: 'mouse',
|
|
193
|
+
event,
|
|
194
|
+
buttons: { ...this._buttonState },
|
|
195
|
+
axes: { ...this._axesState },
|
|
196
|
+
position: { ...this._position },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Handle mouse move events
|
|
202
|
+
*/
|
|
203
|
+
private _handleMouseMove(event : MouseEvent) : void
|
|
204
|
+
{
|
|
205
|
+
// Update position
|
|
206
|
+
this._position = {
|
|
207
|
+
absolute: {
|
|
208
|
+
x: event.clientX,
|
|
209
|
+
y: event.clientY,
|
|
210
|
+
},
|
|
211
|
+
relative: {
|
|
212
|
+
x: event.movementX,
|
|
213
|
+
y: event.movementY,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Update axis values
|
|
218
|
+
this._axesState['axis-x'] = event.clientX;
|
|
219
|
+
this._axesState['axis-y'] = event.clientY;
|
|
220
|
+
|
|
221
|
+
this._notifyInputChanged({
|
|
222
|
+
type: 'mouse',
|
|
223
|
+
event,
|
|
224
|
+
buttons: { ...this._buttonState },
|
|
225
|
+
axes: { ...this._axesState },
|
|
226
|
+
position: { ...this._position },
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Handle mouse wheel events
|
|
232
|
+
*/
|
|
233
|
+
private _handleMouseWheel(event : WheelEvent) : void
|
|
234
|
+
{
|
|
235
|
+
// Update wheel state
|
|
236
|
+
this._wheelState = {
|
|
237
|
+
deltaX: event.deltaX,
|
|
238
|
+
deltaY: event.deltaY,
|
|
239
|
+
deltaZ: event.deltaZ,
|
|
240
|
+
deltaMode: event.deltaMode,
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
this._notifyInputChanged({
|
|
244
|
+
type: 'mouse',
|
|
245
|
+
event,
|
|
246
|
+
buttons: { ...this._buttonState },
|
|
247
|
+
axes: { ...this._axesState },
|
|
248
|
+
position: { ...this._position },
|
|
249
|
+
wheel: { ...this._wheelState },
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Notify subscribers of device connected event
|
|
255
|
+
*/
|
|
256
|
+
private _notifyDeviceConnected() : void
|
|
257
|
+
{
|
|
258
|
+
if(this._onDeviceConnected)
|
|
259
|
+
{
|
|
260
|
+
this._onDeviceConnected(this._mouseDevice);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Notify subscribers of input changed event
|
|
266
|
+
*/
|
|
267
|
+
private _notifyInputChanged(state : MouseInputState) : void
|
|
268
|
+
{
|
|
269
|
+
if(this._onInputChanged)
|
|
270
|
+
{
|
|
271
|
+
this._onInputChanged(this._mouseDevice, state);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Gamepad Value Reader
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { DeviceValueReader, GamepadValueReaderDefinition, InputState } from '../../../interfaces/input.ts';
|
|
6
|
+
|
|
7
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Types of gamepad input sources
|
|
11
|
+
*/
|
|
12
|
+
export type GamepadSourceType = 'button' | 'axis';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Options for configuring a gamepad value reader
|
|
16
|
+
*/
|
|
17
|
+
export interface GamepadReaderOptions
|
|
18
|
+
{
|
|
19
|
+
/**
|
|
20
|
+
* Whether to use the analog value instead of boolean pressed state for buttons
|
|
21
|
+
*/
|
|
22
|
+
useAnalogValue ?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Deadzone value (0.0 - 1.0) for analog axes
|
|
26
|
+
* Input values below this threshold will be treated as 0
|
|
27
|
+
*/
|
|
28
|
+
deadzone ?: number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether to invert the axis values
|
|
32
|
+
*/
|
|
33
|
+
invert ?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Reads values from gamepad input states
|
|
40
|
+
*/
|
|
41
|
+
export class GamepadValueReader implements DeviceValueReader
|
|
42
|
+
{
|
|
43
|
+
/**
|
|
44
|
+
* The type of gamepad input
|
|
45
|
+
*/
|
|
46
|
+
readonly sourceType : GamepadSourceType;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The specific key for this input
|
|
50
|
+
*/
|
|
51
|
+
readonly sourceKey : string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Whether to use analog value for buttons
|
|
55
|
+
*/
|
|
56
|
+
private readonly useAnalogValue : boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Deadzone value for axes
|
|
60
|
+
*/
|
|
61
|
+
private readonly deadzone : number;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Whether to invert axis values
|
|
65
|
+
*/
|
|
66
|
+
private readonly invert : boolean;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Creates a new GamepadValueReader
|
|
70
|
+
*
|
|
71
|
+
* @param sourceType - Type of gamepad input to monitor (button or axis)
|
|
72
|
+
* @param sourceKey - The specific key for this input type
|
|
73
|
+
* @param options - Configuration options
|
|
74
|
+
*/
|
|
75
|
+
constructor(sourceType : GamepadSourceType, sourceKey : string, options : GamepadReaderOptions = {})
|
|
76
|
+
{
|
|
77
|
+
this.sourceType = sourceType;
|
|
78
|
+
this.sourceKey = sourceKey;
|
|
79
|
+
this.useAnalogValue = options.useAnalogValue || false;
|
|
80
|
+
this.deadzone = options.deadzone || 0.1; // Default 10% deadzone
|
|
81
|
+
this.invert = options.invert || false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Gets the value of the input source based on the current state
|
|
86
|
+
*
|
|
87
|
+
* @param state - The current input state
|
|
88
|
+
* @returns The value of the input source
|
|
89
|
+
*/
|
|
90
|
+
public getValue(state : InputState) : boolean | number | undefined
|
|
91
|
+
{
|
|
92
|
+
// Check if the state is from the correct device type
|
|
93
|
+
if(state.type !== 'gamepad')
|
|
94
|
+
{
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
switch (this.sourceType)
|
|
99
|
+
{
|
|
100
|
+
case 'button':
|
|
101
|
+
{
|
|
102
|
+
const buttonState = state.buttons[this.sourceKey];
|
|
103
|
+
|
|
104
|
+
if(!buttonState)
|
|
105
|
+
{
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return this.useAnalogValue ? buttonState.value : buttonState.pressed;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
case 'axis':
|
|
113
|
+
{
|
|
114
|
+
let value = state.axes[this.sourceKey];
|
|
115
|
+
|
|
116
|
+
if(value === undefined)
|
|
117
|
+
{
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Apply deadzone
|
|
122
|
+
if(Math.abs(value) < this.deadzone)
|
|
123
|
+
{
|
|
124
|
+
value = 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Apply inversion if needed
|
|
128
|
+
return this.invert ? -value : value;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
default:
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Creates a GamepadValueReader from a string representation
|
|
138
|
+
*
|
|
139
|
+
* @param sourceTypeString - String in format "sourceType:sourceKey" (e.g., "button:0", "axis:1")
|
|
140
|
+
* @param options - Optional configuration options
|
|
141
|
+
* @returns A new GamepadValueReader instance
|
|
142
|
+
*/
|
|
143
|
+
public static fromString(sourceTypeString : string, options : GamepadReaderOptions = {}) : GamepadValueReader
|
|
144
|
+
{
|
|
145
|
+
const [ sourceType, sourceKey ] = sourceTypeString.split(':');
|
|
146
|
+
|
|
147
|
+
if(!sourceType || !sourceKey)
|
|
148
|
+
{
|
|
149
|
+
throw new Error(`Invalid gamepad source format: ${ sourceTypeString }`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return new GamepadValueReader(
|
|
153
|
+
sourceType as GamepadSourceType,
|
|
154
|
+
sourceKey,
|
|
155
|
+
options
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Returns a JSON-serializable representation of this gamepad value reader
|
|
161
|
+
*
|
|
162
|
+
* @returns A simple object representation that can be converted to JSON
|
|
163
|
+
*/
|
|
164
|
+
public toJSON() : GamepadValueReaderDefinition
|
|
165
|
+
{
|
|
166
|
+
return {
|
|
167
|
+
type: 'gamepad',
|
|
168
|
+
sourceType: this.sourceType,
|
|
169
|
+
sourceKey: this.sourceKey,
|
|
170
|
+
options: {
|
|
171
|
+
useAnalogValue: this.useAnalogValue,
|
|
172
|
+
deadzone: this.deadzone,
|
|
173
|
+
invert: this.invert,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Keyboard Value Reader
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
DeviceValueReader,
|
|
7
|
+
InputState,
|
|
8
|
+
KeyboardInputState,
|
|
9
|
+
KeyboardValueReaderDefinition,
|
|
10
|
+
} from '../../../interfaces/input.ts';
|
|
11
|
+
|
|
12
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Types of keyboard input sources
|
|
16
|
+
*/
|
|
17
|
+
export type KeyboardSourceType = 'key';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Options for configuring a keyboard value reader
|
|
21
|
+
*/
|
|
22
|
+
export interface KeyboardReaderOptions
|
|
23
|
+
{
|
|
24
|
+
/**
|
|
25
|
+
* Whether to use delta state instead of current state
|
|
26
|
+
* When true, the source will only return true on the initial key press
|
|
27
|
+
*/
|
|
28
|
+
useDelta ?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Reads values from keyboard input states
|
|
35
|
+
*/
|
|
36
|
+
export class KeyboardValueReader implements DeviceValueReader
|
|
37
|
+
{
|
|
38
|
+
/**
|
|
39
|
+
* The type of keyboard input (always 'key')
|
|
40
|
+
*/
|
|
41
|
+
public readonly sourceType : KeyboardSourceType = 'key';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The key code to monitor (e.g., "KeyA", "Space")
|
|
45
|
+
*/
|
|
46
|
+
public readonly sourceKey : string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Whether to use delta state instead of current state
|
|
50
|
+
*/
|
|
51
|
+
private readonly useDelta : boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Creates a new KeyboardValueReader
|
|
55
|
+
*
|
|
56
|
+
* @param keyCode - The key code to monitor (e.g., "KeyA", "Space")
|
|
57
|
+
* @param options - Configuration options
|
|
58
|
+
*/
|
|
59
|
+
constructor(keyCode : string, options : KeyboardReaderOptions = {})
|
|
60
|
+
{
|
|
61
|
+
this.sourceKey = keyCode;
|
|
62
|
+
this.useDelta = options.useDelta || false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Gets the value of the key state
|
|
67
|
+
*
|
|
68
|
+
* @param state - The input state
|
|
69
|
+
* @returns The key state value or undefined if the state type is not keyboard
|
|
70
|
+
*/
|
|
71
|
+
public getValue(state : InputState) : boolean | undefined
|
|
72
|
+
{
|
|
73
|
+
// Check if the state is from the correct device type
|
|
74
|
+
if(state.type !== 'keyboard')
|
|
75
|
+
{
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const keyboardState = state as KeyboardInputState;
|
|
80
|
+
|
|
81
|
+
// Get value from either the current state or delta state based on configuration
|
|
82
|
+
if(this.useDelta)
|
|
83
|
+
{
|
|
84
|
+
return keyboardState.delta[this.sourceKey];
|
|
85
|
+
}
|
|
86
|
+
else
|
|
87
|
+
{
|
|
88
|
+
return keyboardState.keys[this.sourceKey];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Creates a KeyboardValueReader from a string representation
|
|
94
|
+
*
|
|
95
|
+
* @param sourceKey - The key code (e.g., "KeyA", "Space")
|
|
96
|
+
* @param options - Optional configuration
|
|
97
|
+
* @returns A new KeyboardValueReader instance
|
|
98
|
+
*/
|
|
99
|
+
public static fromString(sourceKey : string, options : KeyboardReaderOptions = {}) : KeyboardValueReader
|
|
100
|
+
{
|
|
101
|
+
return new KeyboardValueReader(sourceKey, options);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Returns a JSON-serializable representation of this keyboard value reader
|
|
106
|
+
*
|
|
107
|
+
* @returns A simple object representation that can be converted to JSON
|
|
108
|
+
*/
|
|
109
|
+
public toJSON() : KeyboardValueReaderDefinition
|
|
110
|
+
{
|
|
111
|
+
return {
|
|
112
|
+
|
|
113
|
+
type: 'keyboard',
|
|
114
|
+
sourceType: this.sourceType,
|
|
115
|
+
sourceKey: this.sourceKey,
|
|
116
|
+
options: {
|
|
117
|
+
useDelta: this.useDelta,
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Mouse Value Reader
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { DeviceValueReader, InputState, MouseValueReaderDefinition } from '../../../interfaces/input.ts';
|
|
6
|
+
|
|
7
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Types of mouse input sources
|
|
11
|
+
*/
|
|
12
|
+
export type MouseSourceType = 'button' | 'position' | 'wheel';
|
|
13
|
+
|
|
14
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Reads values from mouse input states
|
|
18
|
+
*/
|
|
19
|
+
export class MouseValueReader implements DeviceValueReader
|
|
20
|
+
{
|
|
21
|
+
/**
|
|
22
|
+
* The type of mouse input
|
|
23
|
+
*/
|
|
24
|
+
readonly sourceType : MouseSourceType;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The specific key for this input
|
|
28
|
+
*/
|
|
29
|
+
readonly sourceKey : string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new MouseValueReader
|
|
33
|
+
*
|
|
34
|
+
* @param sourceType - Type of mouse input to monitor (button, position, wheel)
|
|
35
|
+
* @param sourceKey - The specific key for this input type
|
|
36
|
+
*/
|
|
37
|
+
constructor(sourceType : MouseSourceType, sourceKey : string)
|
|
38
|
+
{
|
|
39
|
+
this.sourceType = sourceType;
|
|
40
|
+
this.sourceKey = sourceKey;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Gets the value of the mouse input source
|
|
45
|
+
*
|
|
46
|
+
* @param state - The current input state
|
|
47
|
+
* @returns The value of the input source
|
|
48
|
+
*/
|
|
49
|
+
public getValue(state : InputState) : boolean | number | undefined
|
|
50
|
+
{
|
|
51
|
+
// Check if the state is from the correct device type
|
|
52
|
+
if(state.type !== 'mouse')
|
|
53
|
+
{
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
switch (this.sourceType)
|
|
58
|
+
{
|
|
59
|
+
case 'button':
|
|
60
|
+
{
|
|
61
|
+
const buttonState = state.buttons[this.sourceKey];
|
|
62
|
+
return buttonState ? buttonState.pressed : undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
case 'position':
|
|
66
|
+
{
|
|
67
|
+
// Position keys are in format "positionType:axis" (e.g., "absolute:x")
|
|
68
|
+
const [ posType, axis ] = this.sourceKey.split(':');
|
|
69
|
+
|
|
70
|
+
if(!posType || !axis || (posType !== 'absolute' && posType !== 'relative')
|
|
71
|
+
|| (axis !== 'x' && axis !== 'y'))
|
|
72
|
+
{
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return state.position[posType][axis];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
case 'wheel':
|
|
80
|
+
{
|
|
81
|
+
const isValidWheelKey = this.sourceKey === 'deltaX' || this.sourceKey === 'deltaY'
|
|
82
|
+
|| this.sourceKey === 'deltaZ';
|
|
83
|
+
if(state.wheel && isValidWheelKey)
|
|
84
|
+
{
|
|
85
|
+
return state.wheel[this.sourceKey];
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
default:
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates a MouseValueReader from a string representation
|
|
97
|
+
*
|
|
98
|
+
* @param sourceTypeString - String in format "sourceType:sourceKey" (e.g., "button:0", "position:absolute:x")
|
|
99
|
+
* @returns A new MouseValueReader instance
|
|
100
|
+
*/
|
|
101
|
+
public static fromString(sourceTypeString : string) : MouseValueReader
|
|
102
|
+
{
|
|
103
|
+
const [ sourceType, ...keyParts ] = sourceTypeString.split(':');
|
|
104
|
+
const sourceKey = keyParts.join(':');
|
|
105
|
+
|
|
106
|
+
if(!sourceType || !sourceKey)
|
|
107
|
+
{
|
|
108
|
+
throw new Error(`Invalid mouse source format: ${ sourceTypeString }`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return new MouseValueReader(
|
|
112
|
+
sourceType as MouseSourceType,
|
|
113
|
+
sourceKey
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Returns a JSON-serializable representation of this mouse value reader
|
|
119
|
+
*
|
|
120
|
+
* @returns A simple object representation that can be converted to JSON
|
|
121
|
+
*/
|
|
122
|
+
public toJSON() : MouseValueReaderDefinition
|
|
123
|
+
{
|
|
124
|
+
// Always return consistent 'mouse' type with sourceType and sourceKey
|
|
125
|
+
return {
|
|
126
|
+
type: 'mouse',
|
|
127
|
+
sourceType: this.sourceType,
|
|
128
|
+
sourceKey: this.sourceKey,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
//----------------------------------------------------------------------------------------------------------------------
|