@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.
Files changed (138) hide show
  1. package/.cspell.json +48 -0
  2. package/.eslintignore +8 -0
  3. package/.eslintrc.js +8 -0
  4. package/.prettierignore +0 -0
  5. package/.prettierrc.json +6 -0
  6. package/dist/lib-pixelstreamingfrontend.esm.js +1 -0
  7. package/dist/lib-pixelstreamingfrontend.js +1 -0
  8. package/jest.config.js +18 -0
  9. package/package.json +48 -0
  10. package/readme.md +15 -0
  11. package/src/AFK/AFKController.test.ts +162 -0
  12. package/src/AFK/AFKController.ts +158 -0
  13. package/src/Config/Config.test.ts +222 -0
  14. package/src/Config/Config.ts +970 -0
  15. package/src/Config/SettingBase.ts +65 -0
  16. package/src/Config/SettingFlag.ts +99 -0
  17. package/src/Config/SettingNumber.ts +111 -0
  18. package/src/Config/SettingOption.ts +124 -0
  19. package/src/Config/SettingText.ts +82 -0
  20. package/src/DataChannel/DataChannelController.ts +138 -0
  21. package/src/DataChannel/DataChannelLatencyTestController.ts +129 -0
  22. package/src/DataChannel/DataChannelLatencyTestResults.ts +67 -0
  23. package/src/DataChannel/DataChannelSender.ts +59 -0
  24. package/src/DataChannel/InitialSettings.ts +61 -0
  25. package/src/DataChannel/LatencyTestResults.ts +76 -0
  26. package/src/FreezeFrame/FreezeFrame.ts +114 -0
  27. package/src/FreezeFrame/FreezeFrameController.ts +114 -0
  28. package/src/Inputs/FakeTouchController.ts +199 -0
  29. package/src/Inputs/GamepadController.ts +314 -0
  30. package/src/Inputs/GamepadTypes.ts +10 -0
  31. package/src/Inputs/HoveringMouseEvents.ts +192 -0
  32. package/src/Inputs/IMouseEvents.ts +64 -0
  33. package/src/Inputs/ITouchController.ts +29 -0
  34. package/src/Inputs/InputClassesFactory.ts +140 -0
  35. package/src/Inputs/KeyboardController.ts +354 -0
  36. package/src/Inputs/LockedMouseEvents.ts +287 -0
  37. package/src/Inputs/MouseButtons.ts +25 -0
  38. package/src/Inputs/MouseController.ts +362 -0
  39. package/src/Inputs/SpecialKeyCodes.ts +16 -0
  40. package/src/Inputs/TouchController.ts +208 -0
  41. package/src/Inputs/XRGamepadController.ts +126 -0
  42. package/src/PeerConnectionController/AggregatedStats.ts +311 -0
  43. package/src/PeerConnectionController/CandidatePairStats.ts +17 -0
  44. package/src/PeerConnectionController/CandidateStat.ts +13 -0
  45. package/src/PeerConnectionController/CodecStats.ts +19 -0
  46. package/src/PeerConnectionController/DataChannelStats.ts +17 -0
  47. package/src/PeerConnectionController/InboundRTPStats.ts +154 -0
  48. package/src/PeerConnectionController/InboundTrackStats.ts +34 -0
  49. package/src/PeerConnectionController/OutBoundRTPStats.ts +26 -0
  50. package/src/PeerConnectionController/PeerConnectionController.ts +563 -0
  51. package/src/PeerConnectionController/SessionStats.ts +10 -0
  52. package/src/PeerConnectionController/StreamStats.ts +11 -0
  53. package/src/PixelStreaming/PixelStreaming.test.ts +626 -0
  54. package/src/PixelStreaming/PixelStreaming.ts +851 -0
  55. package/src/UI/OnScreenKeyboard.ts +97 -0
  56. package/src/UeInstanceMessage/ResponseController.ts +47 -0
  57. package/src/UeInstanceMessage/SendMessageController.ts +154 -0
  58. package/src/UeInstanceMessage/StreamMessageController.ts +233 -0
  59. package/src/UeInstanceMessage/ToStreamerMessagesController.ts +62 -0
  60. package/src/Util/CoordinateConverter.ts +289 -0
  61. package/src/Util/EventEmitter.ts +611 -0
  62. package/src/Util/EventListenerTracker.ts +29 -0
  63. package/src/Util/FileUtil.ts +140 -0
  64. package/src/Util/RTCUtils.ts +41 -0
  65. package/src/Util/WebGLUtils.ts +49 -0
  66. package/src/Util/WebXRUtils.ts +25 -0
  67. package/src/VideoPlayer/StreamController.ts +89 -0
  68. package/src/VideoPlayer/VideoPlayer.ts +246 -0
  69. package/src/WebRtcPlayer/WebRtcPlayerController.ts +2158 -0
  70. package/src/WebXR/WebXRController.ts +319 -0
  71. package/src/__test__/mockMediaStream.ts +124 -0
  72. package/src/__test__/mockRTCPeerConnection.ts +347 -0
  73. package/src/__test__/mockRTCRtpReceiver.ts +22 -0
  74. package/src/__test__/mockWebSocket.ts +136 -0
  75. package/src/pixelstreamingfrontend.ts +46 -0
  76. package/tsconfig.jest.json +8 -0
  77. package/tsconfig.json +24 -0
  78. package/types/AFK/AFKController.d.ts +39 -0
  79. package/types/Config/Config.d.ts +218 -0
  80. package/types/Config/SettingBase.d.ts +30 -0
  81. package/types/Config/SettingFlag.d.ts +33 -0
  82. package/types/Config/SettingNumber.d.ts +45 -0
  83. package/types/Config/SettingOption.d.ts +43 -0
  84. package/types/Config/SettingText.d.ts +29 -0
  85. package/types/DataChannel/DataChannelController.d.ts +59 -0
  86. package/types/DataChannel/DataChannelLatencyTestController.d.ts +26 -0
  87. package/types/DataChannel/DataChannelLatencyTestResults.d.ts +46 -0
  88. package/types/DataChannel/DataChannelSender.d.ts +21 -0
  89. package/types/DataChannel/InitialSettings.d.ts +44 -0
  90. package/types/DataChannel/LatencyTestResults.d.ts +31 -0
  91. package/types/FreezeFrame/FreezeFrame.d.ts +36 -0
  92. package/types/FreezeFrame/FreezeFrameController.d.ts +37 -0
  93. package/types/Inputs/FakeTouchController.d.ts +61 -0
  94. package/types/Inputs/GamepadController.d.ts +85 -0
  95. package/types/Inputs/GamepadTypes.d.ts +8 -0
  96. package/types/Inputs/HoveringMouseEvents.d.ts +56 -0
  97. package/types/Inputs/IMouseEvents.d.ts +53 -0
  98. package/types/Inputs/ITouchController.d.ts +24 -0
  99. package/types/Inputs/InputClassesFactory.d.ts +54 -0
  100. package/types/Inputs/KeyboardController.d.ts +62 -0
  101. package/types/Inputs/LockedMouseEvents.d.ts +80 -0
  102. package/types/Inputs/MouseButtons.d.ts +22 -0
  103. package/types/Inputs/MouseController.d.ts +75 -0
  104. package/types/Inputs/SpecialKeyCodes.d.ts +14 -0
  105. package/types/Inputs/TouchController.d.ts +53 -0
  106. package/types/Inputs/XRGamepadController.d.ts +15 -0
  107. package/types/PeerConnectionController/AggregatedStats.d.ts +77 -0
  108. package/types/PeerConnectionController/CandidatePairStats.d.ts +15 -0
  109. package/types/PeerConnectionController/CandidateStat.d.ts +11 -0
  110. package/types/PeerConnectionController/CodecStats.d.ts +14 -0
  111. package/types/PeerConnectionController/DataChannelStats.d.ts +15 -0
  112. package/types/PeerConnectionController/InboundRTPStats.d.ts +141 -0
  113. package/types/PeerConnectionController/InboundTrackStats.d.ts +32 -0
  114. package/types/PeerConnectionController/OutBoundRTPStats.d.ts +23 -0
  115. package/types/PeerConnectionController/PeerConnectionController.d.ts +132 -0
  116. package/types/PeerConnectionController/SessionStats.d.ts +8 -0
  117. package/types/PeerConnectionController/StreamStats.d.ts +9 -0
  118. package/types/PixelStreaming/PixelStreaming.d.ts +259 -0
  119. package/types/UI/OnScreenKeyboard.d.ts +31 -0
  120. package/types/UeInstanceMessage/ResponseController.d.ts +19 -0
  121. package/types/UeInstanceMessage/SendMessageController.d.ts +18 -0
  122. package/types/UeInstanceMessage/StreamMessageController.d.ts +29 -0
  123. package/types/UeInstanceMessage/ToStreamerMessagesController.d.ts +32 -0
  124. package/types/Util/CoordinateConverter.d.ts +100 -0
  125. package/types/Util/EventEmitter.d.ts +422 -0
  126. package/types/Util/EventListenerTracker.d.ts +14 -0
  127. package/types/Util/FileUtil.d.ts +32 -0
  128. package/types/Util/RTCUtils.d.ts +8 -0
  129. package/types/Util/WebGLUtils.d.ts +4 -0
  130. package/types/Util/WebXRUtils.d.ts +9 -0
  131. package/types/VideoPlayer/StreamController.d.ts +24 -0
  132. package/types/VideoPlayer/VideoPlayer.d.ts +78 -0
  133. package/types/WebRtcPlayer/WebRtcPlayerController.d.ts +377 -0
  134. package/types/WebXR/WebXRController.d.ts +26 -0
  135. package/types/pixelstreamingfrontend.d.ts +22 -0
  136. package/webpack.common.js +35 -0
  137. package/webpack.dev.js +35 -0
  138. 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
+ }