Skip to content

Commit

Permalink
Input support custom event target. (#1955)
Browse files Browse the repository at this point in the history
* feat: input support change listenering target
  • Loading branch information
cptbtptpbcptdtptp authored Jan 12, 2024
1 parent e1a511c commit b9023af
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 279 deletions.
15 changes: 12 additions & 3 deletions packages/core/src/Engine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { IHardwareRenderer, IPhysics, IPhysicsManager, IShaderLab, IXRDevice } from "@galacean/engine-design";
import {
IHardwareRenderer,
IInputOptions,
IPhysics,
IPhysicsManager,
IShaderLab,
IXRDevice
} from "@galacean/engine-design";
import { Color } from "@galacean/engine-math";
import { SpriteMaskInteraction } from "./2d";
import { Font } from "./2d/text/Font";
Expand Down Expand Up @@ -256,7 +263,7 @@ export class Engine extends EventDispatcher {
this._textDefaultFont = Font.createFromOS(this, "Arial");
this._textDefaultFont.isGCIgnored = true;

this.inputManager = new InputManager(this);
this.inputManager = new InputManager(this, configuration.input);

const { xrDevice } = configuration;
if (xrDevice) {
Expand Down Expand Up @@ -752,6 +759,8 @@ export interface EngineConfiguration {
xrDevice?: IXRDevice;
/** Color space. */
colorSpace?: ColorSpace;
/** Shader lab */
/** Shader lab. */
shaderLab?: IShaderLab;
/** Input options. */
input?: IInputOptions;
}
29 changes: 6 additions & 23 deletions packages/core/src/input/InputManager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { IInputOptions } from "@galacean/engine-design";
import { Vector3 } from "@galacean/engine-math";
import { Engine } from "../Engine";
import { Scene } from "../Scene";
import { Keys } from "./enums/Keys";
import { PointerButton, _pointerBin2DecMap } from "./enums/PointerButton";
import { KeyboardManager } from "./keyboard/KeyboardManager";
import { Pointer } from "./pointer/Pointer";
import { PointerManager } from "./pointer/PointerManager";
import { WheelManager } from "./wheel/WheelManager";
import { Scene } from "../Scene";

/**
* InputManager manages device input such as mouse, touch, keyboard, etc.
Expand Down Expand Up @@ -150,18 +151,14 @@ export class InputManager {
/**
* @internal
*/
constructor(engine: Engine) {
constructor(engine: Engine, inputOptions?: IInputOptions) {
this._engine = engine;
// @ts-ignore
const canvas = engine._canvas._webCanvas;
if (typeof OffscreenCanvas === "undefined" || !(canvas instanceof OffscreenCanvas)) {
this._wheelManager = new WheelManager(engine);
this._pointerManager = new PointerManager(engine);
this._keyboardManager = new KeyboardManager(engine);
this._onBlur = this._onBlur.bind(this);
window.addEventListener("blur", this._onBlur);
this._onFocus = this._onFocus.bind(this);
window.addEventListener("focus", this._onFocus);
this._wheelManager = new WheelManager(engine, inputOptions?.wheelTarget ?? canvas);
this._pointerManager = new PointerManager(engine, inputOptions?.pointerTarget ?? canvas);
this._keyboardManager = new KeyboardManager(engine, inputOptions?.keyboardTarget ?? window);
this._initialized = true;
}
}
Expand Down Expand Up @@ -189,8 +186,6 @@ export class InputManager {
*/
_destroy(): void {
if (this._initialized) {
window.removeEventListener("blur", this._onBlur);
window.removeEventListener("focus", this._onFocus);
this._wheelManager._destroy();
this._wheelManager = null;
this._pointerManager._destroy();
Expand All @@ -199,16 +194,4 @@ export class InputManager {
this._keyboardManager = null;
}
}

private _onBlur(): void {
this._wheelManager._onBlur();
this._pointerManager._onBlur();
this._keyboardManager._onBlur();
}

private _onFocus(): void {
this._wheelManager._onFocus();
this._pointerManager._onFocus();
this._keyboardManager._onFocus();
}
}
8 changes: 0 additions & 8 deletions packages/core/src/input/interface/IInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,4 @@ export interface IInput {
* Function called when the engine is destroyed.
*/
_destroy(): void;
/**
* Function called when focused.
*/
_onFocus(): void;
/**
* Function called when focus is lost.
*/
_onBlur(): void;
}
77 changes: 31 additions & 46 deletions packages/core/src/input/keyboard/KeyboardManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Engine } from "../../Engine";
import { DisorderedArray } from "../../DisorderedArray";
import { Engine } from "../../Engine";
import { Platform } from "../../Platform";
import { SystemInfo } from "../../SystemInfo";
import { Keys } from "../enums/Keys";
Expand All @@ -24,25 +24,20 @@ export class KeyboardManager implements IInput {
/** @internal */
_curFrameUpList: DisorderedArray<Keys> = new DisorderedArray();

// @internal
_target: EventTarget;
private _engine: Engine;
private _htmlCanvas: HTMLCanvasElement;
private _nativeEvents: KeyboardEvent[] = [];
private _hadListener: boolean = false;

/**
* Create a KeyboardManager.
* @internal
*/
constructor(engine: Engine) {
// @ts-ignore
const htmlCanvas = engine._canvas._webCanvas;
constructor(engine: Engine, target: EventTarget) {
this._engine = engine;
this._htmlCanvas = htmlCanvas;
// Need to set tabIndex to make the canvas focus.
htmlCanvas.tabIndex = htmlCanvas.tabIndex;
this._onBlur = this._onBlur.bind(this);
this._onKeyEvent = this._onKeyEvent.bind(this);
htmlCanvas.addEventListener("keydown", this._onKeyEvent);
htmlCanvas.addEventListener("keyup", this._onKeyEvent);
this._hadListener = true;
this._target = target;
this._addEventListener();
}

/**
Expand Down Expand Up @@ -101,42 +96,11 @@ export class KeyboardManager implements IInput {
}
}

/**
* @internal
*/
_onFocus(): void {
if (!this._hadListener) {
this._htmlCanvas.addEventListener("keydown", this._onKeyEvent);
this._htmlCanvas.addEventListener("keyup", this._onKeyEvent);
this._hadListener = true;
}
}

/**
* @internal
*/
_onBlur(): void {
if (this._hadListener) {
this._htmlCanvas.removeEventListener("keydown", this._onKeyEvent);
this._htmlCanvas.removeEventListener("keyup", this._onKeyEvent);
this._curHeldDownKeyToIndexMap.length = 0;
this._curFrameHeldDownList.length = 0;
this._curFrameDownList.length = 0;
this._curFrameUpList.length = 0;
this._nativeEvents.length = 0;
this._hadListener = false;
}
}

/**
* @internal
*/
_destroy(): void {
if (this._hadListener) {
this._htmlCanvas.removeEventListener("keydown", this._onKeyEvent);
this._htmlCanvas.removeEventListener("keyup", this._onKeyEvent);
this._hadListener = false;
}
this._removeEventListener();
this._curHeldDownKeyToIndexMap.length = 0;
this._curHeldDownKeyToIndexMap = null;
this._upKeyToFrameCountMap.length = 0;
Expand All @@ -151,11 +115,32 @@ export class KeyboardManager implements IInput {
this._curFrameDownList = null;
this._curFrameUpList.length = 0;
this._curFrameUpList = null;
this._htmlCanvas = null;
this._engine = null;
}

private _onBlur() {
this._curHeldDownKeyToIndexMap.length = 0;
this._curFrameHeldDownList.length = 0;
this._curFrameDownList.length = 0;
this._curFrameUpList.length = 0;
this._nativeEvents.length = 0;
}

private _onKeyEvent(evt: KeyboardEvent): void {
this._nativeEvents.push(evt);
}

private _addEventListener(): void {
const { _target: target } = this;
target.addEventListener("keydown", this._onKeyEvent);
target.addEventListener("keyup", this._onKeyEvent);
target.addEventListener("blur", this._onBlur);
}

private _removeEventListener(): void {
const { _target: target } = this;
target.removeEventListener("keydown", this._onKeyEvent);
target.removeEventListener("keyup", this._onKeyEvent);
target.removeEventListener("blur", this._onBlur);
}
}
110 changes: 39 additions & 71 deletions packages/core/src/input/pointer/PointerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,30 @@ export class PointerManager implements IInput {
/** @internal */
_downList: DisorderedArray<PointerButton> = new DisorderedArray();

// @internal
_target: EventTarget;
private _engine: Engine;
private _canvas: Canvas;
private _htmlCanvas: HTMLCanvasElement;
private _nativeEvents: PointerEvent[] = [];
private _pointerPool: Pointer[];
private _hadListener: boolean = false;
private _htmlCanvas: HTMLCanvasElement;

/**
* Create a PointerManager.
* @param engine - The current engine instance
* @param htmlCanvas - HTMLCanvasElement
* @internal
*/
constructor(engine: Engine) {
// @ts-ignore
const htmlCanvas = engine._canvas._webCanvas;
constructor(engine: Engine, target: EventTarget) {
if (target instanceof Window) {
throw "Do not set window as target because window cannot listen to pointer leave event.";
}
this._engine = engine;
this._target = target;
this._canvas = engine.canvas;
this._htmlCanvas = htmlCanvas;
this._onPointerEvent = this._onPointerEvent.bind(this);
this._onFocus();
// @ts-ignore
this._htmlCanvas = engine._canvas._webCanvas;
// If there are no compatibility issues, navigator.maxTouchPoints should be used here
this._pointerPool = new Array<Pointer>(11);
this._onPointerEvent = this._onPointerEvent.bind(this);
this._addEventListener();
}

/**
Expand Down Expand Up @@ -130,7 +132,8 @@ export class PointerManager implements IInput {
const length = events.length;
if (length > 0) {
for (let i = 0; i < length; i++) {
switch (events[i].type) {
const event = events[i];
switch (event.type) {
case "pointerdown":
pointer.phase = PointerPhase.Down;
pointer._firePointerDown(rayCastEntity);
Expand All @@ -151,75 +154,18 @@ export class PointerManager implements IInput {
}
}

/**
* @internal
*/
_onFocus(): void {
if (!this._hadListener) {
const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this;
htmlCanvas.addEventListener("pointerdown", onPointerEvent);
htmlCanvas.addEventListener("pointerup", onPointerEvent);
htmlCanvas.addEventListener("pointerleave", onPointerEvent);
htmlCanvas.addEventListener("pointermove", onPointerEvent);
htmlCanvas.addEventListener("pointercancel", onPointerEvent);
this._hadListener = true;
}
}

/**
* @internal
*/
_onBlur(): void {
if (this._hadListener) {
const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this;
htmlCanvas.removeEventListener("pointerdown", onPointerEvent);
htmlCanvas.removeEventListener("pointerup", onPointerEvent);
htmlCanvas.removeEventListener("pointerleave", onPointerEvent);
htmlCanvas.removeEventListener("pointermove", onPointerEvent);
htmlCanvas.removeEventListener("pointercancel", onPointerEvent);
this._hadListener = false;
this._pointers.length = 0;
this._downList.length = 0;
this._upList.length = 0;
this._nativeEvents.length = 0;
}
}

/**
* @internal
*/
_destroy(): void {
// @ts-ignore
if (this._hadListener) {
const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this;
htmlCanvas.removeEventListener("pointerdown", onPointerEvent);
htmlCanvas.removeEventListener("pointerup", onPointerEvent);
htmlCanvas.removeEventListener("pointerleave", onPointerEvent);
htmlCanvas.removeEventListener("pointermove", onPointerEvent);
htmlCanvas.removeEventListener("pointercancel", onPointerEvent);
this._hadListener = false;
}
this._removeEventListener();
this._pointerPool.length = 0;
this._pointerPool = null;
this._pointers.length = 0;
this._pointers = null;
this._downList.length = 0;
this._downList = null;
this._upList.length = 0;
this._upList = null;
this._nativeEvents.length = 0;
this._nativeEvents = null;
this._upMap.length = 0;
this._upMap = null;
this._downMap.length = 0;
this._downMap = null;
this._htmlCanvas = null;
this._canvas = null;
this._engine = null;
this._upMap.length = 0;
}

private _onPointerEvent(evt: PointerEvent) {
evt.type === "pointerdown" && this._htmlCanvas.focus();
this._nativeEvents.push(evt);
}

Expand Down Expand Up @@ -322,4 +268,26 @@ export class PointerManager implements IInput {
}
return null;
}

private _addEventListener(): void {
const { _target: target, _onPointerEvent: onPointerEvent } = this;
target.addEventListener("pointerdown", onPointerEvent);
target.addEventListener("pointerup", onPointerEvent);
target.addEventListener("pointerleave", onPointerEvent);
target.addEventListener("pointermove", onPointerEvent);
target.addEventListener("pointercancel", onPointerEvent);
}

private _removeEventListener(): void {
const { _target: target, _onPointerEvent: onPointerEvent } = this;
target.removeEventListener("pointerdown", onPointerEvent);
target.removeEventListener("pointerup", onPointerEvent);
target.removeEventListener("pointerleave", onPointerEvent);
target.removeEventListener("pointermove", onPointerEvent);
target.removeEventListener("pointercancel", onPointerEvent);
this._nativeEvents.length = 0;
this._pointers.length = 0;
this._downList.length = 0;
this._upList.length = 0;
}
}
Loading

0 comments on commit b9023af

Please sign in to comment.