wip(type): add types to plugins

This commit is contained in:
pissang 2022-05-02 14:21:59 +08:00
parent e7797a5f94
commit 0b8b348b7d
15 changed files with 1248 additions and 1190 deletions

View File

@ -498,7 +498,7 @@ export type OnframeCallback<T> = (target: T, percent: number) => void;
export type AnimationPropGetter<T> = (target: T, key: string) => InterpolatableType;
export type AnimationPropSetter<T> = (target: T, key: string, value: InterpolatableType) => void;
export default class ProceduralKeyframeAnimator<T> implements Animator {
export default class ProceduralKeyframeAnimator<T = any> implements Animator {
timeline?: Timeline;
targetName?: string;
@ -846,7 +846,7 @@ export default class ProceduralKeyframeAnimator<T> implements Animator {
*
* @param callback
*/
during(cb: OnframeCallback<T>) {
during(cb?: OnframeCallback<T>) {
if (cb) {
this._onframeCbs.push(cb);
}
@ -856,14 +856,14 @@ export default class ProceduralKeyframeAnimator<T> implements Animator {
* Add callback for animation end
* @param cb
*/
done(cb: DoneCallback) {
done(cb?: DoneCallback) {
if (cb) {
this._doneCbs.push(cb);
}
return this;
}
aborted(cb: AbortCallback) {
aborted(cb?: AbortCallback) {
if (cb) {
this._abortedCbs.push(cb);
}

View File

@ -1,4 +1,3 @@
// @ts-nocheck
import Camera, { CameraOpts } from '../Camera';
export interface PerspectiveCameraOpts extends CameraOpts {

View File

@ -132,7 +132,7 @@ class Matrix2 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as mat2.Mat2Array;
}
/**

View File

@ -122,7 +122,7 @@ class Matrix2d {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as mat2d.Mat2dArray;
}
/**

View File

@ -179,7 +179,7 @@ class Matrix3 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as mat3.Mat3Array;
}
/**

View File

@ -379,7 +379,7 @@ class Matrix4 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as mat4.Mat4Array;
}
/**

View File

@ -332,7 +332,7 @@ class Quaternion {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as quat.QuatArray;
}
/**

View File

@ -332,7 +332,7 @@ class Vector2 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as vec2.Vec2Array;
}
// Supply methods that are not in place

View File

@ -402,7 +402,7 @@ class Vector3 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array.slice() as vec3.Vec3Array;
}
/**

View File

@ -328,7 +328,7 @@ class Vector4 {
}
toArray() {
return Array.prototype.slice.call(this.array);
return this.array as vec4.Vec4Array;
}
/**
* @param out

View File

@ -1,12 +1,55 @@
// @ts-nocheck
import Base from '../core/Base';
import Vector3 from '../math/Vector3';
import vendor from '../core/vendor';
import ClayNode from '../Node';
import Timeline from '../Timeline';
import Notifier from '../core/Notifier';
const doc = typeof document === 'undefined' ? {} : document;
const addEvent = vendor.addEventListener;
const removeEvent = vendor.removeEventListener;
const doc = document;
interface FreeControlOpts {
/**
* Scene node to control, mostly it is a camera
*/
target?: ClayNode;
/**
* Target dom to bind with mouse events
*/
domElement: HTMLElement;
/**
* Mouse move sensitivity
* @type {number}
*/
sensitivity: number;
/**
* Target move speed
* @type {number}
*/
speed: number;
/**
* Up axis
* @type {clay.Vector3}
*/
up: Vector3;
/**
* If lock vertical movement
* @type {boolean}
*/
verticalMoveLock: boolean;
/**
* @type {clay.Timeline}
*/
timeline?: Timeline;
}
interface FreeControl extends FreeControlOpts {}
/**
* @constructor clay.plugin.FreeControl
* @example
* const control = new clay.plugin.FreeControl({
* target: camera,
@ -18,60 +61,28 @@ const doc = typeof document === 'undefined' ? {} : document;
* renderer.render(scene, camera);
* });
*/
const FreeControl = Base.extend(
function () {
return /** @lends clay.plugin.FreeControl# */ {
/**
* Scene node to control, mostly it is a camera
* @type {clay.Node}
*/
target: null,
class FreeControl extends Notifier {
private _moveForward = false;
private _moveBackward = false;
private _moveLeft = false;
private _moveRight = false;
/**
* Target dom to bind with mouse events
* @type {HTMLElement}
*/
domElement: null,
private _offsetPitch = 0;
private _offsetRoll = 0;
/**
* Mouse move sensitivity
* @type {number}
*/
sensitivity: 1,
constructor(opts?: Partial<FreeControlOpts>) {
super();
Object.assign(
this,
{
sensitivity: 1,
speed: 0.4,
up: new Vector3(0, 1, 0),
verticalMoveLock: false
},
opts
);
/**
* Target move speed
* @type {number}
*/
speed: 0.4,
/**
* Up axis
* @type {clay.Vector3}
*/
up: new Vector3(0, 1, 0),
/**
* If lock vertical movement
* @type {boolean}
*/
verticalMoveLock: false,
/**
* @type {clay.Timeline}
*/
timeline: null,
_moveForward: false,
_moveBackward: false,
_moveLeft: false,
_moveRight: false,
_offsetPitch: 0,
_offsetRoll: 0
};
},
function () {
this._lockChange = this._lockChange.bind(this);
this._keyDown = this._keyDown.bind(this);
this._keyUp = this._keyUp.bind(this);
@ -80,184 +91,178 @@ const FreeControl = Base.extend(
if (this.domElement) {
this.init();
}
},
/** @lends clay.plugin.FreeControl.prototype */
{
/**
* init control
*/
init: function () {
// Use pointer lock
// http://www.html5rocks.com/en/tutorials/pointerlock/intro/
const el = this.domElement;
}
/**
* init control
*/
init() {
// Use pointer lock
// http://www.html5rocks.com/en/tutorials/pointerlock/intro/
const el = this.domElement;
//Must request pointer lock after click event, can't not do it directly
//Why ? ?
vendor.addEventListener(el, 'click', this._requestPointerLock);
//Must request pointer lock after click event, can't not do it directly
//Why ? ?
addEvent(el, 'click', this._requestPointerLock);
vendor.addEventListener(doc, 'pointerlockchange', this._lockChange);
vendor.addEventListener(doc, 'mozpointerlockchange', this._lockChange);
vendor.addEventListener(doc, 'webkitpointerlockchange', this._lockChange);
addEvent(doc, 'pointerlockchange', this._lockChange);
addEvent(doc, 'mozpointerlockchange', this._lockChange);
addEvent(doc, 'webkitpointerlockchange', this._lockChange);
vendor.addEventListener(doc, 'keydown', this._keyDown);
vendor.addEventListener(doc, 'keyup', this._keyUp);
addEvent(doc, 'keydown', this._keyDown);
addEvent(doc, 'keyup', this._keyUp);
if (this.timeline) {
this.timeline.on('frame', this._detectMovementChange, this);
}
},
/**
* Dispose control
*/
dispose: function () {
const el = this.domElement;
el.exitPointerLock = el.exitPointerLock || el.mozExitPointerLock || el.webkitExitPointerLock;
if (el.exitPointerLock) {
el.exitPointerLock();
}
vendor.removeEventListener(el, 'click', this._requestPointerLock);
vendor.removeEventListener(doc, 'pointerlockchange', this._lockChange);
vendor.removeEventListener(doc, 'mozpointerlockchange', this._lockChange);
vendor.removeEventListener(doc, 'webkitpointerlockchange', this._lockChange);
vendor.removeEventListener(doc, 'keydown', this._keyDown);
vendor.removeEventListener(doc, 'keyup', this._keyUp);
if (this.timeline) {
this.timeline.off('frame', this._detectMovementChange);
}
},
_requestPointerLock: function () {
const el = this;
el.requestPointerLock =
el.requestPointerLock || el.mozRequestPointerLock || el.webkitRequestPointerLock;
el.requestPointerLock();
},
/**
* Control update. Should be invoked every frame
* @param {number} frameTime Frame time
*/
update: function (frameTime) {
const target = this.target;
const position = this.target.position;
let xAxis = target.localTransform.x.normalize();
const zAxis = target.localTransform.z.normalize();
if (this.verticalMoveLock) {
zAxis.y = 0;
zAxis.normalize();
}
const speed = (this.speed * frameTime) / 20;
if (this._moveForward) {
// Opposite direction of z
position.scaleAndAdd(zAxis, -speed);
}
if (this._moveBackward) {
position.scaleAndAdd(zAxis, speed);
}
if (this._moveLeft) {
position.scaleAndAdd(xAxis, -speed / 2);
}
if (this._moveRight) {
position.scaleAndAdd(xAxis, speed / 2);
}
target.rotateAround(
target.position,
this.up,
(-this._offsetPitch * frameTime * Math.PI) / 360
);
xAxis = target.localTransform.x;
target.rotateAround(target.position, xAxis, (-this._offsetRoll * frameTime * Math.PI) / 360);
this._offsetRoll = this._offsetPitch = 0;
},
_lockChange: function () {
if (
doc.pointerLockElement === this.domElement ||
doc.mozPointerLockElement === this.domElement ||
doc.webkitPointerLockElement === this.domElement
) {
vendor.addEventListener(doc, 'mousemove', this._mouseMove, false);
} else {
vendor.removeEventListener(doc, 'mousemove', this._mouseMove);
}
},
_mouseMove: function (e) {
const dx = e.movementX || e.mozMovementX || e.webkitMovementX || 0;
const dy = e.movementY || e.mozMovementY || e.webkitMovementY || 0;
this._offsetPitch += (dx * this.sensitivity) / 200;
this._offsetRoll += (dy * this.sensitivity) / 200;
// Trigger change event to remind renderer do render
this.trigger('change');
},
_detectMovementChange: function (frameTime) {
if (this._moveForward || this._moveBackward || this._moveLeft || this._moveRight) {
this.trigger('change');
}
this.update(frameTime);
},
_keyDown: function (e) {
switch (e.keyCode) {
case 87: //w
case 38: //up arrow
this._moveForward = true;
break;
case 83: //s
case 40: //down arrow
this._moveBackward = true;
break;
case 65: //a
case 37: //left arrow
this._moveLeft = true;
break;
case 68: //d
case 39: //right arrow
this._moveRight = true;
break;
}
// Trigger change event to remind renderer do render
this.trigger('change');
},
_keyUp: function (e) {
switch (e.keyCode) {
case 87: //w
case 38: //up arrow
this._moveForward = false;
break;
case 83: //s
case 40: //down arrow
this._moveBackward = false;
break;
case 65: //a
case 37: //left arrow
this._moveLeft = false;
break;
case 68: //d
case 39: //right arrow
this._moveRight = false;
break;
}
if (this.timeline) {
this.timeline.on('frame', this._detectMovementChange, this);
}
}
);
/**
* Dispose control
*/
dispose() {
const el = this.domElement;
doc.exitPointerLock = doc.exitPointerLock || (doc as any).mozExitPointerLock;
if (doc.exitPointerLock) {
doc.exitPointerLock();
}
removeEvent(el, 'click', this._requestPointerLock);
removeEvent(doc, 'pointerlockchange', this._lockChange);
removeEvent(doc, 'mozpointerlockchange', this._lockChange);
removeEvent(doc, 'webkitpointerlockchange', this._lockChange);
removeEvent(doc, 'keydown', this._keyDown);
removeEvent(doc, 'keyup', this._keyUp);
if (this.timeline) {
this.timeline.off('frame', this._detectMovementChange);
}
}
_requestPointerLock() {
const el = this.domElement;
el.requestPointerLock = el.requestPointerLock || (el as any).mozRequestPointerLock;
el.requestPointerLock();
}
/**
* Control update. Should be invoked every frame
* @param {number} frameTime Frame time
*/
update(frameTime: number) {
const target = this.target;
if (!target) {
return;
}
const position = target.position;
let xAxis = target.localTransform.x.normalize();
const zAxis = target.localTransform.z.normalize();
if (this.verticalMoveLock) {
zAxis.y = 0;
zAxis.normalize();
}
const speed = (this.speed * frameTime) / 20;
if (this._moveForward) {
// Opposite direction of z
position.scaleAndAdd(zAxis, -speed);
}
if (this._moveBackward) {
position.scaleAndAdd(zAxis, speed);
}
if (this._moveLeft) {
position.scaleAndAdd(xAxis, -speed / 2);
}
if (this._moveRight) {
position.scaleAndAdd(xAxis, speed / 2);
}
target.rotateAround(target.position, this.up, (-this._offsetPitch * frameTime * Math.PI) / 360);
xAxis = target.localTransform.x;
target.rotateAround(target.position, xAxis, (-this._offsetRoll * frameTime * Math.PI) / 360);
this._offsetRoll = this._offsetPitch = 0;
}
_lockChange() {
if (
doc.pointerLockElement === this.domElement ||
(doc as any).mozPointerLockElement === this.domElement
) {
addEvent(doc, 'mousemove', this._mouseMove, false);
} else {
removeEvent(doc, 'mousemove', this._mouseMove);
}
}
_mouseMove(e: MouseEvent) {
const dx = e.movementX || (e as any).mozMovementX || 0;
const dy = e.movementY || (e as any).mozMovementY || 0;
this._offsetPitch += (dx * this.sensitivity) / 200;
this._offsetRoll += (dy * this.sensitivity) / 200;
// Trigger change event to remind renderer do render
this.trigger('change');
}
_detectMovementChange(frameTime: number) {
if (this._moveForward || this._moveBackward || this._moveLeft || this._moveRight) {
this.trigger('change');
}
this.update(frameTime);
}
_keyDown(e: KeyboardEvent) {
switch (e.keyCode) {
case 87: //w
case 38: //up arrow
this._moveForward = true;
break;
case 83: //s
case 40: //down arrow
this._moveBackward = true;
break;
case 65: //a
case 37: //left arrow
this._moveLeft = true;
break;
case 68: //d
case 39: //right arrow
this._moveRight = true;
break;
}
// Trigger change event to remind renderer do render
this.trigger('change');
}
_keyUp(e: KeyboardEvent) {
switch (e.keyCode) {
case 87: //w
case 38: //up arrow
this._moveForward = false;
break;
case 83: //s
case 40: //down arrow
this._moveBackward = false;
break;
case 65: //a
case 37: //left arrow
this._moveLeft = false;
break;
case 68: //d
case 39: //right arrow
this._moveRight = false;
break;
}
}
}
export default FreeControl;

View File

@ -1,93 +1,92 @@
// @ts-nocheck
import Base from '../core/Base';
import Vector3 from '../math/Vector3';
import vendor from '../core/vendor';
import Notifier from '../core/Notifier';
import type ClayNode from '../Node';
import type Timeline from '../Timeline';
const addEvent = vendor.addEventListener;
const removeEvent = vendor.removeEventListener;
interface GamepadControlOpts {
/*
* Scene node to control, mostly it is a camera.
*
*/
target?: ClayNode;
/**
* Move speed.
*/
moveSpeed: number;
/**
* Look around speed.
*/
lookAroundSpeed: number;
/**
* Up axis.
*/
up: Vector3;
/**
* Timeline.
*/
timeline?: Timeline;
/**
* Function to be called when a standard gamepad is ready to use.
*/
onStandardGamepadReady?: (gamepad) => void;
/**
* Function to be called when a gamepad is disconnected.
*/
onGamepadDisconnected?: (gamepad) => void;
}
interface GamepadControl extends GamepadControlOpts {}
/**
* Gamepad Control plugin.
*
* @constructor clay.plugin.GamepadControl
*
* @example
* init: function(app) {
* init(app) {
* this._gamepadControl = new clay.plugin.GamepadControl({
* target: camera,
* onStandardGamepadReady: customCallback
* });
* },
*
* loop: function(app) {
* loop(app) {
* this._gamepadControl.update(app.frameTime);
* }
*/
const GamepadControl = Base.extend(
function () {
return /** @lends clay.plugin.GamepadControl# */ {
/**
* Scene node to control, mostly it is a camera.
*
* @type {clay.Node}
*/
target: null,
/**
* Move speed.
*
* @type {number}
*/
moveSpeed: 0.1,
class GamepadControl extends Notifier {
private _moveForward = false;
private _moveBackward = false;
private _moveLeft = false;
private _moveRight = false;
/**
* Look around speed.
*
* @type {number}
*/
lookAroundSpeed: 0.1,
private _offsetPitch = 0;
private _offsetRoll = 0;
/**
* Up axis.
*
* @type {clay.Vector3}
*/
up: new Vector3(0, 1, 0),
private _standardGamepadIndex = 0;
private _standardGamepadAvailable = false;
private _gamepadAxisThreshold = 0.3;
/**
* Timeline.
*
* @type {clay.Timeline}
*/
timeline: null,
constructor(opts?: Partial<GamepadControlOpts>) {
super();
Object.assign(
this,
{
moveSpeed: 0.1,
lookAroundSpeed: 0.1,
up: Vector3.UP
},
opts
);
/**
* Function to be called when a standard gamepad is ready to use.
*
* @type {function}
*/
onStandardGamepadReady: function (gamepad) {},
/**
* Function to be called when a gamepad is disconnected.
*
* @type {function}
*/
onGamepadDisconnected: function (gamepad) {},
// Private properties:
_moveForward: false,
_moveBackward: false,
_moveLeft: false,
_moveRight: false,
_offsetPitch: 0,
_offsetRoll: 0,
_connectedGamepadIndex: 0,
_standardGamepadAvailable: false,
_gamepadAxisThreshold: 0.3
};
},
function () {
this._checkGamepadCompatibility = this._checkGamepadCompatibility.bind(this);
this._disconnectGamepad = this._disconnectGamepad.bind(this);
this._getStandardGamepad = this._getStandardGamepad.bind(this);
@ -100,203 +99,207 @@ const GamepadControl = Base.extend(
if (typeof navigator.getGamepads === 'function') {
this.init();
}
},
/** @lends clay.plugin.GamepadControl.prototype */
{
}
/**
* Init. control.
*/
init() {
/**
* Init. control.
*/
init: function () {
/**
* When user begins to interact with connected gamepad:
*
* @see https://w3c.github.io/gamepad/#dom-gamepadevent
*/
vendor.addEventListener(window, 'gamepadconnected', this._checkGamepadCompatibility);
if (this.timeline) {
this.timeline.on('frame', this.update);
}
vendor.addEventListener(window, 'gamepaddisconnected', this._disconnectGamepad);
},
/**
* Dispose control.
*/
dispose: function () {
vendor.removeEventListener(window, 'gamepadconnected', this._checkGamepadCompatibility);
if (this.timeline) {
this.timeline.off('frame', this.update);
}
vendor.removeEventListener(window, 'gamepaddisconnected', this._disconnectGamepad);
},
/**
* Control's update. Should be invoked every frame.
* When user begins to interact with connected gamepad:
*
* @param {number} frameTime Frame time.
* @see https://w3c.github.io/gamepad/#dom-gamepadevent
*/
update: function (frameTime) {
if (!this._standardGamepadAvailable) {
return;
}
addEvent(window, 'gamepadconnected', this._checkGamepadCompatibility);
this._scanPressedGamepadButtons();
this._scanInclinedGamepadAxes();
if (this.timeline) {
this.timeline.on('frame', this.update);
}
// Update target depending on user input.
addEvent(window, 'gamepaddisconnected', this._disconnectGamepad);
}
const target = this.target;
/**
* Dispose control.
*/
dispose() {
removeEvent(window, 'gamepadconnected', this._checkGamepadCompatibility);
const position = this.target.position;
let xAxis = target.localTransform.x.normalize();
const zAxis = target.localTransform.z.normalize();
if (this.timeline) {
this.timeline.off('frame', this.update);
}
const moveSpeed = (this.moveSpeed * frameTime) / 20;
removeEvent(window, 'gamepaddisconnected', this._disconnectGamepad);
}
if (this._moveForward) {
// Opposite direction of z.
position.scaleAndAdd(zAxis, -moveSpeed);
}
if (this._moveBackward) {
position.scaleAndAdd(zAxis, moveSpeed);
}
if (this._moveLeft) {
position.scaleAndAdd(xAxis, -moveSpeed);
}
if (this._moveRight) {
position.scaleAndAdd(xAxis, moveSpeed);
}
/**
* Control's update. Should be invoked every frame.
*
* @param {number} frameTime Frame time.
*/
update(frameTime: number) {
if (!this._standardGamepadAvailable) {
return;
}
target.rotateAround(
target.position,
this.up,
(-this._offsetPitch * frameTime * Math.PI) / 360
);
xAxis = target.localTransform.x;
target.rotateAround(target.position, xAxis, (-this._offsetRoll * frameTime * Math.PI) / 360);
this._scanPressedGamepadButtons();
this._scanInclinedGamepadAxes();
/*
* If necessary: trigger `update` event.
* XXX This can economize rendering OPs.
*/
if (
this._moveForward === true ||
this._moveBackward === true ||
this._moveLeft === true ||
this._moveRight === true ||
this._offsetPitch !== 0 ||
this._offsetRoll !== 0
) {
this.trigger('update');
}
// Update target depending on user input.
// Reset values to avoid lost of control.
const target = this.target;
if (!target) {
return;
}
this._moveForward = this._moveBackward = this._moveLeft = this._moveRight = false;
this._offsetPitch = this._offsetRoll = 0;
},
const position = target.position;
let xAxis = target.localTransform.x.normalize();
const zAxis = target.localTransform.z.normalize();
// Private methods:
const moveSpeed = (this.moveSpeed * frameTime) / 20;
_checkGamepadCompatibility: function (event) {
/**
* If connected gamepad has a **standard** layout:
*
* @see https://w3c.github.io/gamepad/#remapping about standard.
*/
if (event.gamepad.mapping === 'standard') {
this._standardGamepadIndex = event.gamepad.index;
this._standardGamepadAvailable = true;
if (this._moveForward) {
// Opposite direction of z.
position.scaleAndAdd(zAxis, -moveSpeed);
}
if (this._moveBackward) {
position.scaleAndAdd(zAxis, moveSpeed);
}
if (this._moveLeft) {
position.scaleAndAdd(xAxis, -moveSpeed);
}
if (this._moveRight) {
position.scaleAndAdd(xAxis, moveSpeed);
}
this.onStandardGamepadReady(event.gamepad);
}
},
target.rotateAround(target.position, this.up, (-this._offsetPitch * frameTime * Math.PI) / 360);
xAxis = target.localTransform.x;
target.rotateAround(target.position, xAxis, (-this._offsetRoll * frameTime * Math.PI) / 360);
_disconnectGamepad: function (event) {
this._standardGamepadAvailable = false;
/*
* If necessary: trigger `update` event.
* XXX This can economize rendering OPs.
*/
if (
this._moveForward === true ||
this._moveBackward === true ||
this._moveLeft === true ||
this._moveRight === true ||
this._offsetPitch !== 0 ||
this._offsetRoll !== 0
) {
this.trigger('update');
}
this.onGamepadDisconnected(event.gamepad);
},
// Reset values to avoid lost of control.
_getStandardGamepad: function () {
return navigator.getGamepads()[this._standardGamepadIndex];
},
this._moveForward = this._moveBackward = this._moveLeft = this._moveRight = false;
this._offsetPitch = this._offsetRoll = 0;
}
_scanPressedGamepadButtons: function () {
const gamepadButtons = this._getStandardGamepad().buttons;
// Private methods:
// For each gamepad button:
for (let gamepadButtonId = 0; gamepadButtonId < gamepadButtons.length; gamepadButtonId++) {
// Get user input.
const gamepadButton = gamepadButtons[gamepadButtonId];
_checkGamepadCompatibility(event: GamepadEvent) {
/**
* If connected gamepad has a **standard** layout:
*
* @see https://w3c.github.io/gamepad/#remapping about standard.
*/
if (event.gamepad.mapping === 'standard') {
this._standardGamepadIndex = event.gamepad.index;
this._standardGamepadAvailable = true;
if (gamepadButton.pressed) {
switch (gamepadButtonId) {
// D-pad Up
case 12:
this._moveForward = true;
break;
this.onStandardGamepadReady && this.onStandardGamepadReady(event.gamepad);
}
}
// D-pad Down
case 13:
this._moveBackward = true;
break;
_disconnectGamepad(event: GamepadEvent) {
this._standardGamepadAvailable = false;
// D-pad Left
case 14:
this._moveLeft = true;
break;
this.onGamepadDisconnected && this.onGamepadDisconnected(event.gamepad);
}
// D-pad Right
case 15:
this._moveRight = true;
break;
}
}
}
},
_getStandardGamepad() {
return navigator.getGamepads()[this._standardGamepadIndex];
}
_scanInclinedGamepadAxes: function () {
const gamepadAxes = this._getStandardGamepad().axes;
_scanPressedGamepadButtons() {
const gamepad = this._getStandardGamepad();
const gamepadButtons = gamepad && gamepad.buttons;
if (!gamepadButtons) {
return;
}
// For each gamepad axis:
for (let gamepadAxisId = 0; gamepadAxisId < gamepadAxes.length; gamepadAxisId++) {
// Get user input.
const gamepadAxis = gamepadAxes[gamepadAxisId];
// For each gamepad button:
for (let gamepadButtonId = 0; gamepadButtonId < gamepadButtons.length; gamepadButtonId++) {
// Get user input.
const gamepadButton = gamepadButtons[gamepadButtonId];
// XXX We use a threshold because axes are never neutral.
if (Math.abs(gamepadAxis) > this._gamepadAxisThreshold) {
switch (gamepadAxisId) {
// Left stick X±
case 0:
this._moveLeft = gamepadAxis < 0;
this._moveRight = gamepadAxis > 0;
break;
if (gamepadButton.pressed) {
switch (gamepadButtonId) {
// D-pad Up
case 12:
this._moveForward = true;
break;
// Left stick Y±
case 1:
this._moveForward = gamepadAxis < 0;
this._moveBackward = gamepadAxis > 0;
break;
// D-pad Down
case 13:
this._moveBackward = true;
break;
// Right stick X±
case 2:
this._offsetPitch += gamepadAxis * this.lookAroundSpeed;
break;
// D-pad Left
case 14:
this._moveLeft = true;
break;
// Right stick Y±
case 3:
this._offsetRoll += gamepadAxis * this.lookAroundSpeed;
break;
}
// D-pad Right
case 15:
this._moveRight = true;
break;
}
}
}
}
);
_scanInclinedGamepadAxes() {
const gamepad = this._getStandardGamepad();
const gamepadAxes = gamepad && gamepad.axes;
if (!gamepadAxes) {
return;
}
// For each gamepad axis:
for (let gamepadAxisId = 0; gamepadAxisId < gamepadAxes.length; gamepadAxisId++) {
// Get user input.
const gamepadAxis = gamepadAxes[gamepadAxisId];
// XXX We use a threshold because axes are never neutral.
if (Math.abs(gamepadAxis) > this._gamepadAxisThreshold) {
switch (gamepadAxisId) {
// Left stick X±
case 0:
this._moveLeft = gamepadAxis < 0;
this._moveRight = gamepadAxis > 0;
break;
// Left stick Y±
case 1:
this._moveForward = gamepadAxis < 0;
this._moveBackward = gamepadAxis > 0;
break;
// Right stick X±
case 2:
this._offsetPitch += gamepadAxis * this.lookAroundSpeed;
break;
// Right stick Y±
case 3:
this._offsetRoll += gamepadAxis * this.lookAroundSpeed;
break;
}
}
}
}
}
export default GamepadControl;

View File

@ -1,31 +1,42 @@
// @ts-nocheck
import * as util from '../core/util';
const GestureMgr = function () {
this._track = [];
};
type Target = any;
interface TrackItem {
points: number[][];
touches: Touch[];
target: Target;
event: TouchEvent;
}
GestureMgr.prototype = {
constructor: GestureMgr,
export interface PinchEvent extends TouchEvent {
pinchScale: number;
pinchX: number;
pinchY: number;
}
recognize: function (event, target, root) {
export class GestureMgr {
private _track: TrackItem[] = [];
constructor() {}
recognize(event: TouchEvent, target: Target, root: HTMLElement) {
this._doTrack(event, target, root);
return this._recognize(event);
},
}
clear: function () {
clear() {
this._track.length = 0;
return this;
},
}
_doTrack: function (event, target, root) {
const touches = event.targetTouches;
_doTrack(event: TouchEvent, target: Target, root: HTMLElement) {
const touches = event.touches;
if (!touches) {
return;
}
const trackItem = {
const trackItem: TrackItem = {
points: [],
touches: [],
target: target,
@ -39,9 +50,9 @@ GestureMgr.prototype = {
}
this._track.push(trackItem);
},
}
_recognize: function (event) {
_recognize(event: TouchEvent) {
for (const eventName in recognizers) {
if (util.hasOwn(recognizers, eventName)) {
const gestureInfo = recognizers[eventName](this._track, event);
@ -51,47 +62,59 @@ GestureMgr.prototype = {
}
}
}
};
}
function dist(pointPair) {
function dist(pointPair: number[][]): number {
const dx = pointPair[1][0] - pointPair[0][0];
const dy = pointPair[1][1] - pointPair[0][1];
return Math.sqrt(dx * dx + dy * dy);
}
function center(pointPair) {
function center(pointPair: number[][]): number[] {
return [(pointPair[0][0] + pointPair[1][0]) / 2, (pointPair[0][1] + pointPair[1][1]) / 2];
}
const recognizers = {
pinch: function (track, event) {
const trackLen = track.length;
type Recognizer = (
tracks: TrackItem[],
event: TouchEvent
) =>
| {
type: 'pinch';
target: Target;
event: PinchEvent;
}
| undefined;
const recognizers: Record<string, Recognizer> = {
pinch(tracks: TrackItem[], event: TouchEvent) {
const trackLen = tracks.length;
if (!trackLen) {
return;
}
const pinchEnd = (track[trackLen - 1] || {}).points;
const pinchPre = (track[trackLen - 2] || {}).points || pinchEnd;
const pinchEnd = (tracks[trackLen - 1] || {}).points;
const pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd;
if (pinchPre && pinchPre.length > 1 && pinchEnd && pinchEnd.length > 1) {
let pinchScale = dist(pinchEnd) / dist(pinchPre);
!isFinite(pinchScale) && (pinchScale = 1);
event.pinchScale = pinchScale;
(event as PinchEvent).pinchScale = pinchScale;
const pinchCenter = center(pinchEnd);
event.pinchX = pinchCenter[0];
event.pinchY = pinchCenter[1];
(event as PinchEvent).pinchX = pinchCenter[0];
(event as PinchEvent).pinchY = pinchCenter[1];
return {
type: 'pinch',
target: track[0].target,
event: event
target: tracks[0].target,
event: event as PinchEvent
};
}
}
};
// Only pinch currently.
};
export default GestureMgr;

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
// @ts-nocheck
import Skybox from './Skybox';
export default Skybox;