Skip to content

Commit b1771a1

Browse files
committed
Updated InputPlugin event specificity flow and added stopPropagation support
1 parent 14881bb commit b1771a1

2 files changed

Lines changed: 181 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,32 @@
22

33
## Version 3.13.0 - Yuuki - in development
44

5+
## Pointer and Input Event Updates
6+
7+
The specificity if the input events has been changed to allow you more control over event handling. Previously, the InputPlugin would emit the global `pointerdown` event first, and then the Game Object itself would emit the `pointerdown` event and finally the InputPlugin would emit the `gameobjectdown` event.
8+
9+
The order has now changed. The Game Object will dispatch its `pointerdown` event first. The InputPlugin will then dispatch `gameobjectdown` and finally the less specific of them all, `pointerdown` will be dispatched.
10+
11+
New in 3.13 is the ability to cancel this at any stage. All events are now sent an event object which you can call `event.stopPropagation()` on. This will immediately stop any further listeners from being invoked. If you call `stopPropagation()` after the first Game Object `pointerdown` event, then no more Game Object's will receive their callbacks and the InputPlugin will not dispatch either of its events.
12+
13+
This change has been introduced for `pointerdown`, `pointerup`, `pointermove`, `pointerover` and `pointerout`. No other data is included in the `event` object in this release.
14+
15+
* The Game Object `pointerdown` callback signature has changed. It used to send `pointer, x, y, camera` to the listener. It now sends `pointer, x, y, event` to the listener. If you still need the `camera` property you can get it from `pointer.camera`.
16+
* The Game Object `gameobjectdown` callback signature has a new argument. It now sends `event` as the 3rd argument.
17+
* The `pointerdown` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerdown` and `gameobjectdown`). This gives you the chance to cancel the event before the global listener receives it.
18+
* The Game Object `pointerup` callback signature has a new argument. It now sends the `event` as the 4th argument.
19+
* The Game Object `gameobjectup` callback signature has a new argument. It now sends `event` as the 3rd argument.
20+
* The `pointerup` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerup` and `gameobjectup`). This gives you the chance to cancel the event before the global listener receives it.
21+
* The Game Object `pointermove` callback signature has a new argument. It now sends the `event` as the 4th argument.
22+
* The Game Object `gameobjectmove` callback signature has a new argument. It now sends `event` as the 3rd argument.
23+
* The `pointermove` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointermove` and `gameobjectmove`). This gives you the chance to cancel the event before the global listener receives it.
24+
* The Game Object `pointerover` callback signature has a new argument. It now sends the `event` as the 4th argument.
25+
* The Game Object `gameobjectover` callback signature has a new argument. It now sends `event` as the 3rd argument.
26+
* The `pointerover` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerover` and `gameobjectover`). This gives you the chance to cancel the event before the global listener receives it.
27+
* The Game Object `pointerout` callback signature has a new argument. It now sends the `event` as the 2nd argument.
28+
* The Game Object `gameobjectout` callback signature has a new argument. It now sends `event` as the 3rd argument.
29+
* The `pointerout` event, as dispatched by the InputPlugin, is now sent _after_ the Game Object specific events (`GameObject.pointerout` and `gameobjectout`). This gives you the chance to cancel the event before the global listener receives it.
30+
531
## New Features
632

733
* The `Color` object has a new property `h` which represents the hue of the color. You can tween or adjust this property in real-time and it will automatically update the internal RGB values with it.

src/input/InputPlugin.js

Lines changed: 155 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,33 @@ var InputPlugin = new Class({
201201
*/
202202
this._pollTimer = 0;
203203

204+
var _eventData = { cancelled: false };
205+
206+
/**
207+
* Internal event propagation callback container.
208+
*
209+
* @name Phaser.Input.InputPlugin#_eventContainer
210+
* @type {object}
211+
* @private
212+
* @since 3.13.0
213+
*/
214+
this._eventContainer = {
215+
stopPropagation: function ()
216+
{
217+
_eventData.cancelled = true;
218+
}
219+
};
220+
221+
/**
222+
* Internal event propagation data object.
223+
*
224+
* @name Phaser.Input.InputPlugin#_eventData
225+
* @type {object}
226+
* @private
227+
* @since 3.13.0
228+
*/
229+
this._eventData = _eventData;
230+
204231
/**
205232
* The distance, in pixels, a pointer has to move while being held down, before it thinks it is being dragged.
206233
*
@@ -727,12 +754,15 @@ var InputPlugin = new Class({
727754
*/
728755
processDownEvents: function (pointer)
729756
{
757+
var total = 0;
730758
var currentlyOver = this._temp;
731759

732-
// Contains ALL Game Objects currently over in the array
733-
this.emit('pointerdown', pointer, currentlyOver);
760+
var _eventData = this._eventData;
761+
var _eventContainer = this._eventContainer;
734762

735-
var total = 0;
763+
_eventData.cancelled = false;
764+
765+
var aborted = false;
736766

737767
// Go through all objects the pointer was over and fire their events / callbacks
738768
for (var i = 0; i < currentlyOver.length; i++)
@@ -746,9 +776,27 @@ var InputPlugin = new Class({
746776

747777
total++;
748778

749-
gameObject.emit('pointerdown', pointer, gameObject.input.localX, gameObject.input.localY, pointer.camera);
779+
gameObject.emit('pointerdown', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);
780+
781+
if (_eventData.cancelled)
782+
{
783+
aborted = true;
784+
break;
785+
}
786+
787+
this.emit('gameobjectdown', pointer, gameObject, _eventContainer);
750788

751-
this.emit('gameobjectdown', pointer, gameObject);
789+
if (_eventData.cancelled)
790+
{
791+
aborted = true;
792+
break;
793+
}
794+
}
795+
796+
// Contains ALL Game Objects currently over in the array
797+
if (!aborted)
798+
{
799+
this.emit('pointerdown', pointer, currentlyOver);
752800
}
753801

754802
return total;
@@ -1035,11 +1083,15 @@ var InputPlugin = new Class({
10351083
*/
10361084
processMoveEvents: function (pointer)
10371085
{
1086+
var total = 0;
10381087
var currentlyOver = this._temp;
10391088

1040-
this.emit('pointermove', pointer, currentlyOver);
1089+
var _eventData = this._eventData;
1090+
var _eventContainer = this._eventContainer;
10411091

1042-
var total = 0;
1092+
_eventData.cancelled = false;
1093+
1094+
var aborted = false;
10431095

10441096
// Go through all objects the pointer was over and fire their events / callbacks
10451097
for (var i = 0; i < currentlyOver.length; i++)
@@ -1053,16 +1105,33 @@ var InputPlugin = new Class({
10531105

10541106
total++;
10551107

1056-
gameObject.emit('pointermove', pointer, gameObject.input.localX, gameObject.input.localY);
1108+
gameObject.emit('pointermove', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);
10571109

1058-
this.emit('gameobjectmove', pointer, gameObject);
1110+
if (_eventData.cancelled)
1111+
{
1112+
aborted = true;
1113+
break;
1114+
}
1115+
1116+
this.emit('gameobjectmove', pointer, gameObject, _eventContainer);
1117+
1118+
if (_eventData.cancelled)
1119+
{
1120+
aborted = true;
1121+
break;
1122+
}
10591123

10601124
if (this.topOnly)
10611125
{
10621126
break;
10631127
}
10641128
}
10651129

1130+
if (!aborted)
1131+
{
1132+
this.emit('pointermove', pointer, currentlyOver);
1133+
}
1134+
10661135
return total;
10671136
},
10681137

@@ -1131,12 +1200,17 @@ var InputPlugin = new Class({
11311200

11321201
var totalInteracted = 0;
11331202

1203+
var _eventData = this._eventData;
1204+
var _eventContainer = this._eventContainer;
1205+
1206+
_eventData.cancelled = false;
1207+
1208+
var aborted = false;
1209+
11341210
if (total > 0)
11351211
{
11361212
this.sortGameObjects(justOut);
11371213

1138-
this.emit('pointerout', pointer, justOut);
1139-
11401214
// Call onOut for everything in the justOut array
11411215
for (i = 0; i < total; i++)
11421216
{
@@ -1147,25 +1221,44 @@ var InputPlugin = new Class({
11471221
continue;
11481222
}
11491223

1150-
this.emit('gameobjectout', pointer, gameObject);
1151-
1152-
gameObject.emit('pointerout', pointer);
1224+
gameObject.emit('pointerout', pointer, _eventContainer);
11531225

11541226
manager.resetCursor(gameObject.input);
11551227

11561228
totalInteracted++;
1229+
1230+
if (_eventData.cancelled)
1231+
{
1232+
aborted = true;
1233+
break;
1234+
}
1235+
1236+
this.emit('gameobjectout', pointer, gameObject, _eventContainer);
1237+
1238+
if (_eventData.cancelled)
1239+
{
1240+
aborted = true;
1241+
break;
1242+
}
1243+
}
1244+
1245+
if (!aborted)
1246+
{
1247+
this.emit('pointerout', pointer, justOut);
11571248
}
11581249
}
11591250

11601251
// Process the Just Over objects
11611252
total = justOver.length;
11621253

1254+
_eventData.cancelled = false;
1255+
1256+
aborted = false;
1257+
11631258
if (total > 0)
11641259
{
11651260
this.sortGameObjects(justOver);
11661261

1167-
this.emit('pointerover', pointer, justOver);
1168-
11691262
// Call onOver for everything in the justOver array
11701263
for (i = 0; i < total; i++)
11711264
{
@@ -1176,13 +1269,30 @@ var InputPlugin = new Class({
11761269
continue;
11771270
}
11781271

1179-
this.emit('gameobjectover', pointer, gameObject);
1180-
1181-
gameObject.emit('pointerover', pointer, gameObject.input.localX, gameObject.input.localY);
1272+
gameObject.emit('pointerover', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);
11821273

11831274
manager.setCursor(gameObject.input);
11841275

11851276
totalInteracted++;
1277+
1278+
if (_eventData.cancelled)
1279+
{
1280+
aborted = true;
1281+
break;
1282+
}
1283+
1284+
this.emit('gameobjectover', pointer, gameObject, _eventContainer);
1285+
1286+
if (_eventData.cancelled)
1287+
{
1288+
aborted = true;
1289+
break;
1290+
}
1291+
}
1292+
1293+
if (!aborted)
1294+
{
1295+
this.emit('pointerover', pointer, justOver);
11861296
}
11871297
}
11881298

@@ -1210,8 +1320,12 @@ var InputPlugin = new Class({
12101320
{
12111321
var currentlyOver = this._temp;
12121322

1213-
// Contains ALL Game Objects currently up in the array
1214-
this.emit('pointerup', pointer, currentlyOver);
1323+
var _eventData = this._eventData;
1324+
var _eventContainer = this._eventContainer;
1325+
1326+
_eventData.cancelled = false;
1327+
1328+
var aborted = false;
12151329

12161330
// Go through all objects the pointer was over and fire their events / callbacks
12171331
for (var i = 0; i < currentlyOver.length; i++)
@@ -1225,9 +1339,27 @@ var InputPlugin = new Class({
12251339

12261340
// pointerupoutside
12271341

1228-
gameObject.emit('pointerup', pointer, gameObject.input.localX, gameObject.input.localY);
1342+
gameObject.emit('pointerup', pointer, gameObject.input.localX, gameObject.input.localY, _eventContainer);
12291343

1230-
this.emit('gameobjectup', pointer, gameObject);
1344+
if (_eventData.cancelled)
1345+
{
1346+
aborted = true;
1347+
break;
1348+
}
1349+
1350+
this.emit('gameobjectup', pointer, gameObject, _eventContainer);
1351+
1352+
if (_eventData.cancelled)
1353+
{
1354+
aborted = true;
1355+
break;
1356+
}
1357+
}
1358+
1359+
if (!aborted)
1360+
{
1361+
// Contains ALL Game Objects currently up in the array
1362+
this.emit('pointerup', pointer, currentlyOver);
12311363
}
12321364

12331365
return currentlyOver.length;

0 commit comments

Comments
 (0)