@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.0.5
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/.cspell.json +48 -0
- package/.eslintignore +8 -0
- package/.eslintrc.js +8 -0
- package/.prettierignore +0 -0
- package/.prettierrc.json +6 -0
- package/dist/lib-pixelstreamingfrontend.esm.js +1 -0
- package/dist/lib-pixelstreamingfrontend.js +1 -0
- package/jest.config.js +18 -0
- package/package.json +48 -0
- package/readme.md +15 -0
- package/src/AFK/AFKController.test.ts +162 -0
- package/src/AFK/AFKController.ts +158 -0
- package/src/Config/Config.test.ts +222 -0
- package/src/Config/Config.ts +970 -0
- package/src/Config/SettingBase.ts +65 -0
- package/src/Config/SettingFlag.ts +99 -0
- package/src/Config/SettingNumber.ts +111 -0
- package/src/Config/SettingOption.ts +124 -0
- package/src/Config/SettingText.ts +82 -0
- package/src/DataChannel/DataChannelController.ts +138 -0
- package/src/DataChannel/DataChannelLatencyTestController.ts +129 -0
- package/src/DataChannel/DataChannelLatencyTestResults.ts +67 -0
- package/src/DataChannel/DataChannelSender.ts +59 -0
- package/src/DataChannel/InitialSettings.ts +61 -0
- package/src/DataChannel/LatencyTestResults.ts +76 -0
- package/src/FreezeFrame/FreezeFrame.ts +114 -0
- package/src/FreezeFrame/FreezeFrameController.ts +114 -0
- package/src/Inputs/FakeTouchController.ts +199 -0
- package/src/Inputs/GamepadController.ts +314 -0
- package/src/Inputs/GamepadTypes.ts +10 -0
- package/src/Inputs/HoveringMouseEvents.ts +192 -0
- package/src/Inputs/IMouseEvents.ts +64 -0
- package/src/Inputs/ITouchController.ts +29 -0
- package/src/Inputs/InputClassesFactory.ts +140 -0
- package/src/Inputs/KeyboardController.ts +354 -0
- package/src/Inputs/LockedMouseEvents.ts +287 -0
- package/src/Inputs/MouseButtons.ts +25 -0
- package/src/Inputs/MouseController.ts +362 -0
- package/src/Inputs/SpecialKeyCodes.ts +16 -0
- package/src/Inputs/TouchController.ts +208 -0
- package/src/Inputs/XRGamepadController.ts +126 -0
- package/src/PeerConnectionController/AggregatedStats.ts +311 -0
- package/src/PeerConnectionController/CandidatePairStats.ts +17 -0
- package/src/PeerConnectionController/CandidateStat.ts +13 -0
- package/src/PeerConnectionController/CodecStats.ts +19 -0
- package/src/PeerConnectionController/DataChannelStats.ts +17 -0
- package/src/PeerConnectionController/InboundRTPStats.ts +154 -0
- package/src/PeerConnectionController/InboundTrackStats.ts +34 -0
- package/src/PeerConnectionController/OutBoundRTPStats.ts +26 -0
- package/src/PeerConnectionController/PeerConnectionController.ts +563 -0
- package/src/PeerConnectionController/SessionStats.ts +10 -0
- package/src/PeerConnectionController/StreamStats.ts +11 -0
- package/src/PixelStreaming/PixelStreaming.test.ts +626 -0
- package/src/PixelStreaming/PixelStreaming.ts +851 -0
- package/src/UI/OnScreenKeyboard.ts +97 -0
- package/src/UeInstanceMessage/ResponseController.ts +47 -0
- package/src/UeInstanceMessage/SendMessageController.ts +154 -0
- package/src/UeInstanceMessage/StreamMessageController.ts +233 -0
- package/src/UeInstanceMessage/ToStreamerMessagesController.ts +62 -0
- package/src/Util/CoordinateConverter.ts +289 -0
- package/src/Util/EventEmitter.ts +611 -0
- package/src/Util/EventListenerTracker.ts +29 -0
- package/src/Util/FileUtil.ts +140 -0
- package/src/Util/RTCUtils.ts +41 -0
- package/src/Util/WebGLUtils.ts +49 -0
- package/src/Util/WebXRUtils.ts +25 -0
- package/src/VideoPlayer/StreamController.ts +89 -0
- package/src/VideoPlayer/VideoPlayer.ts +246 -0
- package/src/WebRtcPlayer/WebRtcPlayerController.ts +2158 -0
- package/src/WebXR/WebXRController.ts +319 -0
- package/src/__test__/mockMediaStream.ts +124 -0
- package/src/__test__/mockRTCPeerConnection.ts +347 -0
- package/src/__test__/mockRTCRtpReceiver.ts +22 -0
- package/src/__test__/mockWebSocket.ts +136 -0
- package/src/pixelstreamingfrontend.ts +46 -0
- package/tsconfig.jest.json +8 -0
- package/tsconfig.json +24 -0
- package/types/AFK/AFKController.d.ts +39 -0
- package/types/Config/Config.d.ts +218 -0
- package/types/Config/SettingBase.d.ts +30 -0
- package/types/Config/SettingFlag.d.ts +33 -0
- package/types/Config/SettingNumber.d.ts +45 -0
- package/types/Config/SettingOption.d.ts +43 -0
- package/types/Config/SettingText.d.ts +29 -0
- package/types/DataChannel/DataChannelController.d.ts +59 -0
- package/types/DataChannel/DataChannelLatencyTestController.d.ts +26 -0
- package/types/DataChannel/DataChannelLatencyTestResults.d.ts +46 -0
- package/types/DataChannel/DataChannelSender.d.ts +21 -0
- package/types/DataChannel/InitialSettings.d.ts +44 -0
- package/types/DataChannel/LatencyTestResults.d.ts +31 -0
- package/types/FreezeFrame/FreezeFrame.d.ts +36 -0
- package/types/FreezeFrame/FreezeFrameController.d.ts +37 -0
- package/types/Inputs/FakeTouchController.d.ts +61 -0
- package/types/Inputs/GamepadController.d.ts +85 -0
- package/types/Inputs/GamepadTypes.d.ts +8 -0
- package/types/Inputs/HoveringMouseEvents.d.ts +56 -0
- package/types/Inputs/IMouseEvents.d.ts +53 -0
- package/types/Inputs/ITouchController.d.ts +24 -0
- package/types/Inputs/InputClassesFactory.d.ts +54 -0
- package/types/Inputs/KeyboardController.d.ts +62 -0
- package/types/Inputs/LockedMouseEvents.d.ts +80 -0
- package/types/Inputs/MouseButtons.d.ts +22 -0
- package/types/Inputs/MouseController.d.ts +75 -0
- package/types/Inputs/SpecialKeyCodes.d.ts +14 -0
- package/types/Inputs/TouchController.d.ts +53 -0
- package/types/Inputs/XRGamepadController.d.ts +15 -0
- package/types/PeerConnectionController/AggregatedStats.d.ts +77 -0
- package/types/PeerConnectionController/CandidatePairStats.d.ts +15 -0
- package/types/PeerConnectionController/CandidateStat.d.ts +11 -0
- package/types/PeerConnectionController/CodecStats.d.ts +14 -0
- package/types/PeerConnectionController/DataChannelStats.d.ts +15 -0
- package/types/PeerConnectionController/InboundRTPStats.d.ts +141 -0
- package/types/PeerConnectionController/InboundTrackStats.d.ts +32 -0
- package/types/PeerConnectionController/OutBoundRTPStats.d.ts +23 -0
- package/types/PeerConnectionController/PeerConnectionController.d.ts +132 -0
- package/types/PeerConnectionController/SessionStats.d.ts +8 -0
- package/types/PeerConnectionController/StreamStats.d.ts +9 -0
- package/types/PixelStreaming/PixelStreaming.d.ts +259 -0
- package/types/UI/OnScreenKeyboard.d.ts +31 -0
- package/types/UeInstanceMessage/ResponseController.d.ts +19 -0
- package/types/UeInstanceMessage/SendMessageController.d.ts +18 -0
- package/types/UeInstanceMessage/StreamMessageController.d.ts +29 -0
- package/types/UeInstanceMessage/ToStreamerMessagesController.d.ts +32 -0
- package/types/Util/CoordinateConverter.d.ts +100 -0
- package/types/Util/EventEmitter.d.ts +422 -0
- package/types/Util/EventListenerTracker.d.ts +14 -0
- package/types/Util/FileUtil.d.ts +32 -0
- package/types/Util/RTCUtils.d.ts +8 -0
- package/types/Util/WebGLUtils.d.ts +4 -0
- package/types/Util/WebXRUtils.d.ts +9 -0
- package/types/VideoPlayer/StreamController.d.ts +24 -0
- package/types/VideoPlayer/VideoPlayer.d.ts +78 -0
- package/types/WebRtcPlayer/WebRtcPlayerController.d.ts +377 -0
- package/types/WebXR/WebXRController.d.ts +26 -0
- package/types/pixelstreamingfrontend.d.ts +22 -0
- package/webpack.common.js +35 -0
- package/webpack.dev.js +35 -0
- package/webpack.prod.js +36 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import { SpecialKeyCodes } from './SpecialKeyCodes';
|
|
4
|
+
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
5
|
+
import { ActiveKeys } from './InputClassesFactory';
|
|
6
|
+
import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController';
|
|
7
|
+
import { Config, Flags } from '../Config/Config';
|
|
8
|
+
import { EventListenerTracker } from '../Util/EventListenerTracker';
|
|
9
|
+
|
|
10
|
+
interface ICodeToKeyCode {
|
|
11
|
+
[key: string]: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handles the Keyboard Inputs for the document
|
|
16
|
+
*/
|
|
17
|
+
export class KeyboardController {
|
|
18
|
+
toStreamerMessagesProvider: StreamMessageController;
|
|
19
|
+
activeKeysProvider: ActiveKeys;
|
|
20
|
+
config: Config;
|
|
21
|
+
|
|
22
|
+
// Utility for keeping track of event handlers and unregistering them
|
|
23
|
+
private keyboardEventListenerTracker = new EventListenerTracker();
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* New browser APIs have moved away from KeyboardEvent.keyCode to KeyboardEvent.Code.
|
|
27
|
+
* For details see: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#constants_for_keycode_value
|
|
28
|
+
* We still use old KeyboardEvent.keyCode integers in the UE C++ side, so we need a way to map the new
|
|
29
|
+
* string-based KeyboardEvent.Code to the old integers.
|
|
30
|
+
*/
|
|
31
|
+
CodeToKeyCode: ICodeToKeyCode = {
|
|
32
|
+
Escape: 27,
|
|
33
|
+
Digit0: 48,
|
|
34
|
+
Digit1: 49,
|
|
35
|
+
Digit2: 50,
|
|
36
|
+
Digit3: 51,
|
|
37
|
+
Digit4: 52,
|
|
38
|
+
Digit5: 53,
|
|
39
|
+
Digit6: 54,
|
|
40
|
+
Digit7: 55,
|
|
41
|
+
Digit8: 56,
|
|
42
|
+
Digit9: 57,
|
|
43
|
+
Minus: 173,
|
|
44
|
+
Equal: 187,
|
|
45
|
+
Backspace: 8,
|
|
46
|
+
Tab: 9,
|
|
47
|
+
KeyQ: 81,
|
|
48
|
+
KeyW: 87,
|
|
49
|
+
KeyE: 69,
|
|
50
|
+
KeyR: 82,
|
|
51
|
+
KeyT: 84,
|
|
52
|
+
KeyY: 89,
|
|
53
|
+
KeyU: 85,
|
|
54
|
+
KeyI: 73,
|
|
55
|
+
KeyO: 79,
|
|
56
|
+
KeyP: 80,
|
|
57
|
+
BracketLeft: 219,
|
|
58
|
+
BracketRight: 221,
|
|
59
|
+
Enter: 13,
|
|
60
|
+
ControlLeft: 17,
|
|
61
|
+
KeyA: 65,
|
|
62
|
+
KeyS: 83,
|
|
63
|
+
KeyD: 68,
|
|
64
|
+
KeyF: 70,
|
|
65
|
+
KeyG: 71,
|
|
66
|
+
KeyH: 72,
|
|
67
|
+
KeyJ: 74,
|
|
68
|
+
KeyK: 75,
|
|
69
|
+
KeyL: 76,
|
|
70
|
+
Semicolon: 186,
|
|
71
|
+
Quote: 222,
|
|
72
|
+
Backquote: 192,
|
|
73
|
+
ShiftLeft: 16,
|
|
74
|
+
Backslash: 220,
|
|
75
|
+
KeyZ: 90,
|
|
76
|
+
KeyX: 88,
|
|
77
|
+
KeyC: 67,
|
|
78
|
+
KeyV: 86,
|
|
79
|
+
KeyB: 66,
|
|
80
|
+
KeyN: 78,
|
|
81
|
+
KeyM: 77,
|
|
82
|
+
Comma: 188,
|
|
83
|
+
Period: 190,
|
|
84
|
+
Slash: 191,
|
|
85
|
+
ShiftRight: 253,
|
|
86
|
+
AltLeft: 18,
|
|
87
|
+
Space: 32,
|
|
88
|
+
CapsLock: 20,
|
|
89
|
+
F1: 112,
|
|
90
|
+
F2: 113,
|
|
91
|
+
F3: 114,
|
|
92
|
+
F4: 115,
|
|
93
|
+
F5: 116,
|
|
94
|
+
F6: 117,
|
|
95
|
+
F7: 118,
|
|
96
|
+
F8: 119,
|
|
97
|
+
F9: 120,
|
|
98
|
+
F10: 121,
|
|
99
|
+
F11: 122,
|
|
100
|
+
F12: 123,
|
|
101
|
+
Pause: 19,
|
|
102
|
+
ScrollLock: 145,
|
|
103
|
+
NumpadDivide: 111,
|
|
104
|
+
NumpadMultiply: 106,
|
|
105
|
+
NumpadSubtract: 109,
|
|
106
|
+
NumpadAdd: 107,
|
|
107
|
+
NumpadDecimal: 110,
|
|
108
|
+
Numpad9: 105,
|
|
109
|
+
Numpad8: 104,
|
|
110
|
+
Numpad7: 103,
|
|
111
|
+
Numpad6: 102,
|
|
112
|
+
Numpad5: 101,
|
|
113
|
+
Numpad4: 100,
|
|
114
|
+
Numpad3: 99,
|
|
115
|
+
Numpad2: 98,
|
|
116
|
+
Numpad1: 97,
|
|
117
|
+
Numpad0: 96,
|
|
118
|
+
NumLock: 144,
|
|
119
|
+
ControlRight: 254,
|
|
120
|
+
AltRight: 255,
|
|
121
|
+
Home: 36,
|
|
122
|
+
End: 35,
|
|
123
|
+
ArrowUp: 38,
|
|
124
|
+
ArrowLeft: 37,
|
|
125
|
+
ArrowRight: 39,
|
|
126
|
+
ArrowDown: 40,
|
|
127
|
+
PageUp: 33,
|
|
128
|
+
PageDown: 34,
|
|
129
|
+
Insert: 45,
|
|
130
|
+
Delete: 46,
|
|
131
|
+
ContextMenu: 93
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param toStreamerMessagesProvider Stream message provider class object
|
|
136
|
+
* @param config The applications configuration. We're interested in the suppress browser keys option
|
|
137
|
+
* @param activeKeysProvider Active keys provider class object
|
|
138
|
+
*/
|
|
139
|
+
constructor(
|
|
140
|
+
toStreamerMessagesProvider: StreamMessageController,
|
|
141
|
+
config: Config,
|
|
142
|
+
activeKeysProvider: ActiveKeys
|
|
143
|
+
) {
|
|
144
|
+
this.toStreamerMessagesProvider = toStreamerMessagesProvider;
|
|
145
|
+
this.config = config;
|
|
146
|
+
this.activeKeysProvider = activeKeysProvider;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Registers document keyboard events with the controller
|
|
151
|
+
*/
|
|
152
|
+
registerKeyBoardEvents() {
|
|
153
|
+
const compositionEndHandler = (ev: CompositionEvent) => this.handleOnCompositionEnd(ev);
|
|
154
|
+
const keyDownHandler = (ev: KeyboardEvent) => this.handleOnKeyDown(ev);
|
|
155
|
+
const keyUpHandler = (ev: KeyboardEvent) => this.handleOnKeyUp(ev);
|
|
156
|
+
const keyPressHandler = (ev: KeyboardEvent) => this.handleOnKeyPress(ev);
|
|
157
|
+
|
|
158
|
+
document.addEventListener("compositionend", compositionEndHandler);
|
|
159
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
160
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
161
|
+
|
|
162
|
+
//This has been deprecated as at Jun 13 2021
|
|
163
|
+
document.addEventListener("keypress", keyPressHandler);
|
|
164
|
+
|
|
165
|
+
this.keyboardEventListenerTracker.addUnregisterCallback(
|
|
166
|
+
() => document.removeEventListener("compositionend", compositionEndHandler)
|
|
167
|
+
);
|
|
168
|
+
this.keyboardEventListenerTracker.addUnregisterCallback(
|
|
169
|
+
() => document.removeEventListener("keydown", keyDownHandler)
|
|
170
|
+
);
|
|
171
|
+
this.keyboardEventListenerTracker.addUnregisterCallback(
|
|
172
|
+
() => document.removeEventListener("keyup", keyUpHandler)
|
|
173
|
+
);
|
|
174
|
+
this.keyboardEventListenerTracker.addUnregisterCallback(
|
|
175
|
+
() => document.removeEventListener("keypress", keyPressHandler)
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Unregisters document keyboard events
|
|
181
|
+
*/
|
|
182
|
+
unregisterKeyBoardEvents() {
|
|
183
|
+
this.keyboardEventListenerTracker.unregisterAll();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Handles When a key is down
|
|
188
|
+
* @param keyboardEvent - Keyboard event
|
|
189
|
+
*/
|
|
190
|
+
handleOnKeyDown(keyboardEvent: KeyboardEvent) {
|
|
191
|
+
const keyCode = this.getKeycode(keyboardEvent);
|
|
192
|
+
if (!keyCode || keyCode === 229) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
Logger.Log(
|
|
197
|
+
Logger.GetStackTrace(),
|
|
198
|
+
`key down ${keyCode}, repeat = ${keyboardEvent.repeat}`,
|
|
199
|
+
6
|
|
200
|
+
);
|
|
201
|
+
const toStreamerHandlers =
|
|
202
|
+
this.toStreamerMessagesProvider.toStreamerHandlers;
|
|
203
|
+
toStreamerHandlers.get('KeyDown')([
|
|
204
|
+
this.getKeycode(keyboardEvent),
|
|
205
|
+
keyboardEvent.repeat ? 1 : 0
|
|
206
|
+
]);
|
|
207
|
+
const activeKeys = this.activeKeysProvider.getActiveKeys();
|
|
208
|
+
activeKeys.push(keyCode);
|
|
209
|
+
// Backspace is not considered a keypress in JavaScript but we need it
|
|
210
|
+
// to be so characters may be deleted in a UE text entry field.
|
|
211
|
+
if (keyCode === SpecialKeyCodes.backSpace) {
|
|
212
|
+
document.dispatchEvent(
|
|
213
|
+
new KeyboardEvent('keypress', {
|
|
214
|
+
charCode: SpecialKeyCodes.backSpace
|
|
215
|
+
})
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (
|
|
220
|
+
this.config.isFlagEnabled(Flags.SuppressBrowserKeys) &&
|
|
221
|
+
this.isKeyCodeBrowserKey(keyCode)
|
|
222
|
+
) {
|
|
223
|
+
keyboardEvent.preventDefault();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* handles when a key is up
|
|
229
|
+
* @param keyboardEvent - Keyboard event
|
|
230
|
+
*/
|
|
231
|
+
handleOnKeyUp(keyboardEvent: KeyboardEvent) {
|
|
232
|
+
const keyCode = this.getKeycode(keyboardEvent);
|
|
233
|
+
if (!keyCode) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
Logger.Log(Logger.GetStackTrace(), `key up ${keyCode}`, 6);
|
|
238
|
+
const toStreamerHandlers =
|
|
239
|
+
this.toStreamerMessagesProvider.toStreamerHandlers;
|
|
240
|
+
toStreamerHandlers.get('KeyUp')([ keyCode ]);
|
|
241
|
+
|
|
242
|
+
if (
|
|
243
|
+
this.config.isFlagEnabled(Flags.SuppressBrowserKeys) &&
|
|
244
|
+
this.isKeyCodeBrowserKey(keyCode)
|
|
245
|
+
) {
|
|
246
|
+
keyboardEvent.preventDefault();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Handles when a key is press
|
|
252
|
+
* @param keyboard - Keyboard Event
|
|
253
|
+
*/
|
|
254
|
+
handleOnKeyPress(keyboard: KeyboardEvent) {
|
|
255
|
+
if (!('charCode' in keyboard)) {
|
|
256
|
+
Logger.Warning(
|
|
257
|
+
Logger.GetStackTrace(),
|
|
258
|
+
'KeyboardEvent.charCode is deprecated in this browser, cannot send key press.'
|
|
259
|
+
);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const charCode = keyboard.charCode;
|
|
264
|
+
Logger.Log(Logger.GetStackTrace(), `key press ${charCode}`, 6);
|
|
265
|
+
|
|
266
|
+
const toStreamerHandlers =
|
|
267
|
+
this.toStreamerMessagesProvider.toStreamerHandlers;
|
|
268
|
+
toStreamerHandlers.get('KeyPress')([charCode]);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Handle whenever composition ends (eg chinese simplified)
|
|
273
|
+
* @param compositionEvent - the composition event
|
|
274
|
+
*/
|
|
275
|
+
handleOnCompositionEnd(compositionEvent: CompositionEvent) {
|
|
276
|
+
if (compositionEvent.data && compositionEvent.data.length) {
|
|
277
|
+
compositionEvent.data.split('').forEach((char) => {
|
|
278
|
+
// This keydown, keypress, keyup flow is required to mimic the way characters are
|
|
279
|
+
// normally triggered
|
|
280
|
+
this.handleOnKeyDown(
|
|
281
|
+
new KeyboardEvent('keydown', {
|
|
282
|
+
keyCode: char.toUpperCase().charCodeAt(0),
|
|
283
|
+
charCode: char.charCodeAt(0)
|
|
284
|
+
})
|
|
285
|
+
);
|
|
286
|
+
this.handleOnKeyPress(
|
|
287
|
+
new KeyboardEvent('keypress', {
|
|
288
|
+
keyCode: char.toUpperCase().charCodeAt(0),
|
|
289
|
+
charCode: char.charCodeAt(0)
|
|
290
|
+
})
|
|
291
|
+
);
|
|
292
|
+
this.handleOnKeyUp(
|
|
293
|
+
new KeyboardEvent('keyup', {
|
|
294
|
+
keyCode: char.toUpperCase().charCodeAt(0),
|
|
295
|
+
charCode: char.charCodeAt(0)
|
|
296
|
+
})
|
|
297
|
+
);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Gets the Keycode of the Key pressed
|
|
304
|
+
* @param keyboardEvent - Key board Event
|
|
305
|
+
* @returns - the key code of the Key
|
|
306
|
+
*/
|
|
307
|
+
getKeycode(keyboardEvent: KeyboardEvent) {
|
|
308
|
+
// If we don't have keyCode property because browser API is deprecated then use KeyboardEvent.code instead.
|
|
309
|
+
// See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#constants_for_keycode_value
|
|
310
|
+
if (!('keyCode' in keyboardEvent)) {
|
|
311
|
+
// Convert KeyboardEvent.code string into integer-based key code for backwards compatibility reasons.
|
|
312
|
+
const event = keyboardEvent as KeyboardEvent;
|
|
313
|
+
if (event.code in this.CodeToKeyCode) {
|
|
314
|
+
return this.CodeToKeyCode[event.code];
|
|
315
|
+
} else {
|
|
316
|
+
Logger.Warning(
|
|
317
|
+
Logger.GetStackTrace(),
|
|
318
|
+
`Keyboard code of ${event.code} is not supported in our mapping, ignoring this key.`
|
|
319
|
+
);
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// If we made it here KeyboardEvent.keyCode is still supported so we can safely use it.
|
|
325
|
+
|
|
326
|
+
if (
|
|
327
|
+
keyboardEvent.keyCode === SpecialKeyCodes.shift &&
|
|
328
|
+
keyboardEvent.code === 'ShiftRight'
|
|
329
|
+
) {
|
|
330
|
+
return SpecialKeyCodes.rightShift;
|
|
331
|
+
} else if (
|
|
332
|
+
keyboardEvent.keyCode === SpecialKeyCodes.control &&
|
|
333
|
+
keyboardEvent.code === 'ControlRight'
|
|
334
|
+
) {
|
|
335
|
+
return SpecialKeyCodes.rightControl;
|
|
336
|
+
} else if (
|
|
337
|
+
keyboardEvent.keyCode === SpecialKeyCodes.alt &&
|
|
338
|
+
keyboardEvent.code === 'AltRight'
|
|
339
|
+
) {
|
|
340
|
+
return SpecialKeyCodes.rightAlt;
|
|
341
|
+
} else {
|
|
342
|
+
return keyboardEvent.keyCode;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Browser keys do not have a charCode so we only need to test keyCode.
|
|
348
|
+
* @param keyCode - the browser keycode number
|
|
349
|
+
*/
|
|
350
|
+
isKeyCodeBrowserKey(keyCode: number) {
|
|
351
|
+
// Function keys or tab key are considered "browser keys" that we may wish to suppress by preventing them being process by browser.
|
|
352
|
+
return (keyCode >= 112 && keyCode <= 123) || keyCode === 9;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
import { MouseController } from './MouseController';
|
|
4
|
+
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
5
|
+
import { IMouseEvents } from './IMouseEvents';
|
|
6
|
+
import { NormalizedQuantizedUnsignedCoord } from '../Util/CoordinateConverter';
|
|
7
|
+
import { ActiveKeys } from './InputClassesFactory';
|
|
8
|
+
import { VideoPlayer } from '../VideoPlayer/VideoPlayer';
|
|
9
|
+
import { EventListenerTracker } from '../Util/EventListenerTracker';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Handle the mouse locked events
|
|
13
|
+
*/
|
|
14
|
+
export class LockedMouseEvents implements IMouseEvents {
|
|
15
|
+
x = 0;
|
|
16
|
+
y = 0;
|
|
17
|
+
coord: NormalizedQuantizedUnsignedCoord;
|
|
18
|
+
videoElementProvider: VideoPlayer;
|
|
19
|
+
mouseController: MouseController;
|
|
20
|
+
activeKeysProvider: ActiveKeys;
|
|
21
|
+
updateMouseMovePositionEvent = (mouseEvent: MouseEvent) => {
|
|
22
|
+
this.updateMouseMovePosition(mouseEvent);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Utility for keeping track of event handlers and unregistering them
|
|
26
|
+
private mouseEventListenerTracker = new EventListenerTracker();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param videoElementProvider - Video Player instance
|
|
30
|
+
* @param mouseController - Mouse controller instance
|
|
31
|
+
* @param activeKeysProvider - Active keys provider instance
|
|
32
|
+
* @param playerStyleAttributesProvider - Player style attributes instance
|
|
33
|
+
*/
|
|
34
|
+
constructor(
|
|
35
|
+
videoElementProvider: VideoPlayer,
|
|
36
|
+
mouseController: MouseController,
|
|
37
|
+
activeKeysProvider: ActiveKeys
|
|
38
|
+
) {
|
|
39
|
+
this.videoElementProvider = videoElementProvider;
|
|
40
|
+
this.mouseController = mouseController;
|
|
41
|
+
this.activeKeysProvider = activeKeysProvider;
|
|
42
|
+
const videoElementParent =
|
|
43
|
+
this.videoElementProvider.getVideoParentElement();
|
|
44
|
+
this.x = videoElementParent.getBoundingClientRect().width / 2;
|
|
45
|
+
this.y = videoElementParent.getBoundingClientRect().height / 2;
|
|
46
|
+
this.coord =
|
|
47
|
+
this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(
|
|
48
|
+
this.x,
|
|
49
|
+
this.y
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Unregisters all event handlers
|
|
55
|
+
*/
|
|
56
|
+
unregisterMouseEvents() {
|
|
57
|
+
this.mouseEventListenerTracker.unregisterAll();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Handle when the locked state Changed
|
|
62
|
+
*/
|
|
63
|
+
lockStateChange() {
|
|
64
|
+
const videoElementParent =
|
|
65
|
+
this.videoElementProvider.getVideoParentElement();
|
|
66
|
+
const toStreamerHandlers =
|
|
67
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
68
|
+
|
|
69
|
+
if (
|
|
70
|
+
document.pointerLockElement === videoElementParent ||
|
|
71
|
+
document.mozPointerLockElement === videoElementParent
|
|
72
|
+
) {
|
|
73
|
+
Logger.Log(Logger.GetStackTrace(), 'Pointer locked', 6);
|
|
74
|
+
document.addEventListener(
|
|
75
|
+
'mousemove',
|
|
76
|
+
this.updateMouseMovePositionEvent,
|
|
77
|
+
false
|
|
78
|
+
);
|
|
79
|
+
this.mouseEventListenerTracker.addUnregisterCallback(
|
|
80
|
+
() => document.removeEventListener(
|
|
81
|
+
'mousemove',
|
|
82
|
+
this.updateMouseMovePositionEvent,
|
|
83
|
+
false
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
} else {
|
|
87
|
+
Logger.Log(
|
|
88
|
+
Logger.GetStackTrace(),
|
|
89
|
+
'The pointer lock status is now unlocked',
|
|
90
|
+
6
|
|
91
|
+
);
|
|
92
|
+
// !a new arrow function must not be used here as it will be counted as a new function that cannot be removed
|
|
93
|
+
document.removeEventListener(
|
|
94
|
+
'mousemove',
|
|
95
|
+
this.updateMouseMovePositionEvent,
|
|
96
|
+
false
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// If mouse loses focus, send a key up for all of the currently held-down keys
|
|
100
|
+
// This is necessary as when the mouse loses focus, the windows stops listening for events and as such
|
|
101
|
+
// the keyup listener won't get fired
|
|
102
|
+
let activeKeys = this.activeKeysProvider.getActiveKeys();
|
|
103
|
+
const setKeys = new Set(activeKeys);
|
|
104
|
+
const newKeysIterable: Array<number> = [];
|
|
105
|
+
|
|
106
|
+
setKeys.forEach((setKey: number) => {
|
|
107
|
+
newKeysIterable[setKey];
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
newKeysIterable.forEach((uniqueKeycode) => {
|
|
111
|
+
toStreamerHandlers.get('KeyUp')([uniqueKeycode]);
|
|
112
|
+
});
|
|
113
|
+
// Reset the active keys back to nothing
|
|
114
|
+
activeKeys = [];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Handle the mouse move event, sends the mouse data to the UE Instance
|
|
120
|
+
* @param mouseEvent - Mouse Event
|
|
121
|
+
*/
|
|
122
|
+
updateMouseMovePosition(mouseEvent: MouseEvent) {
|
|
123
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const toStreamerHandlers =
|
|
127
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
128
|
+
const styleWidth =
|
|
129
|
+
this.videoElementProvider.getVideoParentElement().clientWidth;
|
|
130
|
+
const styleHeight =
|
|
131
|
+
this.videoElementProvider.getVideoParentElement().clientHeight;
|
|
132
|
+
|
|
133
|
+
this.x += mouseEvent.movementX;
|
|
134
|
+
this.y += mouseEvent.movementY;
|
|
135
|
+
|
|
136
|
+
if (this.x > styleWidth) {
|
|
137
|
+
this.x -= styleWidth;
|
|
138
|
+
}
|
|
139
|
+
if (this.y > styleHeight) {
|
|
140
|
+
this.y -= styleHeight;
|
|
141
|
+
}
|
|
142
|
+
if (this.x < 0) {
|
|
143
|
+
this.x = styleWidth + this.x;
|
|
144
|
+
}
|
|
145
|
+
if (this.y < 0) {
|
|
146
|
+
this.y = styleHeight - this.y;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.coord =
|
|
150
|
+
this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(
|
|
151
|
+
this.x,
|
|
152
|
+
this.y
|
|
153
|
+
);
|
|
154
|
+
const delta =
|
|
155
|
+
this.mouseController.coordinateConverter.normalizeAndQuantizeSigned(
|
|
156
|
+
mouseEvent.movementX,
|
|
157
|
+
mouseEvent.movementY
|
|
158
|
+
);
|
|
159
|
+
toStreamerHandlers.get('MouseMove')([
|
|
160
|
+
this.coord.x,
|
|
161
|
+
this.coord.y,
|
|
162
|
+
delta.x,
|
|
163
|
+
delta.y
|
|
164
|
+
]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Handle the mouse Down event, sends the mouse data to the UE Instance
|
|
169
|
+
* @param mouseEvent - Mouse Event
|
|
170
|
+
*/
|
|
171
|
+
handleMouseDown(mouseEvent: MouseEvent) {
|
|
172
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const toStreamerHandlers =
|
|
177
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
178
|
+
toStreamerHandlers.get('MouseDown')([
|
|
179
|
+
mouseEvent.button,
|
|
180
|
+
// We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location
|
|
181
|
+
// uses the system cursor location which hasn't moved
|
|
182
|
+
this.coord.x,
|
|
183
|
+
this.coord.y
|
|
184
|
+
]);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Handle the mouse Up event, sends the mouse data to the UE Instance
|
|
189
|
+
* @param mouseEvent - Mouse Event
|
|
190
|
+
*/
|
|
191
|
+
handleMouseUp(mouseEvent: MouseEvent) {
|
|
192
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const toStreamerHandlers =
|
|
196
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
197
|
+
toStreamerHandlers.get('MouseUp')([
|
|
198
|
+
mouseEvent.button,
|
|
199
|
+
// We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location
|
|
200
|
+
// uses the system cursor location which hasn't moved
|
|
201
|
+
this.coord.x,
|
|
202
|
+
this.coord.y
|
|
203
|
+
]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Handle the mouse wheel event, sends the mouse wheel data to the UE Instance
|
|
208
|
+
* @param wheelEvent - Mouse Event
|
|
209
|
+
*/
|
|
210
|
+
handleMouseWheel(wheelEvent: WheelEvent) {
|
|
211
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const toStreamerHandlers =
|
|
215
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
216
|
+
toStreamerHandlers.get('MouseWheel')([
|
|
217
|
+
wheelEvent.wheelDelta,
|
|
218
|
+
// We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location
|
|
219
|
+
// uses the system cursor location which hasn't moved
|
|
220
|
+
this.coord.x,
|
|
221
|
+
this.coord.y
|
|
222
|
+
]);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Handle the mouse double click event, sends the mouse data to the UE Instance
|
|
227
|
+
* @param mouseEvent - Mouse Event
|
|
228
|
+
*/
|
|
229
|
+
handleMouseDouble(mouseEvent: MouseEvent) {
|
|
230
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const toStreamerHandlers =
|
|
234
|
+
this.mouseController.toStreamerMessagesProvider.toStreamerHandlers;
|
|
235
|
+
toStreamerHandlers.get('MouseDouble')([
|
|
236
|
+
mouseEvent.button,
|
|
237
|
+
// We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location
|
|
238
|
+
// uses the system cursor location which hasn't moved
|
|
239
|
+
this.coord.x,
|
|
240
|
+
this.coord.y
|
|
241
|
+
]);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Handle the press mouse buttons event, sends the mouse data to the UE Instance
|
|
246
|
+
* @param mouseEvent - Mouse Event
|
|
247
|
+
*/
|
|
248
|
+
handlePressMouseButtons(mouseEvent: MouseEvent) {
|
|
249
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
this.mouseController.pressMouseButtons(
|
|
253
|
+
mouseEvent.buttons,
|
|
254
|
+
this.x,
|
|
255
|
+
this.y
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Handle the release mouse buttons event, sends the mouse data to the UE Instance
|
|
261
|
+
* @param mouseEvent - Mouse Event
|
|
262
|
+
*/
|
|
263
|
+
handleReleaseMouseButtons(mouseEvent: MouseEvent) {
|
|
264
|
+
if (!this.videoElementProvider.isVideoReady()) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
this.mouseController.releaseMouseButtons(
|
|
268
|
+
mouseEvent.buttons,
|
|
269
|
+
this.x,
|
|
270
|
+
this.y
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Extra types for Document and WheelEvent
|
|
277
|
+
*/
|
|
278
|
+
declare global {
|
|
279
|
+
interface Document {
|
|
280
|
+
mozPointerLockElement: unknown;
|
|
281
|
+
mozExitPointerLock?(): void;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
interface WheelEvent {
|
|
285
|
+
wheelDelta: number;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mouse Button Data
|
|
5
|
+
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
|
|
6
|
+
*/
|
|
7
|
+
export class MouseButton {
|
|
8
|
+
static mainButton = 0; // Left button.
|
|
9
|
+
static auxiliaryButton = 1; // Wheel button.
|
|
10
|
+
static secondaryButton = 2; // Right button.
|
|
11
|
+
static fourthButton = 3; // Browser Back button.
|
|
12
|
+
static fifthButton = 4; // Browser Forward button.
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Mouse Button Mask Data
|
|
17
|
+
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons}
|
|
18
|
+
*/
|
|
19
|
+
export class MouseButtonsMask {
|
|
20
|
+
static primaryButton = 1; // Left button.
|
|
21
|
+
static secondaryButton = 2; // Right button.
|
|
22
|
+
static auxiliaryButton = 4; // Wheel button.
|
|
23
|
+
static fourthButton = 8; // Browser Back button.
|
|
24
|
+
static fifthButton = 16; // Browser Forward button.
|
|
25
|
+
}
|