From 31e5202effaca20ffe5a3f6f231fb497471068f5 Mon Sep 17 00:00:00 2001 From: Paul Date: Mon, 21 Sep 2015 19:22:45 -0700 Subject: [PATCH] Fixes #2062 and forward-support for pointer modes Impact: - *none for touch devices* - *low* / 'expected behavior' for mouse devices Adds a PointerMode enumeration value for better simple input discrimination in the future. The added Button#justReleasedPreventsOver controls if a just-release event on a pointer prevents it from being able to trigger an over event. The default value is PointerMode.CONTACT which means this 'release guard' applies only to touch inputs. It should fix #2062 as Mouse (PointerMode.CURSOR) input is not caught in the default. Also expands Button#forceOut to accept a PointerMode value such that it can be controlled per-input mode. This is a configurable partial revert of a possibly rogue commit in 2.1.3 and the behavior persists through 2.4.3. --- src/gameobjects/Button.js | 22 ++++++++++++++++++---- src/input/Input.js | 4 ++-- src/input/Pointer.js | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/gameobjects/Button.js b/src/gameobjects/Button.js index 1fc1119f4..f3e498085 100644 --- a/src/gameobjects/Button.js +++ b/src/gameobjects/Button.js @@ -166,10 +166,20 @@ Phaser.Button = function (game, x, y, key, callback, callbackContext, overFrame, /** * If true then onOver events (such as onOverSound) will only be triggered if the Pointer object causing them was the Mouse Pointer. * The frame will still be changed as applicable. + * * @property {boolean} onOverMouseOnly * @default */ this.onOverMouseOnly = false; + + /** + * Suppresse the over event if a pointer was just released and it matches the given {@link Phaser.PointerModer pointer mode bitmask}. + * + * This behavior was introduced in Phaser 2.3.1; this property is a soft-revert of the change. + * + * @property {Phaser.PointerMode?} justReleasedPreventsOver=ACTIVE_CURSOR + */ + this.justReleasedPreventsOver = Phaser.PointerMode.TOUCH; /** * When true the the texture frame will not be automatically switched on up/down/over/out events. @@ -180,7 +190,10 @@ Phaser.Button = function (game, x, y, key, callback, callbackContext, overFrame, /** * When the Button is touched / clicked and then released you can force it to enter a state of "out" instead of "up". - * @property {boolean} forceOut + * + * This can also accept a {@link Phaser.PointerModer pointer mode bitmask} for more refined control. + * + * @property {boolean|Phaser.PointerMode} forceOut=false * @default */ this.forceOut = false; @@ -472,9 +485,10 @@ Phaser.Button.prototype.setUpSound = function (sound, marker) { */ Phaser.Button.prototype.onInputOverHandler = function (sprite, pointer) { - // If the Pointer was only just released then we don't fire an over event - if (pointer.justReleased()) + if (pointer.justReleased() && + (this.justReleasedPreventsOver & pointer.pointerMode) === pointer.pointerMode) { + // If the Pointer was only just released then we don't fire an over event return; } @@ -557,7 +571,7 @@ Phaser.Button.prototype.onInputUpHandler = function (sprite, pointer, isOver) { return; } - if (this.forceOut) + if (this.forceOut === true || (this.forceOut & pointer.pointerMode) === pointer.pointerMode) { this.changeStateFrame(STATE_OUT); } diff --git a/src/input/Input.js b/src/input/Input.js index 2d9056d99..5a4e29cf2 100644 --- a/src/input/Input.js +++ b/src/input/Input.js @@ -374,7 +374,7 @@ Phaser.Input.prototype = { */ boot: function () { - this.mousePointer = new Phaser.Pointer(this.game, 0); + this.mousePointer = new Phaser.Pointer(this.game, 0, Phaser.PointerMode.CURSOR); this.addPointer(); this.addPointer(); @@ -517,7 +517,7 @@ Phaser.Input.prototype = { } var id = this.pointers.length + 1; - var pointer = new Phaser.Pointer(this.game, id); + var pointer = new Phaser.Pointer(this.game, id, Phaser.PointerMode.TOUCH); this.pointers.push(pointer); this['pointer' + id] = pointer; diff --git a/src/input/Pointer.js b/src/input/Pointer.js index 23268293e..8cf6e7dfa 100644 --- a/src/input/Pointer.js +++ b/src/input/Pointer.js @@ -11,8 +11,9 @@ * @constructor * @param {Phaser.Game} game - A reference to the currently running game. * @param {number} id - The ID of the Pointer object within the game. Each game can have up to 10 active pointers. +* @param {Phaser.PointerMode} pointerMode=(CURSOR|CONTACT) - The operational mode of this pointer, eg. CURSOR or TOUCH. */ -Phaser.Pointer = function (game, id) { +Phaser.Pointer = function (game, id, pointerMode) { /** * @property {Phaser.Game} game - A reference to the currently running game. @@ -48,6 +49,11 @@ Phaser.Pointer = function (game, id) { */ this.pointerId = null; + /** + * @property {Phaser.PointerMode} pointerMode - The operational mode of this pointer. + */ + this.pointerMode = pointerMode || (Phaser.PointerMode.CURSOR | Phaser.PointerMode.CONTACT); + /** * @property {any} target - The target property of the Pointer as set by the DOM event when this Pointer is started. * @default @@ -1189,3 +1195,32 @@ Object.defineProperty(Phaser.Pointer.prototype, "worldY", { } }); + +/** +* Enumeration categorizing operational modes of pointers. +* +* PointerType values represent valid bitmasks. +* For example, a value representing both Mouse and Touch devices +* can be expressed as `PointerMode.CURSOR | PointerMode.CONTACT`. +* +* Values may be added for future mode categorizations. +* @class Phaser.PointerMode +*/ +Phaser.PointerMode = { + + /** + * A 'CURSOR' is a pointer with a *passive cursor* such as a mouse, touchpad, watcom stylus, or even TV-control arrow-pad. + * + * It has the property that a cursor is passively moved without activating the input. + * This currently corresponds with {@link Phaser.Pointer#isMouse} property. + * @constant + */ + CURSOR: 1 << 0, + + /** + * A 'CONTACT' pointer has an *active cursor* that only tracks movement when actived; notably this is a touch-style input. + * @constant + */ + CONTACT: 1 << 1 + +};