@epicgames-ps/lib-pixelstreamingfrontend-ue5.5 0.1.3 → 0.2.1
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/.eslintrc.js +1 -1
- package/.prettierrc.json +1 -0
- package/dist/lib-pixelstreamingfrontend.esm.js +1 -1
- package/dist/lib-pixelstreamingfrontend.js +1 -1
- package/package.json +6 -5
- package/src/AFK/AFKController.ts +10 -32
- package/src/Config/Config.ts +179 -201
- package/src/Config/SettingBase.ts +61 -2
- package/src/Config/SettingFlag.ts +10 -48
- package/src/Config/SettingNumber.ts +10 -28
- package/src/Config/SettingOption.ts +13 -46
- package/src/Config/SettingText.ts +9 -37
- package/src/DataChannel/DataChannelController.ts +6 -26
- package/src/DataChannel/DataChannelLatencyTestController.ts +38 -33
- package/src/DataChannel/DataChannelLatencyTestResults.ts +8 -10
- package/src/DataChannel/DataChannelSender.ts +5 -15
- package/src/DataChannel/LatencyTestResults.ts +5 -15
- package/src/FreezeFrame/FreezeFrame.ts +7 -19
- package/src/FreezeFrame/FreezeFrameController.ts +3 -14
- package/src/Inputs/GamepadController.ts +123 -221
- package/src/Inputs/GamepadTypes.ts +23 -0
- package/src/Inputs/IInputController.ts +17 -0
- package/src/Inputs/InputClassesFactory.ts +38 -45
- package/src/Inputs/KeyCodes.ts +114 -0
- package/src/Inputs/KeyboardController.ts +49 -232
- package/src/Inputs/MouseController.ts +71 -297
- package/src/Inputs/MouseControllerHovering.ts +118 -0
- package/src/Inputs/MouseControllerLocked.ts +194 -0
- package/src/Inputs/TouchController.ts +49 -105
- package/src/Inputs/TouchControllerFake.ts +132 -0
- package/src/Inputs/XRGamepadController.ts +35 -44
- package/src/PeerConnectionController/AggregatedStats.ts +26 -54
- package/src/PeerConnectionController/CandidatePairStats.ts +1 -1
- package/src/PeerConnectionController/CandidateStat.ts +1 -1
- package/src/PeerConnectionController/PeerConnectionController.ts +217 -164
- package/src/PixelStreaming/PixelStreaming.ts +174 -226
- package/src/UI/OnScreenKeyboard.ts +14 -9
- package/src/UeInstanceMessage/ResponseController.ts +6 -15
- package/src/UeInstanceMessage/SendMessageController.ts +16 -18
- package/src/UeInstanceMessage/StreamMessageController.ts +3 -12
- package/src/UeInstanceMessage/ToStreamerMessagesController.ts +3 -9
- package/src/Util/EventEmitter.ts +17 -22
- package/src/Util/FileUtil.ts +11 -34
- package/src/Util/IURLSearchParams.ts +25 -0
- package/src/Util/InputCoordTranslator.ts +73 -0
- package/src/Util/RTCUtils.ts +23 -15
- package/src/VideoPlayer/StreamController.ts +6 -23
- package/src/VideoPlayer/VideoPlayer.ts +9 -30
- package/src/WebRtcPlayer/WebRtcPlayerController.ts +328 -690
- package/src/WebXR/WebXRController.ts +82 -94
- package/src/pixelstreamingfrontend.ts +6 -10
- package/types/AFK/AFKController.d.ts +0 -1
- package/types/Config/Config.d.ts +6 -5
- package/types/Config/SettingBase.d.ts +13 -0
- package/types/Config/SettingFlag.d.ts +1 -10
- package/types/Config/SettingNumber.d.ts +1 -5
- package/types/Config/SettingOption.d.ts +1 -10
- package/types/Config/SettingText.d.ts +1 -9
- package/types/DataChannel/DataChannelLatencyTestController.d.ts +1 -1
- package/types/Inputs/GamepadController.d.ts +22 -46
- package/types/Inputs/GamepadTypes.d.ts +7 -0
- package/types/Inputs/IInputController.d.ts +16 -0
- package/types/Inputs/InputClassesFactory.d.ts +7 -8
- package/types/Inputs/KeyCodes.d.ts +5 -0
- package/types/Inputs/KeyboardController.d.ts +17 -45
- package/types/Inputs/MouseController.d.ts +33 -68
- package/types/Inputs/MouseControllerHovering.d.ts +26 -0
- package/types/Inputs/MouseControllerLocked.d.ts +31 -0
- package/types/Inputs/TouchController.d.ts +19 -44
- package/types/Inputs/TouchControllerFake.d.ts +29 -0
- package/types/Inputs/XRGamepadController.d.ts +0 -7
- package/types/PeerConnectionController/PeerConnectionController.d.ts +10 -1
- package/types/PixelStreaming/PixelStreaming.d.ts +14 -2
- package/types/UI/OnScreenKeyboard.d.ts +2 -2
- package/types/Util/EventEmitter.d.ts +1 -1
- package/types/Util/IURLSearchParams.d.ts +9 -0
- package/types/Util/InputCoordTranslator.d.ts +29 -0
- package/types/VideoPlayer/StreamController.d.ts +0 -2
- package/types/WebRtcPlayer/WebRtcPlayerController.d.ts +19 -17
- package/types/pixelstreamingfrontend.d.ts +1 -1
- package/src/Inputs/FakeTouchController.ts +0 -199
- package/src/Inputs/HoveringMouseEvents.ts +0 -192
- package/src/Inputs/IMouseEvents.ts +0 -64
- package/src/Inputs/ITouchController.ts +0 -29
- package/src/Inputs/LockedMouseEvents.ts +0 -287
- package/src/Util/CoordinateConverter.ts +0 -290
- package/src/Util/EventListenerTracker.ts +0 -29
- package/types/Inputs/FakeTouchController.d.ts +0 -61
- package/types/Inputs/HoveringMouseEvents.d.ts +0 -56
- package/types/Inputs/IMouseEvents.d.ts +0 -53
- package/types/Inputs/ITouchController.d.ts +0 -24
- package/types/Inputs/LockedMouseEvents.d.ts +0 -80
- package/types/Util/CoordinateConverter.d.ts +0 -100
- package/types/Util/EventListenerTracker.d.ts +0 -14
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
import { Logger } from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
|
4
4
|
import { WebRtcPlayerController } from '../WebRtcPlayer/WebRtcPlayerController';
|
|
5
5
|
import { XRGamepadController } from '../Inputs/XRGamepadController';
|
|
6
|
-
import { XrFrameEvent } from '../Util/EventEmitter'
|
|
6
|
+
import { XrFrameEvent } from '../Util/EventEmitter';
|
|
7
7
|
import { Flags } from '../pixelstreamingfrontend';
|
|
8
8
|
|
|
9
9
|
export class WebXRController {
|
|
10
10
|
private xrSession: XRSession;
|
|
11
11
|
private xrRefSpace: XRReferenceSpace;
|
|
12
12
|
private gl: WebGL2RenderingContext;
|
|
13
|
-
private xrViewerPose
|
|
13
|
+
private xrViewerPose: XRViewerPose = null;
|
|
14
14
|
// Used for comparisons to ensure two numbers are close enough.
|
|
15
15
|
private EPSILON = 0.0000001;
|
|
16
16
|
|
|
@@ -43,9 +43,7 @@ export class WebXRController {
|
|
|
43
43
|
constructor(webRtcPlayerController: WebRtcPlayerController) {
|
|
44
44
|
this.xrSession = null;
|
|
45
45
|
this.webRtcController = webRtcPlayerController;
|
|
46
|
-
this.xrGamepadController = new XRGamepadController(
|
|
47
|
-
this.webRtcController.streamMessageController
|
|
48
|
-
);
|
|
46
|
+
this.xrGamepadController = new XRGamepadController(this.webRtcController.streamMessageController);
|
|
49
47
|
this.onSessionEnded = new EventTarget();
|
|
50
48
|
this.onSessionStarted = new EventTarget();
|
|
51
49
|
this.onFrame = new EventTarget();
|
|
@@ -53,9 +51,8 @@ export class WebXRController {
|
|
|
53
51
|
|
|
54
52
|
public xrClicked() {
|
|
55
53
|
if (!this.xrSession) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Logger.Error(Logger.GetStackTrace(), "This browser does not support XR.");
|
|
54
|
+
if (!navigator.xr) {
|
|
55
|
+
Logger.Error('This browser does not support XR.');
|
|
59
56
|
return;
|
|
60
57
|
}
|
|
61
58
|
|
|
@@ -71,13 +68,15 @@ export class WebXRController {
|
|
|
71
68
|
}
|
|
72
69
|
|
|
73
70
|
onXrSessionEnded() {
|
|
74
|
-
Logger.
|
|
71
|
+
Logger.Info('XR Session ended');
|
|
75
72
|
this.xrSession = null;
|
|
76
73
|
this.onSessionEnded.dispatchEvent(new Event('xrSessionEnded'));
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
initGL() {
|
|
80
|
-
if (this.gl) {
|
|
77
|
+
if (this.gl) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
81
80
|
const canvas = document.createElement('canvas');
|
|
82
81
|
this.gl = canvas.getContext('webgl2', {
|
|
83
82
|
xrCompatible: true
|
|
@@ -88,10 +87,8 @@ export class WebXRController {
|
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
initShaders() {
|
|
91
|
-
|
|
92
90
|
// shader source code
|
|
93
|
-
const vertexShaderSource: string =
|
|
94
|
-
`
|
|
91
|
+
const vertexShaderSource: string = `
|
|
95
92
|
attribute vec2 a_position;
|
|
96
93
|
attribute vec2 a_texCoord;
|
|
97
94
|
|
|
@@ -106,8 +103,7 @@ export class WebXRController {
|
|
|
106
103
|
}
|
|
107
104
|
`;
|
|
108
105
|
|
|
109
|
-
const fragmentShaderSource: string =
|
|
110
|
-
`
|
|
106
|
+
const fragmentShaderSource: string = `
|
|
111
107
|
precision mediump float;
|
|
112
108
|
|
|
113
109
|
// our texture
|
|
@@ -139,51 +135,28 @@ export class WebXRController {
|
|
|
139
135
|
this.gl.useProgram(shaderProgram);
|
|
140
136
|
|
|
141
137
|
// look up where vertex data needs to go
|
|
142
|
-
this.positionLocation = this.gl.getAttribLocation(
|
|
143
|
-
|
|
144
|
-
'a_position'
|
|
145
|
-
);
|
|
146
|
-
this.texcoordLocation = this.gl.getAttribLocation(
|
|
147
|
-
shaderProgram,
|
|
148
|
-
'a_texCoord'
|
|
149
|
-
);
|
|
138
|
+
this.positionLocation = this.gl.getAttribLocation(shaderProgram, 'a_position');
|
|
139
|
+
this.texcoordLocation = this.gl.getAttribLocation(shaderProgram, 'a_texCoord');
|
|
150
140
|
}
|
|
151
141
|
|
|
152
|
-
updateVideoTexture(){
|
|
153
|
-
|
|
154
|
-
if(!this.videoTexture){
|
|
142
|
+
updateVideoTexture() {
|
|
143
|
+
if (!this.videoTexture) {
|
|
155
144
|
// Create our texture that we use in our shader
|
|
156
145
|
// and bind it once because we never use any other texture.
|
|
157
146
|
this.videoTexture = this.gl.createTexture();
|
|
158
147
|
this.gl.bindTexture(this.gl.TEXTURE_2D, this.videoTexture);
|
|
159
148
|
|
|
160
149
|
// Set the parameters so we can render any size image.
|
|
161
|
-
this.gl.texParameteri(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
);
|
|
166
|
-
this.gl.texParameteri(
|
|
167
|
-
this.gl.TEXTURE_2D,
|
|
168
|
-
this.gl.TEXTURE_WRAP_T,
|
|
169
|
-
this.gl.CLAMP_TO_EDGE
|
|
170
|
-
);
|
|
171
|
-
this.gl.texParameteri(
|
|
172
|
-
this.gl.TEXTURE_2D,
|
|
173
|
-
this.gl.TEXTURE_MIN_FILTER,
|
|
174
|
-
this.gl.LINEAR
|
|
175
|
-
);
|
|
176
|
-
this.gl.texParameteri(
|
|
177
|
-
this.gl.TEXTURE_2D,
|
|
178
|
-
this.gl.TEXTURE_MAG_FILTER,
|
|
179
|
-
this.gl.LINEAR
|
|
180
|
-
);
|
|
150
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
151
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
152
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
153
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
181
154
|
}
|
|
182
155
|
|
|
183
156
|
const videoHeight = this.webRtcController.videoPlayer.getVideoElement().videoHeight;
|
|
184
157
|
const videoWidth = this.webRtcController.videoPlayer.getVideoElement().videoWidth;
|
|
185
158
|
|
|
186
|
-
if(this.prevVideoHeight != videoHeight || this.prevVideoWidth != videoWidth){
|
|
159
|
+
if (this.prevVideoHeight != videoHeight || this.prevVideoWidth != videoWidth) {
|
|
187
160
|
// Do full update of texture if dimensions do not match
|
|
188
161
|
this.gl.texImage2D(
|
|
189
162
|
this.gl.TEXTURE_2D,
|
|
@@ -216,7 +189,7 @@ export class WebXRController {
|
|
|
216
189
|
this.prevVideoWidth = videoWidth;
|
|
217
190
|
}
|
|
218
191
|
|
|
219
|
-
initBuffers(){
|
|
192
|
+
initBuffers() {
|
|
220
193
|
// Create out position buffer and its vertex shader attribute
|
|
221
194
|
{
|
|
222
195
|
// Create a buffer to put the the vertices of the plane we will draw the video stream onto
|
|
@@ -263,14 +236,7 @@ export class WebXRController {
|
|
|
263
236
|
// The texture coordinates to apply for rectangle we are drawing
|
|
264
237
|
this.gl.bufferData(
|
|
265
238
|
this.gl.ARRAY_BUFFER,
|
|
266
|
-
new Float32Array([
|
|
267
|
-
0.0, 0.0,
|
|
268
|
-
1.0, 0.0,
|
|
269
|
-
0.0, 1.0,
|
|
270
|
-
0.0, 1.0,
|
|
271
|
-
1.0, 0.0,
|
|
272
|
-
1.0, 1.0
|
|
273
|
-
]),
|
|
239
|
+
new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]),
|
|
274
240
|
this.gl.STATIC_DRAW
|
|
275
241
|
);
|
|
276
242
|
|
|
@@ -287,7 +253,7 @@ export class WebXRController {
|
|
|
287
253
|
}
|
|
288
254
|
|
|
289
255
|
onXrSessionStarted(session: XRSession) {
|
|
290
|
-
Logger.
|
|
256
|
+
Logger.Info('XR Session started');
|
|
291
257
|
|
|
292
258
|
this.xrSession = session;
|
|
293
259
|
this.xrSession.addEventListener('end', () => {
|
|
@@ -308,9 +274,9 @@ export class WebXRController {
|
|
|
308
274
|
});
|
|
309
275
|
|
|
310
276
|
// Update target framerate to 90 fps if 90 fps is supported in this XR device
|
|
311
|
-
if(this.xrSession.supportedFrameRates) {
|
|
277
|
+
if (this.xrSession.supportedFrameRates) {
|
|
312
278
|
for (const frameRate of this.xrSession.supportedFrameRates) {
|
|
313
|
-
if(frameRate == 90){
|
|
279
|
+
if (frameRate == 90) {
|
|
314
280
|
session.updateTargetFrameRate(90);
|
|
315
281
|
}
|
|
316
282
|
}
|
|
@@ -323,16 +289,22 @@ export class WebXRController {
|
|
|
323
289
|
this.onSessionStarted.dispatchEvent(new Event('xrSessionStarted'));
|
|
324
290
|
}
|
|
325
291
|
|
|
326
|
-
areArraysEqual(a: Float32Array, b: Float32Array)
|
|
327
|
-
return
|
|
292
|
+
areArraysEqual(a: Float32Array, b: Float32Array): boolean {
|
|
293
|
+
return (
|
|
294
|
+
a.length === b.length && a.every((element, index) => Math.abs(element - b[index]) <= this.EPSILON)
|
|
295
|
+
);
|
|
328
296
|
}
|
|
329
297
|
|
|
330
|
-
arePointsEqual(a: DOMPointReadOnly, b: DOMPointReadOnly)
|
|
331
|
-
return
|
|
298
|
+
arePointsEqual(a: DOMPointReadOnly, b: DOMPointReadOnly): boolean {
|
|
299
|
+
return (
|
|
300
|
+
Math.abs(a.x - b.x) >= this.EPSILON &&
|
|
301
|
+
Math.abs(a.y - b.y) >= this.EPSILON &&
|
|
302
|
+
Math.abs(a.z - b.z) >= this.EPSILON
|
|
303
|
+
);
|
|
332
304
|
}
|
|
333
305
|
|
|
334
306
|
sendXRDataToUE() {
|
|
335
|
-
if(this.leftView == null || this.rightView == null) {
|
|
307
|
+
if (this.leftView == null || this.rightView == null) {
|
|
336
308
|
return;
|
|
337
309
|
}
|
|
338
310
|
|
|
@@ -341,10 +313,11 @@ export class WebXRController {
|
|
|
341
313
|
// the `XREyeViews` is a much larger message and changes infrequently (e.g. only when user changes headset IPD).
|
|
342
314
|
// Therefore, we only need to send it once on startup and then any time it changes.
|
|
343
315
|
// The rest of the time we can send the `XRHMDTransform` message.
|
|
344
|
-
let shouldSendEyeViews =
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
316
|
+
let shouldSendEyeViews =
|
|
317
|
+
this.lastSentLeftEyeProj == null ||
|
|
318
|
+
this.lastSentRightEyeProj == null ||
|
|
319
|
+
this.lastSentRelativeLeftEyePos == null ||
|
|
320
|
+
this.lastSentRelativeRightEyePos == null;
|
|
348
321
|
|
|
349
322
|
const leftEyeTrans = this.leftView.transform.matrix;
|
|
350
323
|
const leftEyeProj = this.leftView.projectionMatrix;
|
|
@@ -353,7 +326,7 @@ export class WebXRController {
|
|
|
353
326
|
const hmdTrans = this.xrViewerPose.transform.matrix;
|
|
354
327
|
|
|
355
328
|
// Check if projection matrices have changed
|
|
356
|
-
if(!shouldSendEyeViews && this.lastSentLeftEyeProj != null && this.lastSentRightEyeProj != null) {
|
|
329
|
+
if (!shouldSendEyeViews && this.lastSentLeftEyeProj != null && this.lastSentRightEyeProj != null) {
|
|
357
330
|
const leftEyeProjUnchanged = this.areArraysEqual(leftEyeProj, this.lastSentLeftEyeProj);
|
|
358
331
|
const rightEyeProjUnchanged = this.areArraysEqual(rightEyeProj, this.lastSentRightEyeProj);
|
|
359
332
|
shouldSendEyeViews = leftEyeProjUnchanged == false || rightEyeProjUnchanged == false;
|
|
@@ -374,14 +347,24 @@ export class WebXRController {
|
|
|
374
347
|
);
|
|
375
348
|
|
|
376
349
|
// Check if relative eye pos has changed (e.g IPD changed)
|
|
377
|
-
if(
|
|
378
|
-
|
|
379
|
-
|
|
350
|
+
if (
|
|
351
|
+
!shouldSendEyeViews &&
|
|
352
|
+
this.lastSentRelativeLeftEyePos != null &&
|
|
353
|
+
this.lastSentRelativeRightEyePos != null
|
|
354
|
+
) {
|
|
355
|
+
const leftEyePosUnchanged = this.arePointsEqual(
|
|
356
|
+
leftEyeRelativePos,
|
|
357
|
+
this.lastSentRelativeLeftEyePos
|
|
358
|
+
);
|
|
359
|
+
const rightEyePosUnchanged = this.arePointsEqual(
|
|
360
|
+
rightEyeRelativePos,
|
|
361
|
+
this.lastSentRelativeRightEyePos
|
|
362
|
+
);
|
|
380
363
|
shouldSendEyeViews = leftEyePosUnchanged == false || rightEyePosUnchanged == false;
|
|
381
364
|
// Note: We are not checking if EyeView rotation changes (as far as I know no HMD supports changing this value at runtime).
|
|
382
365
|
}
|
|
383
366
|
|
|
384
|
-
if(shouldSendEyeViews) {
|
|
367
|
+
if (shouldSendEyeViews) {
|
|
385
368
|
// send transform (4x4) and projection matrix (4x4) data for each eye (left first, then right)
|
|
386
369
|
// prettier-ignore
|
|
387
370
|
this.webRtcController.streamMessageController.toStreamerHandlers.get('XREyeViews')([
|
|
@@ -415,15 +398,26 @@ export class WebXRController {
|
|
|
415
398
|
this.lastSentRightEyeProj = rightEyeProj;
|
|
416
399
|
this.lastSentRelativeLeftEyePos = leftEyeRelativePos;
|
|
417
400
|
this.lastSentRelativeRightEyePos = rightEyeRelativePos;
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
401
|
+
} else {
|
|
420
402
|
// If we don't need to the entire eye views being sent just send the HMD transform
|
|
421
403
|
this.webRtcController.streamMessageController.toStreamerHandlers.get('XRHMDTransform')([
|
|
422
404
|
// HMD 4x4 transform
|
|
423
|
-
hmdTrans[0],
|
|
424
|
-
hmdTrans[
|
|
425
|
-
hmdTrans[
|
|
426
|
-
hmdTrans[
|
|
405
|
+
hmdTrans[0],
|
|
406
|
+
hmdTrans[4],
|
|
407
|
+
hmdTrans[8],
|
|
408
|
+
hmdTrans[12],
|
|
409
|
+
hmdTrans[1],
|
|
410
|
+
hmdTrans[5],
|
|
411
|
+
hmdTrans[9],
|
|
412
|
+
hmdTrans[13],
|
|
413
|
+
hmdTrans[2],
|
|
414
|
+
hmdTrans[6],
|
|
415
|
+
hmdTrans[10],
|
|
416
|
+
hmdTrans[14],
|
|
417
|
+
hmdTrans[3],
|
|
418
|
+
hmdTrans[7],
|
|
419
|
+
hmdTrans[11],
|
|
420
|
+
hmdTrans[15]
|
|
427
421
|
]);
|
|
428
422
|
}
|
|
429
423
|
}
|
|
@@ -432,7 +426,7 @@ export class WebXRController {
|
|
|
432
426
|
this.xrViewerPose = frame.getViewerPose(this.xrRefSpace);
|
|
433
427
|
if (this.xrViewerPose) {
|
|
434
428
|
this.updateViews();
|
|
435
|
-
if(this.leftView == null || this.rightView == null) {
|
|
429
|
+
if (this.leftView == null || this.rightView == null) {
|
|
436
430
|
return;
|
|
437
431
|
}
|
|
438
432
|
|
|
@@ -444,33 +438,27 @@ export class WebXRController {
|
|
|
444
438
|
if (this.webRtcController.config.isFlagEnabled(Flags.XRControllerInput)) {
|
|
445
439
|
this.xrSession.inputSources.forEach(
|
|
446
440
|
(source: XRInputSource, _index: number, _array: XRInputSource[]) => {
|
|
447
|
-
this.xrGamepadController.updateStatus(
|
|
448
|
-
source,
|
|
449
|
-
frame,
|
|
450
|
-
this.xrRefSpace
|
|
451
|
-
);
|
|
441
|
+
this.xrGamepadController.updateStatus(source, frame, this.xrRefSpace);
|
|
452
442
|
},
|
|
453
443
|
this
|
|
454
444
|
);
|
|
455
445
|
}
|
|
456
446
|
|
|
457
|
-
this.xrSession.requestAnimationFrame(
|
|
458
|
-
(time
|
|
459
|
-
this.onXrFrame(time, frame)
|
|
447
|
+
this.xrSession.requestAnimationFrame((time: DOMHighResTimeStamp, frame: XRFrame) =>
|
|
448
|
+
this.onXrFrame(time, frame)
|
|
460
449
|
);
|
|
461
450
|
|
|
462
451
|
this.onFrame.dispatchEvent(new XrFrameEvent({ time, frame }));
|
|
463
452
|
}
|
|
464
453
|
|
|
465
454
|
private updateViews() {
|
|
466
|
-
if(!this.xrViewerPose) {
|
|
455
|
+
if (!this.xrViewerPose) {
|
|
467
456
|
return;
|
|
468
457
|
}
|
|
469
458
|
for (const view of this.xrViewerPose.views) {
|
|
470
|
-
if (view.eye ===
|
|
459
|
+
if (view.eye === 'left') {
|
|
471
460
|
this.leftView = view;
|
|
472
|
-
}
|
|
473
|
-
else if(view.eye === "right") {
|
|
461
|
+
} else if (view.eye === 'right') {
|
|
474
462
|
this.rightView = view;
|
|
475
463
|
}
|
|
476
464
|
}
|
|
@@ -493,8 +481,8 @@ export class WebXRController {
|
|
|
493
481
|
}
|
|
494
482
|
|
|
495
483
|
static isSessionSupported(mode: XRSessionMode): Promise<boolean> {
|
|
496
|
-
if (location.protocol !==
|
|
497
|
-
Logger.Info(
|
|
484
|
+
if (location.protocol !== 'https:') {
|
|
485
|
+
Logger.Info('WebXR requires https, if you want WebXR use https.');
|
|
498
486
|
}
|
|
499
487
|
|
|
500
488
|
if (navigator.xr) {
|
|
@@ -25,22 +25,18 @@ export { PixelStreaming } from './PixelStreaming/PixelStreaming';
|
|
|
25
25
|
export { AFKController as AfkLogic } from './AFK/AFKController';
|
|
26
26
|
|
|
27
27
|
export { LatencyTestResults } from './DataChannel/LatencyTestResults';
|
|
28
|
-
export {
|
|
29
|
-
EncoderSettings,
|
|
30
|
-
InitialSettings,
|
|
31
|
-
WebRTCSettings
|
|
32
|
-
} from './DataChannel/InitialSettings';
|
|
28
|
+
export { EncoderSettings, InitialSettings, WebRTCSettings } from './DataChannel/InitialSettings';
|
|
33
29
|
export { AggregatedStats } from './PeerConnectionController/AggregatedStats';
|
|
34
|
-
export {
|
|
30
|
+
export {
|
|
31
|
+
InputCoordTranslator,
|
|
32
|
+
UntranslatedCoordUnsigned as UnquantizedAndDenormalizeUnsigned
|
|
33
|
+
} from './Util/InputCoordTranslator';
|
|
35
34
|
export { MessageDirection } from './UeInstanceMessage/StreamMessageController';
|
|
36
35
|
|
|
37
36
|
export { CandidatePairStats } from './PeerConnectionController/CandidatePairStats';
|
|
38
37
|
export { CandidateStat } from './PeerConnectionController/CandidateStat';
|
|
39
38
|
export { DataChannelStats } from './PeerConnectionController/DataChannelStats';
|
|
40
|
-
export {
|
|
41
|
-
InboundAudioStats,
|
|
42
|
-
InboundVideoStats
|
|
43
|
-
} from './PeerConnectionController/InboundRTPStats';
|
|
39
|
+
export { InboundAudioStats, InboundVideoStats } from './PeerConnectionController/InboundRTPStats';
|
|
44
40
|
export { OutBoundVideoStats } from './PeerConnectionController/OutBoundRTPStats';
|
|
45
41
|
export * from './Util/EventEmitter';
|
|
46
42
|
export * from '@epicgames-ps/lib-pixelstreamingcommon-ue5.5';
|
package/types/Config/Config.d.ts
CHANGED
|
@@ -11,7 +11,6 @@ export declare class Flags {
|
|
|
11
11
|
static AutoConnect: "AutoConnect";
|
|
12
12
|
static AutoPlayVideo: "AutoPlayVideo";
|
|
13
13
|
static AFKDetection: "TimeoutIfIdle";
|
|
14
|
-
static BrowserSendOffer: "OfferToReceive";
|
|
15
14
|
static HoveringMouseMode: "HoveringMouse";
|
|
16
15
|
static ForceMonoAudio: "ForceMonoAudio";
|
|
17
16
|
static ForceTURN: "ForceTURN";
|
|
@@ -21,6 +20,7 @@ export declare class Flags {
|
|
|
21
20
|
static StartVideoMuted: "StartVideoMuted";
|
|
22
21
|
static SuppressBrowserKeys: "SuppressBrowserKeys";
|
|
23
22
|
static UseMic: "UseMic";
|
|
23
|
+
static UseCamera: "UseCamera";
|
|
24
24
|
static KeyboardInput: "KeyboardInput";
|
|
25
25
|
static MouseInput: "MouseInput";
|
|
26
26
|
static TouchInput: "TouchInput";
|
|
@@ -30,13 +30,14 @@ export declare class Flags {
|
|
|
30
30
|
static HideUI: "HideUI";
|
|
31
31
|
}
|
|
32
32
|
export type FlagsKeys = Exclude<keyof typeof Flags, 'prototype'>;
|
|
33
|
-
export type FlagsIds = typeof Flags[FlagsKeys];
|
|
33
|
+
export type FlagsIds = (typeof Flags)[FlagsKeys];
|
|
34
34
|
/**
|
|
35
35
|
* A collection of numeric parameters that are core to all Pixel Streaming experiences.
|
|
36
36
|
*
|
|
37
37
|
*/
|
|
38
38
|
export declare class NumericParameters {
|
|
39
39
|
static AFKTimeoutSecs: "AFKTimeout";
|
|
40
|
+
static AFKCountdownSecs: "AFKCountdown";
|
|
40
41
|
static MinQP: "MinQP";
|
|
41
42
|
static MaxQP: "MaxQP";
|
|
42
43
|
static WebRTCFPS: "WebRTCFPS";
|
|
@@ -46,7 +47,7 @@ export declare class NumericParameters {
|
|
|
46
47
|
static StreamerAutoJoinInterval: "StreamerAutoJoinInterval";
|
|
47
48
|
}
|
|
48
49
|
export type NumericParametersKeys = Exclude<keyof typeof NumericParameters, 'prototype'>;
|
|
49
|
-
export type NumericParametersIds = typeof NumericParameters[NumericParametersKeys];
|
|
50
|
+
export type NumericParametersIds = (typeof NumericParameters)[NumericParametersKeys];
|
|
50
51
|
/**
|
|
51
52
|
* A collection of textual parameters that are core to all Pixel Streaming experiences.
|
|
52
53
|
*
|
|
@@ -55,7 +56,7 @@ export declare class TextParameters {
|
|
|
55
56
|
static SignallingServerUrl: "ss";
|
|
56
57
|
}
|
|
57
58
|
export type TextParametersKeys = Exclude<keyof typeof TextParameters, 'prototype'>;
|
|
58
|
-
export type TextParametersIds = typeof TextParameters[TextParametersKeys];
|
|
59
|
+
export type TextParametersIds = (typeof TextParameters)[TextParametersKeys];
|
|
59
60
|
/**
|
|
60
61
|
* A collection of enum based parameters that are core to all Pixel Streaming experiences.
|
|
61
62
|
*
|
|
@@ -65,7 +66,7 @@ export declare class OptionParameters {
|
|
|
65
66
|
static StreamerId: "StreamerId";
|
|
66
67
|
}
|
|
67
68
|
export type OptionParametersKeys = Exclude<keyof typeof OptionParameters, 'prototype'>;
|
|
68
|
-
export type OptionParametersIds = typeof OptionParameters[OptionParametersKeys];
|
|
69
|
+
export type OptionParametersIds = (typeof OptionParameters)[OptionParametersKeys];
|
|
69
70
|
/**
|
|
70
71
|
* Utility types for inferring data type based on setting ID
|
|
71
72
|
*/
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
export declare class SettingBase {
|
|
5
5
|
id: string;
|
|
6
6
|
description: string;
|
|
7
|
+
useUrlParams: boolean;
|
|
8
|
+
_urlParams: Record<string, string>;
|
|
7
9
|
_label: string;
|
|
8
10
|
_value: unknown;
|
|
9
11
|
onChange: (changedValue: unknown, setting: SettingBase) => void;
|
|
@@ -27,4 +29,15 @@ export declare class SettingBase {
|
|
|
27
29
|
* @param inValue The new value for the setting.
|
|
28
30
|
*/
|
|
29
31
|
set value(inValue: unknown);
|
|
32
|
+
/**
|
|
33
|
+
* Persist the setting value in URL.
|
|
34
|
+
*/
|
|
35
|
+
updateURLParams(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Allows sub types to provide their value for the url search params.
|
|
38
|
+
*/
|
|
39
|
+
protected getValueAsString(): string;
|
|
40
|
+
private parseURLParams;
|
|
41
|
+
protected hasURLParam(name: string): boolean;
|
|
42
|
+
protected getURLParam(name: string): string;
|
|
30
43
|
}
|
|
@@ -6,17 +6,8 @@ import { SettingBase } from './SettingBase';
|
|
|
6
6
|
export declare class SettingFlag<CustomIds extends string = FlagsIds> extends SettingBase {
|
|
7
7
|
id: FlagsIds | CustomIds;
|
|
8
8
|
onChangeEmit: (changedValue: boolean) => void;
|
|
9
|
-
useUrlParams: boolean;
|
|
10
9
|
constructor(id: FlagsIds | CustomIds, label: string, description: string, defaultFlagValue: boolean, useUrlParams: boolean, defaultOnChangeListener?: (changedValue: unknown, setting: SettingBase) => void);
|
|
11
|
-
|
|
12
|
-
* Parse the flag value from the url parameters.
|
|
13
|
-
* @returns True if the url parameters contains /?id, but False if /?id=false
|
|
14
|
-
*/
|
|
15
|
-
getUrlParamFlag(): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Persist the setting value in URL.
|
|
18
|
-
*/
|
|
19
|
-
updateURLParams(): void;
|
|
10
|
+
protected getValueAsString(): string;
|
|
20
11
|
/**
|
|
21
12
|
* Enables this flag.
|
|
22
13
|
*/
|
|
@@ -8,12 +8,8 @@ export declare class SettingNumber<CustomIds extends string = NumericParametersI
|
|
|
8
8
|
_max: number;
|
|
9
9
|
id: NumericParametersIds | CustomIds;
|
|
10
10
|
onChangeEmit: (changedValue: number) => void;
|
|
11
|
-
useUrlParams: boolean;
|
|
12
11
|
constructor(id: NumericParametersIds | CustomIds, label: string, description: string, min: number, max: number, defaultNumber: number, useUrlParams: boolean, defaultOnChangeListener?: (changedValue: unknown, setting: SettingBase) => void);
|
|
13
|
-
|
|
14
|
-
* Persist the setting value in URL.
|
|
15
|
-
*/
|
|
16
|
-
updateURLParams(): void;
|
|
12
|
+
protected getValueAsString(): string;
|
|
17
13
|
/**
|
|
18
14
|
* Set the number value (will be clamped within range).
|
|
19
15
|
*/
|
|
@@ -7,17 +7,8 @@ export declare class SettingOption<CustomIds extends string = OptionParametersId
|
|
|
7
7
|
id: OptionParametersIds | CustomIds;
|
|
8
8
|
onChangeEmit: (changedValue: string) => void;
|
|
9
9
|
_options: Array<string>;
|
|
10
|
-
useUrlParams: boolean;
|
|
11
10
|
constructor(id: OptionParametersIds | CustomIds, label: string, description: string, defaultTextValue: string, options: Array<string>, useUrlParams: boolean, defaultOnChangeListener?: (changedValue: unknown, setting: SettingBase) => void);
|
|
12
|
-
|
|
13
|
-
* Parse the text value from the url parameters.
|
|
14
|
-
* @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found.
|
|
15
|
-
*/
|
|
16
|
-
getUrlParamText(): string;
|
|
17
|
-
/**
|
|
18
|
-
* Persist the setting value in URL.
|
|
19
|
-
*/
|
|
20
|
-
updateURLParams(): void;
|
|
11
|
+
protected getValueAsString(): string;
|
|
21
12
|
/**
|
|
22
13
|
* Add a change listener to the select element.
|
|
23
14
|
*/
|
|
@@ -8,15 +8,7 @@ export declare class SettingText<CustomIds extends string = TextParametersIds> e
|
|
|
8
8
|
onChangeEmit: (changedValue: string) => void;
|
|
9
9
|
useUrlParams: boolean;
|
|
10
10
|
constructor(id: TextParametersIds | CustomIds, label: string, description: string, defaultTextValue: string, useUrlParams: boolean, defaultOnChangeListener?: (changedValue: unknown, setting: SettingBase) => void);
|
|
11
|
-
|
|
12
|
-
* Parse the text value from the url parameters.
|
|
13
|
-
* @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found.
|
|
14
|
-
*/
|
|
15
|
-
getUrlParamText(): string;
|
|
16
|
-
/**
|
|
17
|
-
* Persist the setting value in URL.
|
|
18
|
-
*/
|
|
19
|
-
updateURLParams(): void;
|
|
11
|
+
protected getValueAsString(): string;
|
|
20
12
|
/**
|
|
21
13
|
* @return The setting's value.
|
|
22
14
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { DataChannelLatencyTestRecord, DataChannelLatencyTestRequest, DataChannelLatencyTestResponse, DataChannelLatencyTestResult, DataChannelLatencyTestSeq, DataChannelLatencyTestTimestamp } from
|
|
2
|
+
import { DataChannelLatencyTestRecord, DataChannelLatencyTestRequest, DataChannelLatencyTestResponse, DataChannelLatencyTestResult, DataChannelLatencyTestSeq, DataChannelLatencyTestTimestamp } from './DataChannelLatencyTestResults';
|
|
3
3
|
export type DataChannelLatencyTestConfig = {
|
|
4
4
|
duration: number;
|
|
5
5
|
rps: number;
|
|
@@ -1,50 +1,6 @@
|
|
|
1
1
|
import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController';
|
|
2
|
+
import { IInputController } from './IInputController';
|
|
2
3
|
import { Controller } from './GamepadTypes';
|
|
3
|
-
/**
|
|
4
|
-
* The class that handles the functionality of gamepads and controllers
|
|
5
|
-
*/
|
|
6
|
-
export declare class GamePadController {
|
|
7
|
-
controllers: Array<Controller>;
|
|
8
|
-
requestAnimationFrame: (callback: FrameRequestCallback) => number;
|
|
9
|
-
toStreamerMessagesProvider: StreamMessageController;
|
|
10
|
-
private gamePadEventListenerTracker;
|
|
11
|
-
/**
|
|
12
|
-
* @param toStreamerMessagesProvider - Stream message instance
|
|
13
|
-
*/
|
|
14
|
-
constructor(toStreamerMessagesProvider: StreamMessageController);
|
|
15
|
-
/**
|
|
16
|
-
* Unregister all event handlers.
|
|
17
|
-
*/
|
|
18
|
-
unregisterGamePadEvents(): void;
|
|
19
|
-
/**
|
|
20
|
-
* Connects the gamepad handler
|
|
21
|
-
* @param gamePadEvent - the activating gamepad event
|
|
22
|
-
*/
|
|
23
|
-
gamePadConnectHandler(gamePadEvent: GamepadEvent): void;
|
|
24
|
-
/**
|
|
25
|
-
* Disconnects the gamepad handler
|
|
26
|
-
* @param gamePadEvent - the activating gamepad event
|
|
27
|
-
*/
|
|
28
|
-
gamePadDisconnectHandler(gamePadEvent: GamepadEvent): void;
|
|
29
|
-
/**
|
|
30
|
-
* Scan for connected gamepads
|
|
31
|
-
*/
|
|
32
|
-
scanGamePads(): void;
|
|
33
|
-
/**
|
|
34
|
-
* Updates the status of the gamepad and sends the inputs
|
|
35
|
-
*/
|
|
36
|
-
updateStatus(): void;
|
|
37
|
-
onGamepadResponseReceived(gamepadId: number): void;
|
|
38
|
-
/**
|
|
39
|
-
* Event to send the gamepadconnected message to the application
|
|
40
|
-
*/
|
|
41
|
-
onGamepadConnected(): void;
|
|
42
|
-
/**
|
|
43
|
-
* Event to send the gamepaddisconnected message to the application
|
|
44
|
-
*/
|
|
45
|
-
onGamepadDisconnected(controllerIdx: number): void;
|
|
46
|
-
onBeforeUnload(_: Event): void;
|
|
47
|
-
}
|
|
48
4
|
/**
|
|
49
5
|
* Additional types for Window and Navigator
|
|
50
6
|
*/
|
|
@@ -60,7 +16,7 @@ declare global {
|
|
|
60
16
|
/**
|
|
61
17
|
* Gamepad layout codes enum
|
|
62
18
|
*/
|
|
63
|
-
export declare enum
|
|
19
|
+
export declare enum GamepadLayout {
|
|
64
20
|
RightClusterBottomButton = 0,
|
|
65
21
|
RightClusterRightButton = 1,
|
|
66
22
|
RightClusterLeftButton = 2,
|
|
@@ -83,3 +39,23 @@ export declare enum gamepadLayout {
|
|
|
83
39
|
RightStickHorizontal = 2,
|
|
84
40
|
RightStickVertical = 3
|
|
85
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Handles gamepad events from the document to send to the streamer.
|
|
44
|
+
*/
|
|
45
|
+
export declare class GamepadController implements IInputController {
|
|
46
|
+
controllers: Array<Controller>;
|
|
47
|
+
streamMessageController: StreamMessageController;
|
|
48
|
+
onGamepadConnectedListener: (event: GamepadEvent) => void;
|
|
49
|
+
onGamepadDisconnectedListener: (event: GamepadEvent) => void;
|
|
50
|
+
beforeUnloadListener: (event: Event) => void;
|
|
51
|
+
requestAnimationFrame: (callback: FrameRequestCallback) => number;
|
|
52
|
+
constructor(streamMessageController: StreamMessageController);
|
|
53
|
+
register(): void;
|
|
54
|
+
unregister(): void;
|
|
55
|
+
onGamepadResponseReceived(gamepadId: number): void;
|
|
56
|
+
private onGamepadConnected;
|
|
57
|
+
private onGamepadDisconnected;
|
|
58
|
+
private scanGamepads;
|
|
59
|
+
private updateStatus;
|
|
60
|
+
private onBeforeUnload;
|
|
61
|
+
}
|
|
@@ -6,3 +6,10 @@ export interface Controller {
|
|
|
6
6
|
prevState: Gamepad;
|
|
7
7
|
id: number | undefined;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Deep copies the values from a gamepad by first converting it to a JSON object and then back to a gamepad
|
|
11
|
+
*
|
|
12
|
+
* @param gamepad the original gamepad
|
|
13
|
+
* @returns a new gamepad object, populated with the original gamepads values
|
|
14
|
+
*/
|
|
15
|
+
export declare function deepCopyGamepad(gamepad: Gamepad): Gamepad;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base interface for all input controllers.
|
|
3
|
+
* Since controllers mostly just register events and handle them the external interface is limited
|
|
4
|
+
* to register/unregister
|
|
5
|
+
*/
|
|
6
|
+
export interface IInputController {
|
|
7
|
+
/**
|
|
8
|
+
* Tells the controller to register itself to the events it needs to operate.
|
|
9
|
+
*/
|
|
10
|
+
register(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Tells the cnotroller to unregister from the events it previously registered to.
|
|
13
|
+
* No behaviour through the controller should happen past this point until register is called again.
|
|
14
|
+
*/
|
|
15
|
+
unregister(): void;
|
|
16
|
+
}
|