From 95f2bef3349b6b715e3261a259afe6e0bed53c9d Mon Sep 17 00:00:00 2001 From: hmuurine Date: Mon, 6 Mar 2023 09:32:58 +0200 Subject: [PATCH] Enable/disable user input devices (#136) * move registerLockedMouseEvents and registerHoveringMouseEvents to MouseController * add a utility that keeps track of registered event handlers for easy unregistering * fix stream handler name MoveMouse -> MouseMove * support unregistering gamepad events * support unregistering keyboard events * support unregistering mouse events * support unregistering touch events * unregister input event handlers before registering new ones * configurable keyboard/mouse/touch/gamepad support * start/stop game pad polling on config enable/disable * UI: add user input config to Settings menu * added config flag EnableXRControllerInput for enabling/disabling XR controller messages * added the new config flags to documentation * smaller version of the settings panel image to better match the old image resolution * Simplify input flag naming. Separate input toggles into new section in the settings panel --- .../Docs/Resources/Images/settings-panel.png | Bin 74415 -> 70136 bytes Frontend/Docs/Settings Panel.md | 9 + Frontend/library/package-lock.json | 4 +- Frontend/library/src/Config/Config.ts | 60 ++++++ .../library/src/Inputs/FakeTouchController.ts | 39 +++- .../library/src/Inputs/GamepadController.ts | 56 ++++-- .../library/src/Inputs/HoveringMouseEvents.ts | 7 + Frontend/library/src/Inputs/IMouseEvents.ts | 5 + .../library/src/Inputs/ITouchController.ts | 5 + .../library/src/Inputs/InputClassesFactory.ts | 94 +--------- .../library/src/Inputs/KeyboardController.ts | 31 +++- .../library/src/Inputs/LockedMouseEvents.ts | 18 ++ .../library/src/Inputs/MouseController.ts | 172 +++++++++++++++++- .../library/src/Inputs/TouchController.ts | 35 +++- .../src/PixelStreaming/PixelStreaming.ts | 31 +++- .../library/src/Util/EventListenerTracker.ts | 29 +++ .../library/src/VideoPlayer/VideoPlayer.ts | 2 - .../WebRtcPlayer/WebRtcPlayerController.ts | 73 ++++++-- Frontend/library/src/WebXR/WebXRController.ts | 23 ++- Frontend/ui-library/package-lock.json | 4 +- Frontend/ui-library/src/Config/ConfigUI.ts | 31 ++++ 21 files changed, 563 insertions(+), 165 deletions(-) create mode 100644 Frontend/library/src/Util/EventListenerTracker.ts diff --git a/Frontend/Docs/Resources/Images/settings-panel.png b/Frontend/Docs/Resources/Images/settings-panel.png index ff16004b62928e74f104b61bfebc5036d46b4352..521bb2634cb90ac6ea1ad98819228276070bc974 100644 GIT binary patch literal 70136 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 literal 74415 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

(rQ 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 diff --git a/Frontend/Docs/Settings Panel.md b/Frontend/Docs/Settings Panel.md index b510a0b8..b2705d62 100644 --- a/Frontend/Docs/Settings Panel.md +++ b/Frontend/Docs/Settings Panel.md @@ -35,6 +35,15 @@ This page will be updated with new features and commands as they become availabl | **Control scheme** | If the scheme is `locked mouse` the browser will use `pointerlock` to capture your mouse, whereas if the scheme is `hovering mouse` you will retain your OS/browser cursor. | | **Color scheme** | Allows you to switch between light mode and dark mode. | +### Input +| **Setting** | **Description** | +| --- | --- | +| **Keyboard input** | If enabled, captures and sends keyboard events to the Unreal Engine application. | +| **Mouse input** | If enabled, captures and sends mouse events to the Unreal Engine application. | +| **Touch input** | If enabled, captures and sends touch events to the Unreal Engine application. | +| **Gamepad input** | If enabled, captures and sends gamepad events to the Unreal Engine application. | +| **XR controller input** | If enabled, captures and sends XR controller events to the Unreal Engine application. | + ### Encoder | **Setting** | **Description** | | --- | --- | diff --git a/Frontend/library/package-lock.json b/Frontend/library/package-lock.json index 9929e2d8..634a3e60 100644 --- a/Frontend/library/package-lock.json +++ b/Frontend/library/package-lock.json @@ -1,12 +1,12 @@ { "name": "@epicgames-ps/lib-pixelstreamingfrontend-ue5.2", - "version": "0.1.1", + "version": "0.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@epicgames-ps/lib-pixelstreamingfrontend-ue5.2", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "dependencies": { "sdp": "^3.1.0" diff --git a/Frontend/library/src/Config/Config.ts b/Frontend/library/src/Config/Config.ts index 200c3d77..6f64fc82 100644 --- a/Frontend/library/src/Config/Config.ts +++ b/Frontend/library/src/Config/Config.ts @@ -27,6 +27,11 @@ export class Flags { static StartVideoMuted = 'StartVideoMuted' as const; static SuppressBrowserKeys = 'SuppressBrowserKeys' as const; static UseMic = 'UseMic' as const; + static KeyboardInput = 'KeyboardInput' as const; + static MouseInput = 'MouseInput' as const; + static TouchInput = 'TouchInput' as const; + static GamepadInput = 'GamepadInput' as const; + static XRControllerInput = 'XRControllerInput' as const; } export type FlagsKeys = Exclude; @@ -398,6 +403,61 @@ export class Config { ) ); + this.flags.set( + Flags.KeyboardInput, + new SettingFlag( + Flags.KeyboardInput, + 'Keyboard input', + 'If enabled, send keyboard events to streamer', + true, + useUrlParams + ) + ); + + this.flags.set( + Flags.MouseInput, + new SettingFlag( + Flags.MouseInput, + 'Mouse input', + 'If enabled, send mouse events to streamer', + true, + useUrlParams + ) + ); + + this.flags.set( + Flags.TouchInput, + new SettingFlag( + Flags.TouchInput, + 'Touch input', + 'If enabled, send touch events to streamer', + true, + useUrlParams + ) + ); + + this.flags.set( + Flags.GamepadInput, + new SettingFlag( + Flags.GamepadInput, + 'Gamepad input', + 'If enabled, send gamepad events to streamer', + true, + useUrlParams + ) + ); + + this.flags.set( + Flags.XRControllerInput, + new SettingFlag( + Flags.XRControllerInput, + 'XR controller input', + 'If enabled, send XR controller events to streamer', + true, + useUrlParams + ) + ); + /** * Numeric parameters */ diff --git a/Frontend/library/src/Inputs/FakeTouchController.ts b/Frontend/library/src/Inputs/FakeTouchController.ts index 982a2f2d..21d63ad9 100644 --- a/Frontend/library/src/Inputs/FakeTouchController.ts +++ b/Frontend/library/src/Inputs/FakeTouchController.ts @@ -5,6 +5,7 @@ import { StreamMessageController } from '../UeInstanceMessage/StreamMessageContr import { VideoPlayer } from '../VideoPlayer/VideoPlayer'; import { ITouchController } from './ITouchController'; import { MouseButton } from './MouseButtons'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; /** * Allows for the usage of fake touch events and implements ITouchController @@ -18,6 +19,9 @@ export class FakeTouchController implements ITouchController { coordinateConverter: CoordinateConverter; videoElementParentClientRect: DOMRect; + // Utility for keeping track of event handlers and unregistering them + private touchEventListenerTracker = new EventListenerTracker(); + /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video element instance @@ -31,9 +35,28 @@ export class FakeTouchController implements ITouchController { this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.videoElementProvider = videoElementProvider; this.coordinateConverter = coordinateConverter; - document.ontouchstart = (ev: TouchEvent) => this.onTouchStart(ev); - document.ontouchend = (ev: TouchEvent) => this.onTouchEnd(ev); - document.ontouchmove = (ev: TouchEvent) => this.onTouchMove(ev); + const ontouchstart = (ev: TouchEvent) => this.onTouchStart(ev); + const ontouchend = (ev: TouchEvent) => this.onTouchEnd(ev); + const ontouchmove = (ev: TouchEvent) => this.onTouchMove(ev); + document.addEventListener('touchstart', ontouchstart, { passive: false }); + document.addEventListener('touchend', ontouchend, { passive: false }); + document.addEventListener('touchmove', ontouchmove, { passive: false }); + this.touchEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener('touchstart', ontouchstart) + ); + this.touchEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener('touchend', ontouchend) + ); + this.touchEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener('touchmove', ontouchmove) + ); + } + + /** + * Unregister all touch events + */ + unregisterTouchEvents() { + this.touchEventListenerTracker.unregisterAll(); } /** @@ -62,8 +85,8 @@ export class FakeTouchController implements ITouchController { const videoElementParent = this.videoElementProvider.getVideoParentElement() as HTMLDivElement; - const mouseEvent = new MouseEvent(touch.type, first_touch); - videoElementParent.onmouseenter(mouseEvent); + const mouseEvent = new MouseEvent('mouseenter', first_touch); + videoElementParent.dispatchEvent(mouseEvent); const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned( this.fakeTouchFinger.x, @@ -107,8 +130,8 @@ export class FakeTouchController implements ITouchController { coord.y ]); - const mouseEvent = new MouseEvent(touchEvent.type, touch); - videoElementParent.onmouseleave(mouseEvent); + const mouseEvent = new MouseEvent('mouseleave', touch); + videoElementParent.dispatchEvent(mouseEvent); this.fakeTouchFinger = null; break; } @@ -140,7 +163,7 @@ export class FakeTouchController implements ITouchController { x - this.fakeTouchFinger.x, y - this.fakeTouchFinger.y ); - toStreamerHandlers.get('MoveMouse')([ + toStreamerHandlers.get('MouseMove')([ coord.x, coord.y, delta.x, diff --git a/Frontend/library/src/Inputs/GamepadController.ts b/Frontend/library/src/Inputs/GamepadController.ts index cdba4bbb..9eaf7ae5 100644 --- a/Frontend/library/src/Inputs/GamepadController.ts +++ b/Frontend/library/src/Inputs/GamepadController.ts @@ -2,6 +2,7 @@ import { Logger } from '../Logger/Logger'; import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; import { Controller } from './GamepadTypes'; /** @@ -12,35 +13,60 @@ export class GamePadController { requestAnimationFrame: (callback: FrameRequestCallback) => number; toStreamerMessagesProvider: StreamMessageController; + // Utility for keeping track of event handlers and unregistering them + private gamePadEventListenerTracker = new EventListenerTracker(); + /** * @param toStreamerMessagesProvider - Stream message instance */ constructor(toStreamerMessagesProvider: StreamMessageController) { this.toStreamerMessagesProvider = toStreamerMessagesProvider; - this.requestAnimationFrame = + this.requestAnimationFrame = ( window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || - window.requestAnimationFrame; + window.requestAnimationFrame + ).bind(window); const browserWindow = window as Window; if ('GamepadEvent' in browserWindow) { - window.addEventListener('gamepadconnected', (ev: GamepadEvent) => - this.gamePadConnectHandler(ev) + const onGamePadConnected = (ev: GamepadEvent) => + this.gamePadConnectHandler(ev); + const onGamePadDisconnected = (ev: GamepadEvent) => + this.gamePadDisconnectHandler(ev); + window.addEventListener('gamepadconnected', onGamePadConnected); + window.addEventListener('gamepaddisconnected', onGamePadDisconnected); + this.gamePadEventListenerTracker.addUnregisterCallback( + () => window.removeEventListener('gamepadconnected', onGamePadConnected) ); - window.addEventListener('gamepaddisconnected', (ev: GamepadEvent) => - this.gamePadDisconnectHandler(ev) + this.gamePadEventListenerTracker.addUnregisterCallback( + () => window.removeEventListener('gamepaddisconnected', onGamePadDisconnected) ); } else if ('WebKitGamepadEvent' in browserWindow) { - window.addEventListener( - 'webkitgamepadconnected', - (ev: GamepadEvent) => this.gamePadConnectHandler(ev) + const onWebkitGamePadConnected = (ev: GamepadEvent) => this.gamePadConnectHandler(ev); + const onWebkitGamePadDisconnected = (ev: GamepadEvent) => this.gamePadDisconnectHandler(ev); + window.addEventListener('webkitgamepadconnected', onWebkitGamePadConnected); + window.addEventListener('webkitgamepaddisconnected', onWebkitGamePadDisconnected); + this.gamePadEventListenerTracker.addUnregisterCallback( + () => window.removeEventListener('webkitgamepadconnected', onWebkitGamePadConnected) ); - window.addEventListener( - 'webkitgamepaddisconnected', - (ev: GamepadEvent) => this.gamePadDisconnectHandler(ev) + this.gamePadEventListenerTracker.addUnregisterCallback( + () => window.removeEventListener('webkitgamepaddisconnected', onWebkitGamePadDisconnected) ); } this.controllers = []; + for (const gamepad of navigator.getGamepads()) { + if (gamepad) { + this.gamePadConnectHandler(new GamepadEvent('gamepadconnected', { gamepad })); + } + } + } + + /** + * Unregisters all event handlers + */ + unregisterGamePadEvents() { + this.gamePadEventListenerTracker.unregisterAll(); + this.controllers = []; } /** @@ -64,7 +90,7 @@ export class GamePadController { 'gamepad: ' + gamepad.id + ' connected', 6 ); - window.requestAnimationFrame(() => this.updateStatus()); + this.requestAnimationFrame(() => this.updateStatus()); } /** @@ -185,7 +211,9 @@ export class GamePadController { } this.controllers[controllerIndex].prevState = currentState; } - this.requestAnimationFrame(() => this.updateStatus()); + if (this.controllers.length > 0) { + this.requestAnimationFrame(() => this.updateStatus()); + } } } diff --git a/Frontend/library/src/Inputs/HoveringMouseEvents.ts b/Frontend/library/src/Inputs/HoveringMouseEvents.ts index 674eafa5..6526dffd 100644 --- a/Frontend/library/src/Inputs/HoveringMouseEvents.ts +++ b/Frontend/library/src/Inputs/HoveringMouseEvents.ts @@ -17,6 +17,13 @@ export class HoveringMouseEvents implements IMouseEvents { this.mouseController = mouseController; } + /** + * Unregister event handlers + */ + unregisterMouseEvents(): void { + // empty for HoveringMouseEvents implementation + } + /** * Handle the mouse move event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event diff --git a/Frontend/library/src/Inputs/IMouseEvents.ts b/Frontend/library/src/Inputs/IMouseEvents.ts index 7c9033cd..65d2dc65 100644 --- a/Frontend/library/src/Inputs/IMouseEvents.ts +++ b/Frontend/library/src/Inputs/IMouseEvents.ts @@ -56,4 +56,9 @@ export interface IMouseEvents { * @param mouseEvent - mouse event */ handleContextMenu?(mouseEvent: MouseEvent): void; + + /** + * Unregisters any registered mouse event handlers + */ + unregisterMouseEvents(): void; } diff --git a/Frontend/library/src/Inputs/ITouchController.ts b/Frontend/library/src/Inputs/ITouchController.ts index 39cb0396..c8f9d562 100644 --- a/Frontend/library/src/Inputs/ITouchController.ts +++ b/Frontend/library/src/Inputs/ITouchController.ts @@ -21,4 +21,9 @@ export interface ITouchController { * @param touchEvent - Touch Event Data */ onTouchMove(touchEvent: TouchEvent): void; + + /** + * Unregisters all touch event handlers + */ + unregisterTouchEvents(): void; } diff --git a/Frontend/library/src/Inputs/InputClassesFactory.ts b/Frontend/library/src/Inputs/InputClassesFactory.ts index c95b2177..74076193 100644 --- a/Frontend/library/src/Inputs/InputClassesFactory.ts +++ b/Frontend/library/src/Inputs/InputClassesFactory.ts @@ -6,9 +6,6 @@ import { MouseController } from './MouseController'; import { TouchController } from './TouchController'; import { GamePadController } from './GamepadController'; import { Config, ControlSchemeType } from '../Config/Config'; -import { LockedMouseEvents } from './LockedMouseEvents'; -import { HoveringMouseEvents } from './HoveringMouseEvents'; -import { IMouseEvents } from './IMouseEvents'; import { Logger } from '../Logger/Logger'; import { CoordinateConverter } from '../Util/CoordinateConverter'; import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController'; @@ -61,110 +58,29 @@ export class InputClassesFactory { const mouseController = new MouseController( this.toStreamerMessagesProvider, this.videoElementProvider, - this.coordinateConverter + this.coordinateConverter, + this.activeKeys ); - mouseController.clearMouseEvents(); switch (controlScheme) { case ControlSchemeType.LockedMouse: - this.registerLockedMouseEvents(mouseController); + mouseController.registerLockedMouseEvents(mouseController); break; case ControlSchemeType.HoveringMouse: - this.registerHoveringMouseEvents(mouseController); + mouseController.registerHoveringMouseEvents(mouseController); break; default: Logger.Info( Logger.GetStackTrace(), 'unknown Control Scheme Type Defaulting to Locked Mouse Events' ); - this.registerLockedMouseEvents(mouseController); + mouseController.registerLockedMouseEvents(mouseController); break; } return mouseController; } - /** - * Register a locked mouse class - * @param mouseController - a mouse controller instance - * @param playerStyleAttributesProvider - a player style attributes instance - */ - registerLockedMouseEvents(mouseController: MouseController) { - const videoElementParent = - this.videoElementProvider.getVideoParentElement() as HTMLDivElement; - const lockedMouseEvents: IMouseEvents = new LockedMouseEvents( - this.videoElementProvider, - mouseController, - this.activeKeys - ); - - videoElementParent.requestPointerLock = - videoElementParent.requestPointerLock || - videoElementParent.mozRequestPointerLock; - document.exitPointerLock = - document.exitPointerLock || document.mozExitPointerLock; - - // minor hack to alleviate ios not supporting pointerlock - if (videoElementParent.requestPointerLock) { - videoElementParent.onclick = () => { - videoElementParent.requestPointerLock(); - }; - } - - const lockStateChangeListener = () => - lockedMouseEvents.lockStateChange(); - document.addEventListener( - 'pointerlockchange', - lockStateChangeListener, - false - ); - document.addEventListener( - 'mozpointerlockchange', - lockStateChangeListener, - false - ); - - videoElementParent.onmousedown = (mouseEvent: MouseEvent) => - lockedMouseEvents.handleMouseDown(mouseEvent); - videoElementParent.onmouseup = (mouseEvent: MouseEvent) => - lockedMouseEvents.handleMouseUp(mouseEvent); - videoElementParent.onwheel = (wheelEvent: WheelEvent) => - lockedMouseEvents.handleMouseWheel(wheelEvent); - videoElementParent.ondblclick = (mouseEvent: MouseEvent) => - lockedMouseEvents.handleMouseDouble(mouseEvent); - videoElementParent.pressMouseButtons = (mouseEvent: MouseEvent) => - lockedMouseEvents.handlePressMouseButtons(mouseEvent); - videoElementParent.releaseMouseButtons = (mouseEvent: MouseEvent) => - lockedMouseEvents.handleReleaseMouseButtons(mouseEvent); - } - - /** - * Register a hovering mouse class - * @param mouseController - A mouse controller object - */ - registerHoveringMouseEvents(mouseController: MouseController) { - const videoElementParent = - this.videoElementProvider.getVideoParentElement() as HTMLDivElement; - const hoveringMouseEvents = new HoveringMouseEvents(mouseController); - - videoElementParent.onmousemove = (mouseEvent: MouseEvent) => - hoveringMouseEvents.updateMouseMovePosition(mouseEvent); - videoElementParent.onmousedown = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handleMouseDown(mouseEvent); - videoElementParent.onmouseup = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handleMouseUp(mouseEvent); - videoElementParent.oncontextmenu = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handleContextMenu(mouseEvent); - videoElementParent.onwheel = (wheelEvent: WheelEvent) => - hoveringMouseEvents.handleMouseWheel(wheelEvent); - videoElementParent.ondblclick = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handleMouseDouble(mouseEvent); - videoElementParent.pressMouseButtons = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handlePressMouseButtons(mouseEvent); - videoElementParent.releaseMouseButtons = (mouseEvent: MouseEvent) => - hoveringMouseEvents.handleReleaseMouseButtons(mouseEvent); - } - /** * register touch events * @param fakeMouseTouch - the faked mouse touch event diff --git a/Frontend/library/src/Inputs/KeyboardController.ts b/Frontend/library/src/Inputs/KeyboardController.ts index 6866c045..f650a832 100644 --- a/Frontend/library/src/Inputs/KeyboardController.ts +++ b/Frontend/library/src/Inputs/KeyboardController.ts @@ -5,6 +5,7 @@ import { Logger } from '../Logger/Logger'; import { ActiveKeys } from './InputClassesFactory'; import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController'; import { Config, Flags } from '../Config/Config'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; interface ICodeToKeyCode { [key: string]: number; @@ -18,6 +19,9 @@ export class KeyboardController { activeKeysProvider: ActiveKeys; config: Config; + // Utility for keeping track of event handlers and unregistering them + private keyboardEventListenerTracker = new EventListenerTracker(); + /* * New browser APIs have moved away from KeyboardEvent.keyCode to KeyboardEvent.Code. * For details see: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#constants_for_keycode_value @@ -146,11 +150,32 @@ export class KeyboardController { * Registers document keyboard events with the controller */ registerKeyBoardEvents() { - document.onkeydown = (ev: KeyboardEvent) => this.handleOnKeyDown(ev); - document.onkeyup = (ev: KeyboardEvent) => this.handleOnKeyUp(ev); + const keyDownHandler = (ev: KeyboardEvent) => this.handleOnKeyDown(ev); + const keyUpHandler = (ev: KeyboardEvent) => this.handleOnKeyUp(ev); + const keyPressHandler = (ev: KeyboardEvent) => this.handleOnKeyPress(ev); + + document.addEventListener("keydown", keyDownHandler); + document.addEventListener("keyup", keyUpHandler); //This has been deprecated as at Jun 13 2021 - document.onkeypress = (ev: KeyboardEvent) => this.handleOnKeyPress(ev); + document.addEventListener("keypress", keyPressHandler); + + this.keyboardEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener("keydown", keyDownHandler) + ); + this.keyboardEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener("keyup", keyUpHandler) + ); + this.keyboardEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener("keypress", keyPressHandler) + ); + } + + /** + * Unregisters document keyboard events + */ + unregisterKeyBoardEvents() { + this.keyboardEventListenerTracker.unregisterAll(); } /** diff --git a/Frontend/library/src/Inputs/LockedMouseEvents.ts b/Frontend/library/src/Inputs/LockedMouseEvents.ts index 38e3af6b..f374eee7 100644 --- a/Frontend/library/src/Inputs/LockedMouseEvents.ts +++ b/Frontend/library/src/Inputs/LockedMouseEvents.ts @@ -6,6 +6,7 @@ import { IMouseEvents } from './IMouseEvents'; import { NormalizedQuantizedUnsignedCoord } from '../Util/CoordinateConverter'; import { ActiveKeys } from './InputClassesFactory'; import { VideoPlayer } from '../VideoPlayer/VideoPlayer'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; /** * Handle the mouse locked events @@ -21,6 +22,9 @@ export class LockedMouseEvents implements IMouseEvents { this.updateMouseMovePosition(mouseEvent); }; + // Utility for keeping track of event handlers and unregistering them + private mouseEventListenerTracker = new EventListenerTracker(); + /** * @param videoElementProvider - Video Player instance * @param mouseController - Mouse controller instance @@ -46,6 +50,13 @@ export class LockedMouseEvents implements IMouseEvents { ); } + /** + * Unregisters all event handlers + */ + unregisterMouseEvents() { + this.mouseEventListenerTracker.unregisterAll(); + } + /** * Handle when the locked state Changed */ @@ -65,6 +76,13 @@ export class LockedMouseEvents implements IMouseEvents { this.updateMouseMovePositionEvent, false ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener( + 'mousemove', + this.updateMouseMovePositionEvent, + false + ) + ); } else { Logger.Log( Logger.GetStackTrace(), diff --git a/Frontend/library/src/Inputs/MouseController.ts b/Frontend/library/src/Inputs/MouseController.ts index 14f14a2c..611d770d 100644 --- a/Frontend/library/src/Inputs/MouseController.ts +++ b/Frontend/library/src/Inputs/MouseController.ts @@ -5,6 +5,11 @@ import { Logger } from '../Logger/Logger'; import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController'; import { CoordinateConverter } from '../Util/CoordinateConverter'; import { VideoPlayer } from '../VideoPlayer/VideoPlayer'; +import { IMouseEvents } from './IMouseEvents'; +import { LockedMouseEvents } from './LockedMouseEvents'; +import { HoveringMouseEvents } from './HoveringMouseEvents'; +import type { ActiveKeys } from './InputClassesFactory'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; /** * Handles the Mouse Inputs for the document @@ -13,6 +18,10 @@ export class MouseController { videoElementProvider: VideoPlayer; toStreamerMessagesProvider: StreamMessageController; coordinateConverter: CoordinateConverter; + activeKeysProvider: ActiveKeys; + + // Utility for keeping track of event handlers and unregistering them + private mouseEventListenerTracker = new EventListenerTracker(); /** * @param toStreamerMessagesProvider - Stream message instance @@ -22,26 +31,160 @@ export class MouseController { constructor( toStreamerMessagesProvider: StreamMessageController, videoElementProvider: VideoPlayer, - coordinateConverter: CoordinateConverter + coordinateConverter: CoordinateConverter, + activeKeysProvider: ActiveKeys ) { this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.coordinateConverter = coordinateConverter; this.videoElementProvider = videoElementProvider; + this.activeKeysProvider = activeKeysProvider; this.registerMouseEnterAndLeaveEvents(); } /** * Clears all the click events on the current video element parent div */ - clearMouseEvents() { + unregisterMouseEvents() { + this.mouseEventListenerTracker.unregisterAll(); + } + + /** + * Register a locked mouse class + * @param mouseController - a mouse controller instance + * @param playerStyleAttributesProvider - a player style attributes instance + */ + registerLockedMouseEvents(mouseController: MouseController) { const videoElementParent = this.videoElementProvider.getVideoParentElement() as HTMLDivElement; - videoElementParent.onclick = null; - videoElementParent.onmousedown = null; - videoElementParent.onmouseup = null; - videoElementParent.onwheel = null; - videoElementParent.onmousemove = null; - videoElementParent.oncontextmenu = null; + const lockedMouseEvents: IMouseEvents = new LockedMouseEvents( + this.videoElementProvider, + mouseController, + this.activeKeysProvider + ); + + videoElementParent.requestPointerLock = + videoElementParent.requestPointerLock || + videoElementParent.mozRequestPointerLock; + document.exitPointerLock = + document.exitPointerLock || document.mozExitPointerLock; + + // minor hack to alleviate ios not supporting pointerlock + if (videoElementParent.requestPointerLock) { + const onclick = () => { + videoElementParent.requestPointerLock(); + }; + videoElementParent.addEventListener('click', onclick); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('click', onclick) + ); + } + + const lockStateChangeListener = () => + lockedMouseEvents.lockStateChange(); + document.addEventListener( + 'pointerlockchange', + lockStateChangeListener, + false + ); + document.addEventListener( + 'mozpointerlockchange', + lockStateChangeListener, + false + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener( + 'pointerlockchange', + lockStateChangeListener, + false + ) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener( + 'mozpointerlockchange', + lockStateChangeListener, + false + ) + ); + + const onmousedown = (mouseEvent: MouseEvent) => + lockedMouseEvents.handleMouseDown(mouseEvent); + const onmouseup = (mouseEvent: MouseEvent) => + lockedMouseEvents.handleMouseUp(mouseEvent); + const onwheel = (wheelEvent: WheelEvent) => + lockedMouseEvents.handleMouseWheel(wheelEvent); + const ondblclick = (mouseEvent: MouseEvent) => + lockedMouseEvents.handleMouseDouble(mouseEvent); + videoElementParent.addEventListener('mousedown', onmousedown); + videoElementParent.addEventListener('mouseup', onmouseup); + videoElementParent.addEventListener('wheel', onwheel); + videoElementParent.addEventListener('dblclick', ondblclick); + + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mousedown', onmousedown) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mouseup', onmouseup) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('wheel', onwheel) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('dblclick', ondblclick) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => lockedMouseEvents.unregisterMouseEvents() + ); + } + + /** + * Register a hovering mouse class + * @param mouseController - A mouse controller object + */ + registerHoveringMouseEvents(mouseController: MouseController) { + const videoElementParent = + this.videoElementProvider.getVideoParentElement() as HTMLDivElement; + const hoveringMouseEvents = new HoveringMouseEvents(mouseController); + + const onmousemove = (mouseEvent: MouseEvent) => + hoveringMouseEvents.updateMouseMovePosition(mouseEvent); + const onmousedown = (mouseEvent: MouseEvent) => + hoveringMouseEvents.handleMouseDown(mouseEvent); + const onmouseup = (mouseEvent: MouseEvent) => + hoveringMouseEvents.handleMouseUp(mouseEvent); + const oncontextmenu = (mouseEvent: MouseEvent) => + hoveringMouseEvents.handleContextMenu(mouseEvent); + const onwheel = (wheelEvent: WheelEvent) => + hoveringMouseEvents.handleMouseWheel(wheelEvent); + const ondblclick = (mouseEvent: MouseEvent) => + hoveringMouseEvents.handleMouseDouble(mouseEvent); + videoElementParent.addEventListener('mousemove', onmousemove); + videoElementParent.addEventListener('mousedown', onmousedown); + videoElementParent.addEventListener('mouseup', onmouseup); + videoElementParent.addEventListener('contextmenu', oncontextmenu); + videoElementParent.addEventListener('wheel', onwheel); + videoElementParent.addEventListener('dblclick', ondblclick); + + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mousemove', onmousemove) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mousedown', onmousedown) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mouseup', onmouseup) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('contextmenu', oncontextmenu) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('wheel', onwheel) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('dblclick', ondblclick) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => hoveringMouseEvents.unregisterMouseEvents() + ); } /** @@ -52,7 +195,7 @@ export class MouseController { this.videoElementProvider.getVideoParentElement() as HTMLDivElement; // Handle when the Mouse has entered the element - videoElementParent.onmouseenter = (event: MouseEvent) => { + const onmouseenter = (event: MouseEvent) => { if (!this.videoElementProvider.isVideoReady()) { return; } @@ -62,7 +205,7 @@ export class MouseController { }; // Handles when the mouse has left the element - videoElementParent.onmouseleave = (event: MouseEvent) => { + const onmouseleave = (event: MouseEvent) => { if (!this.videoElementProvider.isVideoReady()) { return; } @@ -70,6 +213,15 @@ export class MouseController { this.sendMouseLeave(); this.releaseMouseButtons(event.buttons, event.x, event.y); }; + videoElementParent.addEventListener('mouseenter', onmouseenter); + videoElementParent.addEventListener('mouseleave', onmouseleave); + + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mouseenter', onmouseenter) + ); + this.mouseEventListenerTracker.addUnregisterCallback( + () => videoElementParent.removeEventListener('mouseleave', onmouseleave) + ); } /** diff --git a/Frontend/library/src/Inputs/TouchController.ts b/Frontend/library/src/Inputs/TouchController.ts index ff8209cd..83aec684 100644 --- a/Frontend/library/src/Inputs/TouchController.ts +++ b/Frontend/library/src/Inputs/TouchController.ts @@ -5,6 +5,7 @@ import { CoordinateConverter } from '../Util/CoordinateConverter'; import { StreamMessageController } from '../UeInstanceMessage/StreamMessageController'; import { VideoPlayer } from '../VideoPlayer/VideoPlayer'; import { ITouchController } from './ITouchController'; +import { EventListenerTracker } from '../Util/EventListenerTracker'; /** * Handles the Touch input Events */ @@ -17,6 +18,9 @@ export class TouchController implements ITouchController { fingerIds = new Map(); maxByteValue = 255; + // Utility for keeping track of event handlers and unregistering them + private touchEventListenerTracker = new EventListenerTracker(); + /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video Player instance @@ -31,18 +35,41 @@ export class TouchController implements ITouchController { this.videoElementProvider = videoElementProvider; this.coordinateConverter = coordinateConverter; this.videoElementParent = videoElementProvider.getVideoElement(); - this.videoElementParent.ontouchstart = (ev: TouchEvent) => + const ontouchstart = (ev: TouchEvent) => this.onTouchStart(ev); - this.videoElementParent.ontouchend = (ev: TouchEvent) => + const ontouchend = (ev: TouchEvent) => this.onTouchEnd(ev); - this.videoElementParent.ontouchmove = (ev: TouchEvent) => + const ontouchmove = (ev: TouchEvent) => this.onTouchMove(ev); + this.videoElementParent.addEventListener('touchstart', ontouchstart, { passive: false }); + this.videoElementParent.addEventListener('touchend', ontouchend, { passive: false }); + this.videoElementParent.addEventListener('touchmove', ontouchmove, { passive: false }); + this.touchEventListenerTracker.addUnregisterCallback( + () => this.videoElementParent.removeEventListener('touchstart', ontouchstart) + ); + this.touchEventListenerTracker.addUnregisterCallback( + () => this.videoElementParent.removeEventListener('touchend', ontouchend) + ); + this.touchEventListenerTracker.addUnregisterCallback( + () => this.videoElementParent.removeEventListener('touchmove', ontouchmove) + ); Logger.Log(Logger.GetStackTrace(), 'Touch Events Registered', 6); // is this strictly necessary? - document.ontouchmove = (event: TouchEvent) => { + const preventOnTouchMove = (event: TouchEvent) => { event.preventDefault(); }; + document.addEventListener('touchmove', preventOnTouchMove, { passive: false }); + this.touchEventListenerTracker.addUnregisterCallback( + () => document.removeEventListener('touchmove', preventOnTouchMove) + ); + } + + /** + * Unregister all touch events + */ + unregisterTouchEvents() { + this.touchEventListenerTracker.unregisterAll(); } /** diff --git a/Frontend/library/src/PixelStreaming/PixelStreaming.ts b/Frontend/library/src/PixelStreaming/PixelStreaming.ts index ee8bccad..eaa9da07 100644 --- a/Frontend/library/src/PixelStreaming/PixelStreaming.ts +++ b/Frontend/library/src/PixelStreaming/PixelStreaming.ts @@ -153,7 +153,36 @@ export class PixelStreaming { isHoveringMouse ? 'Hovering' : 'Locked' } Mouse` ); - this._webRtcController.activateRegisterMouse(); + this._webRtcController.setMouseInputEnabled(this.config.isFlagEnabled(Flags.MouseInput)); + } + ); + + // user input + this.config._addOnSettingChangedListener( + Flags.KeyboardInput, + (isEnabled: boolean) => { + this._webRtcController.setKeyboardInputEnabled(isEnabled); + } + ); + + this.config._addOnSettingChangedListener( + Flags.MouseInput, + (isEnabled: boolean) => { + this._webRtcController.setMouseInputEnabled(isEnabled); + } + ); + + this.config._addOnSettingChangedListener( + Flags.TouchInput, + (isEnabled: boolean) => { + this._webRtcController.setTouchInputEnabled(isEnabled); + } + ); + + this.config._addOnSettingChangedListener( + Flags.GamepadInput, + (isEnabled: boolean) => { + this._webRtcController.setGamePadInputEnabled(isEnabled); } ); diff --git a/Frontend/library/src/Util/EventListenerTracker.ts b/Frontend/library/src/Util/EventListenerTracker.ts new file mode 100644 index 00000000..c0058690 --- /dev/null +++ b/Frontend/library/src/Util/EventListenerTracker.ts @@ -0,0 +1,29 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +export type UnregisterFunction = () => void; + +export class EventListenerTracker { + private unregisterCallbacks: UnregisterFunction[]; + + constructor() { + this.unregisterCallbacks = []; + } + + /** + * Add a new callback that is executed when unregisterAll is called. + * @param callback + */ + addUnregisterCallback(callback: UnregisterFunction) { + this.unregisterCallbacks.push(callback); + } + + /** + * Execute all callbacks and clear the list. + */ + unregisterAll() { + for (const callback of this.unregisterCallbacks) { + callback(); + } + this.unregisterCallbacks = []; + } +} diff --git a/Frontend/library/src/VideoPlayer/VideoPlayer.ts b/Frontend/library/src/VideoPlayer/VideoPlayer.ts index 0cf4d8e3..2e432174 100644 --- a/Frontend/library/src/VideoPlayer/VideoPlayer.ts +++ b/Frontend/library/src/VideoPlayer/VideoPlayer.ts @@ -8,8 +8,6 @@ import { Logger } from '../Logger/Logger'; */ declare global { interface HTMLElement { - pressMouseButtons?(mouseEvent: MouseEvent): void; - releaseMouseButtons?(mouseEvent: MouseEvent): void; mozRequestPointerLock?(): void; } } diff --git a/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts b/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts index 6d4e0b49..1d13e2c1 100644 --- a/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts +++ b/Frontend/library/src/WebRtcPlayer/WebRtcPlayerController.ts @@ -1026,10 +1026,7 @@ export class WebRtcPlayerController { return; } - this.touchController = this.inputClassesFactory.registerTouch( - this.config.isFlagEnabled(Flags.FakeMouseWithTouches), - this.videoElementParentClientRect - ); + this.setTouchInputEnabled(this.config.isFlagEnabled(Flags.TouchInput)); this.pixelStreaming.dispatchEvent(new PlayStreamEvent()); if (this.streamController.audioElement.srcObject) { @@ -1421,11 +1418,9 @@ export class WebRtcPlayerController { this.statsTimerHandle = window.setInterval(() => this.getStats(), 1000); /* */ - this.activateRegisterMouse(); - this.keyboardController = this.inputClassesFactory.registerKeyBoard( - this.config - ); - this.gamePadController = this.inputClassesFactory.registerGamePad(); + this.setMouseInputEnabled(this.config.isFlagEnabled(Flags.MouseInput)); + this.setKeyboardInputEnabled(this.config.isFlagEnabled(Flags.KeyboardInput)); + this.setGamePadInputEnabled(this.config.isFlagEnabled(Flags.GamepadInput)); } /** @@ -1503,17 +1498,6 @@ export class WebRtcPlayerController { } } - /** - * registers the mouse for use in WebRtcPlayerController - */ - activateRegisterMouse() { - const mouseMode = this.config.isFlagEnabled(Flags.HoveringMouseMode) - ? ControlSchemeType.HoveringMouse - : ControlSchemeType.LockedMouse; - this.mouseController = - this.inputClassesFactory.registerMouse(mouseMode); - } - /** * Set the freeze frame overlay to the player div */ @@ -1900,6 +1884,55 @@ export class WebRtcPlayerController { this.pixelStreaming._onVideoEncoderAvgQP(this.videoAvgQp); } + /** + * enables/disables keyboard event listeners + */ + setKeyboardInputEnabled(isEnabled: boolean) { + this.keyboardController?.unregisterKeyBoardEvents(); + if (isEnabled) { + this.keyboardController = this.inputClassesFactory.registerKeyBoard( + this.config + ); + } + } + + /** + * enables/disables mouse event listeners + */ + setMouseInputEnabled(isEnabled: boolean) { + this.mouseController?.unregisterMouseEvents(); + if (isEnabled) { + const mouseMode = this.config.isFlagEnabled(Flags.HoveringMouseMode) + ? ControlSchemeType.HoveringMouse + : ControlSchemeType.LockedMouse; + this.mouseController = + this.inputClassesFactory.registerMouse(mouseMode); + } + } + + /** + * enables/disables touch event listeners + */ + setTouchInputEnabled(isEnabled: boolean) { + this.touchController?.unregisterTouchEvents(); + if (isEnabled) { + this.touchController = this.inputClassesFactory.registerTouch( + this.config.isFlagEnabled(Flags.FakeMouseWithTouches), + this.videoElementParentClientRect + ); + } + } + + /** + * enables/disables game pad event listeners + */ + setGamePadInputEnabled(isEnabled: boolean) { + this.gamePadController?.unregisterGamePadEvents(); + if (isEnabled) { + this.gamePadController = this.inputClassesFactory.registerGamePad(); + } + } + registerDataChannelEventEmitters(dataChannel: DataChannelController) { dataChannel.onOpen = (label, event) => this.pixelStreaming.dispatchEvent( diff --git a/Frontend/library/src/WebXR/WebXRController.ts b/Frontend/library/src/WebXR/WebXRController.ts index c2d087b6..0f6ae948 100644 --- a/Frontend/library/src/WebXR/WebXRController.ts +++ b/Frontend/library/src/WebXR/WebXRController.ts @@ -6,6 +6,7 @@ import { WebGLUtils } from '../Util/WebGLUtils'; import { Controller } from '../Inputs/GamepadTypes'; import { XRGamepadController } from '../Inputs/XRGamepadController'; import { XrFrameEvent } from '../Util/EventEmitter' +import { Flags } from '../pixelstreamingfrontend'; export class WebXRController { private xrSession: XRSession; @@ -190,16 +191,18 @@ export class WebXRController { this.render(this.webRtcController.videoPlayer.getVideoElement()); } - this.xrSession.inputSources.forEach( - (source: XRInputSource, index: number, array: XRInputSource[]) => { - this.xrGamepadController.updateStatus( - source, - frame, - this.xrRefSpace - ); - }, - this - ); + if (this.webRtcController.config.isFlagEnabled(Flags.XRControllerInput)) { + this.xrSession.inputSources.forEach( + (source: XRInputSource, index: number, array: XRInputSource[]) => { + this.xrGamepadController.updateStatus( + source, + frame, + this.xrRefSpace + ); + }, + this + ); + } this.xrSession.requestAnimationFrame( (time: DOMHighResTimeStamp, frame: XRFrame) => diff --git a/Frontend/ui-library/package-lock.json b/Frontend/ui-library/package-lock.json index b36eee45..332fbd66 100644 --- a/Frontend/ui-library/package-lock.json +++ b/Frontend/ui-library/package-lock.json @@ -1,12 +1,12 @@ { "name": "@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.2", - "version": "0.0.3", + "version": "0.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@epicgames-ps/lib-pixelstreamingfrontend-ui-ue5.2", - "version": "0.0.3", + "version": "0.0.4", "license": "MIT", "dependencies": { "jss": "^10.9.2", diff --git a/Frontend/ui-library/src/Config/ConfigUI.ts b/Frontend/ui-library/src/Config/ConfigUI.ts index 43891f22..ffcb0665 100644 --- a/Frontend/ui-library/src/Config/ConfigUI.ts +++ b/Frontend/ui-library/src/Config/ConfigUI.ts @@ -220,6 +220,37 @@ export class ConfigUI { this.addSettingFlag(viewSettingsSection, this.flagsUi.get(LightMode)); + /* Setup all encoder related settings under this section */ + const inputSettingsSection = this.buildSectionWithHeading( + settingsElem, + 'Input' + ); + + this.addSettingFlag( + inputSettingsSection, + this.flagsUi.get(Flags.KeyboardInput) + ); + + this.addSettingFlag( + inputSettingsSection, + this.flagsUi.get(Flags.MouseInput) + ); + + this.addSettingFlag( + inputSettingsSection, + this.flagsUi.get(Flags.TouchInput) + ); + + this.addSettingFlag( + inputSettingsSection, + this.flagsUi.get(Flags.GamepadInput) + ); + + this.addSettingFlag( + inputSettingsSection, + this.flagsUi.get(Flags.XRControllerInput) + ); + /* Setup all encoder related settings under this section */ const encoderSettingsSection = this.buildSectionWithHeading( settingsElem,