UNPKG

phaser4-rex-plugins

Version:
378 lines (314 loc) 10.6 kB
import EventEmitterMethods from '../../../utils/eventemitter/EventEmitterMethods.js'; import GetSceneObject from '../../../utils/system/GetSceneObject.js'; import Clear from '../../../utils/object/Clear.js'; import IsPointerInBounds from '../../../utils/input/IsPointerInBounds.js'; const GetValue = Phaser.Utils.Objects.GetValue; const SpliceOne = Phaser.Utils.Array.SpliceOne; const DistanceBetween = Phaser.Math.Distance.Between; const AngleBetween = Phaser.Math.Angle.Between; class TwoPointersTracer { constructor(gameObject, config) { var scene = GetSceneObject(gameObject); if (scene === gameObject) { gameObject = undefined; } var amount = scene.input.manager.pointersTotal - 1; if (amount < 2) { scene.input.addPointer(2 - amount); } this.scene = scene; this.gameObject = gameObject; if (gameObject) { gameObject.setInteractive(GetValue(config, 'inputConfig', undefined)); } // Event emitter this.setEventEmitter(GetValue(config, 'eventEmitter', undefined)); this._enable = undefined; this.pointers = []; this.movedState = {}; this.resetFromJSON(config); this.boot(); } resetFromJSON(o) { this.setEnable(GetValue(o, "enable", true)); this.bounds = GetValue(o, 'bounds', undefined); this.tracerState = TOUCH0; this.pointers.length = 0; Clear(this.movedState); return this; } boot() { if (this.gameObject) { this.gameObject.on('pointerdown', this.onPointerDown, this); } else { this.scene.input.on('pointerdown', this.onPointerDown, this); } this.scene.input.on('pointerup', this.onPointerUp, this); this.scene.input.on('gameout', this.dragCancel, this); this.scene.input.on('pointermove', this.onPointerMove, this); this.scene.sys.events.once('shutdown', this.destroy, this); } shutdown() { if (!this.scene) { return } this.destroyEventEmitter(); this.pointers.length = 0; Clear(this.movedState); if (this.gameObject) { // GameObject events will be removed when this gameObject destroyed // this.gameObject.off('pointerdown', this.onPointerDown, this); } else { this.scene.input.off('pointerdown', this.onPointerDown, this); } this.scene.input.off('pointerup', this.onPointerUp, this); this.scene.input.off('gameout', this.dragCancel, this); this.scene.input.off('pointermove', this.onPointerMove, this); this.scene.sys.events.off('shutdown', this.destroy, this); this.scene = undefined; this.gameObject = undefined; } destroy() { this.shutdown(); } get enable() { return this._enable; } set enable(e) { if (this._enable === e) { return; } if (!e) { this.dragCancel(); } this._enable = e; return this; } setEnable(e) { if (e === undefined) { e = true; } this.enable = e; return this; } toggleEnable() { this.setEnable(!this.enable); return this; } onPointerDown(pointer) { if (!this.enable) { return; } if (this.pointers.length === 2) { return; } var isInsideBounds = (this.bounds) ? this.bounds.contains(pointer.x, pointer.y) : true; if (!isInsideBounds) { return; } var index = this.pointers.indexOf(pointer); if (index !== -1) { // Already in catched pointers return; } this.movedState[pointer.id] = false; this.pointers.push(pointer); this.pointerCamera = pointer.camera; switch (this.tracerState) { case TOUCH0: this.tracerState = TOUCH1; this.onDrag1Start(); break; case TOUCH1: this.tracerState = TOUCH2; this.onDrag2Start(); break; } } onPointerUp(pointer) { if (!this.enable) { return; } var isInsideBounds = (this.bounds) ? this.bounds.contains(pointer.x, pointer.y) : true; if (!isInsideBounds) { return; } var index = this.pointers.indexOf(pointer); if (index === -1) { // Not in catched pointers return; } else { delete this.movedState[pointer.id]; SpliceOne(this.pointers, index); } switch (this.tracerState) { case TOUCH1: this.tracerState = TOUCH0; this.onDrag1End(); break; case TOUCH2: this.tracerState = TOUCH1; this.onDrag2End(); this.onDrag1Start(); break; } } onPointerMove(pointer) { if (!this.enable) { return; } if (pointer.isDown) { var isInsideBounds = (this.bounds) ? this.bounds.contains(pointer.x, pointer.y) : true; var isCatchedPointer = (this.pointers.indexOf(pointer) !== -1); if (!isCatchedPointer && isInsideBounds) { // Pointer moves into bounds // this.onPointerDown(pointer); } else if (isCatchedPointer && !isInsideBounds) { // Pointer moves out of bounds, lose pointer this.onPointerUp(pointer); } else { // Pointer drags in bounds if (!this.movedState[pointer.id]) { this.movedState[pointer.id] = (pointer.x !== pointer.downX) || (pointer.y !== pointer.downY); } if (this.movedState[pointer.id]) { switch (this.tracerState) { case TOUCH1: this.onDrag1(); break; case TOUCH2: this.onDrag2(); break; } } } } } dragCancel() { if (this.tracerState === TOUCH2) { this.onDrag2End(); } this.pointers.length = 0; Clear(this.movedState); this.tracerState = TOUCH0; return this; } onDrag1Start() { this.emit('drag1start', this); } onDrag1End() { this.emit('drag1end', this); } onDrag1() { this.emit('drag1', this); } onDrag2Start() { this.emit('drag2start', this); } onDrag2End() { this.emit('drag2end', this); } onDrag2() { this.emit('drag2', this); } get distanceBetween() { if (this.tracerState !== TOUCH2) { return 0; } var p0 = this.pointers[0], p1 = this.pointers[1]; return DistanceBetween(p0.x, p0.y, p1.x, p1.y); } get angleBetween() { if (this.tracerState !== TOUCH2) { return 0; } var p0 = this.pointers[0], p1 = this.pointers[1]; return AngleBetween(p0.x, p0.y, p1.x, p1.y); } get drag1Vector() { var pointer = this.pointers[0]; if (pointer && this.movedState[pointer.id]) { var p1 = pointer.position; var p0 = pointer.prevPosition; tmpDragVector.x = p1.x - p0.x; tmpDragVector.y = p1.y - p0.y; } else { tmpDragVector.x = 0; tmpDragVector.y = 0; } return tmpDragVector; } get centerX() { if (this.tracerState !== TOUCH2) { return 0; } var p0 = this.pointers[0].position; var p1 = this.pointers[1].position; return (p0.x + p1.x) / 2; } get centerY() { if (this.tracerState !== TOUCH2) { return 0; } var p0 = this.pointers[0].position; var p1 = this.pointers[1].position; return (p0.y + p1.y) / 2; } get prevCenterX() { if (this.tracerState !== TOUCH2) { return 0; } var preP0 = (this.movedState[this.pointers[0].id]) ? this.pointers[0].prevPosition : this.pointers[0].position; var preP1 = (this.movedState[this.pointers[1].id]) ? this.pointers[1].prevPosition : this.pointers[1].position; return (preP0.x + preP1.x) / 2; } get prevCenterY() { if (this.tracerState !== TOUCH2) { return 0; } var preP0 = (this.movedState[this.pointers[0].id]) ? this.pointers[0].prevPosition : this.pointers[0].position; var preP1 = (this.movedState[this.pointers[1].id]) ? this.pointers[1].prevPosition : this.pointers[1].position; return (preP0.y + preP1.y) / 2; } get movementCenterX() { return this.centerX - this.prevCenterX; } get movementCenterY() { return this.centerY - this.prevCenterY; } setRecongizedStateObject(stateObject) { this.recongizedState = stateObject; return this; } get state() { return this.recongizedState.state; } set state(newState) { this.recongizedState.state = newState; } cancel() { this.state = IDLE; return this; } isPointer0InGameObject(gameObject, preTest, postTest) { var pointer = this.pointers[0]; if (!pointer) { return false; } return IsPointerInBounds(gameObject, pointer, preTest, postTest); } isPointer1InGameObject(gameObject, preTest, postTest) { var pointer = this.pointers[1]; if (!pointer) { return false; } return IsPointerInBounds(gameObject, pointer, preTest, postTest); } } Object.assign( TwoPointersTracer.prototype, EventEmitterMethods ); var tmpDragVector = {}; const TOUCH0 = 0; const TOUCH1 = 1; const TOUCH2 = 2; const IDLE = 'IDLE'; export default TwoPointersTracer;