From 730c84e3e39cf7c93cfdcdf0ff616d8affc81627 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 4 Jan 2019 16:34:59 +0000 Subject: [PATCH] Draggable Game Objects would not work if you had multiple Scenes running in parallel, with draggable objects in both of them. Only the top-most Scene would work fully. Items in the bottom Scene would never finish their drag cycle, causing them to get stuck. Fix #4249 --- CHANGELOG.md | 4 ++ src/input/InputPlugin.js | 90 +++++++++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6bd7a985..98a6b2fed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -119,6 +119,10 @@ one set of bindings ever created, which makes things a lot cleaner. * The Input Plugin has a new event you can listen to: `pointerupoutside`, which is triggered whenever the mouse or a pointer is released while outside of the Game canvas. Listen to it with `this.input.on('pointerupoutside')` from within a Scene. * `Pointer.downElement` is a new property that holds the target of the DOM Event that triggered when the Pointer was pressed down. If this is within the game, this will be the game canvas element. * `Pointer.upElement` is a new property that holds the target of the DOM Event that triggered when the Pointer was released. If this is within the game, this will be the game canvas element. +* The `Pointer.dragState` property has been removed. This is no longer used internally as it has to be tracked per Scene, not on a global level. +* `InputPlugin.setDragState` is a new internal method that sets the drag state for the given Pointer. +* `InputPlugin.getDragState` is a new internal method that gets the drag state for the given Pointer. +* Draggable Game Objects would not work if you had multiple Scenes running in parallel, with draggable objects in both of them. Only the top-most Scene would work fully. Items in the bottom Scene would never finish their drag cycle, causing them to get stuck. Fix #4249 (thanks @probt) ### New Features diff --git a/src/input/InputPlugin.js b/src/input/InputPlugin.js index 46c698604..d75f838b0 100644 --- a/src/input/InputPlugin.js +++ b/src/input/InputPlugin.js @@ -324,6 +324,16 @@ var InputPlugin = new Class({ */ this._drag = { 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], 6: [], 7: [], 8: [], 9: [], 10: [] }; + /** + * A array containing the dragStates, for this Scene, index by the Pointer ID. + * + * @name Phaser.Input.InputPlugin#_dragState + * @type {integer[]} + * @private + * @since 3.16.0 + */ + this._dragState = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; + /** * A list of all Interactive Objects currently considered as being 'over' by any pointer, indexed by pointer ID. * @@ -818,6 +828,53 @@ var InputPlugin = new Class({ return total; }, + /** + * Returns the drag state of the given Pointer for this Input Plugin. + * + * The state will be one of the following: + * + * 0 = Not dragging anything + * 1 = Primary button down and objects below, so collect a draglist + * 2 = Pointer being checked if meets drag criteria + * 3 = Pointer meets criteria, notify the draglist + * 4 = Pointer actively dragging the draglist and has moved + * 5 = Pointer actively dragging but has been released, notify draglist + * + * @method Phaser.Input.InputPlugin#getDragState + * @since 3.16.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to get the drag state for. + * + * @return {integer} The drag state of the given Pointer. + */ + getDragState: function (pointer) + { + return this._dragState[pointer.id]; + }, + + /** + * Sets the drag state of the given Pointer for this Input Plugin. + * + * The state must be one of the following values: + * + * 0 = Not dragging anything + * 1 = Primary button down and objects below, so collect a draglist + * 2 = Pointer being checked if meets drag criteria + * 3 = Pointer meets criteria, notify the draglist + * 4 = Pointer actively dragging the draglist and has moved + * 5 = Pointer actively dragging but has been released, notify draglist + * + * @method Phaser.Input.InputPlugin#setDragState + * @since 3.16.0 + * + * @param {Phaser.Input.Pointer} pointer - The Pointer to set the drag state for. + * @param {integer} state - The drag state value. An integer between 0 and 5. + */ + setDragState: function (pointer, state) + { + this._dragState[pointer.id] = state; + }, + /** * An internal method that handles the Pointer drag events. * @@ -865,19 +922,19 @@ var InputPlugin = new Class({ // 4 = Pointer actively dragging the draglist and has moved // 5 = Pointer actively dragging but has been released, notify draglist - if (pointer.dragState === 0 && pointer.primaryDown && pointer.justDown && currentlyOver.length > 0) + if (this.getDragState(pointer) === 0 && pointer.primaryDown && pointer.justDown && currentlyOver.length > 0) { - pointer.dragState = 1; + this.setDragState(pointer, 1); } - else if (pointer.dragState > 0 && !pointer.primaryDown && pointer.justUp) + else if (this.getDragState(pointer) > 0 && !pointer.primaryDown && pointer.justUp) { - pointer.dragState = 5; + this.setDragState(pointer, 5); } // Process the various drag states // 1 = Primary button down and objects below, so collect a draglist - if (pointer.dragState === 1) + if (this.getDragState(pointer) === 1) { // Get draggable objects, sort them, pick the top (or all) and store them somewhere var draglist = []; @@ -894,7 +951,7 @@ var InputPlugin = new Class({ if (draglist.length === 0) { - pointer.dragState = 0; + this.setDragState(pointer, 0); return 0; } @@ -914,35 +971,35 @@ var InputPlugin = new Class({ if (this.dragDistanceThreshold === 0 && this.dragTimeThreshold === 0) { // No drag criteria, so snap immediately to mode 3 - pointer.dragState = 3; + this.setDragState(pointer, 3); } else { // Check the distance / time - pointer.dragState = 2; + this.setDragState(pointer, 2); } } // 2 = Pointer being checked if meets drag criteria - if (pointer.dragState === 2) + if (this.getDragState(pointer) === 2) { // Has it moved far enough to be considered a drag? if (this.dragDistanceThreshold > 0 && DistanceBetween(pointer.x, pointer.y, pointer.downX, pointer.downY) >= this.dragDistanceThreshold) { // Alrighty, we've got a drag going on ... - pointer.dragState = 3; + this.setDragState(pointer, 3); } // Held down long enough to be considered a drag? if (this.dragTimeThreshold > 0 && (time >= pointer.downTime + this.dragTimeThreshold)) { // Alrighty, we've got a drag going on ... - pointer.dragState = 3; + this.setDragState(pointer, 3); } } // 3 = Pointer meets criteria and is freshly down, notify the draglist - if (pointer.dragState === 3) + if (this.getDragState(pointer) === 3) { list = this._drag[pointer.id]; @@ -965,13 +1022,13 @@ var InputPlugin = new Class({ this.emit('dragstart', pointer, gameObject); } - pointer.dragState = 4; + this.setDragState(pointer, 4); return list.length; } // 4 = Pointer actively dragging the draglist and has moved - if (pointer.dragState === 4 && pointer.justMoved && !pointer.justUp) + if (this.getDragState(pointer) === 4 && pointer.justMoved && !pointer.justUp) { var dropZones = this._tempZones; @@ -1054,7 +1111,7 @@ var InputPlugin = new Class({ } // 5 = Pointer was actively dragging but has been released, notify draglist - if (pointer.dragState === 5) + if (this.getDragState(pointer) === 5) { list = this._drag[pointer.id]; @@ -1092,7 +1149,7 @@ var InputPlugin = new Class({ } } - pointer.dragState = 0; + this.setDragState(pointer, 0); list.splice(0); } @@ -2228,6 +2285,7 @@ var InputPlugin = new Class({ this._draggable.length = 0; this._pendingRemoval.length = 0; this._pendingInsertion.length = 0; + this._dragState.length = 0; for (var i = 0; i < 10; i++) {