From 55c8d78172dd9f07dd7ca981e0dcdde1bfc31165 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Wed, 15 Jun 2022 18:10:41 +0800 Subject: [PATCH 01/19] op:Input. --- packages/core/src/Engine.ts | 8 +- packages/core/src/input/IInput.ts | 22 ++ packages/core/src/input/InputManager.ts | 232 +++++++++++++++--- packages/core/src/input/enums/InputType.ts | 7 + packages/core/src/input/enums/PointerType.ts | 29 +++ .../src/input/keyboard/KeyboardManager.ts | 196 ++++++++------- .../core/src/input/pointer/PointerManager.ts | 125 ++++++++-- packages/core/src/input/wheel/WheelManager.ts | 74 ++++++ 8 files changed, 547 insertions(+), 146 deletions(-) create mode 100644 packages/core/src/input/IInput.ts create mode 100644 packages/core/src/input/enums/InputType.ts create mode 100644 packages/core/src/input/enums/PointerType.ts create mode 100644 packages/core/src/input/wheel/WheelManager.ts diff --git a/packages/core/src/Engine.ts b/packages/core/src/Engine.ts index 4d072611e8..a43958cedb 100644 --- a/packages/core/src/Engine.ts +++ b/packages/core/src/Engine.ts @@ -280,10 +280,8 @@ export class Engine extends EventDispatcher { scene._activeCameras.sort((camera1, camera2) => camera1.priority - camera2.priority); componentsManager.callScriptOnStart(); - if (this.physicsManager._initialized) { - this.physicsManager._update(deltaTime / 1000.0); - } - this.inputManager._update(); + this.physicsManager._initialized && this.physicsManager._update(deltaTime / 1000.0); + this.inputManager._initialized && this.inputManager._update(); componentsManager.callScriptOnUpdate(deltaTime); componentsManager.callAnimationUpdate(deltaTime); componentsManager.callScriptOnLateUpdate(deltaTime); @@ -311,7 +309,7 @@ export class Engine extends EventDispatcher { if (this._sceneManager) { this._whiteTexture2D.destroy(true); this._whiteTextureCube.destroy(true); - this.inputManager._destroy(); + this.inputManager._initialized && this.inputManager._destroy(); this.trigger(new Event("shutdown", this)); engineFeatureManager.callFeatureMethod(this, "shutdown", [this]); diff --git a/packages/core/src/input/IInput.ts b/packages/core/src/input/IInput.ts new file mode 100644 index 0000000000..ab787781b3 --- /dev/null +++ b/packages/core/src/input/IInput.ts @@ -0,0 +1,22 @@ +export interface IInput { + /** + * Handler function updated every frame. + */ + _update(frameCount?: number): void; + /** + * Function called when the input changes from disabled to enabled state. + */ + _enable(): void; + /** + * Function called when the input changes from enabled to disabled state. + */ + _disable(): void; + /** + * Function called when the engine is destroyed. + */ + _destroy(): void; + /** + * Function called when focus is lost. + */ + _onBlur(): void; +} diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index ad989bdf59..cb6d8996cf 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -3,73 +3,232 @@ import { KeyboardManager } from "./keyboard/KeyboardManager"; import { Keys } from "./enums/Keys"; import { Pointer } from "./pointer/Pointer"; import { PointerManager } from "./pointer/PointerManager"; +import { PointerButton } from "./enums/PointerType"; +import { WheelManager } from "./wheel/WheelManager"; +import { InputType } from "./enums/InputType"; +import { Vector2 } from "@oasis-engine/math"; /** * InputManager manages device input such as mouse, touch, keyboard, etc. */ export class InputManager { - /** Disable input for offscreen rendering. */ - private _enabled: boolean = true; + /** Sometimes the input module will not be initialized, such as off-screen rendering. */ + /** @internal */ + _initialized: boolean = false; + + private _enabledTypes: number = InputType.None; + private _curFrameCount: number; + + private _wheelManager: WheelManager; private _pointerManager: PointerManager; private _keyboardManager: KeyboardManager; + /** + * Set of received input types. + */ + get enabledTypes(): number { + return this._enabledTypes; + } + /** * Pointer List. */ - get pointers(): Readonly { - return this._enabled ? this._pointerManager._pointers : null; + get pointers(): Readonly { + return this._initialized ? this._pointerManager._pointers : null; } /** * Whether to handle multi-pointer. */ get multiPointerEnabled(): boolean { - return this._enabled ? this._pointerManager._multiPointerEnabled : false; + return this._initialized ? this._pointerManager._multiPointerEnabled : false; } set multiPointerEnabled(enabled: boolean) { - this._enabled && (this._pointerManager._multiPointerEnabled = enabled); + this._initialized && (this._pointerManager._multiPointerEnabled = enabled); + } + + /** + * Get the change of the scroll wheel on the x-axis. + * @returns Change value + */ + get wheelDeltaX(): number { + return this._initialized ? this._wheelManager._deltaX : 0; + } + + /** + * Get the change of the scroll wheel on the y-axis. + * @returns Change value + */ + get wheelDeltaY(): number { + return this._initialized ? this._wheelManager._deltaY : 0; + } + + /** + * Get the change of the scroll wheel on the z-axis. + * @returns Change value + */ + get wheelDeltaZ(): number { + return this._initialized ? this._wheelManager._deltaY : 0; + } + + /** + * Get the change of the pointer. + * @returns Change value + */ + get pointerMovingDelta(): Readonly { + return this._initialized ? this._pointerManager._movingDelta : null; + } + + /** + * Handle this type of input. + * @param type - The type of the input + */ + enableInput(type: InputType): void { + if (this._initialized) { + const diff = this._enabledTypes ^ type; + if (diff) { + this._enabledTypes |= type; + diff & InputType.Wheel && this._wheelManager._enable(); + diff & InputType.Pointer && this._pointerManager._enable(); + diff & InputType.Keyboard && this._keyboardManager._enable(); + } + } + } + + /** + * Does not handle this type of input. + * @param type - The type of the input + */ + disableInput(type: InputType): void { + if (this._initialized) { + const same = this._enabledTypes & type; + if (same) { + this._enabledTypes &= ~type; + same & InputType.Wheel && this._wheelManager._disable(); + same & InputType.Pointer && this._pointerManager._disable(); + same & InputType.Keyboard && this._keyboardManager._disable(); + } + } } /** * Whether the key is being held down, if there is no parameter, return whether any key is being held down. * @param key - The keys of the keyboard - * @returns Whether the key is being held down. + * @returns Whether the key is being held down */ - isKeyHeldDown(key?: Keys): boolean { - if (key === undefined) { - return this._keyboardManager._curFrameHeldDownList.length > 0; + isKeyHeldDown(key?: Keys | string | number): boolean { + if (this._initialized) { + if (key === undefined) { + return this._keyboardManager._curFrameDownList.length > 0; + } else if (typeof key === "string") { + return !!this._keyboardManager._curHeldDownKeyToIndexMap[Keys[key]]; + } else { + return !!this._keyboardManager._curHeldDownKeyToIndexMap[key]; + } } else { - return !!this._keyboardManager._curHeldDownKeyToIndexMap[key]; + return false; } } /** * Whether the key starts to be pressed down during the current frame, if there is no parameter, return whether any key starts to be pressed down during the current frame. * @param key - The keys of the keyboard - * @returns Whether the key starts to be pressed down during the current frame. + * @returns Whether the key starts to be pressed down during the current frame */ - isKeyDown(key?: Keys): boolean { - if (key === undefined) { - return this._keyboardManager._curFrameDownList.length > 0; + isKeyDown(key?: Keys | string | number): boolean { + if (this._initialized) { + if (key === undefined) { + return this._keyboardManager._curFrameDownList.length > 0; + } else if (typeof key === "string") { + return this._keyboardManager._downKeyToFrameCountMap[Keys[key]] === this._curFrameCount; + } else { + return this._keyboardManager._downKeyToFrameCountMap[key] === this._curFrameCount; + } } else { - return this._keyboardManager._downKeyToFrameCountMap[key] === this._keyboardManager._curFrameCount; + return false; } } /** * Whether the key is released during the current frame, if there is no parameter, return whether any key released during the current frame. * @param key - The keys of the keyboard - * @returns Whether the key is released during the current frame. + * @returns Whether the key is released during the current frame + */ + isKeyUp(key?: Keys | string | number): boolean { + if (this._initialized) { + if (key === undefined) { + return this._keyboardManager._curFrameUpList.length > 0; + } else if (typeof key === "string") { + return this._keyboardManager._upKeyToFrameCountMap[Keys[key]] === this._curFrameCount; + } else { + return this._keyboardManager._upKeyToFrameCountMap[key] === this._curFrameCount; + } + } else { + return false; + } + } + + /** + * Whether the button is being held down, if there is no parameter, return whether any button is being held down. + * @param button - The buttons on a mouse device + * @returns Whether the button is being held down + */ + isButtonHeldDown(button?: PointerButton): boolean { + if (this._initialized) { + if (button === undefined) { + return this._pointerManager._heldDownList.length > 0; + } else { + return !!this._pointerManager._heldDownMap[button]; + } + } else { + return false; + } + } + + /** + * Whether the button starts to be pressed down during the current frame, if there is no parameter, return whether any button starts to be pressed down during the current frame. + * @param button - The buttons on a mouse device + * @returns Whether the button starts to be pressed down during the current frame */ - isKeyUp(key?: Keys): boolean { - if (key === undefined) { - return this._keyboardManager._curFrameUpList.length > 0; + isButtonDown(button: PointerButton): boolean { + if (this._initialized) { + if (button === undefined) { + return this._pointerManager._downList.length > 0; + } else { + return this._pointerManager._downMap[button] === this._curFrameCount; + } } else { - return this._keyboardManager._upKeyToFrameCountMap[key] === this._keyboardManager._curFrameCount; + return false; } } + /** + * Whether the button is released during the current frame, if there is no parameter, return whether any button released during the current frame. + * @param button - The buttons on a mouse device + * @returns Whether the button is released during the current frame + */ + isButtonUp(button: PointerButton): boolean { + if (this._initialized) { + if (button === undefined) { + return this._pointerManager._upList.length > 0; + } else { + return this._pointerManager._upMap[button] === this._curFrameCount; + } + } else { + return false; + } + } + + /** + * Set hotkey. + * @param key - The name of hotkey + * @param value - The value of hotkey + */ + registerHotKey(key: string, value: number): void { + Keys[key] = value; + } + /** * @internal */ @@ -77,13 +236,13 @@ export class InputManager { // @ts-ignore const canvas = engine._canvas._webCanvas; if (canvas instanceof HTMLCanvasElement) { - this._enabled = true; + this._enabledTypes = InputType.All; + this._wheelManager = new WheelManager(canvas); this._pointerManager = new PointerManager(engine, canvas); this._keyboardManager = new KeyboardManager(); this._onBlur = this._onBlur.bind(this); window.addEventListener("blur", this._onBlur); - } else { - this._enabled = false; + this._initialized = true; } } @@ -91,26 +250,27 @@ export class InputManager { * @internal */ _update(): void { - if (this._enabled) { - this._pointerManager._update(); - this._keyboardManager._update(); - } + ++this._curFrameCount; + const { _enabledTypes: enabledTypes } = this; + enabledTypes & InputType.Wheel && this._wheelManager._update(); + enabledTypes & InputType.Pointer && this._pointerManager._update(this._curFrameCount); + enabledTypes & InputType.Keyboard && this._keyboardManager._update(this._curFrameCount); } /** * @internal */ _destroy(): void { - if (this._enabled) { - window.removeEventListener("blur", this._onBlur); - this._pointerManager._destroy(); - this._keyboardManager._destroy(); - } + window.removeEventListener("blur", this._onBlur); + this._wheelManager._destroy(); + this._pointerManager._destroy(); + this._keyboardManager._destroy(); } private _onBlur(): void { - if (this._enabled) { - this._keyboardManager._onBlur(); - } + const { _enabledTypes: enabledTypes } = this; + enabledTypes & InputType.Wheel && this._wheelManager._onBlur(); + enabledTypes & InputType.Pointer && this._pointerManager._onBlur(); + enabledTypes & InputType.Keyboard && this._keyboardManager._onBlur(); } } diff --git a/packages/core/src/input/enums/InputType.ts b/packages/core/src/input/enums/InputType.ts new file mode 100644 index 0000000000..4ce97b3fdd --- /dev/null +++ b/packages/core/src/input/enums/InputType.ts @@ -0,0 +1,7 @@ +export enum InputType { + None = 0, + Wheel = 1, + Pointer = 2, + Keyboard = 4, + All = 7 +} diff --git a/packages/core/src/input/enums/PointerType.ts b/packages/core/src/input/enums/PointerType.ts new file mode 100644 index 0000000000..768b64829a --- /dev/null +++ b/packages/core/src/input/enums/PointerType.ts @@ -0,0 +1,29 @@ +/** + * Defines values that specify the buttons on a mouse device. + * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) + * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) + */ +export enum PointerButton { + // MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. + Left = 0, + // MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). + Middle = 1, + // MUST indicate the secondary button (in general, the right button, often used to display a context menu). + Right = 2, + // MUST indicate the X1 (back) button. + XButton1 = 3, + // MUST indicate the X2 (forward) button. + XButton2 = 4, + // MUST indicate the X3 button. + XButton3 = 5, + // MUST indicate the X4 button. + XButton4 = 6, + // MUST indicate the X5 button. + XButton5 = 7, + // MUST indicate the X6 button. + XButton6 = 8, + // MUST indicate the X7 button. + XButton7 = 9, + // MUST indicate the X8 button. + XButton8 = 10 +} diff --git a/packages/core/src/input/keyboard/KeyboardManager.ts b/packages/core/src/input/keyboard/KeyboardManager.ts index a36c45fd16..763170cbf8 100644 --- a/packages/core/src/input/keyboard/KeyboardManager.ts +++ b/packages/core/src/input/keyboard/KeyboardManager.ts @@ -1,4 +1,3 @@ - import { DisorderedArray } from "../../DisorderedArray"; import { Keys } from "../enums/Keys"; @@ -7,101 +6,120 @@ import { Keys } from "../enums/Keys"; * @internal */ export class KeyboardManager { - /** @internal */ - _curFrameCount: number = 0; - /** @internal */ - _curHeldDownKeyToIndexMap: number[] = []; - /** @internal */ - _upKeyToFrameCountMap: number[] = []; - /** @internal */ - _downKeyToFrameCountMap: number[] = []; + /** @internal */ + _curHeldDownKeyToIndexMap: number[] = []; + /** @internal */ + _upKeyToFrameCountMap: number[] = []; + /** @internal */ + _downKeyToFrameCountMap: number[] = []; - /** @internal */ - _curFrameHeldDownList: DisorderedArray = new DisorderedArray(); - /** @internal */ - _curFrameDownList: DisorderedArray = new DisorderedArray(); - /** @internal */ - _curFrameUpList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _curFrameHeldDownList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _curFrameDownList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _curFrameUpList: DisorderedArray = new DisorderedArray(); - private _nativeEvents: KeyboardEvent[] = []; - private _onKeyEvent: (evt: KeyboardEvent) => void; + private _nativeEvents: KeyboardEvent[] = []; - /** - * Create a KeyboardManager. - */ - constructor() { - this._onKeyEvent = (evt: KeyboardEvent) => { - this._nativeEvents.push(evt); - } - window.addEventListener('keydown', this._onKeyEvent); - window.addEventListener('keyup', this._onKeyEvent); - } + /** + * Create a KeyboardManager. + */ + constructor() { + this._onKeyEvent = this._onKeyEvent.bind(this); + window.addEventListener("keydown", this._onKeyEvent); + window.addEventListener("keyup", this._onKeyEvent); + } - /** - * @internal - */ - _update(): void { - const curFrameCount = ++this._curFrameCount; - const { _nativeEvents: nativeEvents, _curFrameDownList: curFrameDownList, _curFrameUpList: curFrameUpList } = this; - curFrameDownList.length = 0; - curFrameUpList.length = 0; - if (nativeEvents.length > 0) { - const { _curHeldDownKeyToIndexMap: curHeldDownKeyToIndexMap, _curFrameHeldDownList: curFrameHeldDownList, _downKeyToFrameCountMap: downKeyToFrameCountMap, _upKeyToFrameCountMap: upKeyToFrameCountMap } = this; - for (let i = 0, n = nativeEvents.length; i < n; i++) { - const evt = nativeEvents[i]; - const codeKey = Keys[evt.code]; - switch (evt.type) { - case 'keydown': - // Filter the repeated triggers of the keyboard. - if (curHeldDownKeyToIndexMap[codeKey] == null) { - curFrameDownList.add(codeKey); - curFrameHeldDownList.add(codeKey); - curHeldDownKeyToIndexMap[codeKey] = curFrameHeldDownList.length - 1; - downKeyToFrameCountMap[codeKey] = curFrameCount; - } - break; - case 'keyup': - const delIndex = curHeldDownKeyToIndexMap[codeKey]; - if (delIndex != null) { - curHeldDownKeyToIndexMap[codeKey] = null; - const swapCode = curFrameHeldDownList.deleteByIndex(delIndex); - swapCode && (curHeldDownKeyToIndexMap[swapCode] = delIndex); - } - curFrameUpList.add(codeKey); - upKeyToFrameCountMap[codeKey] = curFrameCount; - break; - default: - break; - } + /** + * @internal + */ + _update(frameCount: number): void { + const { _nativeEvents: nativeEvents, _curFrameDownList: curFrameDownList, _curFrameUpList: curFrameUpList } = this; + curFrameDownList.length = 0; + curFrameUpList.length = 0; + if (nativeEvents.length > 0) { + const { + _curHeldDownKeyToIndexMap: curHeldDownKeyToIndexMap, + _curFrameHeldDownList: curFrameHeldDownList, + _downKeyToFrameCountMap: downKeyToFrameCountMap, + _upKeyToFrameCountMap: upKeyToFrameCountMap + } = this; + for (let i = 0, n = nativeEvents.length; i < n; i++) { + const evt = nativeEvents[i]; + const codeKey = Keys[evt.code]; + switch (evt.type) { + case "keydown": + // Filter the repeated triggers of the keyboard. + if (curHeldDownKeyToIndexMap[codeKey] === null) { + curFrameDownList.add(codeKey); + curFrameHeldDownList.add(codeKey); + curHeldDownKeyToIndexMap[codeKey] = curFrameHeldDownList.length - 1; + downKeyToFrameCountMap[codeKey] = frameCount; } - nativeEvents.length = 0; + break; + case "keyup": + const delIndex = curHeldDownKeyToIndexMap[codeKey]; + if (delIndex !== null) { + curHeldDownKeyToIndexMap[codeKey] = null; + const swapCode = curFrameHeldDownList.deleteByIndex(delIndex); + swapCode && (curHeldDownKeyToIndexMap[swapCode] = delIndex); + } + curFrameUpList.add(codeKey); + upKeyToFrameCountMap[codeKey] = frameCount; + break; + default: + break; } + } + nativeEvents.length = 0; } + } - /** - * @internal - */ - _onBlur(): void { - this._curHeldDownKeyToIndexMap.length = 0; - this._nativeEvents.length = 0; - this._curFrameHeldDownList.length = 0; - this._curFrameDownList.length = 0; - this._curFrameUpList.length = 0; - } + /** + * @internal + */ + _enable(): void { + window.addEventListener("keydown", this._onKeyEvent); + window.addEventListener("keyup", this._onKeyEvent); + } - /** - * @internal - */ - _destroy(): void { - window.removeEventListener('keydown', this._onKeyEvent); - window.removeEventListener('keyup', this._onKeyEvent); - this._curHeldDownKeyToIndexMap = null; - this._upKeyToFrameCountMap = null; - this._downKeyToFrameCountMap = null; - this._nativeEvents = null; + /** + * @internal + */ + _disable(): void { + window.removeEventListener("keydown", this._onKeyEvent); + window.removeEventListener("keyup", this._onKeyEvent); + } - this._curFrameHeldDownList = null; - this._curFrameDownList = null; - this._curFrameUpList = null; - } -} \ No newline at end of file + /** + * @internal + */ + _onBlur(): void { + this._curHeldDownKeyToIndexMap.length = 0; + this._curFrameHeldDownList.length = 0; + this._curFrameDownList.length = 0; + this._curFrameUpList.length = 0; + this._nativeEvents.length = 0; + } + + /** + * @internal + */ + _destroy(): void { + window.removeEventListener("keydown", this._onKeyEvent); + window.removeEventListener("keyup", this._onKeyEvent); + this._curHeldDownKeyToIndexMap = null; + this._upKeyToFrameCountMap = null; + this._downKeyToFrameCountMap = null; + this._nativeEvents = null; + + this._curFrameHeldDownList = null; + this._curFrameDownList = null; + this._curFrameUpList = null; + } + + private _onKeyEvent(evt: KeyboardEvent): void { + this._nativeEvents.push(evt); + } +} diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 5fef1f00dc..b2a6ca2977 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -1,17 +1,20 @@ import { Ray, Vector2 } from "@oasis-engine/math"; import { Canvas } from "../../Canvas"; +import { DisorderedArray } from "../../DisorderedArray"; import { Engine } from "../../Engine"; import { Entity } from "../../Entity"; import { CameraClearFlags } from "../../enums/CameraClearFlags"; -import { HitResult, PhysicsManager } from "../../physics"; +import { HitResult } from "../../physics"; import { PointerPhase } from "../enums/PointerPhase"; +import { PointerButton } from "../enums/PointerType"; +import { IInput } from "../IInput"; import { Pointer } from "./Pointer"; /** * Pointer Manager. * @internal */ -export class PointerManager { +export class PointerManager implements IInput { private static _tempRay: Ray = new Ray(); private static _tempPoint: Vector2 = new Vector2(); private static _tempHitResult: HitResult = new HitResult(); @@ -19,10 +22,26 @@ export class PointerManager { /** @internal */ _pointers: Pointer[] = []; /** @internal */ + _movingDelta: Vector2 = new Vector2(); + /** @internal */ _multiPointerEnabled: boolean = true; + /** @internal */ + _heldDownMap: number[] = []; + /** @internal */ + _upMap: number[] = []; + /** @internal */ + _downMap: number[] = []; + /** @internal */ + _heldDownList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _downList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _upList: DisorderedArray = new DisorderedArray(); + private _engine: Engine; private _canvas: Canvas; + private _htmlCanvas: HTMLCanvasElement; private _nativeEvents: PointerEvent[] = []; private _pointerPool: Pointer[]; private _keyEventList: number[] = []; @@ -40,11 +59,13 @@ export class PointerManager { constructor(engine: Engine, htmlCanvas: HTMLCanvasElement) { this._engine = engine; this._canvas = engine.canvas; + this._htmlCanvas = htmlCanvas; htmlCanvas.style.touchAction = "none"; - // prettier-ignore - htmlCanvas.onpointerdown = htmlCanvas.onpointerup = htmlCanvas.onpointerout = htmlCanvas.onpointermove = (evt: PointerEvent) => { - this._nativeEvents.push(evt); - }; + const onPointerEvent = (this._onPointerEvent = this._onPointerEvent.bind(this)); + htmlCanvas.addEventListener("pointerdown", onPointerEvent); + htmlCanvas.addEventListener("pointerup", onPointerEvent); + htmlCanvas.addEventListener("pointerout", onPointerEvent); + htmlCanvas.addEventListener("pointermove", onPointerEvent); // If there are no compatibility issues, navigator.maxTouchPoints should be used here. this._pointerPool = new Array(11); } @@ -52,9 +73,12 @@ export class PointerManager { /** * @internal */ - _update(): void { + _update(frameCount: number): void { this._needOverallPointers && this._overallPointers(); - this._nativeEvents.length > 0 && this._handlePointerEvent(this._nativeEvents); + this._downList.length = 0; + this._upList.length = 0; + this._movingDelta.setValue(0, 0); + this._nativeEvents.length > 0 && this._handlePointerEvent(this._nativeEvents, frameCount); if (this._engine.physicsManager._initialized) { const rayCastEntity = this._pointerRayCast(); const { _keyEventCount: keyEventCount } = this; @@ -80,6 +104,38 @@ export class PointerManager { } } + /** + * @internal + */ + _enable(): void { + const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; + htmlCanvas.addEventListener("pointerdown", onPointerEvent); + htmlCanvas.addEventListener("pointerup", onPointerEvent); + htmlCanvas.addEventListener("pointerout", onPointerEvent); + htmlCanvas.addEventListener("pointermove", onPointerEvent); + } + + /** + * @internal + */ + _disable(): void { + const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; + htmlCanvas.removeEventListener("pointerdown", onPointerEvent); + htmlCanvas.removeEventListener("pointerup", onPointerEvent); + htmlCanvas.removeEventListener("pointerout", onPointerEvent); + htmlCanvas.removeEventListener("pointermove", onPointerEvent); + } + + /** + * @internal + */ + _onBlur(): void { + this._heldDownMap.length = 0; + this._heldDownList.length = 0; + this._downList.length = 0; + this._upList.length = 0; + } + /** * @internal */ @@ -97,6 +153,10 @@ export class PointerManager { this._canvas = null; } + private _onPointerEvent(evt: PointerEvent) { + this._nativeEvents.push(evt); + } + private _overallPointers(): void { const { _pointers: pointers } = this; let deleteCount = 0; @@ -159,13 +219,24 @@ export class PointerManager { updatedPointer.phase = phase; } - private _handlePointerEvent(nativeEvents: PointerEvent[]): void { - const { _pointers: pointers, _keyEventList: keyEventList } = this; + private _handlePointerEvent(nativeEvents: PointerEvent[], frameCount: number): void { + const { + _pointers: pointers, + _keyEventList: keyEventList, + _heldDownMap: heldDownMap, + _upMap: upMap, + _downMap: downMap, + _heldDownList: heldDownList, + _upList: upList, + _downList: downList + } = this; let activePointerCount = pointers.length; + let delIndex: number; const nativeEventsLen = nativeEvents.length; for (let i = 0; i < nativeEventsLen; i++) { const evt = nativeEvents[i]; - let pointerIndex = this._getIndexByPointerID(evt.pointerId); + const pointerButton: PointerButton = evt.hasOwnProperty("button") ? evt.button : PointerButton.Left; + const pointerIndex = this._getIndexByPointerID(evt.pointerId); switch (evt.type) { case "pointerdown": if (pointerIndex === -1) { @@ -175,12 +246,24 @@ export class PointerManager { this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Down); } activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); + downList.add(pointerButton); + heldDownList.add(pointerButton); + heldDownMap[pointerButton] = heldDownList.length - 1; + downMap[pointerButton] = frameCount; break; case "pointerup": if (pointerIndex >= 0) { this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Up); activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); } + delIndex = heldDownMap[pointerButton]; + if (delIndex != null) { + heldDownMap[pointerButton] = null; + const swapCode = heldDownList.deleteByIndex(delIndex); + swapCode && (heldDownMap[swapCode] = delIndex); + } + upList.add(pointerButton); + upMap[pointerButton] = frameCount; break; case "pointermove": if (pointerIndex === -1) { @@ -196,16 +279,21 @@ export class PointerManager { --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); this._needOverallPointers = true; } + delIndex = heldDownMap[pointerButton]; + if (delIndex !== null) { + heldDownMap[pointerButton] = null; + const swapCode = heldDownList.deleteByIndex(delIndex); + swapCode && (heldDownMap[swapCode] = delIndex); + } break; } } const pointerCount = pointers.length; if (pointerCount > 0) { - const { _canvas: canvas, _currentPosition: currentPosition } = this; - // @ts-ignore - const pixelRatioWidth = canvas.width / (canvas._webCanvas as HTMLCanvasElement).clientWidth; - // @ts-ignore - const pixelRatioHeight = canvas.height / (canvas._webCanvas as HTMLCanvasElement).clientHeight; + const { _canvas: canvas, _currentPosition: currentPosition, _htmlCanvas: htmlCanvas } = this; + const { x: lastX, y: lastY } = currentPosition; + const pixelRatioWidth = canvas.width / htmlCanvas.clientWidth; + const pixelRatioHeight = canvas.height / htmlCanvas.clientHeight; if (activePointerCount === 0) { // Get the pointer coordinates when leaving, and use it to correctly dispatch the click event. const lastNativeEvent = nativeEvents[nativeEventsLen - 1]; @@ -223,6 +311,11 @@ export class PointerManager { } currentPosition.scale(1 / pointerCount); } + // Update pointer moving delta. + // Todo: Need to consider if the last coordinate is(0, 0). + if (lastX !== 0 || lastY !== 0) { + this._movingDelta.setValue(currentPosition.x - lastX, currentPosition.y - lastY); + } } nativeEvents.length = 0; } diff --git a/packages/core/src/input/wheel/WheelManager.ts b/packages/core/src/input/wheel/WheelManager.ts new file mode 100644 index 0000000000..14bbd3a10b --- /dev/null +++ b/packages/core/src/input/wheel/WheelManager.ts @@ -0,0 +1,74 @@ +import { IInput } from "../IInput"; + +/** + * Wheel Manager. + * @internal + */ +export class WheelManager implements IInput { + /** @internal */ + _deltaX: number = 0; + /** @internal */ + _deltaY: number = 0; + /** @internal */ + _deltaZ: number = 0; + + private _nativeEvents: WheelEvent[] = []; + private _canvas: HTMLCanvasElement; + + /** + * Create a KeyboardManager. + */ + constructor(htmlCanvas: HTMLCanvasElement) { + this._onWheelEvent = this._onWheelEvent.bind(this); + htmlCanvas.addEventListener("wheel", this._onWheelEvent); + } + + /** + * @internal + */ + _update(): void { + this._deltaX = this._deltaY = this._deltaZ = 0; + const { _nativeEvents: nativeEvents } = this; + if (nativeEvents.length > 0) { + for (let i = nativeEvents.length - 1; i >= 0; i--) { + const evt = nativeEvents[i]; + this._deltaX += evt.deltaX; + this._deltaY += evt.deltaY; + this._deltaZ += evt.deltaZ; + } + } + } + + /** + * @internal + */ + _enable(): void { + this._canvas.addEventListener("wheel", this._onWheelEvent); + } + + /** + * @internal + */ + _disable(): void { + this._canvas.removeEventListener("wheel", this._onWheelEvent); + } + + /** + * @internal + */ + _onBlur(): void { + this._nativeEvents.length = 0; + } + + /** + * @internal + */ + _destroy(): void { + this._canvas.removeEventListener("wheel", this._onWheelEvent); + this._nativeEvents = null; + } + + private _onWheelEvent(evt: WheelEvent): void { + this._nativeEvents.push(evt); + } +} From fdc57921e1c673fbdd71e3a11be6f778edea859a Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 21 Jun 2022 14:28:55 +0800 Subject: [PATCH 02/19] feat: update code --- packages/core/src/input/InputManager.ts | 20 ++++++-- .../core/src/input/enums/PointerButton.ts | 29 +++++++++++ packages/core/src/input/enums/PointerType.ts | 29 ----------- packages/core/src/input/index.ts | 3 +- .../src/input/keyboard/KeyboardManager.ts | 4 +- packages/core/src/input/pointer/Pointer.ts | 3 ++ .../core/src/input/pointer/PointerManager.ts | 50 +++++++++++-------- 7 files changed, 80 insertions(+), 58 deletions(-) create mode 100644 packages/core/src/input/enums/PointerButton.ts delete mode 100644 packages/core/src/input/enums/PointerType.ts diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index cb6d8996cf..1816f21027 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -3,7 +3,7 @@ import { KeyboardManager } from "./keyboard/KeyboardManager"; import { Keys } from "./enums/Keys"; import { Pointer } from "./pointer/Pointer"; import { PointerManager } from "./pointer/PointerManager"; -import { PointerButton } from "./enums/PointerType"; +import { PointerButton } from "./enums/PointerButton"; import { WheelManager } from "./wheel/WheelManager"; import { InputType } from "./enums/InputType"; import { Vector2 } from "@oasis-engine/math"; @@ -17,7 +17,7 @@ export class InputManager { _initialized: boolean = false; private _enabledTypes: number = InputType.None; - private _curFrameCount: number; + private _curFrameCount: number = 0; private _wheelManager: WheelManager; private _pointerManager: PointerManager; @@ -80,6 +80,16 @@ export class InputManager { return this._initialized ? this._pointerManager._movingDelta : null; } + /** + * Get the position of the pointer. + * @returns The position of the pointer + */ + get pointerPosition(): Readonly { + return this._initialized && this._pointerManager._pointers.length > 0 + ? this._pointerManager._currentPosition + : null; + } + /** * Handle this type of input. * @param type - The type of the input @@ -122,9 +132,9 @@ export class InputManager { if (key === undefined) { return this._keyboardManager._curFrameDownList.length > 0; } else if (typeof key === "string") { - return !!this._keyboardManager._curHeldDownKeyToIndexMap[Keys[key]]; + return this._keyboardManager._curHeldDownKeyToIndexMap[Keys[key]] != null; } else { - return !!this._keyboardManager._curHeldDownKeyToIndexMap[key]; + return this._keyboardManager._curHeldDownKeyToIndexMap[key] != null; } } else { return false; @@ -179,7 +189,7 @@ export class InputManager { if (button === undefined) { return this._pointerManager._heldDownList.length > 0; } else { - return !!this._pointerManager._heldDownMap[button]; + return this._pointerManager._heldDownMap[button] != null; } } else { return false; diff --git a/packages/core/src/input/enums/PointerButton.ts b/packages/core/src/input/enums/PointerButton.ts new file mode 100644 index 0000000000..43b46bf829 --- /dev/null +++ b/packages/core/src/input/enums/PointerButton.ts @@ -0,0 +1,29 @@ +/** + * Defines values that specify the buttons on a mouse device. + * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) + * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) + */ +export enum PointerButton { + /** MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ + Left = 0, + /** MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). */ + Middle = 1, + /** MUST indicate the secondary button (in general, the right button, often used to display a context menu). */ + Right = 2, + /** MUST indicate the X1 (back) button. */ + XButton1 = 3, + /** MUST indicate the X2 (forward) button. */ + XButton2 = 4, + /** MUST indicate the X3 button. */ + XButton3 = 5, + /** MUST indicate the X4 button. */ + XButton4 = 6, + /** MUST indicate the X5 button. */ + XButton5 = 7, + /** MUST indicate the X6 button. */ + XButton6 = 8, + /** MUST indicate the X7 button. */ + XButton7 = 9, + /** MUST indicate the X8 button. */ + XButton8 = 10 +} diff --git a/packages/core/src/input/enums/PointerType.ts b/packages/core/src/input/enums/PointerType.ts deleted file mode 100644 index 768b64829a..0000000000 --- a/packages/core/src/input/enums/PointerType.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Defines values that specify the buttons on a mouse device. - * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) - * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) - */ -export enum PointerButton { - // MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. - Left = 0, - // MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). - Middle = 1, - // MUST indicate the secondary button (in general, the right button, often used to display a context menu). - Right = 2, - // MUST indicate the X1 (back) button. - XButton1 = 3, - // MUST indicate the X2 (forward) button. - XButton2 = 4, - // MUST indicate the X3 button. - XButton3 = 5, - // MUST indicate the X4 button. - XButton4 = 6, - // MUST indicate the X5 button. - XButton5 = 7, - // MUST indicate the X6 button. - XButton6 = 8, - // MUST indicate the X7 button. - XButton7 = 9, - // MUST indicate the X8 button. - XButton8 = 10 -} diff --git a/packages/core/src/input/index.ts b/packages/core/src/input/index.ts index eccbaf0429..8edd5391dc 100644 --- a/packages/core/src/input/index.ts +++ b/packages/core/src/input/index.ts @@ -1,4 +1,5 @@ export { PointerPhase } from "./enums/PointerPhase"; export { Pointer } from "./pointer/Pointer"; export { InputManager } from "./InputManager"; -export { Keys } from "./enums/Keys"; \ No newline at end of file +export { Keys } from "./enums/Keys"; +export { PointerButton } from "./enums/PointerButton"; diff --git a/packages/core/src/input/keyboard/KeyboardManager.ts b/packages/core/src/input/keyboard/KeyboardManager.ts index 763170cbf8..198802ce32 100644 --- a/packages/core/src/input/keyboard/KeyboardManager.ts +++ b/packages/core/src/input/keyboard/KeyboardManager.ts @@ -51,7 +51,7 @@ export class KeyboardManager { switch (evt.type) { case "keydown": // Filter the repeated triggers of the keyboard. - if (curHeldDownKeyToIndexMap[codeKey] === null) { + if (curHeldDownKeyToIndexMap[codeKey] == null) { curFrameDownList.add(codeKey); curFrameHeldDownList.add(codeKey); curHeldDownKeyToIndexMap[codeKey] = curFrameHeldDownList.length - 1; @@ -60,7 +60,7 @@ export class KeyboardManager { break; case "keyup": const delIndex = curHeldDownKeyToIndexMap[codeKey]; - if (delIndex !== null) { + if (delIndex != null) { curHeldDownKeyToIndexMap[codeKey] = null; const swapCode = curFrameHeldDownList.deleteByIndex(delIndex); swapCode && (curHeldDownKeyToIndexMap[swapCode] = delIndex); diff --git a/packages/core/src/input/pointer/Pointer.ts b/packages/core/src/input/pointer/Pointer.ts index 3539654b80..61799e0725 100644 --- a/packages/core/src/input/pointer/Pointer.ts +++ b/packages/core/src/input/pointer/Pointer.ts @@ -1,4 +1,5 @@ import { Vector2 } from "@oasis-engine/math"; +import { PointerButton } from "../enums/PointerButton"; import { PointerPhase } from "../enums/PointerPhase"; /** @@ -10,6 +11,8 @@ export class Pointer { * @remark Start from 0. */ readonly id: number; + /** The button of pointer. */ + button: PointerButton = PointerButton.Left; /** The phase of pointer. */ phase: PointerPhase = PointerPhase.Leave; /** The position of the pointer in screen space pixel coordinates. */ diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index b2a6ca2977..0a5c755626 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -6,7 +6,7 @@ import { Entity } from "../../Entity"; import { CameraClearFlags } from "../../enums/CameraClearFlags"; import { HitResult } from "../../physics"; import { PointerPhase } from "../enums/PointerPhase"; -import { PointerButton } from "../enums/PointerType"; +import { PointerButton } from "../enums/PointerButton"; import { IInput } from "../IInput"; import { Pointer } from "./Pointer"; @@ -39,6 +39,11 @@ export class PointerManager implements IInput { /** @internal */ _upList: DisorderedArray = new DisorderedArray(); + /** @internal */ + _currentPosition: Vector2 = new Vector2(); + private _currentPressedEntity: Entity; + private _currentEnteredEntity: Entity; + private _engine: Engine; private _canvas: Canvas; private _htmlCanvas: HTMLCanvasElement; @@ -47,9 +52,6 @@ export class PointerManager implements IInput { private _keyEventList: number[] = []; private _keyEventCount: number = 0; private _needOverallPointers: boolean = false; - private _currentPosition: Vector2 = new Vector2(); - private _currentPressedEntity: Entity; - private _currentEnteredEntity: Entity; /** * Create a PointerManager. @@ -184,7 +186,7 @@ export class PointerManager implements IInput { return -1; } - private _addPointer(pointerId: number, x: number, y: number, phase: PointerPhase): void { + private _addPointer(pointerId: number, x: number, y: number, button: PointerButton, phase: PointerPhase): void { const { _pointers: pointers } = this; const lastCount = pointers.length; if (lastCount === 0 || this._multiPointerEnabled) { @@ -202,20 +204,24 @@ export class PointerManager implements IInput { } pointer._uniqueID = pointerId; pointer._needUpdate = true; + pointer.button = button; pointer.position.setValue(x, y); pointer.phase = phase; pointers.splice(i, 0, pointer); } } - private _removePointer(pointerIndex: number): void { - this._pointers[pointerIndex].phase = PointerPhase.Leave; + private _removePointer(pointerIndex: number): PointerButton { + const leavePointer = this._pointers[pointerIndex]; + leavePointer.phase = PointerPhase.Leave; + return leavePointer.button; } - private _updatePointer(pointerIndex: number, x: number, y: number, phase: PointerPhase): void { + private _updatePointer(pointerIndex: number, x: number, y: number, button: PointerButton, phase: PointerPhase): void { const updatedPointer = this._pointers[pointerIndex]; updatedPointer.position.setValue(x, y); updatedPointer._needUpdate = true; + updatedPointer.button = button; updatedPointer.phase = phase; } @@ -235,28 +241,29 @@ export class PointerManager implements IInput { const nativeEventsLen = nativeEvents.length; for (let i = 0; i < nativeEventsLen; i++) { const evt = nativeEvents[i]; - const pointerButton: PointerButton = evt.hasOwnProperty("button") ? evt.button : PointerButton.Left; + const pointerButton: PointerButton = evt.button | PointerButton.Left; const pointerIndex = this._getIndexByPointerID(evt.pointerId); switch (evt.type) { case "pointerdown": if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Down); + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); activePointerCount++; } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Down); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); } activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); downList.add(pointerButton); + heldDownMap[pointerButton] = heldDownList.length; heldDownList.add(pointerButton); - heldDownMap[pointerButton] = heldDownList.length - 1; downMap[pointerButton] = frameCount; break; case "pointerup": if (pointerIndex >= 0) { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Up); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Up); activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); } delIndex = heldDownMap[pointerButton]; + console.log("移除了button", pointerButton); if (delIndex != null) { heldDownMap[pointerButton] = null; const swapCode = heldDownList.deleteByIndex(delIndex); @@ -267,10 +274,10 @@ export class PointerManager implements IInput { break; case "pointermove": if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Move); + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); activePointerCount++; } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Move); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); } break; case "pointerout": @@ -278,12 +285,13 @@ export class PointerManager implements IInput { this._removePointer(pointerIndex); --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); this._needOverallPointers = true; - } - delIndex = heldDownMap[pointerButton]; - if (delIndex !== null) { - heldDownMap[pointerButton] = null; - const swapCode = heldDownList.deleteByIndex(delIndex); - swapCode && (heldDownMap[swapCode] = delIndex); + + delIndex = heldDownMap[pointerButton]; + if (delIndex != null) { + heldDownMap[pointerButton] = null; + const swapCode = heldDownList.deleteByIndex(delIndex); + swapCode && (heldDownMap[swapCode] = delIndex); + } } break; } From 1cbf4feebd82b3ff12246864486e27860126b895 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Thu, 30 Jun 2022 15:33:01 +0800 Subject: [PATCH 03/19] feat: update code --- packages/core/src/input/InputManager.ts | 9 ++++++ packages/core/src/input/enums/InputType.ts | 8 +++++ .../core/src/input/{ => interface}/IInput.ts | 4 +++ .../src/input/keyboard/KeyboardManager.ts | 21 ++++++++---- .../core/src/input/pointer/PointerManager.ts | 32 +++++++++++++++---- packages/core/src/input/wheel/WheelManager.ts | 13 ++++++-- 6 files changed, 73 insertions(+), 14 deletions(-) rename packages/core/src/input/{ => interface}/IInput.ts (87%) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index 1816f21027..cf35b23be4 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -252,6 +252,8 @@ export class InputManager { this._keyboardManager = new KeyboardManager(); this._onBlur = this._onBlur.bind(this); window.addEventListener("blur", this._onBlur); + this._onFocus = this._onFocus.bind(this); + window.addEventListener("focus", this._onFocus); this._initialized = true; } } @@ -283,4 +285,11 @@ export class InputManager { enabledTypes & InputType.Pointer && this._pointerManager._onBlur(); enabledTypes & InputType.Keyboard && this._keyboardManager._onBlur(); } + + private _onFocus(): void { + const { _enabledTypes: enabledTypes } = this; + enabledTypes & InputType.Wheel && this._wheelManager._onFocus(); + enabledTypes & InputType.Pointer && this._pointerManager._onFocus(); + enabledTypes & InputType.Keyboard && this._keyboardManager._onFocus(); + } } diff --git a/packages/core/src/input/enums/InputType.ts b/packages/core/src/input/enums/InputType.ts index 4ce97b3fdd..44007f1dd7 100644 --- a/packages/core/src/input/enums/InputType.ts +++ b/packages/core/src/input/enums/InputType.ts @@ -1,7 +1,15 @@ +/** + * Enumeration of input types. + */ export enum InputType { + /** Nothing. */ None = 0, + /** Wheel. */ Wheel = 1, + /** Mouse, touch, pen, etc. */ Pointer = 2, + /** Keyboard. */ Keyboard = 4, + /** Everything above. */ All = 7 } diff --git a/packages/core/src/input/IInput.ts b/packages/core/src/input/interface/IInput.ts similarity index 87% rename from packages/core/src/input/IInput.ts rename to packages/core/src/input/interface/IInput.ts index ab787781b3..87bb077964 100644 --- a/packages/core/src/input/IInput.ts +++ b/packages/core/src/input/interface/IInput.ts @@ -15,6 +15,10 @@ export interface IInput { * Function called when the engine is destroyed. */ _destroy(): void; + /** + * Function called when focused. + */ + _onFocus(): void; /** * Function called when focus is lost. */ diff --git a/packages/core/src/input/keyboard/KeyboardManager.ts b/packages/core/src/input/keyboard/KeyboardManager.ts index 198802ce32..416eb0a2bc 100644 --- a/packages/core/src/input/keyboard/KeyboardManager.ts +++ b/packages/core/src/input/keyboard/KeyboardManager.ts @@ -1,11 +1,12 @@ import { DisorderedArray } from "../../DisorderedArray"; import { Keys } from "../enums/Keys"; +import { IInput } from "../interface/IInput"; /** * Keyboard Manager. * @internal */ -export class KeyboardManager { +export class KeyboardManager implements IInput { /** @internal */ _curHeldDownKeyToIndexMap: number[] = []; /** @internal */ @@ -90,17 +91,25 @@ export class KeyboardManager { _disable(): void { window.removeEventListener("keydown", this._onKeyEvent); window.removeEventListener("keyup", this._onKeyEvent); + this._curHeldDownKeyToIndexMap.length = 0; + this._curFrameHeldDownList.length = 0; + this._curFrameDownList.length = 0; + this._curFrameUpList.length = 0; + this._nativeEvents.length = 0; + } + + /** + * @internal + */ + _onFocus(): void { + this._enable(); } /** * @internal */ _onBlur(): void { - this._curHeldDownKeyToIndexMap.length = 0; - this._curFrameHeldDownList.length = 0; - this._curFrameDownList.length = 0; - this._curFrameUpList.length = 0; - this._nativeEvents.length = 0; + this._disable(); } /** diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 0a5c755626..2cd4e1ba6a 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -7,7 +7,7 @@ import { CameraClearFlags } from "../../enums/CameraClearFlags"; import { HitResult } from "../../physics"; import { PointerPhase } from "../enums/PointerPhase"; import { PointerButton } from "../enums/PointerButton"; -import { IInput } from "../IInput"; +import { IInput } from "../interface/IInput"; import { Pointer } from "./Pointer"; /** @@ -68,6 +68,7 @@ export class PointerManager implements IInput { htmlCanvas.addEventListener("pointerup", onPointerEvent); htmlCanvas.addEventListener("pointerout", onPointerEvent); htmlCanvas.addEventListener("pointermove", onPointerEvent); + htmlCanvas.addEventListener("pointercancel", onPointerEvent); // If there are no compatibility issues, navigator.maxTouchPoints should be used here. this._pointerPool = new Array(11); } @@ -115,6 +116,7 @@ export class PointerManager implements IInput { htmlCanvas.addEventListener("pointerup", onPointerEvent); htmlCanvas.addEventListener("pointerout", onPointerEvent); htmlCanvas.addEventListener("pointermove", onPointerEvent); + htmlCanvas.addEventListener("pointercancel", onPointerEvent); } /** @@ -126,16 +128,30 @@ export class PointerManager implements IInput { htmlCanvas.removeEventListener("pointerup", onPointerEvent); htmlCanvas.removeEventListener("pointerout", onPointerEvent); htmlCanvas.removeEventListener("pointermove", onPointerEvent); + htmlCanvas.removeEventListener("pointercancel", onPointerEvent); + this._nativeEvents.length = 0; + this._pointerPool.length = 0; + this._currentPosition = null; + this._currentEnteredEntity = null; + this._currentPressedEntity = null; + this._heldDownMap.length = 0; + this._heldDownList.length = 0; + this._downList.length = 0; + this._upList.length = 0; + } + + /** + * @internal + */ + _onFocus(): void { + this._enable(); } /** * @internal */ _onBlur(): void { - this._heldDownMap.length = 0; - this._heldDownList.length = 0; - this._downList.length = 0; - this._upList.length = 0; + this._disable(); } /** @@ -263,7 +279,7 @@ export class PointerManager implements IInput { activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); } delIndex = heldDownMap[pointerButton]; - console.log("移除了button", pointerButton); + console.log("pointerup", pointerButton); if (delIndex != null) { heldDownMap[pointerButton] = null; const swapCode = heldDownList.deleteByIndex(delIndex); @@ -281,6 +297,7 @@ export class PointerManager implements IInput { } break; case "pointerout": + console.log("pointerout", pointerButton); if (pointerIndex >= 0) { this._removePointer(pointerIndex); --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); @@ -294,6 +311,9 @@ export class PointerManager implements IInput { } } break; + case "pointercancel": + console.log("pointercancel", pointerButton); + break; } } const pointerCount = pointers.length; diff --git a/packages/core/src/input/wheel/WheelManager.ts b/packages/core/src/input/wheel/WheelManager.ts index 14bbd3a10b..6ed1332d1f 100644 --- a/packages/core/src/input/wheel/WheelManager.ts +++ b/packages/core/src/input/wheel/WheelManager.ts @@ -1,4 +1,4 @@ -import { IInput } from "../IInput"; +import { IInput } from "../interface/IInput"; /** * Wheel Manager. @@ -51,13 +51,22 @@ export class WheelManager implements IInput { */ _disable(): void { this._canvas.removeEventListener("wheel", this._onWheelEvent); + this._nativeEvents.length = 0; + this._deltaX = this._deltaY = this._deltaZ = 0; + } + + /** + * @internal + */ + _onFocus(): void { + this._enable(); } /** * @internal */ _onBlur(): void { - this._nativeEvents.length = 0; + this._disable(); } /** From a41805d0a93314756aba825e050a11294fa70105 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Thu, 30 Jun 2022 23:44:00 +0800 Subject: [PATCH 04/19] feat: opt input --- packages/core/src/input/InputManager.ts | 4 +- .../core/src/input/enums/PointerButton.ts | 29 ++--- .../core/src/input/pointer/PointerManager.ts | 108 +++++++----------- 3 files changed, 59 insertions(+), 82 deletions(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index cf35b23be4..b079eef503 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -187,9 +187,9 @@ export class InputManager { isButtonHeldDown(button?: PointerButton): boolean { if (this._initialized) { if (button === undefined) { - return this._pointerManager._heldDownList.length > 0; + return this._pointerManager._buttons !== PointerButton.None; } else { - return this._pointerManager._heldDownMap[button] != null; + return (this._pointerManager._buttons & button) !== 0; } } else { return false; diff --git a/packages/core/src/input/enums/PointerButton.ts b/packages/core/src/input/enums/PointerButton.ts index 43b46bf829..2b0820f5b8 100644 --- a/packages/core/src/input/enums/PointerButton.ts +++ b/packages/core/src/input/enums/PointerButton.ts @@ -1,29 +1,30 @@ /** * Defines values that specify the buttons on a mouse device. - * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) - * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) + * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-buttons) */ export enum PointerButton { + /** No button. */ + None = 0x0, /** MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ - Left = 0, - /** MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). */ - Middle = 1, + Left = 0x1, /** MUST indicate the secondary button (in general, the right button, often used to display a context menu). */ - Right = 2, + Right = 0x2, + /** MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). */ + Middle = 0x4, /** MUST indicate the X1 (back) button. */ - XButton1 = 3, + XButton1 = 0x8, /** MUST indicate the X2 (forward) button. */ - XButton2 = 4, + XButton2 = 0x10, /** MUST indicate the X3 button. */ - XButton3 = 5, + XButton3 = 0x20, /** MUST indicate the X4 button. */ - XButton4 = 6, + XButton4 = 0x40, /** MUST indicate the X5 button. */ - XButton5 = 7, + XButton5 = 0x80, /** MUST indicate the X6 button. */ - XButton6 = 8, + XButton6 = 0x100, /** MUST indicate the X7 button. */ - XButton7 = 9, + XButton7 = 0x200, /** MUST indicate the X8 button. */ - XButton8 = 10 + XButton8 = 0x300 } diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index beed0a700d..00bb83fe43 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -27,14 +27,12 @@ export class PointerManager implements IInput { _multiPointerEnabled: boolean = true; /** @internal */ - _heldDownMap: number[] = []; + _buttons: number = PointerButton.None; /** @internal */ _upMap: number[] = []; /** @internal */ _downMap: number[] = []; /** @internal */ - _heldDownList: DisorderedArray = new DisorderedArray(); - /** @internal */ _downList: DisorderedArray = new DisorderedArray(); /** @internal */ _upList: DisorderedArray = new DisorderedArray(); @@ -134,8 +132,6 @@ export class PointerManager implements IInput { this._currentPosition = null; this._currentEnteredEntity = null; this._currentPressedEntity = null; - this._heldDownMap.length = 0; - this._heldDownList.length = 0; this._downList.length = 0; this._upList.length = 0; } @@ -245,76 +241,56 @@ export class PointerManager implements IInput { const { _pointers: pointers, _keyEventList: keyEventList, - _heldDownMap: heldDownMap, _upMap: upMap, _downMap: downMap, - _heldDownList: heldDownList, _upList: upList, _downList: downList } = this; let activePointerCount = pointers.length; - let delIndex: number; const nativeEventsLen = nativeEvents.length; - for (let i = 0; i < nativeEventsLen; i++) { - const evt = nativeEvents[i]; - const pointerButton: PointerButton = evt.button | PointerButton.Left; - const pointerIndex = this._getIndexByPointerID(evt.pointerId); - switch (evt.type) { - case "pointerdown": - if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); - activePointerCount++; - } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); - } - activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); - downList.add(pointerButton); - heldDownMap[pointerButton] = heldDownList.length; - heldDownList.add(pointerButton); - downMap[pointerButton] = frameCount; - break; - case "pointerup": - if (pointerIndex >= 0) { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Up); - activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); - } - delIndex = heldDownMap[pointerButton]; - console.log("pointerup", pointerButton); - if (delIndex != null) { - heldDownMap[pointerButton] = null; - const swapCode = heldDownList.deleteByIndex(delIndex); - swapCode && (heldDownMap[swapCode] = delIndex); - } - upList.add(pointerButton); - upMap[pointerButton] = frameCount; - break; - case "pointermove": - if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); - activePointerCount++; - } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); - } - break; - case "pointerout": - console.log("pointerout", pointerButton); - if (pointerIndex >= 0) { - this._removePointer(pointerIndex); - --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); - this._needOverallPointers = true; - - delIndex = heldDownMap[pointerButton]; - if (delIndex != null) { - heldDownMap[pointerButton] = null; - const swapCode = heldDownList.deleteByIndex(delIndex); - swapCode && (heldDownMap[swapCode] = delIndex); + if (nativeEventsLen > 0) { + for (let i = 0; i < nativeEventsLen; i++) { + const evt = nativeEvents[i]; + const pointerButton: PointerButton = evt.button | PointerButton.Left; + const pointerIndex = this._getIndexByPointerID(evt.pointerId); + switch (evt.type) { + case "pointerdown": + if (pointerIndex === -1) { + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); + activePointerCount++; + } else { + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); } - } - break; - case "pointercancel": - console.log("pointercancel", pointerButton); - break; + activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); + downList.add(pointerButton); + downMap[pointerButton] = frameCount; + break; + case "pointerup": + if (pointerIndex >= 0) { + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Up); + activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); + } + upList.add(pointerButton); + upMap[pointerButton] = frameCount; + break; + case "pointermove": + if (pointerIndex === -1) { + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); + activePointerCount++; + } else { + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); + } + break; + case "pointerout": + if (pointerIndex >= 0) { + this._removePointer(pointerIndex); + --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); + this._needOverallPointers = true; + } + break; + } } + this._buttons = nativeEvents[nativeEventsLen - 1].buttons; } const pointerCount = pointers.length; if (pointerCount > 0) { From cdf3569098af55be655b773c62b867f99f935ceb Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Thu, 30 Jun 2022 23:53:00 +0800 Subject: [PATCH 05/19] feat: opt input --- packages/core/src/input/pointer/Pointer.ts | 3 --- .../core/src/input/pointer/PointerManager.ts | 19 ++++++++----------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/core/src/input/pointer/Pointer.ts b/packages/core/src/input/pointer/Pointer.ts index 61799e0725..3539654b80 100644 --- a/packages/core/src/input/pointer/Pointer.ts +++ b/packages/core/src/input/pointer/Pointer.ts @@ -1,5 +1,4 @@ import { Vector2 } from "@oasis-engine/math"; -import { PointerButton } from "../enums/PointerButton"; import { PointerPhase } from "../enums/PointerPhase"; /** @@ -11,8 +10,6 @@ export class Pointer { * @remark Start from 0. */ readonly id: number; - /** The button of pointer. */ - button: PointerButton = PointerButton.Left; /** The phase of pointer. */ phase: PointerPhase = PointerPhase.Leave; /** The position of the pointer in screen space pixel coordinates. */ diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 00bb83fe43..367a616230 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -198,7 +198,7 @@ export class PointerManager implements IInput { return -1; } - private _addPointer(pointerId: number, x: number, y: number, button: PointerButton, phase: PointerPhase): void { + private _addPointer(pointerId: number, x: number, y: number, phase: PointerPhase): void { const { _pointers: pointers } = this; const lastCount = pointers.length; if (lastCount === 0 || this._multiPointerEnabled) { @@ -216,24 +216,21 @@ export class PointerManager implements IInput { } pointer._uniqueID = pointerId; pointer._needUpdate = true; - pointer.button = button; pointer.position.set(x, y); pointer.phase = phase; pointers.splice(i, 0, pointer); } } - private _removePointer(pointerIndex: number): PointerButton { + private _removePointer(pointerIndex: number): void { const leavePointer = this._pointers[pointerIndex]; leavePointer.phase = PointerPhase.Leave; - return leavePointer.button; } - private _updatePointer(pointerIndex: number, x: number, y: number, button: PointerButton, phase: PointerPhase): void { + private _updatePointer(pointerIndex: number, x: number, y: number, phase: PointerPhase): void { const updatedPointer = this._pointers[pointerIndex]; updatedPointer.position.set(x, y); updatedPointer._needUpdate = true; - updatedPointer.button = button; updatedPointer.phase = phase; } @@ -256,10 +253,10 @@ export class PointerManager implements IInput { switch (evt.type) { case "pointerdown": if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Down); activePointerCount++; } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Down); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Down); } activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); downList.add(pointerButton); @@ -267,7 +264,7 @@ export class PointerManager implements IInput { break; case "pointerup": if (pointerIndex >= 0) { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Up); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Up); activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); } upList.add(pointerButton); @@ -275,10 +272,10 @@ export class PointerManager implements IInput { break; case "pointermove": if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); + this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Move); activePointerCount++; } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, pointerButton, PointerPhase.Move); + this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Move); } break; case "pointerout": From 5b7be80c33a02787fbc30c5511d60df3d61eb208 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Thu, 30 Jun 2022 23:57:29 +0800 Subject: [PATCH 06/19] feat: opt input --- packages/core/src/input/pointer/PointerManager.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 367a616230..e195a24e73 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -66,7 +66,6 @@ export class PointerManager implements IInput { htmlCanvas.addEventListener("pointerup", onPointerEvent); htmlCanvas.addEventListener("pointerout", onPointerEvent); htmlCanvas.addEventListener("pointermove", onPointerEvent); - htmlCanvas.addEventListener("pointercancel", onPointerEvent); // If there are no compatibility issues, navigator.maxTouchPoints should be used here. this._pointerPool = new Array(11); } @@ -114,7 +113,6 @@ export class PointerManager implements IInput { htmlCanvas.addEventListener("pointerup", onPointerEvent); htmlCanvas.addEventListener("pointerout", onPointerEvent); htmlCanvas.addEventListener("pointermove", onPointerEvent); - htmlCanvas.addEventListener("pointercancel", onPointerEvent); } /** @@ -126,7 +124,6 @@ export class PointerManager implements IInput { htmlCanvas.removeEventListener("pointerup", onPointerEvent); htmlCanvas.removeEventListener("pointerout", onPointerEvent); htmlCanvas.removeEventListener("pointermove", onPointerEvent); - htmlCanvas.removeEventListener("pointercancel", onPointerEvent); this._nativeEvents.length = 0; this._pointerPool.length = 0; this._currentPosition = null; From eb006eba34e88d485a84a4975ca009ab26342cce Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Fri, 1 Jul 2022 00:06:46 +0800 Subject: [PATCH 07/19] feat: opt input --- packages/core/src/input/InputManager.ts | 4 +-- .../core/src/input/enums/PointerButton.ts | 29 +++++++++---------- .../core/src/input/pointer/PointerManager.ts | 5 +++- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index b079eef503..faff551e89 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -187,9 +187,9 @@ export class InputManager { isButtonHeldDown(button?: PointerButton): boolean { if (this._initialized) { if (button === undefined) { - return this._pointerManager._buttons !== PointerButton.None; + return this._pointerManager._buttons !== 0; } else { - return (this._pointerManager._buttons & button) !== 0; + return (this._pointerManager._buttons & PointerManager.Buttons[button]) !== 0; } } else { return false; diff --git a/packages/core/src/input/enums/PointerButton.ts b/packages/core/src/input/enums/PointerButton.ts index 2b0820f5b8..43b46bf829 100644 --- a/packages/core/src/input/enums/PointerButton.ts +++ b/packages/core/src/input/enums/PointerButton.ts @@ -1,30 +1,29 @@ /** * Defines values that specify the buttons on a mouse device. - * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-buttons) + * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) + * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) */ export enum PointerButton { - /** No button. */ - None = 0x0, /** MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ - Left = 0x1, - /** MUST indicate the secondary button (in general, the right button, often used to display a context menu). */ - Right = 0x2, + Left = 0, /** MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). */ - Middle = 0x4, + Middle = 1, + /** MUST indicate the secondary button (in general, the right button, often used to display a context menu). */ + Right = 2, /** MUST indicate the X1 (back) button. */ - XButton1 = 0x8, + XButton1 = 3, /** MUST indicate the X2 (forward) button. */ - XButton2 = 0x10, + XButton2 = 4, /** MUST indicate the X3 button. */ - XButton3 = 0x20, + XButton3 = 5, /** MUST indicate the X4 button. */ - XButton4 = 0x40, + XButton4 = 6, /** MUST indicate the X5 button. */ - XButton5 = 0x80, + XButton5 = 7, /** MUST indicate the X6 button. */ - XButton6 = 0x100, + XButton6 = 8, /** MUST indicate the X7 button. */ - XButton7 = 0x200, + XButton7 = 9, /** MUST indicate the X8 button. */ - XButton8 = 0x300 + XButton8 = 10 } diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index e195a24e73..d2923b3570 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -15,6 +15,9 @@ import { Pointer } from "./Pointer"; * @internal */ export class PointerManager implements IInput { + /** Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-buttons) */ + public static Buttons = [0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400]; + private static _tempRay: Ray = new Ray(); private static _tempPoint: Vector2 = new Vector2(); private static _tempHitResult: HitResult = new HitResult(); @@ -27,7 +30,7 @@ export class PointerManager implements IInput { _multiPointerEnabled: boolean = true; /** @internal */ - _buttons: number = PointerButton.None; + _buttons: number = 0x0; /** @internal */ _upMap: number[] = []; /** @internal */ From 9f4181a8e09eed91c1ff5e45918b7820fd6552a5 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:07:59 +0800 Subject: [PATCH 08/19] feat: update code --- packages/core/src/input/InputManager.ts | 121 +++++------------- .../core/src/input/enums/PointerButton.ts | 24 ++-- packages/core/src/input/interface/IInput.ts | 8 -- .../src/input/keyboard/KeyboardManager.ts | 40 +++--- .../core/src/input/pointer/PointerManager.ts | 56 ++++---- packages/core/src/input/wheel/WheelManager.ts | 46 +++---- 6 files changed, 103 insertions(+), 192 deletions(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index faff551e89..eba86ef13d 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -6,7 +6,7 @@ import { PointerManager } from "./pointer/PointerManager"; import { PointerButton } from "./enums/PointerButton"; import { WheelManager } from "./wheel/WheelManager"; import { InputType } from "./enums/InputType"; -import { Vector2 } from "@oasis-engine/math"; +import { Vector2, Vector3 } from "@oasis-engine/math"; /** * InputManager manages device input such as mouse, touch, keyboard, etc. @@ -15,21 +15,12 @@ export class InputManager { /** Sometimes the input module will not be initialized, such as off-screen rendering. */ /** @internal */ _initialized: boolean = false; - - private _enabledTypes: number = InputType.None; private _curFrameCount: number = 0; private _wheelManager: WheelManager; private _pointerManager: PointerManager; private _keyboardManager: KeyboardManager; - /** - * Set of received input types. - */ - get enabledTypes(): number { - return this._enabledTypes; - } - /** * Pointer List. */ @@ -52,24 +43,8 @@ export class InputManager { * Get the change of the scroll wheel on the x-axis. * @returns Change value */ - get wheelDeltaX(): number { - return this._initialized ? this._wheelManager._deltaX : 0; - } - - /** - * Get the change of the scroll wheel on the y-axis. - * @returns Change value - */ - get wheelDeltaY(): number { - return this._initialized ? this._wheelManager._deltaY : 0; - } - - /** - * Get the change of the scroll wheel on the z-axis. - * @returns Change value - */ - get wheelDeltaZ(): number { - return this._initialized ? this._wheelManager._deltaY : 0; + get wheelDelta(): Readonly { + return this._initialized ? this._wheelManager._delta : null; } /** @@ -90,38 +65,6 @@ export class InputManager { : null; } - /** - * Handle this type of input. - * @param type - The type of the input - */ - enableInput(type: InputType): void { - if (this._initialized) { - const diff = this._enabledTypes ^ type; - if (diff) { - this._enabledTypes |= type; - diff & InputType.Wheel && this._wheelManager._enable(); - diff & InputType.Pointer && this._pointerManager._enable(); - diff & InputType.Keyboard && this._keyboardManager._enable(); - } - } - } - - /** - * Does not handle this type of input. - * @param type - The type of the input - */ - disableInput(type: InputType): void { - if (this._initialized) { - const same = this._enabledTypes & type; - if (same) { - this._enabledTypes &= ~type; - same & InputType.Wheel && this._wheelManager._disable(); - same & InputType.Pointer && this._pointerManager._disable(); - same & InputType.Keyboard && this._keyboardManager._disable(); - } - } - } - /** * Whether the key is being held down, if there is no parameter, return whether any key is being held down. * @param key - The keys of the keyboard @@ -180,16 +123,16 @@ export class InputManager { } /** - * Whether the button is being held down, if there is no parameter, return whether any button is being held down. - * @param button - The buttons on a mouse device - * @returns Whether the button is being held down + * Whether the pointer is being held down, if there is no parameter, return whether any pointer is being held down. + * @param pointerButton - The pointerButton on a pointer device + * @returns Whether the pointer is being held down */ - isButtonHeldDown(button?: PointerButton): boolean { + isPointerHeldDown(pointerButton?: PointerButton): boolean { if (this._initialized) { - if (button === undefined) { + if (pointerButton === undefined) { return this._pointerManager._buttons !== 0; } else { - return (this._pointerManager._buttons & PointerManager.Buttons[button]) !== 0; + return (this._pointerManager._buttons & PointerManager.Buttons[pointerButton]) !== 0; } } else { return false; @@ -197,16 +140,16 @@ export class InputManager { } /** - * Whether the button starts to be pressed down during the current frame, if there is no parameter, return whether any button starts to be pressed down during the current frame. - * @param button - The buttons on a mouse device - * @returns Whether the button starts to be pressed down during the current frame + * Whether the pointer starts to be pressed down during the current frame, if there is no parameter, return whether any pointer starts to be pressed down during the current frame. + * @param pointerButton - The pointerButton on a pointer device + * @returns Whether the pointer starts to be pressed down during the current frame */ - isButtonDown(button: PointerButton): boolean { + isPointerDown(pointerButton: PointerButton): boolean { if (this._initialized) { - if (button === undefined) { + if (pointerButton === undefined) { return this._pointerManager._downList.length > 0; } else { - return this._pointerManager._downMap[button] === this._curFrameCount; + return this._pointerManager._downMap[pointerButton] === this._curFrameCount; } } else { return false; @@ -214,16 +157,16 @@ export class InputManager { } /** - * Whether the button is released during the current frame, if there is no parameter, return whether any button released during the current frame. - * @param button - The buttons on a mouse device - * @returns Whether the button is released during the current frame + * Whether the pointer is released during the current frame, if there is no parameter, return whether any pointer released during the current frame. + * @param pointerButton - The pointerButtons on a mouse device + * @returns Whether the pointer is released during the current frame */ - isButtonUp(button: PointerButton): boolean { + isPointerUp(pointerButton: PointerButton): boolean { if (this._initialized) { - if (button === undefined) { + if (pointerButton === undefined) { return this._pointerManager._upList.length > 0; } else { - return this._pointerManager._upMap[button] === this._curFrameCount; + return this._pointerManager._upMap[pointerButton] === this._curFrameCount; } } else { return false; @@ -246,7 +189,6 @@ export class InputManager { // @ts-ignore const canvas = engine._canvas._webCanvas; if (canvas instanceof HTMLCanvasElement) { - this._enabledTypes = InputType.All; this._wheelManager = new WheelManager(canvas); this._pointerManager = new PointerManager(engine, canvas); this._keyboardManager = new KeyboardManager(); @@ -263,10 +205,9 @@ export class InputManager { */ _update(): void { ++this._curFrameCount; - const { _enabledTypes: enabledTypes } = this; - enabledTypes & InputType.Wheel && this._wheelManager._update(); - enabledTypes & InputType.Pointer && this._pointerManager._update(this._curFrameCount); - enabledTypes & InputType.Keyboard && this._keyboardManager._update(this._curFrameCount); + this._wheelManager._update(); + this._pointerManager._update(this._curFrameCount); + this._keyboardManager._update(this._curFrameCount); } /** @@ -280,16 +221,14 @@ export class InputManager { } private _onBlur(): void { - const { _enabledTypes: enabledTypes } = this; - enabledTypes & InputType.Wheel && this._wheelManager._onBlur(); - enabledTypes & InputType.Pointer && this._pointerManager._onBlur(); - enabledTypes & InputType.Keyboard && this._keyboardManager._onBlur(); + this._wheelManager._onBlur(); + this._pointerManager._onBlur(); + this._keyboardManager._onBlur(); } private _onFocus(): void { - const { _enabledTypes: enabledTypes } = this; - enabledTypes & InputType.Wheel && this._wheelManager._onFocus(); - enabledTypes & InputType.Pointer && this._pointerManager._onFocus(); - enabledTypes & InputType.Keyboard && this._keyboardManager._onFocus(); + this._wheelManager._onFocus(); + this._pointerManager._onFocus(); + this._keyboardManager._onFocus(); } } diff --git a/packages/core/src/input/enums/PointerButton.ts b/packages/core/src/input/enums/PointerButton.ts index 43b46bf829..8890d9d708 100644 --- a/packages/core/src/input/enums/PointerButton.ts +++ b/packages/core/src/input/enums/PointerButton.ts @@ -1,29 +1,29 @@ /** - * Defines values that specify the buttons on a mouse device. + * Defines values that specify the buttons on a pointer device. * Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-button) * Refer to Microsoft's documentation.(https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.mousebutton?view=windowsdesktop-6.0) */ export enum PointerButton { - /** MUST indicate the primary button of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ + /** Indicate the primary pointer of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ Left = 0, - /** MUST indicate the auxiliary button (in general, the middle button, often combined with a mouse wheel). */ + /** Indicate the auxiliary pointer (in general, the middle button, often combined with a mouse wheel). */ Middle = 1, - /** MUST indicate the secondary button (in general, the right button, often used to display a context menu). */ + /** Indicate the secondary pointer (in general, the right button, often used to display a context menu). */ Right = 2, - /** MUST indicate the X1 (back) button. */ + /** Indicate the X1 (back) pointer. */ XButton1 = 3, - /** MUST indicate the X2 (forward) button. */ + /** Indicate the X2 (forward) pointer. */ XButton2 = 4, - /** MUST indicate the X3 button. */ + /** Indicate the X3 pointer. */ XButton3 = 5, - /** MUST indicate the X4 button. */ + /** Indicate the X4 pointer. */ XButton4 = 6, - /** MUST indicate the X5 button. */ + /** Indicate the X5 pointer. */ XButton5 = 7, - /** MUST indicate the X6 button. */ + /** Indicate the X6 pointer. */ XButton6 = 8, - /** MUST indicate the X7 button. */ + /** Indicate the X7 pointer. */ XButton7 = 9, - /** MUST indicate the X8 button. */ + /** Indicate the X8 pointer. */ XButton8 = 10 } diff --git a/packages/core/src/input/interface/IInput.ts b/packages/core/src/input/interface/IInput.ts index 87bb077964..cfc0a20867 100644 --- a/packages/core/src/input/interface/IInput.ts +++ b/packages/core/src/input/interface/IInput.ts @@ -3,14 +3,6 @@ export interface IInput { * Handler function updated every frame. */ _update(frameCount?: number): void; - /** - * Function called when the input changes from disabled to enabled state. - */ - _enable(): void; - /** - * Function called when the input changes from enabled to disabled state. - */ - _disable(): void; /** * Function called when the engine is destroyed. */ diff --git a/packages/core/src/input/keyboard/KeyboardManager.ts b/packages/core/src/input/keyboard/KeyboardManager.ts index 416eb0a2bc..f5d8749cfd 100644 --- a/packages/core/src/input/keyboard/KeyboardManager.ts +++ b/packages/core/src/input/keyboard/KeyboardManager.ts @@ -22,6 +22,7 @@ export class KeyboardManager implements IInput { _curFrameUpList: DisorderedArray = new DisorderedArray(); private _nativeEvents: KeyboardEvent[] = []; + private _hadListener: boolean = false; /** * Create a KeyboardManager. @@ -30,6 +31,7 @@ export class KeyboardManager implements IInput { this._onKeyEvent = this._onKeyEvent.bind(this); window.addEventListener("keydown", this._onKeyEvent); window.addEventListener("keyup", this._onKeyEvent); + this._hadListener = true; } /** @@ -77,39 +79,31 @@ export class KeyboardManager implements IInput { } } - /** - * @internal - */ - _enable(): void { - window.addEventListener("keydown", this._onKeyEvent); - window.addEventListener("keyup", this._onKeyEvent); - } - - /** - * @internal - */ - _disable(): void { - window.removeEventListener("keydown", this._onKeyEvent); - window.removeEventListener("keyup", this._onKeyEvent); - this._curHeldDownKeyToIndexMap.length = 0; - this._curFrameHeldDownList.length = 0; - this._curFrameDownList.length = 0; - this._curFrameUpList.length = 0; - this._nativeEvents.length = 0; - } - /** * @internal */ _onFocus(): void { - this._enable(); + if (!this._hadListener) { + window.addEventListener("keydown", this._onKeyEvent); + window.addEventListener("keyup", this._onKeyEvent); + this._hadListener = true; + } } /** * @internal */ _onBlur(): void { - this._disable(); + if (this._hadListener) { + window.removeEventListener("keydown", this._onKeyEvent); + window.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; + } } /** diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index d2923b3570..4d443a2bb3 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -53,6 +53,7 @@ export class PointerManager implements IInput { private _keyEventList: number[] = []; private _keyEventCount: number = 0; private _needOverallPointers: boolean = false; + private _hadListener: boolean = false; /** * Create a PointerManager. @@ -69,6 +70,7 @@ export class PointerManager implements IInput { htmlCanvas.addEventListener("pointerup", onPointerEvent); htmlCanvas.addEventListener("pointerout", onPointerEvent); htmlCanvas.addEventListener("pointermove", onPointerEvent); + this._hadListener = true; // If there are no compatibility issues, navigator.maxTouchPoints should be used here. this._pointerPool = new Array(11); } @@ -107,47 +109,39 @@ export class PointerManager implements IInput { } } - /** - * @internal - */ - _enable(): void { - const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; - htmlCanvas.addEventListener("pointerdown", onPointerEvent); - htmlCanvas.addEventListener("pointerup", onPointerEvent); - htmlCanvas.addEventListener("pointerout", onPointerEvent); - htmlCanvas.addEventListener("pointermove", onPointerEvent); - } - - /** - * @internal - */ - _disable(): void { - const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; - htmlCanvas.removeEventListener("pointerdown", onPointerEvent); - htmlCanvas.removeEventListener("pointerup", onPointerEvent); - htmlCanvas.removeEventListener("pointerout", onPointerEvent); - htmlCanvas.removeEventListener("pointermove", onPointerEvent); - this._nativeEvents.length = 0; - this._pointerPool.length = 0; - this._currentPosition = null; - this._currentEnteredEntity = null; - this._currentPressedEntity = null; - this._downList.length = 0; - this._upList.length = 0; - } - /** * @internal */ _onFocus(): void { - this._enable(); + if (!this._hadListener) { + const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; + htmlCanvas.addEventListener("pointerdown", onPointerEvent); + htmlCanvas.addEventListener("pointerup", onPointerEvent); + htmlCanvas.addEventListener("pointerout", onPointerEvent); + htmlCanvas.addEventListener("pointermove", onPointerEvent); + this._hadListener = true; + } } /** * @internal */ _onBlur(): void { - this._disable(); + if (this._hadListener) { + const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; + htmlCanvas.removeEventListener("pointerdown", onPointerEvent); + htmlCanvas.removeEventListener("pointerup", onPointerEvent); + htmlCanvas.removeEventListener("pointerout", onPointerEvent); + htmlCanvas.removeEventListener("pointermove", onPointerEvent); + this._nativeEvents.length = 0; + this._pointerPool.length = 0; + this._currentPosition = null; + this._currentEnteredEntity = null; + this._currentPressedEntity = null; + this._downList.length = 0; + this._upList.length = 0; + this._hadListener = false; + } } /** diff --git a/packages/core/src/input/wheel/WheelManager.ts b/packages/core/src/input/wheel/WheelManager.ts index 6ed1332d1f..696ba6db37 100644 --- a/packages/core/src/input/wheel/WheelManager.ts +++ b/packages/core/src/input/wheel/WheelManager.ts @@ -1,3 +1,4 @@ +import { Vector3 } from "@oasis-engine/math"; import { IInput } from "../interface/IInput"; /** @@ -6,14 +7,11 @@ import { IInput } from "../interface/IInput"; */ export class WheelManager implements IInput { /** @internal */ - _deltaX: number = 0; - /** @internal */ - _deltaY: number = 0; - /** @internal */ - _deltaZ: number = 0; + _delta: Vector3 = new Vector3(); private _nativeEvents: WheelEvent[] = []; private _canvas: HTMLCanvasElement; + private _hadListener: boolean; /** * Create a KeyboardManager. @@ -21,52 +19,46 @@ export class WheelManager implements IInput { constructor(htmlCanvas: HTMLCanvasElement) { this._onWheelEvent = this._onWheelEvent.bind(this); htmlCanvas.addEventListener("wheel", this._onWheelEvent); + this._hadListener = true; } /** * @internal */ _update(): void { - this._deltaX = this._deltaY = this._deltaZ = 0; + const { _delta: delta } = this; + delta.setValue(0, 0, 0); const { _nativeEvents: nativeEvents } = this; if (nativeEvents.length > 0) { for (let i = nativeEvents.length - 1; i >= 0; i--) { const evt = nativeEvents[i]; - this._deltaX += evt.deltaX; - this._deltaY += evt.deltaY; - this._deltaZ += evt.deltaZ; + delta.x += evt.deltaX; + delta.y += evt.deltaY; + delta.z += evt.deltaZ; } } } - /** - * @internal - */ - _enable(): void { - this._canvas.addEventListener("wheel", this._onWheelEvent); - } - - /** - * @internal - */ - _disable(): void { - this._canvas.removeEventListener("wheel", this._onWheelEvent); - this._nativeEvents.length = 0; - this._deltaX = this._deltaY = this._deltaZ = 0; - } - /** * @internal */ _onFocus(): void { - this._enable(); + if (!this._hadListener) { + this._canvas.addEventListener("wheel", this._onWheelEvent); + this._hadListener = true; + } } /** * @internal */ _onBlur(): void { - this._disable(); + if (this._hadListener) { + this._canvas.removeEventListener("wheel", this._onWheelEvent); + this._nativeEvents.length = 0; + this._delta.setValue(0, 0, 0); + this._hadListener = false; + } } /** From f809a565a7d2939e5695bffdbe3160f3aa09f693 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:18:14 +0800 Subject: [PATCH 09/19] feat: update code --- packages/core/src/input/wheel/WheelManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/input/wheel/WheelManager.ts b/packages/core/src/input/wheel/WheelManager.ts index 696ba6db37..3b9031e777 100644 --- a/packages/core/src/input/wheel/WheelManager.ts +++ b/packages/core/src/input/wheel/WheelManager.ts @@ -27,7 +27,7 @@ export class WheelManager implements IInput { */ _update(): void { const { _delta: delta } = this; - delta.setValue(0, 0, 0); + delta.set(0, 0, 0); const { _nativeEvents: nativeEvents } = this; if (nativeEvents.length > 0) { for (let i = nativeEvents.length - 1; i >= 0; i--) { @@ -56,7 +56,7 @@ export class WheelManager implements IInput { if (this._hadListener) { this._canvas.removeEventListener("wheel", this._onWheelEvent); this._nativeEvents.length = 0; - this._delta.setValue(0, 0, 0); + this._delta.set(0, 0, 0); this._hadListener = false; } } From 447756c30029851d72ca4a5b6d7a2a18850f4b76 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:26:11 +0800 Subject: [PATCH 10/19] feat: update code --- packages/core/src/input/InputManager.ts | 1 - packages/core/src/input/enums/InputType.ts | 15 --------------- 2 files changed, 16 deletions(-) delete mode 100644 packages/core/src/input/enums/InputType.ts diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index eba86ef13d..7fcfdb02d5 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -5,7 +5,6 @@ import { Pointer } from "./pointer/Pointer"; import { PointerManager } from "./pointer/PointerManager"; import { PointerButton } from "./enums/PointerButton"; import { WheelManager } from "./wheel/WheelManager"; -import { InputType } from "./enums/InputType"; import { Vector2, Vector3 } from "@oasis-engine/math"; /** diff --git a/packages/core/src/input/enums/InputType.ts b/packages/core/src/input/enums/InputType.ts deleted file mode 100644 index 44007f1dd7..0000000000 --- a/packages/core/src/input/enums/InputType.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Enumeration of input types. - */ -export enum InputType { - /** Nothing. */ - None = 0, - /** Wheel. */ - Wheel = 1, - /** Mouse, touch, pen, etc. */ - Pointer = 2, - /** Keyboard. */ - Keyboard = 4, - /** Everything above. */ - All = 7 -} From 47010f9f41d8899d7c0e4d7d8d5ba758d657d88d Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:30:31 +0800 Subject: [PATCH 11/19] feat: update code --- packages/core/src/input/enums/PointerButton.ts | 6 +++--- packages/core/src/input/pointer/PointerManager.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/input/enums/PointerButton.ts b/packages/core/src/input/enums/PointerButton.ts index 8890d9d708..8060aabe7e 100644 --- a/packages/core/src/input/enums/PointerButton.ts +++ b/packages/core/src/input/enums/PointerButton.ts @@ -5,11 +5,11 @@ */ export enum PointerButton { /** Indicate the primary pointer of the device (in general, the left button or the only button on single-button devices, used to activate a user interface control or select text) or the un-initialized value. */ - Left = 0, + Primary = 0, /** Indicate the auxiliary pointer (in general, the middle button, often combined with a mouse wheel). */ - Middle = 1, + Auxiliary = 1, /** Indicate the secondary pointer (in general, the right button, often used to display a context menu). */ - Right = 2, + Secondary = 2, /** Indicate the X1 (back) pointer. */ XButton1 = 3, /** Indicate the X2 (forward) pointer. */ diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 4d443a2bb3..da55ca6e97 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -242,7 +242,7 @@ export class PointerManager implements IInput { if (nativeEventsLen > 0) { for (let i = 0; i < nativeEventsLen; i++) { const evt = nativeEvents[i]; - const pointerButton: PointerButton = evt.button | PointerButton.Left; + const pointerButton: PointerButton = evt.button | PointerButton.Primary; const pointerIndex = this._getIndexByPointerID(evt.pointerId); switch (evt.type) { case "pointerdown": From 532a62be3a23d562083fd081f911c2daac56e379 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:42:52 +0800 Subject: [PATCH 12/19] feat: update code --- packages/core/src/input/InputManager.ts | 26 +++++-------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index 7fcfdb02d5..1e39fa8d5c 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -11,11 +11,10 @@ import { Vector2, Vector3 } from "@oasis-engine/math"; * InputManager manages device input such as mouse, touch, keyboard, etc. */ export class InputManager { - /** Sometimes the input module will not be initialized, such as off-screen rendering. */ - /** @internal */ + /** @internal Sometimes the input module will not be initialized, such as off-screen rendering. */ _initialized: boolean = false; - private _curFrameCount: number = 0; + private _curFrameCount: number = 0; private _wheelManager: WheelManager; private _pointerManager: PointerManager; private _keyboardManager: KeyboardManager; @@ -69,12 +68,10 @@ export class InputManager { * @param key - The keys of the keyboard * @returns Whether the key is being held down */ - isKeyHeldDown(key?: Keys | string | number): boolean { + isKeyHeldDown(key?: Keys): boolean { if (this._initialized) { if (key === undefined) { return this._keyboardManager._curFrameDownList.length > 0; - } else if (typeof key === "string") { - return this._keyboardManager._curHeldDownKeyToIndexMap[Keys[key]] != null; } else { return this._keyboardManager._curHeldDownKeyToIndexMap[key] != null; } @@ -88,12 +85,10 @@ export class InputManager { * @param key - The keys of the keyboard * @returns Whether the key starts to be pressed down during the current frame */ - isKeyDown(key?: Keys | string | number): boolean { + isKeyDown(key?: Keys): boolean { if (this._initialized) { if (key === undefined) { return this._keyboardManager._curFrameDownList.length > 0; - } else if (typeof key === "string") { - return this._keyboardManager._downKeyToFrameCountMap[Keys[key]] === this._curFrameCount; } else { return this._keyboardManager._downKeyToFrameCountMap[key] === this._curFrameCount; } @@ -107,12 +102,10 @@ export class InputManager { * @param key - The keys of the keyboard * @returns Whether the key is released during the current frame */ - isKeyUp(key?: Keys | string | number): boolean { + isKeyUp(key?: Keys): boolean { if (this._initialized) { if (key === undefined) { return this._keyboardManager._curFrameUpList.length > 0; - } else if (typeof key === "string") { - return this._keyboardManager._upKeyToFrameCountMap[Keys[key]] === this._curFrameCount; } else { return this._keyboardManager._upKeyToFrameCountMap[key] === this._curFrameCount; } @@ -172,15 +165,6 @@ export class InputManager { } } - /** - * Set hotkey. - * @param key - The name of hotkey - * @param value - The value of hotkey - */ - registerHotKey(key: string, value: number): void { - Keys[key] = value; - } - /** * @internal */ From 7bc44b66f0dba82a379bf870ae6d881afc8c11cb Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:50:19 +0800 Subject: [PATCH 13/19] feat: update code --- packages/core/src/input/InputManager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index 1e39fa8d5c..a298471d17 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -198,6 +198,7 @@ export class InputManager { */ _destroy(): void { window.removeEventListener("blur", this._onBlur); + window.removeEventListener("focus", this._onFocus); this._wheelManager._destroy(); this._pointerManager._destroy(); this._keyboardManager._destroy(); From 288970761330710b47142af093e6cd67d5fc57c6 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:53:27 +0800 Subject: [PATCH 14/19] feat: update code --- packages/core/src/Engine.ts | 4 ++-- packages/core/src/input/InputManager.ts | 25 ++++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/core/src/Engine.ts b/packages/core/src/Engine.ts index a43958cedb..c795ccf46d 100644 --- a/packages/core/src/Engine.ts +++ b/packages/core/src/Engine.ts @@ -281,7 +281,7 @@ export class Engine extends EventDispatcher { componentsManager.callScriptOnStart(); this.physicsManager._initialized && this.physicsManager._update(deltaTime / 1000.0); - this.inputManager._initialized && this.inputManager._update(); + this.inputManager._update(); componentsManager.callScriptOnUpdate(deltaTime); componentsManager.callAnimationUpdate(deltaTime); componentsManager.callScriptOnLateUpdate(deltaTime); @@ -309,7 +309,7 @@ export class Engine extends EventDispatcher { if (this._sceneManager) { this._whiteTexture2D.destroy(true); this._whiteTextureCube.destroy(true); - this.inputManager._initialized && this.inputManager._destroy(); + this.inputManager._destroy(); this.trigger(new Event("shutdown", this)); engineFeatureManager.callFeatureMethod(this, "shutdown", [this]); diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index a298471d17..f744e1bb9c 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -12,8 +12,7 @@ import { Vector2, Vector3 } from "@oasis-engine/math"; */ export class InputManager { /** @internal Sometimes the input module will not be initialized, such as off-screen rendering. */ - _initialized: boolean = false; - + private _initialized: boolean = false; private _curFrameCount: number = 0; private _wheelManager: WheelManager; private _pointerManager: PointerManager; @@ -187,21 +186,25 @@ export class InputManager { * @internal */ _update(): void { - ++this._curFrameCount; - this._wheelManager._update(); - this._pointerManager._update(this._curFrameCount); - this._keyboardManager._update(this._curFrameCount); + if (this._initialized) { + ++this._curFrameCount; + this._wheelManager._update(); + this._pointerManager._update(this._curFrameCount); + this._keyboardManager._update(this._curFrameCount); + } } /** * @internal */ _destroy(): void { - window.removeEventListener("blur", this._onBlur); - window.removeEventListener("focus", this._onFocus); - this._wheelManager._destroy(); - this._pointerManager._destroy(); - this._keyboardManager._destroy(); + if (this._initialized) { + window.removeEventListener("blur", this._onBlur); + window.removeEventListener("focus", this._onFocus); + this._wheelManager._destroy(); + this._pointerManager._destroy(); + this._keyboardManager._destroy(); + } } private _onBlur(): void { From f75cc32dd6e0aa8433b219d692d70da4ba217415 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 15:54:35 +0800 Subject: [PATCH 15/19] feat: update code --- packages/core/src/input/InputManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index f744e1bb9c..f5fd294dd7 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -11,7 +11,7 @@ import { Vector2, Vector3 } from "@oasis-engine/math"; * InputManager manages device input such as mouse, touch, keyboard, etc. */ export class InputManager { - /** @internal Sometimes the input module will not be initialized, such as off-screen rendering. */ + /** Sometimes the input module will not be initialized, such as off-screen rendering. */ private _initialized: boolean = false; private _curFrameCount: number = 0; private _wheelManager: WheelManager; From 4e375214260ef238eb2f1314b7929c401bc17dc9 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 16:04:35 +0800 Subject: [PATCH 16/19] feat: update code --- packages/core/src/input/pointer/PointerManager.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index da55ca6e97..fe60c3b5a0 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -28,7 +28,6 @@ export class PointerManager implements IInput { _movingDelta: Vector2 = new Vector2(); /** @internal */ _multiPointerEnabled: boolean = true; - /** @internal */ _buttons: number = 0x0; /** @internal */ @@ -39,9 +38,9 @@ export class PointerManager implements IInput { _downList: DisorderedArray = new DisorderedArray(); /** @internal */ _upList: DisorderedArray = new DisorderedArray(); - /** @internal */ _currentPosition: Vector2 = new Vector2(); + private _currentPressedEntity: Entity; private _currentEnteredEntity: Entity; From 07e3439d64320834558d160493ae0e808a64868a Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Tue, 5 Jul 2022 17:29:12 +0800 Subject: [PATCH 17/19] feat: update code --- packages/core/src/input/InputManager.ts | 2 +- .../core/src/input/keyboard/KeyboardManager.ts | 7 +++++-- .../core/src/input/pointer/PointerManager.ts | 16 ++++++++++++---- packages/core/src/input/wheel/WheelManager.ts | 7 ++++++- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/core/src/input/InputManager.ts b/packages/core/src/input/InputManager.ts index f5fd294dd7..0a1268e32d 100644 --- a/packages/core/src/input/InputManager.ts +++ b/packages/core/src/input/InputManager.ts @@ -70,7 +70,7 @@ export class InputManager { isKeyHeldDown(key?: Keys): boolean { if (this._initialized) { if (key === undefined) { - return this._keyboardManager._curFrameDownList.length > 0; + return this._keyboardManager._curFrameHeldDownList.length > 0; } else { return this._keyboardManager._curHeldDownKeyToIndexMap[key] != null; } diff --git a/packages/core/src/input/keyboard/KeyboardManager.ts b/packages/core/src/input/keyboard/KeyboardManager.ts index f5d8749cfd..c1cbd90c0f 100644 --- a/packages/core/src/input/keyboard/KeyboardManager.ts +++ b/packages/core/src/input/keyboard/KeyboardManager.ts @@ -110,8 +110,11 @@ export class KeyboardManager implements IInput { * @internal */ _destroy(): void { - window.removeEventListener("keydown", this._onKeyEvent); - window.removeEventListener("keyup", this._onKeyEvent); + if (this._hadListener) { + window.removeEventListener("keydown", this._onKeyEvent); + window.removeEventListener("keyup", this._onKeyEvent); + this._hadListener = false; + } this._curHeldDownKeyToIndexMap = null; this._upKeyToFrameCountMap = null; this._downKeyToFrameCountMap = null; diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index d8057894bc..b453bf297e 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -16,7 +16,7 @@ import { Pointer } from "./Pointer"; */ export class PointerManager implements IInput { /** Refer to the W3C standards.(https://www.w3.org/TR/uievents/#dom-mouseevent-buttons) */ - public static Buttons = [0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400]; + public static Buttons = [0x1, 0x4, 0x2, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400]; private static _tempRay: Ray = new Ray(); private static _tempPoint: Vector2 = new Vector2(); @@ -64,6 +64,9 @@ export class PointerManager implements IInput { this._canvas = engine.canvas; this._htmlCanvas = htmlCanvas; htmlCanvas.style.touchAction = "none"; + htmlCanvas.oncontextmenu = (event: UIEvent) => { + return false; + }; const onPointerEvent = (this._onPointerEvent = this._onPointerEvent.bind(this)); htmlCanvas.addEventListener("pointerdown", onPointerEvent); htmlCanvas.addEventListener("pointerup", onPointerEvent); @@ -134,7 +137,6 @@ export class PointerManager implements IInput { htmlCanvas.removeEventListener("pointermove", onPointerEvent); this._nativeEvents.length = 0; this._pointerPool.length = 0; - this._currentPosition = null; this._currentEnteredEntity = null; this._currentPressedEntity = null; this._downList.length = 0; @@ -148,8 +150,14 @@ export class PointerManager implements IInput { */ _destroy(): void { // @ts-ignore - const htmlCanvas = this._canvas._webCanvas as HTMLCanvasElement; - htmlCanvas.onpointerdown = htmlCanvas.onpointerup = htmlCanvas.onpointerout = htmlCanvas.onpointermove = null; + if (this._hadListener) { + const { _htmlCanvas: htmlCanvas, _onPointerEvent: onPointerEvent } = this; + htmlCanvas.removeEventListener("pointerdown", onPointerEvent); + htmlCanvas.removeEventListener("pointerup", onPointerEvent); + htmlCanvas.removeEventListener("pointerout", onPointerEvent); + htmlCanvas.removeEventListener("pointermove", onPointerEvent); + this._hadListener = false; + } this._nativeEvents.length = 0; this._pointerPool.length = 0; this._pointers.length = 0; diff --git a/packages/core/src/input/wheel/WheelManager.ts b/packages/core/src/input/wheel/WheelManager.ts index 3b9031e777..363f936604 100644 --- a/packages/core/src/input/wheel/WheelManager.ts +++ b/packages/core/src/input/wheel/WheelManager.ts @@ -19,6 +19,7 @@ export class WheelManager implements IInput { constructor(htmlCanvas: HTMLCanvasElement) { this._onWheelEvent = this._onWheelEvent.bind(this); htmlCanvas.addEventListener("wheel", this._onWheelEvent); + this._canvas = htmlCanvas; this._hadListener = true; } @@ -36,6 +37,7 @@ export class WheelManager implements IInput { delta.y += evt.deltaY; delta.z += evt.deltaZ; } + nativeEvents.length = 0; } } @@ -65,7 +67,10 @@ export class WheelManager implements IInput { * @internal */ _destroy(): void { - this._canvas.removeEventListener("wheel", this._onWheelEvent); + if (this._hadListener) { + this._canvas.removeEventListener("wheel", this._onWheelEvent); + this._hadListener = false; + } this._nativeEvents = null; } From 44e7b207a473b1ddf55b02ddeada0d567a92ecb2 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Mon, 11 Jul 2022 16:36:57 +0800 Subject: [PATCH 18/19] feat: update code --- packages/core/src/input/pointer/Pointer.ts | 2 - .../core/src/input/pointer/PointerManager.ts | 105 ++++++++---------- 2 files changed, 48 insertions(+), 59 deletions(-) diff --git a/packages/core/src/input/pointer/Pointer.ts b/packages/core/src/input/pointer/Pointer.ts index 3539654b80..f9e374941e 100644 --- a/packages/core/src/input/pointer/Pointer.ts +++ b/packages/core/src/input/pointer/Pointer.ts @@ -17,8 +17,6 @@ export class Pointer { /** @internal */ _uniqueID: number; - /** @internal */ - _needUpdate: boolean = true; /** * @internal diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index b453bf297e..90fee2691f 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -53,6 +53,7 @@ export class PointerManager implements IInput { private _keyEventCount: number = 0; private _needOverallPointers: boolean = false; private _hadListener: boolean = false; + private _lastPositionFrameCount: number = 0; /** * Create a PointerManager. @@ -216,7 +217,6 @@ export class PointerManager implements IInput { pointer = pointerPool[i] = new Pointer(i); } pointer._uniqueID = pointerId; - pointer._needUpdate = true; pointer.position.set(x, y); pointer.phase = phase; pointers.splice(i, 0, pointer); @@ -231,7 +231,6 @@ export class PointerManager implements IInput { private _updatePointer(pointerIndex: number, x: number, y: number, phase: PointerPhase): void { const updatedPointer = this._pointers[pointerIndex]; updatedPointer.position.set(x, y); - updatedPointer._needUpdate = true; updatedPointer.phase = phase; } @@ -245,79 +244,71 @@ export class PointerManager implements IInput { _downList: downList } = this; let activePointerCount = pointers.length; + const pixelRatioW = this._canvas.width / this._htmlCanvas.clientWidth; + const pixelRatioH = this._canvas.height / this._htmlCanvas.clientHeight; const nativeEventsLen = nativeEvents.length; - if (nativeEventsLen > 0) { - for (let i = 0; i < nativeEventsLen; i++) { - const evt = nativeEvents[i]; - const pointerButton: PointerButton = evt.button | PointerButton.Primary; - const pointerIndex = this._getIndexByPointerID(evt.pointerId); - switch (evt.type) { - case "pointerdown": - if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Down); - activePointerCount++; - } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Down); - } - activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); - downList.add(pointerButton); - downMap[pointerButton] = frameCount; - break; - case "pointerup": - if (pointerIndex >= 0) { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Up); - activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); - } - upList.add(pointerButton); - upMap[pointerButton] = frameCount; - break; - case "pointermove": - if (pointerIndex === -1) { - this._addPointer(evt.pointerId, evt.offsetX, evt.offsetY, PointerPhase.Move); - activePointerCount++; - } else { - this._updatePointer(pointerIndex, evt.offsetX, evt.offsetY, PointerPhase.Move); - } - break; - case "pointerout": - if (pointerIndex >= 0) { - this._removePointer(pointerIndex); - --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); - this._needOverallPointers = true; - } - break; - } + for (let i = 0; i < nativeEventsLen; i++) { + const evt = nativeEvents[i]; + const pointerButton: PointerButton = evt.button | PointerButton.Primary; + const pointerIndex = this._getIndexByPointerID(evt.pointerId); + switch (evt.type) { + case "pointerdown": + if (pointerIndex === -1) { + this._addPointer(evt.pointerId, evt.offsetX * pixelRatioW, evt.offsetY * pixelRatioH, PointerPhase.Down); + activePointerCount++; + } else { + this._updatePointer(pointerIndex, evt.offsetX * pixelRatioW, evt.offsetY * pixelRatioH, PointerPhase.Down); + } + activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Down); + downList.add(pointerButton); + downMap[pointerButton] = frameCount; + break; + case "pointerup": + if (pointerIndex >= 0) { + this._updatePointer(pointerIndex, evt.offsetX * pixelRatioW, evt.offsetY * pixelRatioH, PointerPhase.Up); + activePointerCount === 1 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Up); + } + upList.add(pointerButton); + upMap[pointerButton] = frameCount; + break; + case "pointermove": + if (pointerIndex === -1) { + this._addPointer(evt.pointerId, evt.offsetX * pixelRatioW, evt.offsetY * pixelRatioH, PointerPhase.Move); + activePointerCount++; + } else { + this._updatePointer(pointerIndex, evt.offsetX * pixelRatioW, evt.offsetY * pixelRatioH, PointerPhase.Move); + } + break; + case "pointerout": + if (pointerIndex >= 0) { + this._removePointer(pointerIndex); + --activePointerCount === 0 && (keyEventList[this._keyEventCount++] = PointerKeyEvent.Leave); + this._needOverallPointers = true; + } + break; } - this._buttons = nativeEvents[nativeEventsLen - 1].buttons; } + this._buttons = nativeEvents[nativeEventsLen - 1].buttons; const pointerCount = pointers.length; if (pointerCount > 0) { - const { _canvas: canvas, _currentPosition: currentPosition, _htmlCanvas: htmlCanvas } = this; + const { _currentPosition: currentPosition } = this; const { x: lastX, y: lastY } = currentPosition; - const pixelRatioWidth = canvas.width / htmlCanvas.clientWidth; - const pixelRatioHeight = canvas.height / htmlCanvas.clientHeight; if (activePointerCount === 0) { // Get the pointer coordinates when leaving, and use it to correctly dispatch the click event. const lastNativeEvent = nativeEvents[nativeEventsLen - 1]; - currentPosition.set(lastNativeEvent.offsetX * pixelRatioWidth, lastNativeEvent.offsetY * pixelRatioHeight); + currentPosition.set(lastNativeEvent.offsetX * pixelRatioW, lastNativeEvent.offsetY * pixelRatioH); } else { currentPosition.set(0, 0); for (let i = 0; i < pointerCount; i++) { - const pointer = pointers[i]; - const { position } = pointer; - if (pointer._needUpdate) { - position.set(position.x * pixelRatioWidth, position.y * pixelRatioHeight); - pointer._needUpdate = false; - } - currentPosition.add(position); + currentPosition.add(pointers[i].position); } currentPosition.scale(1 / pointerCount); } // Update pointer moving delta. - // Todo: Need to consider if the last coordinate is(0, 0). - if (lastX !== 0 || lastY !== 0) { + if (this._lastPositionFrameCount === frameCount - 1) { this._movingDelta.set(currentPosition.x - lastX, currentPosition.y - lastY); } + this._lastPositionFrameCount = frameCount; } nativeEvents.length = 0; } From db1c609638d20a21bfeca6c0ff566af11f2f0572 Mon Sep 17 00:00:00 2001 From: cptbtptpbcptdtptp Date: Mon, 11 Jul 2022 16:45:48 +0800 Subject: [PATCH 19/19] feat: update code --- packages/core/src/input/pointer/PointerManager.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/input/pointer/PointerManager.ts b/packages/core/src/input/pointer/PointerManager.ts index 4dd6fcf65e..122a09795e 100644 --- a/packages/core/src/input/pointer/PointerManager.ts +++ b/packages/core/src/input/pointer/PointerManager.ts @@ -287,7 +287,6 @@ export class PointerManager implements IInput { } break; } - this._buttons = nativeEvents[nativeEventsLen - 1].buttons; } this._buttons = nativeEvents[nativeEventsLen - 1].buttons; const pointerCount = pointers.length;