Skip to content

Commit acc4922

Browse files
committed
Fixes to the InputPlugin re: drop zones and addition of setInteractive argument.
1 parent ee42432 commit acc4922

4 files changed

Lines changed: 93 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
* Load.plugin now accepts a class as an argument as well as a URL string (thanks @nkholski)
1111
* Tween.complete will allow you to flag a tween as being complete, no matter what stage it is at. If an onComplete callback has been defined it will be invoked. You can set an optional delay before this happens (thanks @Jerenaux for the idea)
1212
* The Headless render mode has been implemented. You can now set HEADLESS as the `renderType` in the Game Config and it will run a special game step that skips rendering. It will still create a Canvas element, as lots of internal systems (like input) rely on it, but it will not draw anything to it. Fix #3256 (thanks @rgk)
13+
* GameObject.setInteractive has a new boolean argument `dropZone` which will allow you to set the object as being a drop zone right from the method.
14+
* Sprites can now be drop zones and have other Game Objects dragged onto them as targets.
1315

1416
### Bug Fixes
1517

@@ -19,6 +21,9 @@
1921
* Swapped the queue loop in the SceneManager to to use `_queue.length` rather than a cached length (thanks @srobertson421)
2022
* When calling `ScenePlugin.launch` the `data` argument is now passed to the queued scenes (thanks @gaudeon)
2123
* Rectangle.top wouldn't reset the `y` position if the value given never exceed the Rectangles bottom. Fix #3290 (thanks @chancezeus)
24+
* The implementation of `topOnly` within the Input Manager had broken the way drop zones worked, as they were now filtered out of the display list before processing. Drop zones are now treated on their own in the Input Plugin meaning you can still have `topOnly` set and still drop an item into a drop zone. This indirectly fixed #3291 (thanks @rexrainbow)
25+
* InputPlugin.clear now properly removes a Game Object from all internal arrays, not just the _list.
26+
* InputPlugin.processOverOut no longer considers an item as being 'out' if it's in the internal `_drag` array.
2227

2328
### Updates
2429

src/gameobjects/GameObject.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,13 @@ var GameObject = new Class({
255255
*
256256
* @param {any} [shape] - A geometric shape that defines the hit area for the Game Object. If not specified a Rectangle will be used.
257257
* @param {function} [callback] - A callback to be invoked when the Game Object is interacted with.
258+
* @param {boolean} [dropZone=false] - Should this Game Object be treated as a drop zone target?
258259
*
259260
* @return {Phaser.GameObjects.GameObject} This GameObject.
260261
*/
261-
setInteractive: function (shape, callback)
262+
setInteractive: function (shape, callback, dropZone)
262263
{
263-
this.scene.sys.input.enable(this, shape, callback);
264+
this.scene.sys.input.enable(this, shape, callback, dropZone);
264265

265266
return this;
266267
},

src/gameobjects/zone/Zone.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,8 @@ var Zone = new Class({
251251
{
252252
if (!this.input)
253253
{
254-
this.setInteractive(shape, callback);
254+
this.setInteractive(shape, callback, true);
255255
}
256-
257-
this.input.dropZone = true;
258256
}
259257

260258
return this;

src/input/InputPlugin.js

Lines changed: 84 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ var InputPlugin = new Class({
184184
*/
185185
this._temp = [];
186186

187+
/**
188+
* Used to temporarily store the results of the Hit Test dropZones
189+
*
190+
* @name Phaser.Input.InputPlugin#_tempZones
191+
* @type {array}
192+
* @private
193+
* @default []
194+
* @since 3.0.0
195+
*/
196+
this._tempZones = [];
197+
187198
/**
188199
* A list of all Game Objects that have been set to be interactive.
189200
*
@@ -314,8 +325,6 @@ var InputPlugin = new Class({
314325
{
315326
current.splice(index, 1);
316327

317-
// TODO: Clear from _draggable, _drag and _over too
318-
319328
this.clear(gameObject);
320329
}
321330
}
@@ -333,9 +342,9 @@ var InputPlugin = new Class({
333342
* @method Phaser.Input.InputPlugin#clear
334343
* @since 3.0.0
335344
*
336-
* @param {[type]} gameObject - [description]
345+
* @param {Phaser.GameObjects.GameObject} gameObject - [description]
337346
*
338-
* @return {[type]} [description]
347+
* @return {Phaser.GameObjects.GameObject} [description]
339348
*/
340349
clear: function (gameObject)
341350
{
@@ -349,6 +358,28 @@ var InputPlugin = new Class({
349358

350359
gameObject.input = null;
351360

361+
// Clear from _draggable, _drag and _over
362+
var index = this._draggable.indexOf(gameObject);
363+
364+
if (index > -1)
365+
{
366+
this._draggable.splice(index, 1);
367+
}
368+
369+
index = this._drag.indexOf(gameObject);
370+
371+
if (index > -1)
372+
{
373+
this._drag.splice(index, 1);
374+
}
375+
376+
index = this._over.indexOf(gameObject);
377+
378+
if (index > -1)
379+
{
380+
this._over.splice(index, 1);
381+
}
382+
352383
return gameObject;
353384
},
354385

@@ -358,7 +389,7 @@ var InputPlugin = new Class({
358389
* @method Phaser.Input.InputPlugin#disable
359390
* @since 3.0.0
360391
*
361-
* @param {[type]} gameObject - [description]
392+
* @param {Phaser.GameObjects.GameObject} gameObject - [description]
362393
*/
363394
disable: function (gameObject)
364395
{
@@ -371,14 +402,17 @@ var InputPlugin = new Class({
371402
* @method Phaser.Input.InputPlugin#enable
372403
* @since 3.0.0
373404
*
374-
* @param {[type]} gameObject - [description]
375-
* @param {[type]} shape - [description]
376-
* @param {[type]} callback - [description]
405+
* @param {Phaser.GameObjects.GameObject} gameObject - [description]
406+
* @param {object} shape - [description]
407+
* @param {function} callback - [description]
408+
* @param {boolean} [dropZone=false] - [description]
377409
*
378-
* @return {[type]} [description]
410+
* @return {Phaser.Input.InputPlugin} This Input Plugin.
379411
*/
380-
enable: function (gameObject, shape, callback)
412+
enable: function (gameObject, shape, callback, dropZone)
381413
{
414+
if (dropZone === undefined) { dropZone = false; }
415+
382416
if (gameObject.input)
383417
{
384418
// If it is already has an InteractiveObject then just enable it and return
@@ -389,6 +423,8 @@ var InputPlugin = new Class({
389423
// Create an InteractiveObject and enable it
390424
this.setHitArea(gameObject, shape, callback);
391425
}
426+
427+
gameObject.input.dropZone = dropZone;
392428

393429
return this;
394430
},
@@ -401,7 +437,7 @@ var InputPlugin = new Class({
401437
*
402438
* @param {[type]} pointer - [description]
403439
*
404-
* @return {[type]} [description]
440+
* @return {array} [description]
405441
*/
406442
hitTestPointer: function (pointer)
407443
{
@@ -413,7 +449,20 @@ var InputPlugin = new Class({
413449

414450
// Get a list of all objects that can be seen by the camera below the pointer in the scene and store in 'output' array.
415451
// All objects in this array are input enabled, as checked by the hitTest method, so we don't need to check later on as well.
416-
return this.manager.hitTest(pointer.x, pointer.y, this._list, camera);
452+
var over = this.manager.hitTest(pointer.x, pointer.y, this._list, camera);
453+
454+
// Filter out the drop zones
455+
for (var i = 0; i < over.length; i++)
456+
{
457+
var obj = over[i];
458+
459+
if (obj.input.dropZone)
460+
{
461+
this._tempZones.push(obj);
462+
}
463+
}
464+
465+
return over;
417466
}
418467
else
419468
{
@@ -466,10 +515,10 @@ var InputPlugin = new Class({
466515
* @method Phaser.Input.InputPlugin#processDragEvents
467516
* @since 3.0.0
468517
*
469-
* @param {[type]} pointer - [description]
470-
* @param {[type]} time - [description]
518+
* @param {number} pointer - [description]
519+
* @param {number} time - [description]
471520
*
472-
* @return {[type]} [description]
521+
* @return {integer} [description]
473522
*/
474523
processDragEvents: function (pointer, time)
475524
{
@@ -601,16 +650,7 @@ var InputPlugin = new Class({
601650
// 4 = Pointer actively dragging the draglist and has moved
602651
if (pointer.dragState === 4 && pointer.justMoved)
603652
{
604-
// Let's filter out currentlyOver for dropZones only
605-
var dropZones = [];
606-
607-
for (c = 0; c < currentlyOver.length; c++)
608-
{
609-
if (currentlyOver[c].input.dropZone)
610-
{
611-
dropZones.push(currentlyOver[c]);
612-
}
613-
}
653+
var dropZones = this._tempZones;
614654

615655
list = this._drag[pointer.id];
616656

@@ -793,6 +833,7 @@ var InputPlugin = new Class({
793833
var justOver = [];
794834
var stillOver = [];
795835
var previouslyOver = this._over[pointer.id];
836+
var currentlyDragging = this._drag[pointer.id];
796837

797838
// Go through all objects the pointer was previously over, and see if it still is.
798839
// Splits the previouslyOver array into two parts: justOut and stillOver
@@ -801,7 +842,7 @@ var InputPlugin = new Class({
801842
{
802843
gameObject = previouslyOver[i];
803844

804-
if (currentlyOver.indexOf(gameObject) === -1)
845+
if (currentlyOver.indexOf(gameObject) === -1 && currentlyDragging.indexOf(gameObject) === -1)
805846
{
806847
// Not in the currentlyOver array, so must be outside of this object now
807848
justOut.push(gameObject);
@@ -1398,10 +1439,8 @@ var InputPlugin = new Class({
13981439
* @method Phaser.Input.InputPlugin#update
13991440
* @since 3.0.0
14001441
*
1401-
* @param {[type]} time - [description]
1402-
* @param {[type]} delta - [description]
1403-
*
1404-
* @return {[type]} [description]
1442+
* @param {number} time - [description]
1443+
* @param {number} delta - [description]
14051444
*/
14061445
update: function (time, delta)
14071446
{
@@ -1435,14 +1474,27 @@ var InputPlugin = new Class({
14351474
return;
14361475
}
14371476

1477+
// Always reset this array
1478+
this._tempZones = [];
1479+
1480+
// _temp contains a hit tested and camera culled list of IO objects
14381481
this._temp = this.hitTestPointer(pointer);
14391482

14401483
this.sortGameObjects(this._temp);
1484+
this.sortGameObjects(this._tempZones);
14411485

1442-
if (this.topOnly && this._temp.length)
1486+
if (this.topOnly)
14431487
{
14441488
// Only the top-most one counts now, so safely ignore the rest
1445-
this._temp.splice(1);
1489+
if (this._temp.length)
1490+
{
1491+
this._temp.splice(1);
1492+
}
1493+
1494+
if (this._tempZones.length)
1495+
{
1496+
this._tempZones.splice(1);
1497+
}
14461498
}
14471499

14481500
var total = this.processDragEvents(pointer, time);

0 commit comments

Comments
 (0)