From e728f3a1b954482b7498c0f82ff0a8c56608a3a3 Mon Sep 17 00:00:00 2001 From: pixelhijack Date: Thu, 29 Mar 2018 21:40:32 +0200 Subject: [PATCH 01/87] [ISSUE #3363] Phaser Scene - passing data to scene init & create methods --- src/scene/SceneManager.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/scene/SceneManager.js b/src/scene/SceneManager.js index e6feb53df..26ed970ec 100644 --- a/src/scene/SceneManager.js +++ b/src/scene/SceneManager.js @@ -180,7 +180,7 @@ var SceneManager = new Class({ { entry = this._start[i]; - this.start(entry); + this.start(entry, entry.scene.data); } this._start.length = 0; @@ -219,7 +219,7 @@ var SceneManager = new Class({ { entry = this._start[i]; - this.start(entry); + this.start(entry, entry.scene.data); } // Clear the pending lists @@ -309,7 +309,7 @@ var SceneManager = new Class({ { if (this.game.isBooted) { - this.start(key); + this.start(key, newScene.sys.settings.data); } else { @@ -695,6 +695,11 @@ var SceneManager = new Class({ } } + if (sceneConfig.hasOwnProperty('data')) + { + newScene.data = sceneConfig.data; + } + return newScene; }, @@ -951,7 +956,7 @@ var SceneManager = new Class({ if (entry.key === key) { entry.autoStart = true; - entry.data = data; + entry.scene.data = data; } } From edb81c9096fdfcad99561ecd59ce7c47382f956e Mon Sep 17 00:00:00 2001 From: Travis O'Neal Date: Fri, 30 Mar 2018 11:24:36 -0400 Subject: [PATCH 02/87] Tween.Restart adds Tween back to the active list for the TweenManager to properly process and replay --- src/tweens/tween/Tween.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tweens/tween/Tween.js b/src/tweens/tween/Tween.js index ac2cc64d7..ae9abc8b8 100644 --- a/src/tweens/tween/Tween.js +++ b/src/tweens/tween/Tween.js @@ -409,8 +409,16 @@ var Tween = new Class({ */ restart: function () { - this.stop(); - this.play(); + if (this.state === TWEEN_CONST.REMOVED) + { + this.seek(0); + this.parent.makeActive(this); + } + else + { + this.stop(); + this.play(); + } }, /** From bf2510bfabecf9d89dd2821a261ae0c9ade17e8b Mon Sep 17 00:00:00 2001 From: Travis O'Neal Date: Fri, 30 Mar 2018 11:27:16 -0400 Subject: [PATCH 03/87] Tween.Restart handles removed tweens properly and readds them back into the --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07c6d9c44..b69a491d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ being passed to the simulation. The default value is 1 to remain consistent with * PathFollower.start has been renamed to `startFollow`, but PathFollower.setPath was still using `PathFollower.start` (thanks @samid737) * BaseSoundManager.rate and BaseSoundManager.detune would incorrectly called `setRate` on its sounds, instead of `calculateRate`. * The Gamepad Axis `getValue` method now correctly applies the threshold and zeroes out the returned value. +* Tween.Restart handles removed tweens properly and readds them back into the +active queue for the TweenManager ### Updates From 9293891c82e63c56bf2b96860b9961318cc266a8 Mon Sep 17 00:00:00 2001 From: Chris Andrew Date: Thu, 5 Apr 2018 19:08:54 +0100 Subject: [PATCH 04/87] Fixed renderCanvas() call in Graphics.generateTexture(). Introduced by altering the signature of the Canvas renderers (c232642a). --- src/gameobjects/graphics/Graphics.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gameobjects/graphics/Graphics.js b/src/gameobjects/graphics/Graphics.js index 85e343fc4..f02ef97ba 100644 --- a/src/gameobjects/graphics/Graphics.js +++ b/src/gameobjects/graphics/Graphics.js @@ -915,10 +915,10 @@ var Graphics = new Class({ /** * Creates a pie-chart slice shape centered at `x`, `y` with the given radius. * You must define the start and end angle of the slice. - * + * * Setting the `anticlockwise` argument to `true` creates a shape similar to Pacman. * Setting it to `false` creates a shape like a slice of pie. - * + * * This method will begin a new path and close the path at the end of it. * To display the actual slice you need to call either `strokePath` or `fillPath` after it. * @@ -1133,7 +1133,7 @@ var Graphics = new Class({ if (ctx) { - this.renderCanvas(sys.game.renderer, this, 0, Graphics.TargetCamera, ctx); + this.renderCanvas(sys.game.renderer, this, 0.0, Graphics.TargetCamera, null, ctx); if (sys.game.renderer.gl && texture) { From 582a742373b5829fd1af6b76ddb615bf04cd5683 Mon Sep 17 00:00:00 2001 From: Evan Date: Thu, 5 Apr 2018 14:21:40 -0500 Subject: [PATCH 05/87] filling in most of the jsdocs for GetFastValue and SpriteSheetFromAtlas --- src/textures/parsers/SpriteSheetFromAtlas.js | 12 +++++++++--- src/utils/object/GetFastValue.js | 14 +++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/textures/parsers/SpriteSheetFromAtlas.js b/src/textures/parsers/SpriteSheetFromAtlas.js index 79262d81a..675819561 100644 --- a/src/textures/parsers/SpriteSheetFromAtlas.js +++ b/src/textures/parsers/SpriteSheetFromAtlas.js @@ -8,17 +8,23 @@ var GetFastValue = require('../../utils/object/GetFastValue'); /** * Parses a Sprite Sheet and adds the Frames to the Texture, where the Sprite Sheet is stored as a frame within an Atlas. - * + * * In Phaser terminology a Sprite Sheet is a texture containing different frames, but each frame is the exact * same size and cannot be trimmed or rotated. * * @function Phaser.Textures.Parsers.SpriteSheetFromAtlas - * @memberOf Phaser.Textures.Parsers + * @memberof Phaser.Textures.Parsers * @since 3.0.0 * * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. * @param {Phaser.Textures.Frame} frame - The Frame that contains the Sprite Sheet. - * @param {object} config - [description] + * @param {object} config - An object describing how to parse the Sprite Sheet. + * @param {number} config.frameWidth - Width in pixels of a single frame in the sprite sheet. + * @param {number} [config.frameHeight] - Height in pixels of a single frame in the sprite sheet. Defaults to frameWidth if not provided. + * @param {number} [config.startFrame=0] - [description] + * @param {number} [config.endFrame=-1] - [description] + * @param {number} [config.margin=0] - If the frames have been drawn with a margin, specify the amount here. + * @param {number} [config.spacing=0] - If the frames have been drawn with spacing between them, specify the amount here. * * @return {Phaser.Textures.Texture} The Texture modified by this parser. */ diff --git a/src/utils/object/GetFastValue.js b/src/utils/object/GetFastValue.js index 309e07604..9d8dc9640 100644 --- a/src/utils/object/GetFastValue.js +++ b/src/utils/object/GetFastValue.js @@ -4,21 +4,17 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -// Source object -// The key as a string, can only be 1 level deep (no periods), must exist at the top level of the source object -// The default value to use if the key doesn't exist - /** - * [description] + * Finds the key within the top level of the {@link source} object, or returns {@link defaultValue} * * @function Phaser.Utils.Object.GetFastValue * @since 3.0.0 * - * @param {object} source - [description] - * @param {string} key - [description] - * @param {*} [defaultValue] - [description] + * @param {object} source - The object to search + * @param {string} key - The key for the property on source. Must exist at the top level of the source object (no periods) + * @param {*} [defaultValue] - The default value to use if the key does not exist. * - * @return {*} [description] + * @return {*} The value if found; otherwise, defaultValue (null if none provided) */ var GetFastValue = function (source, key, defaultValue) { From f70f92b038a8ed745b593277163784b43fe7bebb Mon Sep 17 00:00:00 2001 From: Chris Andrew Date: Thu, 5 Apr 2018 21:07:45 +0100 Subject: [PATCH 06/87] Fixed explicit check for undefined GraphicsCanvasRenderer's parentMatrix, which meant null could not be passed as an argument. --- src/gameobjects/graphics/GraphicsCanvasRenderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gameobjects/graphics/GraphicsCanvasRenderer.js b/src/gameobjects/graphics/GraphicsCanvasRenderer.js index 80cbaf79c..5841a8652 100644 --- a/src/gameobjects/graphics/GraphicsCanvasRenderer.js +++ b/src/gameobjects/graphics/GraphicsCanvasRenderer.js @@ -70,7 +70,7 @@ var GraphicsCanvasRenderer = function (renderer, src, interpolationPercentage, c } ctx.save(); - if (parentMatrix !== undefined) + if (parentMatrix) { var matrix = parentMatrix.matrix; ctx.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); From e54e30ee0b46ae5827a1fd80ec492a913c72b59b Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 5 Apr 2018 17:26:08 -0400 Subject: [PATCH 07/87] Added missing physics property to GameConfig The typescript typings for GameConfig are missing the physics property, so I added it. --- src/boot/Config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/boot/Config.js b/src/boot/Config.js index 5175251f3..55a761af0 100644 --- a/src/boot/Config.js +++ b/src/boot/Config.js @@ -98,6 +98,7 @@ var ValueToColor = require('../display/color/ValueToColor'); * @property {object} [images] - [description] * @property {string} [images.default] - [description] * @property {string} [images.missing] - [description] + * @property {object} [physics=null] - [description] */ /** From e0dc28e4ba260d5089b87950d31ef94fa09d7460 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 6 Apr 2018 11:15:15 +0100 Subject: [PATCH 08/87] Fixed lint errors and added jsdocs --- src/gameobjects/components/Transform.js | 30 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/gameobjects/components/Transform.js b/src/gameobjects/components/Transform.js index daacc5b5c..d79f9135d 100644 --- a/src/gameobjects/components/Transform.js +++ b/src/gameobjects/components/Transform.js @@ -7,7 +7,6 @@ var MATH_CONST = require('../../math/const'); var WrapAngle = require('../../math/angle/Wrap'); var WrapAngleDegrees = require('../../math/angle/WrapDegrees'); -var TransformMatrix = require('./TransformMatrix'); // global bitmask flag for GameObject.renderMask (used by Scale) var _FLAG = 4; // 0100 @@ -371,11 +370,31 @@ var Transform = { return this; }, + /** + * Gets the local transform matrix for this Game Object. + * + * @method Phaser.GameObjects.Components.Transform#getLocalTransformMatrix + * @since 3.4.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} tempMatrix - The matrix to populate with the values from this Game Object. + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. + */ getLocalTransformMatrix: function (tempMatrix) { return tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY); }, + /** + * Gets the world transform matrix for this Game Object, factoring in any parent Containers. + * + * @method Phaser.GameObjects.Components.Transform#getWorldTransformMatrix + * @since 3.4.0 + * + * @param {Phaser.GameObjects.Components.TransformMatrix} tempMatrix - The matrix to populate with the values from this Game Object. + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. + */ getWorldTransformMatrix: function (tempMatrix) { var parent = this.parentContainer; @@ -393,10 +412,11 @@ var Transform = { for (var i = 0; i < length; ++i) { - rootContainer = parents[i]; - tempMatrix.translate(rootContainer.x, rootContainer.y); - tempMatrix.rotate(rootContainer.rotation); - tempMatrix.scale(rootContainer.scaleX, rootContainer.scaleY); + parent = parents[i]; + + tempMatrix.translate(parent.x, parent.y); + tempMatrix.rotate(parent._rotation); + tempMatrix.scale(parent._scaleX, parent._scaleY); } tempMatrix.translate(this.x, this.y); From c08f76935150176ed846323c8007ed4f208c68bd Mon Sep 17 00:00:00 2001 From: Christian Panadero Date: Fri, 6 Apr 2018 18:17:58 +0100 Subject: [PATCH 09/87] Add keyboardManaged#createCursorKeys typedefs --- src/input/keyboard/KeyboardManager.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/input/keyboard/KeyboardManager.js b/src/input/keyboard/KeyboardManager.js index 28e6d35b7..33fe89360 100644 --- a/src/input/keyboard/KeyboardManager.js +++ b/src/input/keyboard/KeyboardManager.js @@ -190,13 +190,24 @@ var KeyboardManager = new Class({ this.target.removeEventListener('keyup', this.handler); }, + /** + * @typedef {object} CursorKeys + * + * @property {Phaser.Input.Keyboard.Key} [up] - [description] + * @property {Phaser.Input.Keyboard.Key} [down] - [description] + * @property {Phaser.Input.Keyboard.Key} [left] - [description] + * @property {Phaser.Input.Keyboard.Key} [right] - [description] + * @property {Phaser.Input.Keyboard.Key} [space] - [description] + * @property {Phaser.Input.Keyboard.Key} [shift] - [description] + */ + /** * Creates and returns an object containing 4 hotkeys for Up, Down, Left and Right, and also space and shift. * * @method Phaser.Input.Keyboard.KeyboardManager#createCursorKeys * @since 3.0.0 * - * @return {object} [description] + * @return {CursorKeys} [description] */ createCursorKeys: function () { From c6a9b0e3ba7b50c67e30e8e0a9e31e2abe4a5c6b Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 12:35:34 +0100 Subject: [PATCH 10/87] Change Log updated --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53414bb03..426a22c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,11 +66,17 @@ being passed to the simulation. The default value is 1 to remain consistent with * List.removeBetween has a new optional argument `skipCallback`. * List.removeAll has a new optional argument `skipCallback`. -### Animation Component Updates +### Animation System Updates We have refactored the Animation API to make it more consistent with the rest of Phaser 3 and to fix some issues. All of the following changes apply to the Animation Component: * Animation durations, delays and repeatDelays are all now specified in milliseconds, not seconds like before. This makes them consistent with Tweens, Sounds and other parts of v3. You can still use the `frameRate` property to set the speed of an animation in frames per second. +* All of the Animation callbacks have been removed, including `onStart`, `onRepat`, `onUpdate` and `onComplete` and the corresponding params arrays like `onStartParams` and the property `callbackScope`. The reason for this is that they were all set on a global level, meaning that if you had 100 Sprites sharing the same animation, it was impossible to set the callbacks to fire for just one of those Sprites, but instead they would fire for all 100 and it was up to you to figure out which Sprite you wanted to update. Instead of callbacks animations now dispatch events on the Game Objects in which they are running. This means you can now do `sprite.on('animationstart')` and it will be invoked at the same point the old `onStart` callback would have been. The new events are: `animationstart`, `animtionrepeat`, `animationupdate` and `animationcomplete`. They're all dispatched from the Game Object that has the animation playing, not from the animation itself. This allows you far more control over what happens in the callbacks and we believe generally makes them more useful. +* The AnimationFrame.onUpdate callback has been removed. You can now use the `animationupdate` event dispatched from the Game Object itself and check the 2nd argument, which is the animation frame. +* Animation.stopAfterDelay is a new method that will stop a Sprites animation after the given time in ms. +* Animation.stopOnRepeat is a new method that will stop a Sprites animation when it goes to repeat. +* Animation.stopOnFrame is a new method that will stop a Sprites animation when it sets the given frame. +* Animation.stop no longer has the `dispatchCallbacks` argument, because it dispatches an event which you can choose to ignore. * `delay` method has been removed. * `setDelay` allows you to define the delay before playback begins. * `getDelay` returns the animation playback delay value. From daa2236998f8af7f37402fc4c52f09362764d763 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 12:35:51 +0100 Subject: [PATCH 11/87] Removed onUpdate --- src/animations/AnimationFrame.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/animations/AnimationFrame.js b/src/animations/AnimationFrame.js index 800730c04..bfcb532e7 100644 --- a/src/animations/AnimationFrame.js +++ b/src/animations/AnimationFrame.js @@ -142,16 +142,6 @@ var AnimationFrame = new Class({ * @since 3.0.0 */ this.progress = 0; - - /** - * A frame specific callback, invoked if this frame gets displayed and the callback is set. - * - * @name Phaser.Animations.AnimationFrame#onUpdate - * @type {?function} - * @default null - * @since 3.0.0 - */ - this.onUpdate = null; }, /** @@ -180,7 +170,6 @@ var AnimationFrame = new Class({ destroy: function () { this.frame = undefined; - this.onUpdate = undefined; } }); From c2edab2d7b08a09e2aa9b5b18acb1882f623a72b Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 12:36:11 +0100 Subject: [PATCH 12/87] Removed all animation callbacks and added events --- src/animations/Animation.js | 115 ++++-------------------------------- 1 file changed, 12 insertions(+), 103 deletions(-) diff --git a/src/animations/Animation.js b/src/animations/Animation.js index bbe6b7020..7d343c4f4 100644 --- a/src/animations/Animation.js +++ b/src/animations/Animation.js @@ -34,7 +34,6 @@ var GetValue = require('../utils/object/GetValue'); * @property {(string|number)} frame - [description] * @property {float} [duration=0] - [description] * @property {boolean} [visible] - [description] - * @property {function} [onUpdate] - [description] */ /** @@ -51,16 +50,6 @@ var GetValue = require('../utils/object/GetValue'); * @property {boolean} [yoyo=false] - Should the animation yoyo? (reverse back down to the start) before repeating? * @property {boolean} [showOnStart=false] - Should sprite.visible = true when the animation starts to play? * @property {boolean} [hideOnComplete=false] - Should sprite.visible = false when the animation finishes? - - * @property {*} [callbackScope] - [description] - * @property {(false|function)} [onStart=false] - [description] - * @property {Array.<*>} [onStartParams] - [description] - * @property {(false|function)} [onRepeat=false] - [description] - * @property {Array.<*>} [onRepeatParams] - [description] - * @property {(false|function)} [onUpdate=false] - [description] - * @property {Array.<*>} [onUpdateParams] - [description] - * @property {(false|function)} [onComplete=false] - [description] - * @property {Array.<*>} [onCompleteParams] - [description] */ /** @@ -250,88 +239,6 @@ var Animation = new Class({ */ this.hideOnComplete = GetValue(config, 'hideOnComplete', false); - /** - * [description] - * - * @name Phaser.Animations.Animation#callbackScope - * @type {*} - * @since 3.0.0 - */ - this.callbackScope = GetValue(config, 'callbackScope', this); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onStart - * @type {(false|function)} - * @since 3.0.0 - */ - this.onStart = GetValue(config, 'onStart', false); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onStartParams - * @type {Array.<*>} - * @since 3.0.0 - */ - this.onStartParams = GetValue(config, 'onStartParams', []); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onRepeat - * @type {(false|function)} - * @since 3.0.0 - */ - this.onRepeat = GetValue(config, 'onRepeat', false); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onRepeatParams - * @type {Array.<*>} - * @since 3.0.0 - */ - this.onRepeatParams = GetValue(config, 'onRepeatParams', []); - - /** - * Called for EVERY frame of the animation. - * See AnimationFrame.onUpdate for a frame specific callback. - * - * @name Phaser.Animations.Animation#onUpdate - * @type {(false|function)} - * @since 3.0.0 - */ - this.onUpdate = GetValue(config, 'onUpdate', false); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onUpdateParams - * @type {Array.<*>} - * @since 3.0.0 - */ - this.onUpdateParams = GetValue(config, 'onUpdateParams', []); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onComplete - * @type {(false|function)} - * @since 3.0.0 - */ - this.onComplete = GetValue(config, 'onComplete', false); - - /** - * [description] - * - * @name Phaser.Animations.Animation#onCompleteParams - * @type {Array.<*>} - * @since 3.0.0 - */ - this.onCompleteParams = GetValue(config, 'onCompleteParams', []); - /** * Global pause. All Game Objects using this Animation instance are impacted by this property. * @@ -431,7 +338,7 @@ var Animation = new Class({ component.parent.visible = false; } - component.stop(true); + component.stop(); }, /** @@ -536,7 +443,6 @@ var Animation = new Class({ animationFrame = new Frame(key, frame, index, textureFrame); animationFrame.duration = GetValue(item, 'duration', 0); - animationFrame.onUpdate = GetValue(item, 'onUpdate', null); animationFrame.isFirst = (!prev); @@ -627,8 +533,6 @@ var Animation = new Class({ component._repeat = this.repeat; component._repeatDelay = this.repeatDelay; component._yoyo = this.yoyo; - component._callbackArgs[1] = this; - component._updateParams = component._callbackArgs.concat(this.onUpdateParams); } component.updateFrame(this.frames[startFrame]); @@ -784,6 +688,11 @@ var Animation = new Class({ */ repeatAnimation: function (component) { + if (component._pendingStop === 2) + { + return this.completeAnimation(component); + } + if (component._repeatDelay > 0 && component.pendingRepeat === false) { component.pendingRepeat = true; @@ -798,13 +707,13 @@ var Animation = new Class({ component.updateFrame(component.currentFrame.nextFrame); - this.getNextTick(component); - - component.pendingRepeat = false; - - if (this.onRepeat) + if (component.isPlaying) { - this.onRepeat.apply(this.callbackScope, component._callbackArgs.concat(this.onRepeatParams)); + this.getNextTick(component); + + component.pendingRepeat = false; + + component.parent.emit('animationrepeat', this, component.currentFrame, component.repeatCounter); } } }, From 777325c046f720ab74cc1601c0c9084ab34fc062 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 12:36:35 +0100 Subject: [PATCH 13/87] Removed callbacks, added events and added new stop methods --- src/gameobjects/components/Animation.js | 131 ++++++++++++++++-------- 1 file changed, 91 insertions(+), 40 deletions(-) diff --git a/src/gameobjects/components/Animation.js b/src/gameobjects/components/Animation.js index f74384b35..3991315ec 100644 --- a/src/gameobjects/components/Animation.js +++ b/src/gameobjects/components/Animation.js @@ -246,24 +246,29 @@ var Animation = new Class({ this._wasPlaying = false; /** - * Container for the callback arguments. + * Internal property tracking if this Animation is waiting to stop. + * + * 0 = No + * 1 = Waiting for ms to pass + * 2 = Waiting for repeat + * 3 = Waiting for specific frame * - * @name Phaser.GameObjects.Components.Animation#_callbackArgs - * @type {array} + * @name Phaser.GameObjects.Components.Animation#_pendingStop + * @type {integer} * @private - * @since 3.0.0 + * @since 3.4.0 */ - this._callbackArgs = [ parent, null ]; + this._pendingStop = 0; /** - * Container for the update arguments. + * Internal property used by _pendingStop. * - * @name Phaser.GameObjects.Components.Animation#_updateParams - * @type {array} + * @name Phaser.GameObjects.Components.Animation#_pendingStopValue + * @type {any} * @private - * @since 3.0.0 + * @since 3.4.0 */ - this._updateParams = []; + this._pendingStopValue; }, /** @@ -475,10 +480,7 @@ var Animation = new Class({ gameObject.visible = true; } - if (anim.onStart) - { - anim.onStart.apply(anim.callbackScope, this._callbackArgs.concat(anim.onStartParams)); - } + gameObject.emit('animationstart', this.currentAnim, this.currentFrame); return gameObject; }, @@ -647,27 +649,74 @@ var Animation = new Class({ }, /** - * Stops the current animation from playing and optionally dispatches any onComplete callbacks. + * Immediately stops the current animation from playing and dispatches the `animationcomplete` event. * * @method Phaser.GameObjects.Components.Animation#stop * @since 3.0.0 * - * @param {boolean} [dispatchCallbacks=false] - [description] - * * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. */ - stop: function (dispatchCallbacks) + stop: function () { - if (dispatchCallbacks === undefined) { dispatchCallbacks = false; } + this._pendingStop = 0; this.isPlaying = false; - var anim = this.currentAnim; + var gameObject = this.parent; - if (dispatchCallbacks && anim.onComplete) - { - anim.onComplete.apply(anim.callbackScope, this._callbackArgs.concat(anim.onCompleteParams)); - } + gameObject.emit('animtioncomplete', this.currentAnim, this.currentFrame); + + return gameObject; + }, + + /** + * Stops the current animation from playing after the specified time delay, given in milliseconds. + * + * @method Phaser.GameObjects.Components.Animation#stopAfterDelay + * @since 3.4.0 + * + * @param {integer} delay - The number of miliseconds to wait before stopping this animation. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopAfterDelay: function (delay) + { + this._pendingStop = 1; + this._pendingStopValue = delay; + + return this.parent; + }, + + /** + * Stops the current animation from playing when it next repeats. + * + * @method Phaser.GameObjects.Components.Animation#stopOnRepeat + * @since 3.4.0 + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopOnRepeat: function () + { + this._pendingStop = 2; + + return this.parent; + }, + + /** + * Stops the current animation from playing when it next sets the given frame. + * If this frame doesn't exist within the animation it will not stop it from playing. + * + * @method Phaser.GameObjects.Components.Animation#stopOnFrame + * @since 3.4.0 + * + * @param {Phaser.Animations.AnimationFrame} delay - The frame to check before stopping this animation. + * + * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. + */ + stopOnFrame: function (frame) + { + this._pendingStop = 3; + this._pendingStopValue = frame; return this.parent; }, @@ -729,16 +778,24 @@ var Animation = new Class({ */ update: function (timestamp, delta) { - if (!this.isPlaying || this.currentAnim.paused) + if (this.isPlaying || !this.currentAnim.paused) { - return; - } + this.accumulator += delta * this._timeScale; - this.accumulator += delta * this._timeScale; + if (this._pendingStop === 1) + { + this._pendingStopValue -= delta; - if (this.accumulator >= this.nextTick) - { - this.currentAnim.setFrame(this); + if (this._pendingStopValue <= 0) + { + return this.currentAnim.completeAnimation(this); + } + } + + if (this.accumulator >= this.nextTick) + { + this.currentAnim.setFrame(this); + } } }, @@ -798,14 +855,11 @@ var Animation = new Class({ var anim = this.currentAnim; - if (anim.onUpdate) - { - anim.onUpdate.apply(anim.callbackScope, this._updateParams); - } + gameObject.emit('animationupdate', anim, animationFrame); - if (animationFrame.onUpdate) + if (this._pendingStop === 3 && this._pendingStopValue === animationFrame) { - animationFrame.onUpdate(gameObject, animationFrame); + this.currentAnim.completeAnimation(this); } } }, @@ -859,9 +913,6 @@ var Animation = new Class({ this.currentAnim = null; this.currentFrame = null; - - this._callbackArgs = []; - this._updateParams = []; } }); From fa43b8c4efd5fff62e36435350d3e466ba72f510 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 15:57:53 +0100 Subject: [PATCH 14/87] Updated change log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 426a22c56..ee142d819 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,7 +71,7 @@ being passed to the simulation. The default value is 1 to remain consistent with We have refactored the Animation API to make it more consistent with the rest of Phaser 3 and to fix some issues. All of the following changes apply to the Animation Component: * Animation durations, delays and repeatDelays are all now specified in milliseconds, not seconds like before. This makes them consistent with Tweens, Sounds and other parts of v3. You can still use the `frameRate` property to set the speed of an animation in frames per second. -* All of the Animation callbacks have been removed, including `onStart`, `onRepat`, `onUpdate` and `onComplete` and the corresponding params arrays like `onStartParams` and the property `callbackScope`. The reason for this is that they were all set on a global level, meaning that if you had 100 Sprites sharing the same animation, it was impossible to set the callbacks to fire for just one of those Sprites, but instead they would fire for all 100 and it was up to you to figure out which Sprite you wanted to update. Instead of callbacks animations now dispatch events on the Game Objects in which they are running. This means you can now do `sprite.on('animationstart')` and it will be invoked at the same point the old `onStart` callback would have been. The new events are: `animationstart`, `animtionrepeat`, `animationupdate` and `animationcomplete`. They're all dispatched from the Game Object that has the animation playing, not from the animation itself. This allows you far more control over what happens in the callbacks and we believe generally makes them more useful. +* All of the Animation callbacks have been removed, including `onStart`, `onRepeat`, `onUpdate` and `onComplete` and the corresponding params arrays like `onStartParams` and the property `callbackScope`. The reason for this is that they were all set on a global level, meaning that if you had 100 Sprites sharing the same animation, it was impossible to set the callbacks to fire for just one of those Sprites, but instead they would fire for all 100 and it was up to you to figure out which Sprite you wanted to update. Instead of callbacks animations now dispatch events on the Game Objects in which they are running. This means you can now do `sprite.on('animationstart')` and it will be invoked at the same point the old `onStart` callback would have been. The new events are: `animationstart`, `animtionrepeat`, `animationupdate` and `animationcomplete`. They're all dispatched from the Game Object that has the animation playing, not from the animation itself. This allows you far more control over what happens in the callbacks and we believe generally makes them more useful. * The AnimationFrame.onUpdate callback has been removed. You can now use the `animationupdate` event dispatched from the Game Object itself and check the 2nd argument, which is the animation frame. * Animation.stopAfterDelay is a new method that will stop a Sprites animation after the given time in ms. * Animation.stopOnRepeat is a new method that will stop a Sprites animation when it goes to repeat. From d1788d8a4cb5b5ea9ab5babca08bb89256c61582 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 15:58:08 +0100 Subject: [PATCH 15/87] Updated jsdocs --- src/gameobjects/components/Animation.js | 40 +++++++++++++++++++++++++ src/sound/BaseSound.js | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/gameobjects/components/Animation.js b/src/gameobjects/components/Animation.js index 3991315ec..44b618b4d 100644 --- a/src/gameobjects/components/Animation.js +++ b/src/gameobjects/components/Animation.js @@ -6,6 +6,40 @@ var Class = require('../../utils/Class'); +/** + * This event is dispatched when an animation starts playing. + * + * @event Phaser.GameObjects.Components.Animation#onStartEvent + * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. + * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. + */ + +/** + * This event is dispatched when an animation repeats. + * + * @event Phaser.GameObjects.Components.Animation#onRepeatEvent + * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. + * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. + * @param {integer} repeatCount - The number of times this animation has repeated. + */ + +/** + * This event is dispatched when an animation updates. This happens when the animation frame changes, + * based on the animation frame rate and other factors like timeScale and delay. + * + * @event Phaser.GameObjects.Components.Animation#onUpdateEvent + * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. + * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. + */ + +/** + * This event is dispatched when an animation completes playing, either naturally or via Animation.stop. + * + * @event Phaser.GameObjects.Components.Animation#onCompleteEvent + * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. + * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. + */ + /** * @classdesc * A Game Object Animation Controller. @@ -443,6 +477,7 @@ var Animation = new Class({ * Plays an Animation on the Game Object that owns this Animation Component. * * @method Phaser.GameObjects.Components.Animation#play + * @fires Phaser.GameObjects.Components.Animation#onStartEvent * @since 3.0.0 * * @param {string} key - The string-based key of the animation to play, as defined previously in the Animation Manager. @@ -652,6 +687,7 @@ var Animation = new Class({ * Immediately stops the current animation from playing and dispatches the `animationcomplete` event. * * @method Phaser.GameObjects.Components.Animation#stop + * @fires Phaser.GameObjects.Components.Animation#onCompleteEvent * @since 3.0.0 * * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. @@ -673,6 +709,7 @@ var Animation = new Class({ * Stops the current animation from playing after the specified time delay, given in milliseconds. * * @method Phaser.GameObjects.Components.Animation#stopAfterDelay + * @fires Phaser.GameObjects.Components.Animation#onCompleteEvent * @since 3.4.0 * * @param {integer} delay - The number of miliseconds to wait before stopping this animation. @@ -691,6 +728,7 @@ var Animation = new Class({ * Stops the current animation from playing when it next repeats. * * @method Phaser.GameObjects.Components.Animation#stopOnRepeat + * @fires Phaser.GameObjects.Components.Animation#onCompleteEvent * @since 3.4.0 * * @return {Phaser.GameObjects.GameObject} The Game Object that owns this Animation Component. @@ -707,6 +745,7 @@ var Animation = new Class({ * If this frame doesn't exist within the animation it will not stop it from playing. * * @method Phaser.GameObjects.Components.Animation#stopOnFrame + * @fires Phaser.GameObjects.Components.Animation#onCompleteEvent * @since 3.4.0 * * @param {Phaser.Animations.AnimationFrame} delay - The frame to check before stopping this animation. @@ -837,6 +876,7 @@ var Animation = new Class({ * Internal frame change handler. * * @method Phaser.GameObjects.Components.Animation#updateFrame + * @fires Phaser.GameObjects.Components.Animation#onUpdateEvent * @private * @since 3.0.0 * diff --git a/src/sound/BaseSound.js b/src/sound/BaseSound.js index 90889e28f..c615ac31c 100644 --- a/src/sound/BaseSound.js +++ b/src/sound/BaseSound.js @@ -12,7 +12,7 @@ var NOOP = require('../utils/NOOP'); /** * @classdesc - * Class containing all the shared state and behaviour of a sound object, independent of the implementation. + * Class containing all the shared state and behavior of a sound object, independent of the implementation. * * @class BaseSound * @extends Phaser.Events.EventEmitter From 9e0f113c92f6e6d8e270e3e4b2aa4f59f7fce2fa Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 16:16:03 +0100 Subject: [PATCH 16/87] Added jsdocs --- src/textures/parsers/SpriteSheet.js | 8 +++++++- src/textures/parsers/SpriteSheetFromAtlas.js | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/textures/parsers/SpriteSheet.js b/src/textures/parsers/SpriteSheet.js index a995f21d0..869733ad9 100644 --- a/src/textures/parsers/SpriteSheet.js +++ b/src/textures/parsers/SpriteSheet.js @@ -22,7 +22,13 @@ var GetFastValue = require('../../utils/object/GetFastValue'); * @param {integer} y - [description] * @param {integer} width - [description] * @param {integer} height - [description] - * @param {object} config - [description] + * @param {object} config - An object describing how to parse the Sprite Sheet. + * @param {number} config.frameWidth - Width in pixels of a single frame in the sprite sheet. + * @param {number} [config.frameHeight] - Height in pixels of a single frame in the sprite sheet. Defaults to frameWidth if not provided. + * @param {number} [config.startFrame=0] - [description] + * @param {number} [config.endFrame=-1] - [description] + * @param {number} [config.margin=0] - If the frames have been drawn with a margin, specify the amount here. + * @param {number} [config.spacing=0] - If the frames have been drawn with spacing between them, specify the amount here. * * @return {Phaser.Textures.Texture} The Texture modified by this parser. */ diff --git a/src/textures/parsers/SpriteSheetFromAtlas.js b/src/textures/parsers/SpriteSheetFromAtlas.js index 675819561..f5fcc15a0 100644 --- a/src/textures/parsers/SpriteSheetFromAtlas.js +++ b/src/textures/parsers/SpriteSheetFromAtlas.js @@ -13,7 +13,7 @@ var GetFastValue = require('../../utils/object/GetFastValue'); * same size and cannot be trimmed or rotated. * * @function Phaser.Textures.Parsers.SpriteSheetFromAtlas - * @memberof Phaser.Textures.Parsers + * @memberOf Phaser.Textures.Parsers * @since 3.0.0 * * @param {Phaser.Textures.Texture} texture - The Texture to add the Frames to. From b3a20d475a3a177d56a99339f3d9bfcabd1fb28a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 16:18:48 +0100 Subject: [PATCH 17/87] Removed null and updated log --- CHANGELOG.md | 2 +- src/boot/Config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee142d819..c55017c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,7 +118,7 @@ We have refactored the Animation API to make it more consistent with the rest of My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs: -@gabegordon @melissaelopez @samid737 @nbs @tgrajewski @pagesrichie @hexus @mbrickn @erd0s @icbat @Matthew-Herman @ampled +@gabegordon @melissaelopez @samid737 @nbs @tgrajewski @pagesrichie @hexus @mbrickn @erd0s @icbat @Matthew-Herman @ampled @mkimmet diff --git a/src/boot/Config.js b/src/boot/Config.js index 55a761af0..930653ffe 100644 --- a/src/boot/Config.js +++ b/src/boot/Config.js @@ -98,7 +98,7 @@ var ValueToColor = require('../display/color/ValueToColor'); * @property {object} [images] - [description] * @property {string} [images.default] - [description] * @property {string} [images.missing] - [description] - * @property {object} [physics=null] - [description] + * @property {object} [physics] - [description] */ /** From c3584347543ee3b964164ec11d6339aa44ab1497 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 17:04:48 +0100 Subject: [PATCH 18/87] Updated log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c55017c25..c06cbeefe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,7 +118,7 @@ We have refactored the Animation API to make it more consistent with the rest of My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs: -@gabegordon @melissaelopez @samid737 @nbs @tgrajewski @pagesrichie @hexus @mbrickn @erd0s @icbat @Matthew-Herman @ampled @mkimmet +@gabegordon @melissaelopez @samid737 @nbs @tgrajewski @pagesrichie @hexus @mbrickn @erd0s @icbat @Matthew-Herman @ampled @mkimmet @PaNaVTEC From b7ae0295bcf291ca7c44c2aee82fbcb10ef33a99 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sat, 7 Apr 2018 17:52:10 +0100 Subject: [PATCH 19/87] No need to use globalAlpha or run fillRect twice. --- src/renderer/canvas/CanvasRenderer.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/renderer/canvas/CanvasRenderer.js b/src/renderer/canvas/CanvasRenderer.js index 507054323..a3806e690 100644 --- a/src/renderer/canvas/CanvasRenderer.js +++ b/src/renderer/canvas/CanvasRenderer.js @@ -441,22 +441,20 @@ var CanvasRenderer = new Class({ } ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.globalCompositeOperation = 'source-over'; - if (camera._fadeAlpha > 0 || camera._flashAlpha > 0) + if (camera._fadeAlpha > 0) { - ctx.globalCompositeOperation = 'source-over'; - // fade rendering - ctx.fillStyle = 'rgb(' + (camera._fadeRed * 255) + ',' + (camera._fadeGreen * 255) + ',' + (camera._fadeBlue * 255) + ')'; - ctx.globalAlpha = camera._fadeAlpha; + ctx.fillStyle = 'rgba(' + (camera._fadeRed * 255) + ',' + (camera._fadeGreen * 255) + ',' + (camera._fadeBlue * 255) + ',' + camera._fadeAlpha + ')'; ctx.fillRect(camera.x, camera.y, camera.width, camera.height); + } + if (camera._flashAlpha > 0) + { // flash rendering - ctx.fillStyle = 'rgb(' + (camera._flashRed * 255) + ',' + (camera._flashGreen * 255) + ',' + (camera._flashBlue * 255) + ')'; - ctx.globalAlpha = camera._flashAlpha; + ctx.fillStyle = 'rgba(' + (camera._flashRed * 255) + ',' + (camera._flashGreen * 255) + ',' + (camera._flashBlue * 255) + ',' + camera._flashAlpha + ')'; ctx.fillRect(camera.x, camera.y, camera.width, camera.height); - - ctx.globalAlpha = 1.0; } // Reset the camera scissor From 5f7d3fa4a1d7fa3a774eb82667fb141cd85dc318 Mon Sep 17 00:00:00 2001 From: Matt Chiasson Date: Sat, 7 Apr 2018 17:51:51 -0400 Subject: [PATCH 20/87] closes #3520 Phaser.Display.Canvas.CanvasPool.first now returns the available pool item instead of always returning null. --- src/display/canvas/CanvasPool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/display/canvas/CanvasPool.js b/src/display/canvas/CanvasPool.js index bcf7ea283..8c7ac15e8 100644 --- a/src/display/canvas/CanvasPool.js +++ b/src/display/canvas/CanvasPool.js @@ -126,13 +126,13 @@ var CanvasPool = function () { if (canvasType === undefined) { canvasType = CONST.CANVAS; } - pool.forEach(function (container) - { + for (var i = 0, len = pool.length; i < len; i++) { + var container = pool[i]; if (!container.parent && container.type === canvasType) { return container; } - }); + }; return null; }; From 12c521d4d7008d4d5f22e69ac398b93479582a92 Mon Sep 17 00:00:00 2001 From: Evan Cobb Date: Sat, 7 Apr 2018 17:14:53 -0500 Subject: [PATCH 21/87] documenting UppercaseFirst --- src/utils/string/UppercaseFirst.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/utils/string/UppercaseFirst.js b/src/utils/string/UppercaseFirst.js index 54811d23a..307439261 100644 --- a/src/utils/string/UppercaseFirst.js +++ b/src/utils/string/UppercaseFirst.js @@ -5,14 +5,23 @@ */ /** - * [description] + * Capitalizes the first letter of a string if there is one. + * @example + * UppercaseFirst('abc'); + * // returns 'Abc' + * @example + * UppercaseFirst('the happy family'); + * // returns 'The happy family' + * @example + * UppercaseFirst(''); + * // returns '' * * @function Phaser.Utils.String.UppercaseFirst * @since 3.0.0 * - * @param {string} str - [description] + * @param {string} str - The string to capitalize. * - * @return {string} [description] + * @return {string} A new string, same as the first, but with the first letter capitalized. */ var UppercaseFirst = function (str) { From 70bedbdce0f5b940ee958f999a46a73076237f4a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Sun, 8 Apr 2018 17:01:43 +0100 Subject: [PATCH 22/87] Check if animation exists --- src/gameobjects/components/Animation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gameobjects/components/Animation.js b/src/gameobjects/components/Animation.js index 44b618b4d..8002b105a 100644 --- a/src/gameobjects/components/Animation.js +++ b/src/gameobjects/components/Animation.js @@ -817,7 +817,7 @@ var Animation = new Class({ */ update: function (timestamp, delta) { - if (this.isPlaying || !this.currentAnim.paused) + if (this.currentAnim && (this.isPlaying || !this.currentAnim.paused)) { this.accumulator += delta * this._timeScale; From 4270660c315ea56a4f163d284a9ada056c11c8be Mon Sep 17 00:00:00 2001 From: Evan Cobb Date: Sun, 8 Apr 2018 14:13:02 -0500 Subject: [PATCH 23/87] adding documentation to some files with only one [description] tag --- src/actions/RotateAround.js | 3 ++- src/actions/Shuffle.js | 3 ++- src/boot/Game.js | 2 +- src/dom/AddToDOM.js | 2 +- src/gameobjects/GameObject.js | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/actions/RotateAround.js b/src/actions/RotateAround.js index 91702d55e..a8b0a7b44 100644 --- a/src/actions/RotateAround.js +++ b/src/actions/RotateAround.js @@ -8,10 +8,11 @@ var RotateAroundDistance = require('../math/RotateAroundDistance'); var DistanceBetween = require('../math/distance/DistanceBetween'); /** - * [description] + * Rotates each item around the given point by the given angle. * * @function Phaser.Actions.RotateAround * @since 3.0.0 + * @see Phaser.Math.RotateAroundDistance * * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] * diff --git a/src/actions/Shuffle.js b/src/actions/Shuffle.js index 61f722329..d27410319 100644 --- a/src/actions/Shuffle.js +++ b/src/actions/Shuffle.js @@ -7,10 +7,11 @@ var ArrayShuffle = require('../utils/array/Shuffle'); /** - * [description] + * Shuffles the array in place. The shuffled array is both modified and returned. * * @function Phaser.Actions.Shuffle * @since 3.0.0 + * @see Phaser.Utils.Array.Shuffle * * @generic {Phaser.GameObjects.GameObject[]} G - [items,$return] * diff --git a/src/boot/Game.js b/src/boot/Game.js index 014f55727..cadf8964b 100644 --- a/src/boot/Game.js +++ b/src/boot/Game.js @@ -154,7 +154,7 @@ var Game = new Class({ this.cache = new CacheManager(this); /** - * [description] + * An instance of the Data Manager * * @name Phaser.Game#registry * @type {Phaser.Data.DataManager} diff --git a/src/dom/AddToDOM.js b/src/dom/AddToDOM.js index 41216c835..de6aec433 100644 --- a/src/dom/AddToDOM.js +++ b/src/dom/AddToDOM.js @@ -13,7 +13,7 @@ * * @param {HTMLElement} element - The element to be added to the DOM. Usually a Canvas object. * @param {(string|HTMLElement)} [parent] - The parent in which to add the element. Can be a string which is passed to `getElementById` or an actual DOM object. - * @param {boolean} [overflowHidden=true] - [description] + * @param {boolean} [overflowHidden=true] - Whether or not to hide overflowing content inside the parent. * * @return {HTMLElement} The element that was added to the DOM. */ diff --git a/src/gameobjects/GameObject.js b/src/gameobjects/GameObject.js index 0f31888cb..22eb2804a 100644 --- a/src/gameobjects/GameObject.js +++ b/src/gameobjects/GameObject.js @@ -195,10 +195,11 @@ var GameObject = new Class({ }, /** - * [description] + * Adds a DataManager to this object. * * @method Phaser.GameObjects.GameObject#setDataEnabled * @since 3.0.0 + * @see Phaser.Data.DataManager * * @return {Phaser.GameObjects.GameObject} This GameObject. */ From abfd2440a0e8ac603617c6148cc6f2de0e1f59c3 Mon Sep 17 00:00:00 2001 From: Matt Chiasson Date: Sun, 8 Apr 2018 21:01:48 -0400 Subject: [PATCH 24/87] fixed travis failure --- src/display/canvas/CanvasPool.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/display/canvas/CanvasPool.js b/src/display/canvas/CanvasPool.js index 8c7ac15e8..2255e92f1 100644 --- a/src/display/canvas/CanvasPool.js +++ b/src/display/canvas/CanvasPool.js @@ -126,13 +126,14 @@ var CanvasPool = function () { if (canvasType === undefined) { canvasType = CONST.CANVAS; } - for (var i = 0, len = pool.length; i < len; i++) { + for (var i = 0, len = pool.length; i < len; i++) + { var container = pool[i]; if (!container.parent && container.type === canvasType) { return container; } - }; + } return null; }; From 6ae000a5a075ed69add96e000b8847a04cd4a094 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 10:24:31 +0100 Subject: [PATCH 25/87] Updated change log --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c06cbeefe..64ba8cb9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ being passed to the simulation. The default value is 1 to remain consistent with * Line.getPointA and Line.getPointB incorrectly set the values into the Vector2 (thanks @Tomas2h) * DynamicTilemapLayer now uses the ComputedSize component, which stops it breaking if you call `setDisplaySize` (thanks Babsobar) * StaticTilemapLayer now uses the ComputedSize component, which stops it breaking if you call `setDisplaySize` (thanks Babsobar) +* CanvasPool.first always returned `null`, and now returns the first available Canvas. Fix #3520 (thanks @mchiasson) +* When starting a new Scene with an optional `data` argument it wouldn't get passed through if the Scene was not yet available (i.e. the game had not fully booted). The data is now passed to the Scene `init` method and stored in the Scene Settings data property. Fix #3363 (thanks @pixelhijack) ### Updates From bf368ab70bfd33d16047f5e41282391933c38f9a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 12:56:28 +0100 Subject: [PATCH 26/87] ScenePlugin.restart allows you to restart the current Scene. It's the same result as calling `ScenePlugin.start` without any arguments, but is more clear. --- src/scene/ScenePlugin.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/scene/ScenePlugin.js b/src/scene/ScenePlugin.js index bb6628859..b534f0685 100644 --- a/src/scene/ScenePlugin.js +++ b/src/scene/ScenePlugin.js @@ -121,6 +121,34 @@ var ScenePlugin = new Class({ return this; }, + /** + * Restarts this Scene. + * + * @method Phaser.Scenes.ScenePlugin#restart + * @since 3.4.0 + * + * @param {object} [data] - The Scene data. + * + * @return {Phaser.Scenes.ScenePlugin} This ScenePlugin object. + */ + restart: function (data) + { + var key = this.key; + + if (this.settings.status !== CONST.RUNNING) + { + this.manager.queueOp('stop', key); + this.manager.queueOp('start', key, data); + } + else + { + this.manager.stop(key); + this.manager.start(key, data); + } + + return this; + }, + /** * Add the Scene into the Scene Manager and start it if 'autoStart' is true or the Scene config 'active' property is set. * From 66a9bec9bb8e2d27fbf7fae05c825b8c3bfa8021 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 12:57:03 +0100 Subject: [PATCH 27/87] Only set data if it's not undefined. --- src/scene/Systems.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/scene/Systems.js b/src/scene/Systems.js index 047b5f6ef..32fce514f 100644 --- a/src/scene/Systems.js +++ b/src/scene/Systems.js @@ -491,6 +491,7 @@ var Systems = new Class({ /** * Start this Scene running and rendering. + * Called automatically by the SceneManager. * * @method Phaser.Scenes.Systems#start * @since 3.0.0 @@ -499,9 +500,12 @@ var Systems = new Class({ */ start: function (data) { - this.settings.status = CONST.START; + if (data) + { + this.settings.data = data; + } - this.settings.data = data; + this.settings.status = CONST.START; this.settings.active = true; this.settings.visible = true; From ca2097f4e20d578d5f5fe2605c6b77a6cc70e3a5 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 12:57:47 +0100 Subject: [PATCH 28/87] Recoded how the boot data and processing works to allow for more flexibility when setting-up scenes. Updates #3470 --- src/scene/SceneManager.js | 149 ++++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 46 deletions(-) diff --git a/src/scene/SceneManager.js b/src/scene/SceneManager.js index eec8be0a2..73519c60c 100644 --- a/src/scene/SceneManager.js +++ b/src/scene/SceneManager.js @@ -91,14 +91,36 @@ var SceneManager = new Class({ this._queue = []; /** - * The number of Scenes to process. + * Boot time data to merge. * - * @name Phaser.Scenes.SceneManager#_processing - * @type {integer} + * @name Phaser.Scenes.SceneManager#_data + * @type {object} * @private + * @since 3.4.0 + */ + this._data = {}; + + /** + * Is the Scene Manager actively processing the Scenes list? + * + * @name Phaser.Scenes.SceneManager#isProcessing + * @type {boolean} + * @default false + * @readOnly * @since 3.0.0 */ - this._processing = 0; + this.isProcessing = false; + + /** + * Has the Scene Manager properly started? + * + * @name Phaser.Scenes.SceneManager#isBooted + * @type {boolean} + * @default false + * @readOnly + * @since 3.4.0 + */ + this.isBooted = false; if (sceneConfig) { @@ -132,6 +154,11 @@ var SceneManager = new Class({ */ bootQueue: function () { + if (this.isBooted) + { + return; + } + var i; var entry; var key; @@ -166,6 +193,17 @@ var SceneManager = new Class({ this.scenes.push(newScene); + // Any data to inject? + if (this._data[key]) + { + newScene.sys.settings.data = this._data[key].data; + + if (this._data[key].autoStart) + { + entry.autoStart = true; + } + } + if (entry.autoStart || newScene.sys.settings.active) { this._start.push(key); @@ -175,12 +213,16 @@ var SceneManager = new Class({ // Clear the pending lists this._pending.length = 0; + this._data = {}; + + this.isBooted = true; + // _start might have been populated by the above for (i = 0; i < this._start.length; i++) { entry = this._start[i]; - this.start(entry, entry.scene.data); + this.start(entry); } this._start.length = 0; @@ -211,7 +253,7 @@ var SceneManager = new Class({ { entry = this._pending[i]; - this.add(entry.key, entry.scene, entry.autoStart); + this.add(entry.key, entry.scene, entry.autoStart, entry.data); } // _start might have been populated by this.add @@ -219,7 +261,7 @@ var SceneManager = new Class({ { entry = this._start[i]; - this.start(entry, entry.scene.data); + this.start(entry); } // Clear the pending lists @@ -259,21 +301,23 @@ var SceneManager = new Class({ * @param {string} key - A unique key used to reference the Scene, i.e. `MainMenu` or `Level1`. * @param {(Phaser.Scene|SettingsConfig|function)} sceneConfig - The config for the Scene * @param {boolean} [autoStart=false] - If `true` the Scene will be started immediately after being added. + * @param {object} [data] - Optional data object. This will be set as Scene.settings.data and passed to `Scene.init`. * - * @return {?Phaser.Scene} The added Scene, if it was added immediately. + * @return {?Phaser.Scene} The added Scene, if it was added immediately, otherwise `null`. */ - add: function (key, sceneConfig, autoStart) + add: function (key, sceneConfig, autoStart, data) { if (autoStart === undefined) { autoStart = false; } + if (data === undefined) { data = {}; } - // if not booted, then put scene into a holding pattern - if (this._processing === 1 || !this.game.isBooted) + // If processing or not booted then put scene into a holding pattern + if (this.isProcessing || !this.isBooted) { this._pending.push({ key: key, scene: sceneConfig, autoStart: autoStart, - data: {} + data: data }); return null; @@ -298,6 +342,9 @@ var SceneManager = new Class({ newScene = this.createSceneFromFunction(key, sceneConfig); } + // Any data to inject? + newScene.sys.settings.data = data; + // Replace key in case the scene changed it key = newScene.sys.settings.key; @@ -307,13 +354,13 @@ var SceneManager = new Class({ if (autoStart || newScene.sys.settings.active) { - if (this.game.isBooted) + if (this._pending.length) { - this.start(key, newScene.sys.settings.data); + this._start.push(key); } else { - this._start.push(key); + this.start(key); } } @@ -338,7 +385,7 @@ var SceneManager = new Class({ */ remove: function (key) { - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'remove', keyA: key, keyB: null }); } @@ -468,7 +515,7 @@ var SceneManager = new Class({ { this.processQueue(); - this._processing = 1; + this.isProcessing = true; // Loop through the active scenes in reverse order for (var i = this.scenes.length - 1; i >= 0; i--) @@ -523,7 +570,7 @@ var SceneManager = new Class({ } } - this._processing = 0; + this.isProcessing = false; }, /** @@ -693,13 +740,18 @@ var SceneManager = new Class({ { for (var propertyKey in sceneConfig.extend) { - newScene[propertyKey] = sceneConfig.extend[propertyKey]; - } - } + var value = sceneConfig.extend[propertyKey]; - if (sceneConfig.hasOwnProperty('data')) - { - newScene.data = sceneConfig.data; + if (propertyKey === 'data' && newScene.hasOwnProperty('data') && typeof value === 'object') + { + // Populate the DataManager + newScene.data.merge(value); + } + else if (propertyKey !== 'sys') + { + newScene[propertyKey] = value; + } + } } return newScene; @@ -940,27 +992,19 @@ var SceneManager = new Class({ * @since 3.0.0 * * @param {string} key - The Scene to start. - * @param {object} [data] - The Scene data. + * @param {object} [data] - Optional data object to pass to Scene.Settings and Scene.init. * * @return {Phaser.Scenes.SceneManager} This SceneManager. */ start: function (key, data) { - if (data === undefined) { data = {}; } - - // If the Game is not booted, then put the Scene into a holding pattern - if (!this.game.isBooted) + // If the Scene Manager is not running, then put the Scene into a holding pattern + if (!this.isBooted) { - for (var i = 0; i < this._pending.length; i++) - { - var entry = this._pending[i]; - - if (entry.key === key) - { - entry.autoStart = true; - entry.scene.data = data; - } - } + this._data[key] = { + autoStart: true, + data: data + }; return this; } @@ -1102,7 +1146,7 @@ var SceneManager = new Class({ */ bringToTop: function (key) { - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'bringToTop', keyA: key, keyB: null }); } @@ -1136,7 +1180,7 @@ var SceneManager = new Class({ */ sendToBack: function (key) { - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'sendToBack', keyA: key, keyB: null }); } @@ -1168,7 +1212,7 @@ var SceneManager = new Class({ */ moveDown: function (key) { - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'moveDown', keyA: key, keyB: null }); } @@ -1202,7 +1246,7 @@ var SceneManager = new Class({ */ moveUp: function (key) { - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'moveUp', keyA: key, keyB: null }); } @@ -1244,7 +1288,7 @@ var SceneManager = new Class({ return this; } - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'moveAbove', keyA: keyA, keyB: keyB }); } @@ -1288,7 +1332,7 @@ var SceneManager = new Class({ return this; } - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'moveBelow', keyA: keyA, keyB: keyB }); } @@ -1312,6 +1356,19 @@ var SceneManager = new Class({ return this; }, + /** + * Queue a Scene operation for the next update. + * + * @method Phaser.Scenes.SceneManager#queueOp + * @private + * @since 3.0.0 + * + * @param {string} op - The operation to perform. + * @param {(string|Phaser.Scene)} keyA - Scene A. + * @param {(string|Phaser.Scene)} [keyB] - Scene B. + * + * @return {Phaser.Scenes.SceneManager} This SceneManager. + */ queueOp: function (op, keyA, keyB) { this._queue.push({ op: op, keyA: keyA, keyB: keyB }); @@ -1337,7 +1394,7 @@ var SceneManager = new Class({ return this; } - if (this._processing) + if (this.isProcessing) { this._queue.push({ op: 'swapPosition', keyA: keyA, keyB: keyB }); } From 7a02cac7390da11656d789d69b35310c2c30c21b Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 12:57:55 +0100 Subject: [PATCH 29/87] Updated change log --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3199aea39..84d45d276 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ being passed to the simulation. The default value is 1 to remain consistent with * Graphics.slice allows you to easily draw a Pacman, or slice of pie shape to a Graphics object. * List.addCallback is a new optional callback that is invoked every time a new child is added to the List. You can use this to have a callback fire when children are added to the Display List. * List.removeCallback is a new optional callback that is invoked every time a new child is removed from the List. You can use this to have a callback fire when children are removed from the Display List. +* ScenePlugin.restart allows you to restart the current Scene. It's the same result as calling `ScenePlugin.start` without any arguments, but is more clear. ### Bug Fixes @@ -45,7 +46,7 @@ being passed to the simulation. The default value is 1 to remain consistent with * DynamicTilemapLayer now uses the ComputedSize component, which stops it breaking if you call `setDisplaySize` (thanks Babsobar) * StaticTilemapLayer now uses the ComputedSize component, which stops it breaking if you call `setDisplaySize` (thanks Babsobar) * CanvasPool.first always returned `null`, and now returns the first available Canvas. Fix #3520 (thanks @mchiasson) -* When starting a new Scene with an optional `data` argument it wouldn't get passed through if the Scene was not yet available (i.e. the game had not fully booted). The data is now passed to the Scene `init` method and stored in the Scene Settings data property. Fix #3363 (thanks @pixelhijack) +* When starting a new Scene with an optional `data` argument it wouldn't get passed through if the Scene was not yet available (i.e. the game had not fully booted). The data is now passed to the Scene `init` and `create` methods and stored in the Scene Settings `data` property. Fix #3363 (thanks @pixelhijack) * Tween.Restart handles removed tweens properly and readds them back into the active queue for the TweenManager (thanks @wtravO) ### Updates @@ -68,6 +69,10 @@ being passed to the simulation. The default value is 1 to remain consistent with * List.removeAt has a new optional argument `skipCallback`. * List.removeBetween has a new optional argument `skipCallback`. * List.removeAll has a new optional argument `skipCallback`. +* When using the `extend` property of a Scene config object it will now block overwriting the Scene `sys` property. +* When using the `extend` property of a Scene config object, if you define a property called `data` that has an object set, it will populate the Scenes Data Manager with those values. +* SceneManager._processing has been renamed to `isProcessing` which is now a boolean, not an integer. It's also now public and read-only. +* SceneManager.isBooted is a new boolean read-only property that lets you know if the Scene Manager has performed its initial boot sequence. ### Animation System Updates From 833355a9a48518cca22ada7311fe2f854f2e8299 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 13:25:20 +0100 Subject: [PATCH 30/87] Tween.resume will now call `Tween.play` on a tween that was paused due to its config object, not as a result of having its paused method called. Fix #3452 --- CHANGELOG.md | 3 ++- src/tweens/tween/Tween.js | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84d45d276..81fff8bb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,8 @@ being passed to the simulation. The default value is 1 to remain consistent with * StaticTilemapLayer now uses the ComputedSize component, which stops it breaking if you call `setDisplaySize` (thanks Babsobar) * CanvasPool.first always returned `null`, and now returns the first available Canvas. Fix #3520 (thanks @mchiasson) * When starting a new Scene with an optional `data` argument it wouldn't get passed through if the Scene was not yet available (i.e. the game had not fully booted). The data is now passed to the Scene `init` and `create` methods and stored in the Scene Settings `data` property. Fix #3363 (thanks @pixelhijack) -* Tween.Restart handles removed tweens properly and readds them back into the active queue for the TweenManager (thanks @wtravO) +* Tween.restart handles removed tweens properly and reads them back into the active queue for the TweenManager (thanks @wtravO) +* Tween.resume will now call `Tween.play` on a tween that was paused due to its config object, not as a result of having its paused method called. Fix #3452 (thanks @jazen) ### Updates diff --git a/src/tweens/tween/Tween.js b/src/tweens/tween/Tween.js index ae9abc8b8..bb83891d1 100644 --- a/src/tweens/tween/Tween.js +++ b/src/tweens/tween/Tween.js @@ -483,7 +483,8 @@ var Tween = new Class({ }, /** - * [description] + * Called by TweenManager.preUpdate as part of its loop to check pending and active tweens. + * Should not be called directly. * * @method Phaser.Tweens.Tween#init * @since 3.0.0 @@ -519,6 +520,7 @@ var Tween = new Class({ if (this.paused && !this.parentIsTimeline) { this.state = TWEEN_CONST.PENDING_ADD; + this._pausedState = TWEEN_CONST.INIT; return false; } @@ -734,6 +736,10 @@ var Tween = new Class({ this.state = this._pausedState; } + else + { + this.play(); + } return this; }, From c7037628e2d45afab049b2f4d497fb78a298d089 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 13:48:11 +0100 Subject: [PATCH 31/87] Fixed lint error --- src/display/canvas/CanvasPool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/display/canvas/CanvasPool.js b/src/display/canvas/CanvasPool.js index 2255e92f1..3a5900369 100644 --- a/src/display/canvas/CanvasPool.js +++ b/src/display/canvas/CanvasPool.js @@ -126,9 +126,10 @@ var CanvasPool = function () { if (canvasType === undefined) { canvasType = CONST.CANVAS; } - for (var i = 0, len = pool.length; i < len; i++) + for (var i = 0; i < pool.length; i++) { var container = pool[i]; + if (!container.parent && container.type === canvasType) { return container; From 5f9972c79116ce36d29bb7852b7dc33549205e7e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 13:55:41 +0100 Subject: [PATCH 32/87] LoaderPlugin.isReady referenced a constant that no longer exists. Fix #3503 --- CHANGELOG.md | 1 + src/loader/LoaderPlugin.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81fff8bb2..6414ef2a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ being passed to the simulation. The default value is 1 to remain consistent with * When starting a new Scene with an optional `data` argument it wouldn't get passed through if the Scene was not yet available (i.e. the game had not fully booted). The data is now passed to the Scene `init` and `create` methods and stored in the Scene Settings `data` property. Fix #3363 (thanks @pixelhijack) * Tween.restart handles removed tweens properly and reads them back into the active queue for the TweenManager (thanks @wtravO) * Tween.resume will now call `Tween.play` on a tween that was paused due to its config object, not as a result of having its paused method called. Fix #3452 (thanks @jazen) +* LoaderPlugin.isReady referenced a constant that no longer exists. Fix #3503 (thanks @Twilrom) ### Updates diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 7c9b545e9..63f8bd1b5 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -369,7 +369,7 @@ var LoaderPlugin = new Class({ */ isReady: function () { - return (this.state === CONST.LOADER_IDLE || this.state === CONST.LOADER_COMPLETE || this.state === CONST.LOADER_FAILED); + return (this.state === CONST.LOADER_IDLE || this.state === CONST.LOADER_COMPLETE); }, /** From 5c89c9900c74e33ec4846420071cef476cdc6f43 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 14:09:04 +0100 Subject: [PATCH 33/87] BaseSound.config now contains all defaults. Fix #3525 --- src/sound/BaseSound.js | 11 ++++++++--- src/sound/webaudio/WebAudioSound.js | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sound/BaseSound.js b/src/sound/BaseSound.js index c615ac31c..4959d36cc 100644 --- a/src/sound/BaseSound.js +++ b/src/sound/BaseSound.js @@ -120,10 +120,15 @@ var BaseSound = new Class({ * @since 3.0.0 */ this.config = { - /** - * Initializing delay config setting - */ + + mute: false, + volume: 1, + rate: 1, + detune: 0, + seek: 0, + loop: false, delay: 0 + }; /** diff --git a/src/sound/webaudio/WebAudioSound.js b/src/sound/webaudio/WebAudioSound.js index ec5e8b214..00da6b490 100644 --- a/src/sound/webaudio/WebAudioSound.js +++ b/src/sound/webaudio/WebAudioSound.js @@ -541,7 +541,7 @@ var WebAudioSound = new Class({ var now = this.manager.context.currentTime; - if (this.source) + if (this.source && typeof this.totalRate === 'number') { this.source.playbackRate.setValueAtTime(this.totalRate, now); } From c2236e47eb3abfceeb157108ca8cebb4de0ea0c6 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 14:17:17 +0100 Subject: [PATCH 34/87] Added webpack section to README. --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 98ae73dbe..bb5bfe93c 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,12 @@ The documentation for Phaser 3 is an on-going project. Please help us by searchi They are automatically generated from the jsdoc comments in the Phaser source code. If you wish to help refine them then you must edit the Phaser jsdoc blocks directly. You can find more details, including the source to the conversion tool we wrote in the Docs repo. +### Webpack + +We use Webpack to build Phaser and we take advantage of several features specific to Webpack to do this, including `raw-loader` to handle our shader files and build-time flags for renderer swapping. + +If you wish to use Webpack with Phaser then please use our [Phaser 3 Project Template](https://github.com/photonstorm/phaser3-project-template) as it's already set-up to handle the build conditions Phaser needs. + ### License Phaser is released under the [MIT License](https://opensource.org/licenses/MIT). From d15d9107785e35df17cce1c0ffc6cef8ec6e9c68 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 16:00:33 +0100 Subject: [PATCH 35/87] Removed camera.cullTilemap because nothing uses it any more --- src/cameras/2d/Camera.js | 71 ++-------------------------------------- 1 file changed, 2 insertions(+), 69 deletions(-) diff --git a/src/cameras/2d/Camera.js b/src/cameras/2d/Camera.js index bc3b118cb..30779ddcb 100644 --- a/src/cameras/2d/Camera.js +++ b/src/cameras/2d/Camera.js @@ -550,7 +550,7 @@ var Camera = new Class({ { var object = renderableObjects[index]; - if (!object.hasOwnProperty('width')) + if (!object.hasOwnProperty('width') || object.parentContainer) { culledObjects.push(object); continue; @@ -628,7 +628,7 @@ var Camera = new Class({ { var object = interactiveObjects[index].gameObject; - if (!object.hasOwnProperty('width')) + if (!object.hasOwnProperty('width') || object.parentContainer) { culledObjects.push(interactiveObjects[index]); continue; @@ -655,73 +655,6 @@ var Camera = new Class({ return culledObjects; }, - /** - * [description] - * - * @method Phaser.Cameras.Scene2D.Camera#cullTilemap - * @since 3.0.0 - * - * @param {Phaser.Tilemaps.Tilemap} tilemap - [description] - * - * @return {Phaser.GameObjects.GameObject[]} [description] - */ - cullTilemap: function (tilemap) - { - var cameraMatrix = this.matrix.matrix; - - var mva = cameraMatrix[0]; - var mvb = cameraMatrix[1]; - var mvc = cameraMatrix[2]; - var mvd = cameraMatrix[3]; - - /* First Invert Matrix */ - var determinant = (mva * mvd) - (mvb * mvc); - - var tiles = tilemap.tiles; - - if (!determinant) - { - return tiles; - } - - var mve = cameraMatrix[4]; - var mvf = cameraMatrix[5]; - var scrollX = this.scrollX; - var scrollY = this.scrollY; - var cameraW = this.width; - var cameraH = this.height; - var culledObjects = this.culledObjects; - var length = tiles.length; - var tileW = tilemap.tileWidth; - var tileH = tilemap.tileHeight; - var cullW = cameraW + tileW; - var cullH = cameraH + tileH; - var scrollFactorX = tilemap.scrollFactorX; - var scrollFactorY = tilemap.scrollFactorY; - - determinant = 1 / determinant; - - culledObjects.length = 0; - - for (var index = 0; index < length; ++index) - { - var tile = tiles[index]; - var tileX = (tile.x - (scrollX * scrollFactorX)); - var tileY = (tile.y - (scrollY * scrollFactorY)); - var tx = (tileX * mva + tileY * mvc + mve); - var ty = (tileX * mvb + tileY * mvd + mvf); - var tw = ((tileX + tileW) * mva + (tileY + tileH) * mvc + mve); - var th = ((tileX + tileW) * mvb + (tileY + tileH) * mvd + mvf); - - if (tx > -tileW && ty > -tileH && tw < cullW && th < cullH) - { - culledObjects.push(tile); - } - } - - return culledObjects; - }, - /** * Fades the Camera in from the given color over the duration specified. * From 381963c01470ad2746444201141a617454838857 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 16:01:16 +0100 Subject: [PATCH 36/87] Removed localToWorld (no longer needed) --- src/gameobjects/container/Container.js | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index d7bbd71bf..cc3b301e6 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -209,32 +209,6 @@ var Container = new Class({ return output; }, - /** - * - * - * @method Phaser.GameObjects.Container#localToWorld - * @since 3.4.0 - * - * @param {Phaser.GameObjects.GameObject} child - The child of this Container. - * @param {Phaser.Cameras.Scene2D.Camera} [camera] - The camera to transform against. - * @param {(object|Phaser.Geom.Point|Phaser.Math.Vector2)} [output] - A destination object to store the transformed point in. If none given a Vector2 will be created and returned. - * - * @return {(object|Phaser.Geom.Point|Phaser.Math.Vector2)} The transformed point. - */ - localToWorld: function (child, camera, output) - { - if (camera === undefined) { camera = this.scene.sys.cameras.main; } - if (output === undefined) { output = new Vector2(); } - - if (this.exists(child)) - { - // Do matrix magic here - // See: Camera.getWorldPoint and InputManager.hitTest - } - - return output; - }, - /** * Destroys this Container removing it and all children from the Display List and * severing all ties to parent resources. From 9d39bd7b459f3c80d4d4f09b18bd8da7c1aa8221 Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Mon, 9 Apr 2018 12:32:08 -0300 Subject: [PATCH 37/87] Container alpha added --- src/gameobjects/container/Container.js | 2 ++ src/gameobjects/container/ContainerCanvasRenderer.js | 8 +++++++- src/gameobjects/container/ContainerWebGLRenderer.js | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index d7bbd71bf..0fb69c2e2 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -36,6 +36,7 @@ var Container = new Class({ Extends: GameObject, Mixins: [ + Components.Alpha, Components.BlendMode, Components.Depth, Components.Transform, @@ -128,6 +129,7 @@ var Container = new Class({ this._displayList = scene.sys.displayList; this.setPosition(x, y); + this.clearAlpha(); if (Array.isArray(children)) { diff --git a/src/gameobjects/container/ContainerCanvasRenderer.js b/src/gameobjects/container/ContainerCanvasRenderer.js index 5982d0628..9e98f45ed 100644 --- a/src/gameobjects/container/ContainerCanvasRenderer.js +++ b/src/gameobjects/container/ContainerCanvasRenderer.js @@ -45,9 +45,15 @@ var ContainerCanvasRenderer = function (renderer, container, interpolationPercen transformMatrix.scale(container.scaleX, container.scaleY); } + var alpha = container._alpha; + for (var index = 0; index < children.length; ++index) { - children[index].renderCanvas(renderer, children[index], interpolationPercentage, camera, transformMatrix); + var child = children[index]; + var childAlpha = child._alpha; + child.setAlpha(childAlpha * alpha); + child.renderCanvas(renderer, child, interpolationPercentage, camera, transformMatrix); + child.setAlpha(childAlpha); } }; diff --git a/src/gameobjects/container/ContainerWebGLRenderer.js b/src/gameobjects/container/ContainerWebGLRenderer.js index 576e320f1..c00af31f5 100644 --- a/src/gameobjects/container/ContainerWebGLRenderer.js +++ b/src/gameobjects/container/ContainerWebGLRenderer.js @@ -45,9 +45,15 @@ var ContainerWebGLRenderer = function (renderer, container, interpolationPercent transformMatrix.scale(container.scaleX, container.scaleY); } + var alpha = container._alpha; + for (var index = 0; index < children.length; ++index) { - children[index].renderWebGL(renderer, children[index], interpolationPercentage, camera, transformMatrix); + var child = children[index]; + var childAlpha = child._alpha; + child.setAlpha(childAlpha * alpha); + child.renderWebGL(renderer, child, interpolationPercentage, camera, transformMatrix); + child.setAlpha(childAlpha); } }; From 5c69bd054ea627cfe851e1d6a42a9b1fe531665b Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 16:42:33 +0100 Subject: [PATCH 38/87] Added property getters --- src/gameobjects/components/TransformMatrix.js | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/gameobjects/components/TransformMatrix.js b/src/gameobjects/components/TransformMatrix.js index 9d17344e0..12fcf650a 100644 --- a/src/gameobjects/components/TransformMatrix.js +++ b/src/gameobjects/components/TransformMatrix.js @@ -60,6 +60,117 @@ var TransformMatrix = new Class({ }; }, + a: { + + get: function () + { + return this.matrix[0]; + }, + + set: function (value) + { + this.matrix[0] = value; + } + + }, + + b: { + + get: function () + { + return this.matrix[1]; + }, + + set: function (value) + { + this.matrix[1] = value; + } + + }, + + c: { + + get: function () + { + return this.matrix[2]; + }, + + set: function (value) + { + this.matrix[2] = value; + } + + }, + + d: { + + get: function () + { + return this.matrix[3]; + }, + + set: function (value) + { + this.matrix[3] = value; + } + + }, + + tx: { + + get: function () + { + return this.matrix[4]; + }, + + set: function (value) + { + this.matrix[4] = value; + } + + }, + + ty: { + + get: function () + { + return this.matrix[5]; + }, + + set: function (value) + { + this.matrix[5] = value; + } + + }, + + rotation: { + + get: function () + { + return Math.acos(this.a / this.scaleX) * (Math.atan(-this.c / this.a) < 0 ? -1 : 1); + } + + }, + + scaleX: { + + get: function () + { + return Math.sqrt((this.a * this.a) + (this.c * this.c)); + } + + }, + + scaleY: { + + get: function () + { + return Math.sqrt((this.b * this.b) + (this.d * this.d)); + } + + }, + /** * [description] * From 04990d687049e0491c3874fc90fe4153560e78a0 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 16:42:51 +0100 Subject: [PATCH 39/87] Input checks for container parents --- src/input/InputManager.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/input/InputManager.js b/src/input/InputManager.js index ca81b75b4..92c67b020 100644 --- a/src/input/InputManager.js +++ b/src/input/InputManager.js @@ -12,6 +12,7 @@ var Mouse = require('./mouse/MouseManager'); var Pointer = require('./Pointer'); var Rectangle = require('../geom/rectangle/Rectangle'); var Touch = require('./touch/TouchManager'); +var TransformMatrix = require('../gameobjects/components/TransformMatrix'); var TransformXY = require('../math/TransformXY'); /** @@ -195,6 +196,16 @@ var InputManager = new Class({ */ this._tempHitTest = []; + /** + * [description] + * + * @name Phaser.Input.InputManager#_tempMatrix + * @type {Phaser.GameObjects.Components.TransformMatrix} + * @private + * @since 3.4.0 + */ + this._tempMatrix = new TransformMatrix(); + game.events.once('boot', this.boot, this); }, @@ -383,6 +394,8 @@ var InputManager = new Class({ var res = this.game.config.resolution; + var matrix = this._tempMatrix; + for (var i = 0; i < culledGameObjects.length; i++) { var gameObject = culledGameObjects[i]; @@ -395,7 +408,16 @@ var InputManager = new Class({ var px = tempPoint.x * res + (camera.scrollX * gameObject.scrollFactorX) - camera.scrollX; var py = tempPoint.y * res + (camera.scrollY * gameObject.scrollFactorY) - camera.scrollY; - TransformXY(px, py, gameObject.x, gameObject.y, gameObject.rotation, gameObject.scaleX, gameObject.scaleY, point); + if (gameObject.parentContainer) + { + gameObject.getWorldTransformMatrix(matrix); + + TransformXY(px, py, matrix.tx, matrix.ty, matrix.rotation, matrix.scaleX, matrix.scaleY, point); + } + else + { + TransformXY(px, py, gameObject.x, gameObject.y, gameObject.rotation, gameObject.scaleX, gameObject.scaleY, point); + } if (this.pointWithinHitArea(gameObject, point.x, point.y)) { From ca2a575726de470104d76e7222e19b271e2507aa Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 16:46:03 +0100 Subject: [PATCH 40/87] Added jsdocs --- src/gameobjects/components/TransformMatrix.js | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/gameobjects/components/TransformMatrix.js b/src/gameobjects/components/TransformMatrix.js index 12fcf650a..302540e63 100644 --- a/src/gameobjects/components/TransformMatrix.js +++ b/src/gameobjects/components/TransformMatrix.js @@ -60,6 +60,13 @@ var TransformMatrix = new Class({ }; }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#a + * @type {number} + * @since 3.4.0 + */ a: { get: function () @@ -74,6 +81,13 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#b + * @type {number} + * @since 3.4.0 + */ b: { get: function () @@ -88,6 +102,13 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#c + * @type {number} + * @since 3.4.0 + */ c: { get: function () @@ -102,6 +123,13 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#d + * @type {number} + * @since 3.4.0 + */ d: { get: function () @@ -116,6 +144,13 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#tx + * @type {number} + * @since 3.4.0 + */ tx: { get: function () @@ -130,6 +165,13 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#ty + * @type {number} + * @since 3.4.0 + */ ty: { get: function () @@ -144,6 +186,14 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#rotation + * @type {number} + * @readOnly + * @since 3.4.0 + */ rotation: { get: function () @@ -153,6 +203,14 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#scaleX + * @type {number} + * @readOnly + * @since 3.4.0 + */ scaleX: { get: function () @@ -162,6 +220,14 @@ var TransformMatrix = new Class({ }, + /** + * [description] + * + * @name Phaser.GameObjects.Components.TransformMatrix#scaleY + * @type {number} + * @readOnly + * @since 3.4.0 + */ scaleY: { get: function () From 3c5d3db267c3dc4bf0ba04475ed3d5436099fb5f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Mon, 9 Apr 2018 17:33:55 +0100 Subject: [PATCH 41/87] Testing exclusive setting --- CHANGELOG.md | 1 + src/gameobjects/container/Container.js | 69 +++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6414ef2a3..11a981c10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ being passed to the simulation. The default value is 1 to remain consistent with * When using the `extend` property of a Scene config object, if you define a property called `data` that has an object set, it will populate the Scenes Data Manager with those values. * SceneManager._processing has been renamed to `isProcessing` which is now a boolean, not an integer. It's also now public and read-only. * SceneManager.isBooted is a new boolean read-only property that lets you know if the Scene Manager has performed its initial boot sequence. +* TransformMatrix has the following new getter and setters: `a`, `b`, `c`, `d`, `tx` and `ty`. It also has the following new getters: `scaleX`, `scaleY` and `rotation`. ### Animation System Updates diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 7672ff432..3ba4c9451 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -70,6 +70,26 @@ var Container = new Class({ */ this.list = []; + /** + * Does this Container exclusively manage its children? + * + * The default is `true` which means a child added to this Container cannot + * belong in another Container, which includes the Scene display list. + * + * If you disable this then this Container will no longer exclusively manage its children. + * This allows you to create all kinds of interesting graphical effects, such as replicating + * Game Objects without reparenting them all over the Scene. + * However, doing so will prevent children from receiving any kind of input event or have + * their physics bodies work by default, as they're no longer a single entity on the + * display list, but are being replicated where-ever this Container is. + * + * @name Phaser.GameObjects.Container#exclusive + * @type {boolean} + * @default true + * @since 3.4.0 + */ + this.exclusive = true; + /** * The cursor position. * @@ -137,6 +157,35 @@ var Container = new Class({ } }, + /** + * Does this Container exclusively manage its children? + * + * The default is `true` which means a child added to this Container cannot + * belong in another Container, which includes the Scene display list. + * + * If you disable this then this Container will no longer exclusively manage its children. + * This allows you to create all kinds of interesting graphical effects, such as replicating + * Game Objects without reparenting them all over the Scene. + * However, doing so will prevent children from receiving any kind of input event or have + * their physics bodies work by default, as they're no longer a single entity on the + * display list, but are being replicated where-ever this Container is. + * + * @method Phaser.GameObjects.Container#setExclusive + * @since 3.4.0 + * + * @param {boolean} [value=true] - The exclusive state of this Container. + * + * @return {Phaser.GameObjects.Container} This Container. + */ + setExclusive: function (value) + { + if (value === undefined) { value = true; } + + this.exclusive = value; + + return this; + }, + /** * Internal add handler. * @@ -149,16 +198,19 @@ var Container = new Class({ */ addHandler: function (list, gameObject) { - this._displayList.remove(gameObject); - gameObject.on('destroy', this.remove, this); - if (gameObject.parentContainer) + if (this.exclusive) { - gameObject.parentContainer.remove(gameObject); - } + this._displayList.remove(gameObject); - gameObject.parentContainer = list; + if (gameObject.parentContainer) + { + gameObject.parentContainer.remove(gameObject); + } + + gameObject.parentContainer = list; + } }, /** @@ -175,7 +227,10 @@ var Container = new Class({ { gameObject.off('destroy', list.remove, this); - gameObject.parentContainer = null; + if (this.exclusive) + { + gameObject.parentContainer = null; + } }, /** From 593245742ea7532836ef4f48277539a3df715b2d Mon Sep 17 00:00:00 2001 From: Sebastian Warmbrunn Date: Mon, 9 Apr 2018 21:16:45 +0200 Subject: [PATCH 42/87] Add a config to merge keys into scene InjectionMap This way the defaults of the scene injection map are kept and the user is able to merge with those defaults. --- src/scene/Settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scene/Settings.js b/src/scene/Settings.js index 7974e95a1..6837f2813 100644 --- a/src/scene/Settings.js +++ b/src/scene/Settings.js @@ -6,6 +6,7 @@ var CONST = require('./const'); var GetValue = require('../utils/object/GetValue'); +var Merge = require('../utils/object/Merge'); var InjectionMap = require('./InjectionMap'); // TODO 22/03/2018 Fix "plugins" type @@ -87,7 +88,7 @@ var Settings = { // Scene Property Injection Map - map: GetValue(config, 'map', InjectionMap), + map: GetValue(config, 'map', Merge(InjectionMap, GetValue(config, 'mapAdd', {}))), // Physics From 968c0a3aecdd1e04ca3adfacec4bc6d985e68195 Mon Sep 17 00:00:00 2001 From: Sebastian Warmbrunn Date: Mon, 9 Apr 2018 21:32:19 +0200 Subject: [PATCH 43/87] Add typedef for new scene config option mapAdd Also add a description for mapAdd and map config options. --- src/scene/Settings.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scene/Settings.js b/src/scene/Settings.js index 6837f2813..885f755d1 100644 --- a/src/scene/Settings.js +++ b/src/scene/Settings.js @@ -19,7 +19,8 @@ var InjectionMap = require('./InjectionMap'); * @property {boolean} [visible=true] - [description] * @property {(false|LoaderFileObject[])} [files=false] - [description] * @property {?(InputJSONCameraObject|InputJSONCameraObject[])} [cameras=null] - [description] - * @property {Object.} [map] - [description] + * @property {Object.} [map] - Overwrites the default injection map for a scene. + * @property {Object.} [mapAdd] - Extends the injection map for a scene. * @property {object} [physics={}] - [description] * @property {object} [loader={}] - [description] * @property {(false|*)} [plugins=false] - [description] From 5d1405c4d9545622d65d6ad852fc9989501666af Mon Sep 17 00:00:00 2001 From: Sebastian Warmbrunn Date: Mon, 9 Apr 2018 21:40:00 +0200 Subject: [PATCH 44/87] Add change to CHANGELOG.md This adds a description of the new scene config option mapAdd to the changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a981c10..3c9beef15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New Features +* A new property was added to the scene config, `mapAdd` which is used to extend the default injection map of a scene instead of overwriting it. * A new property was added to Matter.World, `correction` which is used in the Engine.update call and allows you to adjust the time being passed to the simulation. The default value is 1 to remain consistent with previous releases. * Group.destroy has a new optional argument `destroyChildren` which will automatically call `destroy` on all children of a Group if set to true (the default is false, hence it doesn't change the public API). Fix #3246 (thanks @DouglasLapsley) From 330eac1ebcf0cc048e3e3c1042a3b359ada70e24 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 04:00:39 +0100 Subject: [PATCH 45/87] List is now internally using all of the new Utils.Array functions. --- CHANGELOG.md | 24 ++ src/structs/List.js | 398 ++++++---------------------- src/utils/array/Add.js | 111 ++++++++ src/utils/array/AddAt.js | 116 ++++++++ src/utils/array/BringToTop.js | 32 +++ src/utils/array/CountAllMatching.js | 36 +++ src/utils/array/Each.js | 40 +++ src/utils/array/EachInRange.js | 57 ++++ src/utils/array/GetAll.js | 51 ++++ src/utils/array/GetFirstElement.js | 39 +++ src/utils/array/GetRandomElement.js | 12 +- src/utils/array/MoveDown.js | 36 +++ src/utils/array/MoveTo.js | 41 +++ src/utils/array/MoveUp.js | 36 +++ src/utils/array/Remove.js | 85 ++++++ src/utils/array/RemoveAt.js | 45 ++++ src/utils/array/RemoveBetween.js | 61 +++++ src/utils/array/Replace.js | 33 +++ src/utils/array/SendToBack.js | 32 +++ src/utils/array/SetAll.js | 56 ++++ src/utils/array/SpliceOne.js | 5 +- src/utils/array/Swap.js | 42 +++ src/utils/array/index.js | 26 +- 23 files changed, 1088 insertions(+), 326 deletions(-) create mode 100644 src/utils/array/Add.js create mode 100644 src/utils/array/AddAt.js create mode 100644 src/utils/array/BringToTop.js create mode 100644 src/utils/array/CountAllMatching.js create mode 100644 src/utils/array/Each.js create mode 100644 src/utils/array/EachInRange.js create mode 100644 src/utils/array/GetAll.js create mode 100644 src/utils/array/GetFirstElement.js create mode 100644 src/utils/array/MoveDown.js create mode 100644 src/utils/array/MoveTo.js create mode 100644 src/utils/array/MoveUp.js create mode 100644 src/utils/array/Remove.js create mode 100644 src/utils/array/RemoveAt.js create mode 100644 src/utils/array/RemoveBetween.js create mode 100644 src/utils/array/Replace.js create mode 100644 src/utils/array/SendToBack.js create mode 100644 src/utils/array/SetAll.js create mode 100644 src/utils/array/Swap.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a981c10..9baba8eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,25 @@ being passed to the simulation. The default value is 1 to remain consistent with * List.addCallback is a new optional callback that is invoked every time a new child is added to the List. You can use this to have a callback fire when children are added to the Display List. * List.removeCallback is a new optional callback that is invoked every time a new child is removed from the List. You can use this to have a callback fire when children are removed from the Display List. * ScenePlugin.restart allows you to restart the current Scene. It's the same result as calling `ScenePlugin.start` without any arguments, but is more clear. +* Utils.Array.Add allows you to add one or more items safely to an array, with optional limits and callbacks. +* Utils.Array.AddAt allows you to add one or more items safely to an array at a specified position, with optional limits and callbacks. +* Utils.Array.BringToTop allows you to bring an array element to the top of the array. +* Utils.Array.CountAllMatching will scan an array and count all elements with properties matching the given value. +* Utils.Array.Each will pass each element of an array to a given callback, with optional arguments. +* Utils.Array.EachInRange will pass each element of an array in a given range to a callback, with optional arguments. +* Utils.Array.GetAll will return all elements from an array, with optional property and value comparisons. +* Utils.Array.GetFirst will return the first element in an array, with optional property and value comparisons. +* Utils.Array.GetRandomElement has been renamed to GetRandom and will return a random element from an array. +* Utils.Array.MoveDown will move the given array element down one position in the array. +* Utils.Array.MoveTo will move the given array element to the given position in the array. +* Utils.Array.MoveUp will move the given array element up one position in the array. +* Utils.Array.Remove will remove the given element or array of elements from the array, with an optional callback. +* Utils.Array.RemoveAt will remove the element from the given position in the array, with an optional callback. +* Utils.Array.RemoveBetween will remove the elements between the given range in the array, with an optional callback. +* Utils.Array.Replace will replace an existing element in an array with a new one. +* Utils.Array.SendToBack allows you to send an array element to the bottom of the array. +* Utils.Array.SetAll will set a property on all elements of an array to the given value, with optional range limits. +* Utils.Array.Swap will swap the position of two elements in an array. ### Bug Fixes @@ -76,6 +95,11 @@ being passed to the simulation. The default value is 1 to remain consistent with * SceneManager._processing has been renamed to `isProcessing` which is now a boolean, not an integer. It's also now public and read-only. * SceneManager.isBooted is a new boolean read-only property that lets you know if the Scene Manager has performed its initial boot sequence. * TransformMatrix has the following new getter and setters: `a`, `b`, `c`, `d`, `tx` and `ty`. It also has the following new getters: `scaleX`, `scaleY` and `rotation`. +* List.getByKey has been removed. Use `List.getFirst` instead which offers the exact same functionality. +* List.sortIndexHandler has been removed because it's no longer required. +* List.sort no longer takes an array as its argument, instead it only sorts the List contents by the defined property. +* List.addMultiple has been removed. Used `List.add` instead which offers the exact same functionality. +* List is now internally using all of the new Utils.Array functions. ### Animation System Updates diff --git a/src/structs/List.js b/src/structs/List.js index 0eff9600a..e174f7421 100644 --- a/src/structs/List.js +++ b/src/structs/List.js @@ -4,8 +4,10 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var ArrayUtils = require('../utils/array'); var Class = require('../utils/Class'); var NOOP = require('../utils/NOOP'); +var StableSort = require('../utils/array/StableSort'); /** * @callback EachListCallback @@ -82,6 +84,15 @@ var List = new Class({ * @since 3.4.0 */ this.removeCallback = NOOP; + + /** + * The property key to sort by. + * + * @name Phaser.Structs.List#_sortKey + * @type {string} + * @since 3.4.0 + */ + this._sortKey = ''; }, /** @@ -99,25 +110,13 @@ var List = new Class({ */ add: function (child, skipCallback) { - if (Array.isArray(child)) + if (skipCallback) { - return this.addMultiple(child, skipCallback); + return ArrayUtils.Add(this.list, child); } else { - // Is child already in this display list? - - if (this.getIndex(child) === -1) - { - this.list.push(child); - - if (!skipCallback) - { - this.addCallback(this, child); - } - } - - return child; + return ArrayUtils.Add(this.list, child, 0, this.addCallback, this); } }, @@ -137,53 +136,14 @@ var List = new Class({ */ addAt: function (child, index, skipCallback) { - if (index === undefined) { index = 0; } - - if (this.list.length === 0) + if (skipCallback) { - return this.add(child, skipCallback); + return ArrayUtils.AddAt(this.list, child, index); } - - if (index >= 0 && index <= this.list.length) + else { - if (this.getIndex(child) === -1) - { - this.list.splice(index, 0, child); - - if (!skipCallback) - { - this.addCallback(this, child); - } - } + return ArrayUtils.AddAt(this.list, child, index, 0, this.addCallback, this); } - - return child; - }, - - /** - * [description] - * - * @method Phaser.Structs.List#addMultiple - * @since 3.0.0 - * - * @genericUse {T[]} - [children,$return] - * - * @param {Array.<*>} children - [description] - * @param {boolean} [skipCallback=false] - Skip calling the List.addCallback if this child is added successfully. - * - * @return {Array.<*>} [description] - */ - addMultiple: function (children, skipCallback) - { - if (Array.isArray(children)) - { - for (var i = 0; i < children.length; i++) - { - this.add(children[i], skipCallback); - } - } - - return children; }, /** @@ -222,30 +182,37 @@ var List = new Class({ }, /** - * Given an array of objects, sort the array and return it, - * so that the objects are in index order with the lowest at the bottom. + * Sort the contents of this List so the items are in order based + * on the given property. For example, `sort('alpha')` would sort the List + * contents based on the value of their `alpha` property. * * @method Phaser.Structs.List#sort * @since 3.0.0 * * @genericUse {T[]} - [children,$return] * - * @param {Array.<*>} children - [description] + * @param {string} property - The property to lexically sort by. * * @return {Array.<*>} [description] */ - sort: function (children) + sort: function (property) { - if (children === undefined) { children = this.list; } + if (property) + { + this._sortKey = property; - return children.sort(this.sortIndexHandler.bind(this)); + StableSort.inplace(this.list, this.sortHandler); + } + + return this; }, /** * [description] * - * @method Phaser.Structs.List#sortIndexHandler - * @since 3.0.0 + * @method Phaser.Structs.List#sortHandler + * @private + * @since 3.4.0 * * @genericUse {T} - [childA,childB] * @@ -254,58 +221,15 @@ var List = new Class({ * * @return {integer} [description] */ - sortIndexHandler: function (childA, childB) + sortHandler: function (childA, childB) { - // The lower the index, the lower down the display list they are - var indexA = this.getIndex(childA); - var indexB = this.getIndex(childB); - - if (indexA < indexB) - { - return -1; - } - else if (indexA > indexB) - { - return 1; - } - - // Technically this shouldn't happen, but if the GO wasn't part of this display list then it'll - // have an index of -1, so in some cases it can - return 0; + return childA[this._sortKey] - childB[this._sortKey]; }, /** - * Gets the first item from the set based on the property strictly equaling the value given. - * Returns null if not found. - * - * @method Phaser.Structs.List#getByKey - * @since 3.0.0 - * - * @genericUse {T} - [value] - * @genericUse {T | null} - [$return] - * - * @param {string} property - The property to check against the value. - * @param {*} value - The value to check if the property strictly equals. - * - * @return {?*} The item that was found, or null if nothing matched. - */ - getByKey: function (property, value) - { - for (var i = 0; i < this.list.length; i++) - { - if (this.list[i][property] === value) - { - return this.list[i]; - } - } - - return null; - }, - - /** - * Searches the Group for the first instance of a child with the `name` + * Searches for the first instance of a child with its `name` * property matching the given argument. Should more than one child have - * the same name only the first instance is returned. + * the same name only the first is returned. * * @method Phaser.Structs.List#getByName * @since 3.0.0 @@ -318,7 +242,7 @@ var List = new Class({ */ getByName: function (name) { - return this.getByKey('name', name); + return ArrayUtils.GetFirst(this.list, 'name', name); }, /** @@ -336,17 +260,7 @@ var List = new Class({ */ getRandom: function (startIndex, length) { - if (startIndex === undefined) { startIndex = 0; } - if (length === undefined) { length = this.list.length; } - - if (length === 0 || length > this.list.length) - { - return null; - } - - var randomIndex = startIndex + Math.floor(Math.random() * length); - - return this.list[randomIndex]; + return ArrayUtils.GetRandom(this.list, startIndex, length); }, /** @@ -367,20 +281,7 @@ var List = new Class({ */ getFirst: function (property, value, startIndex, endIndex) { - if (startIndex === undefined) { startIndex = 0; } - if (endIndex === undefined) { endIndex = this.list.length; } - - for (var i = startIndex; i < endIndex; i++) - { - var child = this.list[i]; - - if (child[property] === value) - { - return child; - } - } - - return null; + return ArrayUtils.GetFirstElement(this.list, property, value, startIndex, endIndex); }, /** @@ -388,7 +289,11 @@ var List = new Class({ * * You can optionally specify a matching criteria using the `property` and `value` arguments. * - * For example: `getAll('visible', true)` would return only children that have their visible property set. + * For example: `getAll('parent')` would return only children that have a property called `parent`. + * + * You can also specify a value to compare the property to: + * + * `getAll('visible', true)` would return only children that have their visible property set to `true`. * * Optionally you can specify a start and end index. For example if this List had 100 children, * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only @@ -402,36 +307,14 @@ var List = new Class({ * * @param {string} [property] - An optional property to test against the value argument. * @param {*} [value] - If property is set then Child.property must strictly equal this value to be included in the results. - * @param {integer} [startIndex=0] - The first child index to start the search from. + * @param {integer} [startIndex] - The first child index to start the search from. * @param {integer} [endIndex] - The last child index to search up until. * * @return {Array.<*>} [description] */ getAll: function (property, value, startIndex, endIndex) { - if (startIndex === undefined) { startIndex = 0; } - if (endIndex === undefined) { endIndex = this.list.length; } - - var output = []; - - for (var i = startIndex; i < endIndex; i++) - { - var child = this.list[i]; - - if (property) - { - if (child[property] === value) - { - output.push(child); - } - } - else - { - output.push(child); - } - } - - return output; + return ArrayUtils.GetAll(this.list, property, value, startIndex, endIndex); }, /** @@ -449,19 +332,7 @@ var List = new Class({ */ count: function (property, value) { - var total = 0; - - for (var i = 0; i < this.list.length; i++) - { - var child = this.list[i]; - - if (child[property] === value) - { - total++; - } - } - - return total; + return ArrayUtils.CountAllMatching(this.list, property, value); }, /** @@ -477,21 +348,7 @@ var List = new Class({ */ swap: function (child1, child2) { - if (child1 === child2) - { - return; - } - - var index1 = this.getIndex(child1); - var index2 = this.getIndex(child2); - - if (index1 < 0 || index2 < 0) - { - throw new Error('List.swap: Supplied objects must be children of the same list'); - } - - this.list[index1] = child2; - this.list[index2] = child1; + ArrayUtils.Swap(this.list, child1, child2); }, /** @@ -509,20 +366,7 @@ var List = new Class({ */ moveTo: function (child, index) { - var currentIndex = this.getIndex(child); - - if (currentIndex === -1 || index < 0 || index >= this.list.length) - { - throw new Error('List.moveTo: The supplied index is out of bounds'); - } - - // Remove - this.list.splice(currentIndex, 1); - - // Add in new location - this.list.splice(index, 0, child); - - return child; + return ArrayUtils.MoveTo(this.list, child, index); }, /** @@ -540,19 +384,14 @@ var List = new Class({ */ remove: function (child, skipCallback) { - var index = this.list.indexOf(child); - - if (index !== -1) + if (skipCallback) { - this.list.splice(index, 1); - - if (!skipCallback) - { - this.removeCallback(this, child); - } + return ArrayUtils.Remove(this.list, child); + } + else + { + return ArrayUtils.Remove(this.list, child, this.removeCallback, this); } - - return child; }, /** @@ -570,19 +409,14 @@ var List = new Class({ */ removeAt: function (index, skipCallback) { - var child = this.list[index]; - - if (child) + if (skipCallback) { - this.children.splice(index, 1); - - if (!skipCallback) - { - this.removeCallback(this, child); - } + return ArrayUtils.RemoveAt(this.list, index); + } + else + { + return ArrayUtils.RemoveAt(this.list, index, this.removeCallback, this); } - - return child; }, /** @@ -593,37 +427,21 @@ var List = new Class({ * * @genericUse {T[]} - [$return] * - * @param {integer} [beginIndex=0] - [description] + * @param {integer} [startIndex=0] - [description] * @param {integer} [endIndex] - [description] * @param {boolean} [skipCallback=false] - Skip calling the List.removeCallback. * * @return {Array.<*>} [description] */ - removeBetween: function (beginIndex, endIndex, skipCallback) + removeBetween: function (startIndex, endIndex, skipCallback) { - if (beginIndex === undefined) { beginIndex = 0; } - if (endIndex === undefined) { endIndex = this.list.length; } - - var range = endIndex - beginIndex; - - if (range > 0 && range <= endIndex) + if (skipCallback) { - var removed = this.list.splice(beginIndex, range); - - if (!skipCallback) - { - this.removeCallback(this, removed); - } - - return removed; - } - else if (range === 0 && this.list.length === 0) - { - return []; + return ArrayUtils.RemoveBetween(this.list, startIndex, endIndex); } else { - throw new Error('List.removeBetween: Range Error, numeric values are outside the acceptable range'); + return ArrayUtils.RemoveBetween(this.list, startIndex, endIndex, this.removeCallback, this); } }, @@ -665,13 +483,7 @@ var List = new Class({ */ bringToTop: function (child) { - if (this.getIndex(child) < this.list.length) - { - this.remove(child, true); - this.add(child, true); - } - - return child; + return ArrayUtils.BringToTop(this.list, child); }, /** @@ -688,13 +500,7 @@ var List = new Class({ */ sendToBack: function (child) { - if (this.getIndex(child) > 0) - { - this.remove(child, true); - this.addAt(child, 0, true); - } - - return child; + return ArrayUtils.SendToBack(this.list, child); }, /** @@ -711,17 +517,7 @@ var List = new Class({ */ moveUp: function (child) { - var a = this.getIndex(child); - - if (a !== -1 && a < this.list.length - 1) - { - var b = this.getAt(a + 1); - - if (b) - { - this.swap(child, b); - } - } + ArrayUtils.MoveUp(this.list, child); return child; }, @@ -740,17 +536,7 @@ var List = new Class({ */ moveDown: function (child) { - var a = this.getIndex(child); - - if (a > 0) - { - var b = this.getAt(a - 1); - - if (b) - { - this.swap(child, b); - } - } + ArrayUtils.MoveDown(this.list, child); return child; }, @@ -784,13 +570,7 @@ var List = new Class({ */ shuffle: function () { - for (var i = this.list.length - 1; i > 0; i--) - { - var j = Math.floor(Math.random() * (i + 1)); - var temp = this.list[i]; - this.list[i] = this.list[j]; - this.list[j] = temp; - } + ArrayUtils.Shuffle(this.list); return this; }, @@ -810,16 +590,7 @@ var List = new Class({ */ replace: function (oldChild, newChild) { - var index = this.getIndex(oldChild); - - if (index !== -1) - { - this.remove(oldChild); - - this.addAt(newChild, index); - - return oldChild; - } + return ArrayUtils.Replace(this.list, oldChild, newChild); }, /** @@ -847,18 +618,16 @@ var List = new Class({ * * @genericUse {T} - [value] * - * @param {string} key - [description] + * @param {string} property - [description] * @param {*} value - [description] + * @param {integer} [startIndex] - The first child index to start the search from. + * @param {integer} [endIndex] - The last child index to search up until. */ - setAll: function (key, value) + setAll: function (property, value, startIndex, endIndex) { - for (var i = 0; i < this.list.length; i++) - { - if (this.list[i]) - { - this.list[i][key] = value; - } - } + ArrayUtils.SetAll(this.list, property, value, startIndex, endIndex); + + return this; }, /** @@ -873,11 +642,11 @@ var List = new Class({ * @param {*} [thisArg] - Value to use as `this` when executing callback. * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. */ - each: function (callback, thisArg) + each: function (callback, context) { var args = [ null ]; - for (var i = 1; i < arguments.length; i++) + for (var i = 2; i < arguments.length; i++) { args.push(arguments[i]); } @@ -885,7 +654,8 @@ var List = new Class({ for (i = 0; i < this.list.length; i++) { args[0] = this.list[i]; - callback.apply(thisArg, args); + + callback.apply(context, args); } }, diff --git a/src/utils/array/Add.js b/src/utils/array/Add.js new file mode 100644 index 000000000..39a118a3a --- /dev/null +++ b/src/utils/array/Add.js @@ -0,0 +1,111 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Adds the given item, or array of items, to the array. + * + * Each item must be unique within the array. + * + * The array is modified in-place and returned. + * + * You can optionally specify a limit to the maximum size of the array. If the quantity of items being + * added will take the array length over this limit, it will stop adding once the limit is reached. + * + * You can optionally specify a callback to be invoked for each item successfully added to the array. + * + * @function Phaser.Utils.Array.Add + * @since 3.4.0 + * + * @param {array} array - The array to be added to. + * @param {*|Array.<*>} item - The item, or array of items, to add to the array. Each item must be unique within the array. + * @param {integer} [limit] - Optional limit which caps the size of the array. + * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {array} The input array. + */ +var Add = function (array, item, limit, callback, context) +{ + if (context === undefined) { context = array; } + + if (limit) + { + var remaining = limit - array.length; + + // There's nothing more we can do here, the array is full + if (remaining <= 0) + { + return null; + } + } + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + if (array.indexOf(item) === -1) + { + array.push(item); + + if (callback) + { + callback.call(context, item); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to insert + + // Ensure all the items are unique + var itemLength = item.length - 1; + + while (itemLength >= 0) + { + if (array.indexOf(item[itemLength]) !== -1) + { + // Already exists in array, so remove it + item.pop(); + } + + itemLength--; + } + + // Anything left? + itemLength = item.length; + + if (itemLength === 0) + { + return null; + } + + if (limit && itemLength > remaining) + { + item.splice(remaining); + + itemLength = remaining; + } + + for (var i = 0; i < itemLength; i++) + { + var entry = item[i]; + + array.push(entry); + + if (callback) + { + callback.call(context, entry); + } + } + + return item; +}; + +module.exports = Add; diff --git a/src/utils/array/AddAt.js b/src/utils/array/AddAt.js new file mode 100644 index 000000000..110ba17cd --- /dev/null +++ b/src/utils/array/AddAt.js @@ -0,0 +1,116 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Adds the given item, or array of items, to the array starting at the index specified. + * + * Each item must be unique within the array. + * + * Existing elements in the array are shifted up. + * + * The array is modified in-place and returned. + * + * You can optionally specify a limit to the maximum size of the array. If the quantity of items being + * added will take the array length over this limit, it will stop adding once the limit is reached. + * + * You can optionally specify a callback to be invoked for each item successfully added to the array. + * + * @function Phaser.Utils.Array.AddAt + * @since 3.4.0 + * + * @param {array} array - The array to be added to. + * @param {*} item - The item, or array of items, to add to the array. + * @param {integer} [index=0] - The index in the array where the item will be inserted. + * @param {integer} [limit] - Optional limit which caps the size of the array. + * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {array} The input array. + */ +var AddAt = function (array, item, index, limit, callback, context) +{ + if (index === undefined) { index = 0; } + if (context === undefined) { context = array; } + + if (limit) + { + var remaining = limit - array.length; + + // There's nothing more we can do here, the array is full + if (remaining <= 0) + { + return null; + } + } + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + if (array.indexOf(item) === -1) + { + array.splice(index, 0, item); + + if (callback) + { + callback.call(context, entry); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to insert + + // Ensure all the items are unique + var itemLength = item.length - 1; + + while (itemLength >= 0) + { + if (array.indexOf(item[itemLength]) !== -1) + { + // Already exists in array, so remove it + item.pop(); + } + + itemLength--; + } + + // Anything left? + itemLength = item.length; + + if (itemLength === 0) + { + return null; + } + + // Truncate to the limit + if (limit && itemLength > remaining) + { + item.splice(remaining); + + itemLength = remaining; + } + + for (var i = itemLength; i > 0; i--) + { + var entry = item[i]; + + array.splice(index, 0, entry); + + if (callback) + { + callback.call(context, entry); + } + } + + return item; +}; + +module.exports = AddAt; diff --git a/src/utils/array/BringToTop.js b/src/utils/array/BringToTop.js new file mode 100644 index 000000000..2fb7e3f9d --- /dev/null +++ b/src/utils/array/BringToTop.js @@ -0,0 +1,32 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Moves the given element to the top of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.BringToTop + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * + * @return {*} The element that was moved. + */ +var BringToTop = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex < array.length - 2) + { + array.splice(currentIndex, 1); + array.push(item); + } + + return item; +}; + +module.exports = BringToTop; diff --git a/src/utils/array/CountAllMatching.js b/src/utils/array/CountAllMatching.js new file mode 100644 index 000000000..084e9b707 --- /dev/null +++ b/src/utils/array/CountAllMatching.js @@ -0,0 +1,36 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Returns the total number of elements in the array which have a property matching the given value. + * + * @function Phaser.Utils.Array.CountAllMatching + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} property - The property to test on each array element. + * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * + * @return {integer} The total number of elements with properties matching the given value. + */ +var CountAllMatching = function (array, property, value) +{ + var total = 0; + + for (var i = 0; i < array.length; i++) + { + var child = array[i]; + + if (child[property] === value) + { + total++; + } + } + + return total; +}; + +module.exports = CountAllMatching; diff --git a/src/utils/array/Each.js b/src/utils/array/Each.js new file mode 100644 index 000000000..49ecded23 --- /dev/null +++ b/src/utils/array/Each.js @@ -0,0 +1,40 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Passes each element in the array to the given callback. + * + * @function Phaser.Utils.Array.Each + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {function} callback - A callback to be invoked for each item in the array. + * @param {object} context - The context in which the callback is invoked. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {array} The input array. + */ +var Each = function (array, callback, context) +{ + var i; + var args = [ null ]; + + for (i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < array.length; i++) + { + args[0] = array[i]; + + callback.apply(context, args); + } + + return array; +}; + +module.exports = Each; diff --git a/src/utils/array/EachInRange.js b/src/utils/array/EachInRange.js new file mode 100644 index 000000000..dd426f88c --- /dev/null +++ b/src/utils/array/EachInRange.js @@ -0,0 +1,57 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Passes each element in the array, between the start and end indexes, to the given callback. + * + * @function Phaser.Utils.Array.EachInRange + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {function} callback - A callback to be invoked for each item in the array. + * @param {object} context - The context in which the callback is invoked. + * @param {integer} startIndex - The start index to search from. + * @param {integer} endIndex - The end index to search to. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {array} The input array. + */ +var EachInRange = function (array, callback, context, startIndex, endIndex) +{ + var len = array.length; + + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = len; } + + if (endIndex > len) + { + endIndex = len; + } + + if (startIndex < 0 || startIndex > len || startIndex >= endIndex) + { + throw new Error('Range Error: Values outside acceptable range'); + } + + var i; + var args = [ null ]; + + for (i = 5; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = startIndex; i < endIndex; i++) + { + args[0] = array[i]; + + callback.apply(context, args); + } + + return array; +}; + +module.exports = EachInRange; diff --git a/src/utils/array/GetAll.js b/src/utils/array/GetAll.js new file mode 100644 index 000000000..d5a86585c --- /dev/null +++ b/src/utils/array/GetAll.js @@ -0,0 +1,51 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Returns all elements in the array. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('visible', true)` would return only children that have their visible property set. + * + * Optionally you can specify a start and end index. For example if this List had 100 children, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 children in the List. + * + * @function Phaser.Utils.Array.GetAll + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} [property] - The property to test on each array element. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {integer} [startIndex] - An optional start index to search from. + * @param {integer} [endIndex] - An optional end index to search to. + * + * @return {array} All matching elements from the array. + */ +var GetAll = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + var output = []; + + for (var i = startIndex; i < endIndex; i++) + { + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + output.push(child); + } + } + + return output; +}; + +module.exports = GetAll; diff --git a/src/utils/array/GetFirstElement.js b/src/utils/array/GetFirstElement.js new file mode 100644 index 000000000..ae6c5368d --- /dev/null +++ b/src/utils/array/GetFirstElement.js @@ -0,0 +1,39 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Returns the first element from the array which optionally has a property matching the given value. + * + * @function Phaser.Utils.Array.GetFirstElement + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} property - The property to test on each array element. + * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=array.length] - An optional end index to search up to (but not included) + * + * @return {object} The first matching element from the array, or `null` if no element could be found in the range given. + */ +var GetFirstElement = function (array, property, value, startIndex, endIndex) +{ + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + + for (var i = startIndex; i < endIndex; i++) + { + var child = array[i]; + + if (!property || child[property] === value) + { + return child; + } + } + + return null; +}; + +module.exports = GetFirstElement; diff --git a/src/utils/array/GetRandomElement.js b/src/utils/array/GetRandomElement.js index eb5bd467d..2796df2b9 100644 --- a/src/utils/array/GetRandomElement.js +++ b/src/utils/array/GetRandomElement.js @@ -5,23 +5,23 @@ */ /** - * [description] + * Returns a Random element from the array. * * @function Phaser.Utils.Array.GetRandomElement * @since 3.0.0 * * @param {array} array - The array to select the random entry from. - * @param {integer} [start=0] - [description] - * @param {integer} [length=array.length] - [description] + * @param {integer} [startIndex=0] - An optional start index. + * @param {integer} [length=array.length] - An optional length, the total number of elements (from the startIndex) to choose from. * * @return {object} A random element from the array, or `null` if no element could be found in the range given. */ -var GetRandomElement = function (array, start, length) +var GetRandomElement = function (array, startIndex, length) { - if (start === undefined) { start = 0; } + if (startIndex === undefined) { startIndex = 0; } if (length === undefined) { length = array.length; } - var randomIndex = start + Math.floor(Math.random() * length); + var randomIndex = startIndex + Math.floor(Math.random() * length); return (array[randomIndex] === undefined) ? null : array[randomIndex]; }; diff --git a/src/utils/array/MoveDown.js b/src/utils/array/MoveDown.js new file mode 100644 index 000000000..bc6d823dc --- /dev/null +++ b/src/utils/array/MoveDown.js @@ -0,0 +1,36 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Moves the given array element down one place in the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveDown + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item - The element to move down the array. + * + * @return {array} The input array. + */ +var MoveDown = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex > 0) + { + var item2 = array[currentIndex - 1]; + + var index2 = array.indexOf(item2); + + array[currentIndex] = item2; + array[index2] = item; + } + + return array; +}; + +module.exports = MoveDown; diff --git a/src/utils/array/MoveTo.js b/src/utils/array/MoveTo.js new file mode 100644 index 000000000..b15f36f6e --- /dev/null +++ b/src/utils/array/MoveTo.js @@ -0,0 +1,41 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Moves an element in an array to a new position within the same array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveTo + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * @param {integer} index - The new index that the element will be moved to. + * + * @return {*} The element that was moved. + */ +var MoveTo = function (array, item, index) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex === -1 || index < 0 || index >= array.length) + { + throw new Error('Supplied index out of bounds'); + } + + if (currentIndex !== index) + { + // Remove + array.splice(currentIndex, 1); + + // Add in new location + array.splice(index, 0, item); + } + + return item; +}; + +module.exports = MoveTo; diff --git a/src/utils/array/MoveUp.js b/src/utils/array/MoveUp.js new file mode 100644 index 000000000..7b61e7440 --- /dev/null +++ b/src/utils/array/MoveUp.js @@ -0,0 +1,36 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Moves the given array element up one place in the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.MoveUp + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item - The element to move up the array. + * + * @return {array} The input array. + */ +var MoveUp = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex < array.length - 2) + { + var item2 = array[currentIndex + 1]; + + var index2 = array.indexOf(item2); + + array[currentIndex] = item2; + array[index2] = item; + } + + return array; +}; + +module.exports = MoveUp; diff --git a/src/utils/array/Remove.js b/src/utils/array/Remove.js new file mode 100644 index 000000000..7415b2303 --- /dev/null +++ b/src/utils/array/Remove.js @@ -0,0 +1,85 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var SpliceOne = require('./SpliceOne'); + +/** + * Removes the given item, or array of items, from the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for each item successfully removed from the array. + * + * @function Phaser.Utils.Array.Remove + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {*|Array.<*>} item - The item, or array of items, to be removed from the array. + * @param {function} [callback] - A callback to be invoked for each item successfully removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {*|Array.<*>} The item, or array of items, that were successfully removed from the array. + */ +var Remove = function (array, item, callback, context) +{ + if (context === undefined) { context = array; } + + var index; + + // Fast path to avoid array mutation and iteration + if (!Array.isArray(item)) + { + index = array.indexOf(item); + + if (index !== -1) + { + SpliceOne(array, index); + + if (callback) + { + callback.call(context, item); + } + + return item; + } + else + { + return null; + } + } + + // If we got this far, we have an array of items to remove + + var itemLength = item.length - 1; + + while (itemLength >= 0) + { + var entry = item[itemLength]; + + index = array.indexOf(entry); + + if (index !== -1) + { + SpliceOne(array, index); + + if (callback) + { + callback.call(context, entry); + } + } + else + { + // Item wasn't found in the array, so remove it from our return results + item.pop(); + } + + itemLength--; + } + + return item; +}; + +module.exports = Remove; diff --git a/src/utils/array/RemoveAt.js b/src/utils/array/RemoveAt.js new file mode 100644 index 000000000..3203195b7 --- /dev/null +++ b/src/utils/array/RemoveAt.js @@ -0,0 +1,45 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var SpliceOne = require('./SpliceOne'); + +/** + * Removes the item from the given position in the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for the item if it is successfully removed from the array. + * + * @function Phaser.Utils.Array.RemoveAt + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {integer} index - The array index to remove the item from. The index must be in bounds or it will throw an error. + * @param {function} [callback] - A callback to be invoked for the item removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {*} The item that was removed. + */ +var RemoveAt = function (array, index, callback, context) +{ + if (context === undefined) { context = array; } + + if (index < 0 || index > array.length - 1) + { + throw new Error('Index out of bounds'); + } + + var item = SpliceOne(array, index); + + if (callback) + { + callback.call(context, item); + } + + return item; +}; + +module.exports = RemoveAt; diff --git a/src/utils/array/RemoveBetween.js b/src/utils/array/RemoveBetween.js new file mode 100644 index 000000000..a45608399 --- /dev/null +++ b/src/utils/array/RemoveBetween.js @@ -0,0 +1,61 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Removes the item within the given range in the array. + * + * The array is modified in-place. + * + * You can optionally specify a callback to be invoked for the item/s successfully removed from the array. + * + * @function Phaser.Utils.Array.RemoveBetween + * @since 3.4.0 + * + * @param {array} array - The array to be modified. + * @param {integer} startIndex - The start index to remove from. + * @param {integer} endIndex - The end index to remove to. + * @param {function} [callback] - A callback to be invoked for the item removed from the array. + * @param {object} [context] - The context in which the callback is invoked. + * + * @return {Array.<*>} An array of items that were removed. + */ +var RemoveBetween = function (array, startIndex, endIndex, callback, context) +{ + if (context === undefined) { context = array; } + + var len = array.length; + + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = len; } + + if (endIndex > len) + { + endIndex = len; + } + + if (startIndex < 0 || startIndex > len || startIndex >= endIndex) + { + throw new Error('Range Error: Values outside acceptable range'); + } + + var size = endIndex - startIndex; + + var removed = array.splice(startIndex, size); + + if (callback) + { + for (var i = 0; i < removed.length; i++) + { + var entry = removed[i]; + + callback.call(context, entry); + } + } + + return removed; +}; + +module.exports = RemoveBetween; diff --git a/src/utils/array/Replace.js b/src/utils/array/Replace.js new file mode 100644 index 000000000..c44ef5d4c --- /dev/null +++ b/src/utils/array/Replace.js @@ -0,0 +1,33 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Replaces an element of the array with the new element. + * The new element cannot already be a member of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.Replace + * @since 3.4.0 + * + * @param {*} oldChild - The element in the array that will be replaced. + * @param {*} newChild - The element to be inserted into the array at the position of `oldChild`. + * + * @return {*} Returns the oldChild that was replaced. + */ +var Replace = function (array, oldChild, newChild) +{ + var index1 = array.indexOf(oldChild); + var index2 = array.indexOf(newChild); + + if (index1 !== -1 && index2 === -1) + { + array[index1] = newChild; + } + + return oldChild; +}; + +module.exports = Replace; diff --git a/src/utils/array/SendToBack.js b/src/utils/array/SendToBack.js new file mode 100644 index 000000000..86eed1975 --- /dev/null +++ b/src/utils/array/SendToBack.js @@ -0,0 +1,32 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Moves the given element to the bottom of the array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.SendToBack + * @since 3.4.0 + * + * @param {array} array - The array. + * @param {*} item - The element to move. + * + * @return {*} The element that was moved. + */ +var SendToBack = function (array, item) +{ + var currentIndex = array.indexOf(item); + + if (currentIndex !== -1 && currentIndex > 0) + { + array.splice(currentIndex, 1); + array.unshift(item); + } + + return item; +}; + +module.exports = SendToBack; diff --git a/src/utils/array/SetAll.js b/src/utils/array/SetAll.js new file mode 100644 index 000000000..77679ca85 --- /dev/null +++ b/src/utils/array/SetAll.js @@ -0,0 +1,56 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Scans the array for elements with the given property. If found, the property is set to the `value`. + * + * For example: `SetAll('visible', true)` would set all elements that have a `visible` property to `false`. + * + * Optionally you can specify a start and end index. For example if the array had 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would update only the first 50 elements. + * + * @function Phaser.Utils.Array.SetAll + * @since 3.4.0 + * + * @param {array} array - The array to search. + * @param {string} property - The property to test for on each array element. + * @param {*} value - The value to set the property to. + * @param {integer} [startIndex] - An optional start index to search from. + * @param {integer} [endIndex] - An optional end index to search to. + * + * @return {array} The input array. + */ +var SetAll = function (array, property, value, startIndex, endIndex) +{ + var len = array.length; + + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = len; } + + if (endIndex > len) + { + endIndex = len; + } + + if (startIndex < 0 || startIndex > len || startIndex > endIndex) + { + throw new Error('Range Error: Values outside acceptable range'); + } + + for (var i = startIndex; i < endIndex; i++) + { + var entry = array[i]; + + if (entry.hasOwnProperty(property)) + { + entry[property] = value; + } + } + + return array; +}; + +module.exports = SetAll; diff --git a/src/utils/array/SpliceOne.js b/src/utils/array/SpliceOne.js index 036fd9811..63bf8d565 100644 --- a/src/utils/array/SpliceOne.js +++ b/src/utils/array/SpliceOne.js @@ -4,10 +4,9 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -// Based on code by Mike Reinstein - /** - * Removes a single item from an array and returns it without creating gc (like the native splice does) + * Removes a single item from an array and returns it without creating gc, like the native splice does. + * Based on code by Mike Reinstein. * * @function Phaser.Utils.Array.SpliceOne * @since 3.0.0 diff --git a/src/utils/array/Swap.js b/src/utils/array/Swap.js new file mode 100644 index 000000000..68a64d06f --- /dev/null +++ b/src/utils/array/Swap.js @@ -0,0 +1,42 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Swaps the position of two elements in the given array. + * The elements must exist in the same array. + * The array is modified in-place. + * + * @function Phaser.Utils.Array.Swap + * @since 3.4.0 + * + * @param {array} array - The input array. + * @param {*} item1 - The first element to swap. + * @param {*} item2 - The second element to swap. + * + * @return {array} The input array. + */ +var Swap = function (array, item1, item2) +{ + if (item1 === item2) + { + return; + } + + var index1 = array.indexOf(item1); + var index2 = array.indexOf(item2); + + if (index1 < 0 || index2 < 0) + { + throw new Error('Supplied items must be elements of the same array'); + } + + array[index1] = item2; + array[index2] = item1; + + return array; +}; + +module.exports = Swap; diff --git a/src/utils/array/index.js b/src/utils/array/index.js index 999561fc7..e47f127fc 100644 --- a/src/utils/array/index.js +++ b/src/utils/array/index.js @@ -10,17 +10,37 @@ module.exports = { - FindClosestInSorted: require('./FindClosestInSorted'), - GetRandomElement: require('./GetRandomElement'), Matrix: require('./matrix'), + + Add: require('./Add'), + AddAt: require('./AddAt'), + BringToTop: require('./BringToTop'), + CountAllMatching: require('./CountAllMatching'), + Each: require('./Each'), + EachInRange: require('./EachInRange'), + FindClosestInSorted: require('./FindClosestInSorted'), + GetAll: require('./GetAll'), + GetFirst: require('./GetFirst'), + GetRandom: require('./GetRandom'), + MoveDown: require('./MoveDown'), + MoveTo: require('./MoveTo'), + MoveUp: require('./MoveUp'), NumberArray: require('./NumberArray'), NumberArrayStep: require('./NumberArrayStep'), QuickSelect: require('./QuickSelect'), Range: require('./Range'), + Remove: require('./Remove'), + RemoveAt: require('./RemoveAt'), + RemoveBetween: require('./RemoveBetween'), RemoveRandomElement: require('./RemoveRandomElement'), + Replace: require('./Replace'), RotateLeft: require('./RotateLeft'), RotateRight: require('./RotateRight'), + SendToBack: require('./SendToBack'), + SetAll: require('./SetAll'), Shuffle: require('./Shuffle'), - SpliceOne: require('./SpliceOne') + SpliceOne: require('./SpliceOne'), + StableSort: require('./StableSort'), + Swap: require('./Swap') }; From a6303aad8cc2e82f6aad48799f4d6162bc73c205 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 04:01:24 +0100 Subject: [PATCH 46/87] Renamed files --- src/utils/array/{GetFirstElement.js => GetFirst.js} | 0 src/utils/array/{GetRandomElement.js => GetRandom.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/utils/array/{GetFirstElement.js => GetFirst.js} (100%) rename src/utils/array/{GetRandomElement.js => GetRandom.js} (100%) diff --git a/src/utils/array/GetFirstElement.js b/src/utils/array/GetFirst.js similarity index 100% rename from src/utils/array/GetFirstElement.js rename to src/utils/array/GetFirst.js diff --git a/src/utils/array/GetRandomElement.js b/src/utils/array/GetRandom.js similarity index 100% rename from src/utils/array/GetRandomElement.js rename to src/utils/array/GetRandom.js From cdfe2e0ea2de3cd10c39b20f82197debf2c05f5f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 04:13:38 +0100 Subject: [PATCH 47/87] Fixed references --- src/gameobjects/container/Container.js | 16 ++++++++-------- src/gameobjects/particles/ParticleEmitter.js | 4 ++-- src/tilemaps/components/Randomize.js | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 3ba4c9451..63360a9e8 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -126,7 +126,7 @@ var Container = new Class({ * @private * @since 3.4.0 */ - this.addCallback = this.addHandler; + this.addCallback = this.addHandler.bind(this); /** * A callback that is invoked every time a child is removed from this list. @@ -136,7 +136,7 @@ var Container = new Class({ * @private * @since 3.4.0 */ - this.removeCallback = this.removeHandler; + this.removeCallback = this.removeHandler.bind(this); /** * A reference to the Scene Display List. @@ -151,9 +151,9 @@ var Container = new Class({ this.setPosition(x, y); this.clearAlpha(); - if (Array.isArray(children)) + if (children) { - this.addMultiple(children); + this.add(children); } }, @@ -196,7 +196,7 @@ var Container = new Class({ * @param {Phaser.GameObjects.Container} list - The List the Game Object was added to (also this Container) * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just added to this Container. */ - addHandler: function (list, gameObject) + addHandler: function (gameObject) { gameObject.on('destroy', this.remove, this); @@ -209,7 +209,7 @@ var Container = new Class({ gameObject.parentContainer.remove(gameObject); } - gameObject.parentContainer = list; + gameObject.parentContainer = this; } }, @@ -223,9 +223,9 @@ var Container = new Class({ * @param {Phaser.GameObjects.Container} list - The List the Game Object was removed from (also this Container) * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just removed from this Container. */ - removeHandler: function (list, gameObject) + removeHandler: function (gameObject) { - gameObject.off('destroy', list.remove, this); + gameObject.off('destroy', this.remove, this); if (this.exclusive) { diff --git a/src/gameobjects/particles/ParticleEmitter.js b/src/gameobjects/particles/ParticleEmitter.js index b1cc2b5dd..1f84b124e 100644 --- a/src/gameobjects/particles/ParticleEmitter.js +++ b/src/gameobjects/particles/ParticleEmitter.js @@ -11,7 +11,7 @@ var DeathZone = require('./zones/DeathZone'); var EdgeZone = require('./zones/EdgeZone'); var EmitterOp = require('./EmitterOp'); var GetFastValue = require('../../utils/object/GetFastValue'); -var GetRandomElement = require('../../utils/array/GetRandomElement'); +var GetRandom = require('../../utils/array/GetRandom'); var HasAny = require('../../utils/object/HasAny'); var HasValue = require('../../utils/object/HasValue'); var Particle = require('./Particle'); @@ -943,7 +943,7 @@ var ParticleEmitter = new Class({ } else if (this.randomFrame) { - return GetRandomElement(this.frames); + return GetRandom(this.frames); } else { diff --git a/src/tilemaps/components/Randomize.js b/src/tilemaps/components/Randomize.js index a5134bc7c..cc52b8e19 100644 --- a/src/tilemaps/components/Randomize.js +++ b/src/tilemaps/components/Randomize.js @@ -5,7 +5,7 @@ */ var GetTilesWithin = require('./GetTilesWithin'); -var GetRandomElement = require('../../utils/array/GetRandomElement'); +var GetRandom = require('../../utils/array/GetRandom'); /** * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the @@ -44,7 +44,7 @@ var Randomize = function (tileX, tileY, width, height, indexes, layer) for (i = 0; i < tiles.length; i++) { - tiles[i].index = GetRandomElement(indexes); + tiles[i].index = GetRandom(indexes); } }; From 47dc14079b66b7cf942f97ae0a91871222729916 Mon Sep 17 00:00:00 2001 From: Antriel Date: Tue, 10 Apr 2018 14:19:51 +0200 Subject: [PATCH 48/87] fix Timeline#destroy --- src/tweens/Timeline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tweens/Timeline.js b/src/tweens/Timeline.js index 4fc36fac7..ece97eb99 100644 --- a/src/tweens/Timeline.js +++ b/src/tweens/Timeline.js @@ -852,7 +852,7 @@ var Timeline = new Class({ { for (var i = 0; i < this.data.length; i++) { - this.data[i].destroy(); + this.data[i].stop(); } } From bf81a7dd06f2f6ef13bf934096ffe26a6d366611 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:20:50 +0100 Subject: [PATCH 49/87] TransformMatrix.destroy is a new method that will clear out the array and object used by a Matrix internally. --- CHANGELOG.md | 1 + src/gameobjects/components/TransformMatrix.js | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9baba8eb1..57048c8c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ being passed to the simulation. The default value is 1 to remain consistent with * Utils.Array.SendToBack allows you to send an array element to the bottom of the array. * Utils.Array.SetAll will set a property on all elements of an array to the given value, with optional range limits. * Utils.Array.Swap will swap the position of two elements in an array. +* TransformMatrix.destroy is a new method that will clear out the array and object used by a Matrix internally. ### Bug Fixes diff --git a/src/gameobjects/components/TransformMatrix.js b/src/gameobjects/components/TransformMatrix.js index 302540e63..f0e2523d0 100644 --- a/src/gameobjects/components/TransformMatrix.js +++ b/src/gameobjects/components/TransformMatrix.js @@ -562,6 +562,18 @@ var TransformMatrix = new Class({ matrix[3] = cr * scaleY; return this; + }, + + /** + * Destroys this Transform Matrix. + * + * @method Phaser.GameObjects.Components.TransformMatrix#destroy + * @since 3.4.0 + */ + destroy: function () + { + this.matrix = null; + this.decomposedMatrix = null; } }); From 68ef6f86307dd468ee41cc230b52944288f042fa Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:21:04 +0100 Subject: [PATCH 50/87] Removed parentContainer reference --- src/gameobjects/GameObject.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gameobjects/GameObject.js b/src/gameobjects/GameObject.js index 22eb2804a..8d32ab54f 100644 --- a/src/gameobjects/GameObject.js +++ b/src/gameobjects/GameObject.js @@ -375,6 +375,8 @@ var GameObject = new Class({ this.scene = undefined; + this.parentContainer = undefined; + this.removeAllListeners(); } From 9fb1a72b704d5f8b6c6ffab97d60f825adaddefe Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:21:10 +0100 Subject: [PATCH 51/87] Typo --- src/tilemaps/components/WeightedRandomize.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tilemaps/components/WeightedRandomize.js b/src/tilemaps/components/WeightedRandomize.js index d843f844f..e50e63d71 100644 --- a/src/tilemaps/components/WeightedRandomize.js +++ b/src/tilemaps/components/WeightedRandomize.js @@ -8,7 +8,7 @@ var GetTilesWithin = require('./GetTilesWithin'); /** * Randomizes the indexes of a rectangular region of tiles (in tile coordinates) within the - * specified layer. Each tile will recieve a new index. New indexes are drawn from the given + * specified layer. Each tile will receive a new index. New indexes are drawn from the given * weightedIndexes array. An example weighted array: * * [ From 82e99bf130e5894716abb068f80573fbb2a746ee Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:21:30 +0100 Subject: [PATCH 52/87] All now using SafeRange to cut down on duplicated code --- src/utils/array/CountAllMatching.js | 22 +++++++++++---- src/utils/array/EachInRange.js | 37 ++++++++++--------------- src/utils/array/GetAll.js | 25 ++++++++++------- src/utils/array/GetFirst.js | 36 ++++++++++++++++-------- src/utils/array/GetRandom.js | 6 ++-- src/utils/array/RemoveBetween.js | 42 +++++++++++++--------------- src/utils/array/Replace.js | 10 +++++-- src/utils/array/SafeRange.js | 43 +++++++++++++++++++++++++++++ src/utils/array/SetAll.js | 29 ++++++++----------- src/utils/array/index.js | 1 + 10 files changed, 155 insertions(+), 96 deletions(-) create mode 100644 src/utils/array/SafeRange.js diff --git a/src/utils/array/CountAllMatching.js b/src/utils/array/CountAllMatching.js index 084e9b707..9263123b5 100644 --- a/src/utils/array/CountAllMatching.js +++ b/src/utils/array/CountAllMatching.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** * Returns the total number of elements in the array which have a property matching the given value. * @@ -13,20 +15,28 @@ * @param {array} array - The array to search. * @param {string} property - The property to test on each array element. * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {integer} [startIndex] - An optional start index to search from. + * @param {integer} [endIndex] - An optional end index to search to. * * @return {integer} The total number of elements with properties matching the given value. */ -var CountAllMatching = function (array, property, value) +var CountAllMatching = function (array, property, value, startIndex, endIndex) { + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } + var total = 0; - for (var i = 0; i < array.length; i++) + if (SafeRange(array, startIndex, endIndex)) { - var child = array[i]; - - if (child[property] === value) + for (var i = startIndex; i < endIndex; i++) { - total++; + var child = array[i]; + + if (child[property] === value) + { + total++; + } } } diff --git a/src/utils/array/EachInRange.js b/src/utils/array/EachInRange.js index dd426f88c..a6e122f10 100644 --- a/src/utils/array/EachInRange.js +++ b/src/utils/array/EachInRange.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** * Passes each element in the array, between the start and end indexes, to the given callback. * @@ -21,34 +23,25 @@ */ var EachInRange = function (array, callback, context, startIndex, endIndex) { - var len = array.length; - if (startIndex === undefined) { startIndex = 0; } - if (endIndex === undefined) { endIndex = len; } + if (endIndex === undefined) { endIndex = array.length; } - if (endIndex > len) + if (SafeRange(array, startIndex, endIndex)) { - endIndex = len; - } + var i; + var args = [ null ]; - if (startIndex < 0 || startIndex > len || startIndex >= endIndex) - { - throw new Error('Range Error: Values outside acceptable range'); - } + for (i = 5; i < arguments.length; i++) + { + args.push(arguments[i]); + } - var i; - var args = [ null ]; + for (i = startIndex; i < endIndex; i++) + { + args[0] = array[i]; - for (i = 5; i < arguments.length; i++) - { - args.push(arguments[i]); - } - - for (i = startIndex; i < endIndex; i++) - { - args[0] = array[i]; - - callback.apply(context, args); + callback.apply(context, args); + } } return array; diff --git a/src/utils/array/GetAll.js b/src/utils/array/GetAll.js index d5a86585c..9d1eac2f7 100644 --- a/src/utils/array/GetAll.js +++ b/src/utils/array/GetAll.js @@ -4,16 +4,18 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** * Returns all elements in the array. * * You can optionally specify a matching criteria using the `property` and `value` arguments. * - * For example: `getAll('visible', true)` would return only children that have their visible property set. + * For example: `getAll('visible', true)` would return only elements that have their visible property set. * - * Optionally you can specify a start and end index. For example if this List had 100 children, + * Optionally you can specify a start and end index. For example if the array had 100 elements, * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only - * the first 50 children in the List. + * the first 50 elements. * * @function Phaser.Utils.Array.GetAll * @since 3.4.0 @@ -33,15 +35,18 @@ var GetAll = function (array, property, value, startIndex, endIndex) var output = []; - for (var i = startIndex; i < endIndex; i++) + if (SafeRange(array, startIndex, endIndex)) { - var child = array[i]; - - if (!property || - (property && value === undefined && child.hasOwnProperty(property)) || - (property && value !== undefined && child[property] === value)) + for (var i = startIndex; i < endIndex; i++) { - output.push(child); + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + output.push(child); + } } } diff --git a/src/utils/array/GetFirst.js b/src/utils/array/GetFirst.js index ae6c5368d..e456222bc 100644 --- a/src/utils/array/GetFirst.js +++ b/src/utils/array/GetFirst.js @@ -4,36 +4,50 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** - * Returns the first element from the array which optionally has a property matching the given value. + * Returns the first element in the array. * - * @function Phaser.Utils.Array.GetFirstElement + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('visible', true)` would return the first element that had its `visible` property set. + * + * Optionally you can specify a start and end index. For example if the array had 100 elements, + * and you set `startIndex` to 0 and `endIndex` to 50, it would search only the first 50 elements. + * + * @function Phaser.Utils.Array.GetFirst * @since 3.4.0 * * @param {array} array - The array to search. - * @param {string} property - The property to test on each array element. - * @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {string} [property] - The property to test on each array element. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. * @param {integer} [startIndex=0] - An optional start index to search from. * @param {integer} [endIndex=array.length] - An optional end index to search up to (but not included) * * @return {object} The first matching element from the array, or `null` if no element could be found in the range given. */ -var GetFirstElement = function (array, property, value, startIndex, endIndex) +var GetFirst = function (array, property, value, startIndex, endIndex) { if (startIndex === undefined) { startIndex = 0; } if (endIndex === undefined) { endIndex = array.length; } - for (var i = startIndex; i < endIndex; i++) + if (SafeRange(array, startIndex, endIndex)) { - var child = array[i]; - - if (!property || child[property] === value) + for (var i = startIndex; i < endIndex; i++) { - return child; + var child = array[i]; + + if (!property || + (property && value === undefined && child.hasOwnProperty(property)) || + (property && value !== undefined && child[property] === value)) + { + return child; + } } } return null; }; -module.exports = GetFirstElement; +module.exports = GetFirst; diff --git a/src/utils/array/GetRandom.js b/src/utils/array/GetRandom.js index 2796df2b9..8d1ee9647 100644 --- a/src/utils/array/GetRandom.js +++ b/src/utils/array/GetRandom.js @@ -7,7 +7,7 @@ /** * Returns a Random element from the array. * - * @function Phaser.Utils.Array.GetRandomElement + * @function Phaser.Utils.Array.GetRandom * @since 3.0.0 * * @param {array} array - The array to select the random entry from. @@ -16,7 +16,7 @@ * * @return {object} A random element from the array, or `null` if no element could be found in the range given. */ -var GetRandomElement = function (array, startIndex, length) +var GetRandom = function (array, startIndex, length) { if (startIndex === undefined) { startIndex = 0; } if (length === undefined) { length = array.length; } @@ -26,4 +26,4 @@ var GetRandomElement = function (array, startIndex, length) return (array[randomIndex] === undefined) ? null : array[randomIndex]; }; -module.exports = GetRandomElement; +module.exports = GetRandom; diff --git a/src/utils/array/RemoveBetween.js b/src/utils/array/RemoveBetween.js index a45608399..d898538c1 100644 --- a/src/utils/array/RemoveBetween.js +++ b/src/utils/array/RemoveBetween.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** * Removes the item within the given range in the array. * @@ -24,38 +26,32 @@ */ var RemoveBetween = function (array, startIndex, endIndex, callback, context) { + if (startIndex === undefined) { startIndex = 0; } + if (endIndex === undefined) { endIndex = array.length; } if (context === undefined) { context = array; } - var len = array.length; - - if (startIndex === undefined) { startIndex = 0; } - if (endIndex === undefined) { endIndex = len; } - - if (endIndex > len) + if (SafeRange(array, startIndex, endIndex)) { - endIndex = len; - } + var size = endIndex - startIndex; - if (startIndex < 0 || startIndex > len || startIndex >= endIndex) - { - throw new Error('Range Error: Values outside acceptable range'); - } + var removed = array.splice(startIndex, size); - var size = endIndex - startIndex; - - var removed = array.splice(startIndex, size); - - if (callback) - { - for (var i = 0; i < removed.length; i++) + if (callback) { - var entry = removed[i]; + for (var i = 0; i < removed.length; i++) + { + var entry = removed[i]; - callback.call(context, entry); + callback.call(context, entry); + } } - } - return removed; + return removed; + } + else + { + return []; + } }; module.exports = RemoveBetween; diff --git a/src/utils/array/Replace.js b/src/utils/array/Replace.js index c44ef5d4c..d7261f245 100644 --- a/src/utils/array/Replace.js +++ b/src/utils/array/Replace.js @@ -15,7 +15,7 @@ * @param {*} oldChild - The element in the array that will be replaced. * @param {*} newChild - The element to be inserted into the array at the position of `oldChild`. * - * @return {*} Returns the oldChild that was replaced. + * @return {boolean} Returns true if the oldChild was successfully replaced, otherwise returns false. */ var Replace = function (array, oldChild, newChild) { @@ -25,9 +25,13 @@ var Replace = function (array, oldChild, newChild) if (index1 !== -1 && index2 === -1) { array[index1] = newChild; - } - return oldChild; + return true; + } + else + { + return false; + } }; module.exports = Replace; diff --git a/src/utils/array/SafeRange.js b/src/utils/array/SafeRange.js new file mode 100644 index 000000000..abc0848eb --- /dev/null +++ b/src/utils/array/SafeRange.js @@ -0,0 +1,43 @@ +/** + * @author Richard Davey + * @copyright 2018 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +/** + * Tests if the start and end indexes are a safe range for the given array. + * + * @function Phaser.Utils.Array.SafeRange + * @since 3.4.0 + * + * @param {array} array - The array to check. + * @param {integer} startIndex - The start index. + * @param {integer} endIndex - The end index. + * @param {boolean} [throwError=true] - Throw an error if the range is out of bounds. + * + * @return {boolean} True if the range is safe, otherwise false. + */ +var SafeRange = function (array, startIndex, endIndex, throwError) +{ + var len = array.length; + + if (startIndex < 0 || + startIndex > len || + startIndex >= endIndex || + endIndex > len || + startIndex + endIndex > len) + { + if (throwError) + { + throw new Error('Range Error: Values outside acceptable range'); + } + + return false; + } + else + { + return true; + } +}; + +module.exports = SafeRange; diff --git a/src/utils/array/SetAll.js b/src/utils/array/SetAll.js index 77679ca85..caf61607c 100644 --- a/src/utils/array/SetAll.js +++ b/src/utils/array/SetAll.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var SafeRange = require('./SafeRange'); + /** * Scans the array for elements with the given property. If found, the property is set to the `value`. * @@ -25,28 +27,19 @@ */ var SetAll = function (array, property, value, startIndex, endIndex) { - var len = array.length; - if (startIndex === undefined) { startIndex = 0; } - if (endIndex === undefined) { endIndex = len; } + if (endIndex === undefined) { endIndex = array.length; } - if (endIndex > len) + if (SafeRange(array, startIndex, endIndex)) { - endIndex = len; - } - - if (startIndex < 0 || startIndex > len || startIndex > endIndex) - { - throw new Error('Range Error: Values outside acceptable range'); - } - - for (var i = startIndex; i < endIndex; i++) - { - var entry = array[i]; - - if (entry.hasOwnProperty(property)) + for (var i = startIndex; i < endIndex; i++) { - entry[property] = value; + var entry = array[i]; + + if (entry.hasOwnProperty(property)) + { + entry[property] = value; + } } } diff --git a/src/utils/array/index.js b/src/utils/array/index.js index e47f127fc..f411de35c 100644 --- a/src/utils/array/index.js +++ b/src/utils/array/index.js @@ -36,6 +36,7 @@ module.exports = { Replace: require('./Replace'), RotateLeft: require('./RotateLeft'), RotateRight: require('./RotateRight'), + SafeRange: require('./SafeRange'), SendToBack: require('./SendToBack'), SetAll: require('./SetAll'), Shuffle: require('./Shuffle'), From be7b52b1b94039ffa151260e8e62e7163fb84d6f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:21:46 +0100 Subject: [PATCH 53/87] No longer extends List, but implements its own methods directly. --- src/gameobjects/container/Container.js | 903 ++++++++++++++++++++++--- 1 file changed, 827 insertions(+), 76 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 63360a9e8..91a2c2b3f 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -5,10 +5,10 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var ArrayUtils = require('../../utils/array'); var Class = require('../../utils/Class'); var Components = require('../components'); var GameObject = require('../GameObject'); -var List = require('../../structs/List'); var Render = require('./ContainerRender'); var Vector2 = require('../../math/Vector2'); @@ -22,9 +22,11 @@ var Vector2 = require('../../math/Vector2'); * @constructor * @since 3.4.0 * + * @extends Phaser.GameObjects.Components.Alpha * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.Depth * @extends Phaser.GameObjects.Components.Transform - * @extends Phaser.Structs.List + * @extends Phaser.GameObjects.Components.Visible * * @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time. * @param {number} [x=0] - The horizontal position of this Game Object in the world. @@ -41,8 +43,7 @@ var Container = new Class({ Components.Depth, Components.Transform, Components.Visible, - Render, - List + Render ], initialize: @@ -51,16 +52,6 @@ var Container = new Class({ { GameObject.call(this, scene, 'Container'); - /** - * The parent property as used by the List methods. - * - * @name Phaser.GameObjects.Container#parent - * @type {Phaser.GameObjects.Container} - * @private - * @since 3.4.0 - */ - this.parent = this; - /** * An array holding the children of this Container. * @@ -117,27 +108,7 @@ var Container = new Class({ * @since 3.4.0 */ this.tempTransformMatrix = new Components.TransformMatrix(); - - /** - * A callback that is invoked every time a child is added to this list. - * - * @name Phaser.GameObjects.Container#addCallback - * @type {function} - * @private - * @since 3.4.0 - */ - this.addCallback = this.addHandler.bind(this); - - /** - * A callback that is invoked every time a child is removed from this list. - * - * @name Phaser.GameObjects.Container#removeCallback - * @type {function} - * @private - * @since 3.4.0 - */ - this.removeCallback = this.removeHandler.bind(this); - + /** * A reference to the Scene Display List. * @@ -148,7 +119,17 @@ var Container = new Class({ */ this._displayList = scene.sys.displayList; + /** + * The property key to sort by. + * + * @name Phaser.GameObjects.Container#_sortKey + * @type {string} + * @since 3.4.0 + */ + this._sortKey = ''; + this.setPosition(x, y); + this.clearAlpha(); if (children) @@ -193,7 +174,6 @@ var Container = new Class({ * @private * @since 3.4.0 * - * @param {Phaser.GameObjects.Container} list - The List the Game Object was added to (also this Container) * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just added to this Container. */ addHandler: function (gameObject) @@ -220,7 +200,6 @@ var Container = new Class({ * @private * @since 3.4.0 * - * @param {Phaser.GameObjects.Container} list - The List the Game Object was removed from (also this Container) * @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just removed from this Container. */ removeHandler: function (gameObject) @@ -267,12 +246,815 @@ var Container = new Class({ }, /** - * Destroys this Container removing it and all children from the Display List and - * severing all ties to parent resources. + * Adds the given Game Object, or array of Game Objects, to this Container. + * + * Each Game Object must be unique within the Container. + * + * @method Phaser.GameObjects.Container#add + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*|Array.<*>} child - The item, or array of items, to add to the array. Each item must be unique within the array. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + add: function (child) + { + ArrayUtils.Add(this.list, child, 0, this.addHandler, this); + + return this; + }, + + /** + * [description] + * + * @method Phaser.GameObjects.Container#addAt + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {*} child - [description] + * @param {integer} [index=0] - [description] + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + addAt: function (child, index) + { + ArrayUtils.AddAt(this.list, child, index, 0, this.addHandler, this); + + return this; + }, + + /** + * [description] + * + * @method Phaser.GameObjects.Container#getAt + * @since 3.4.0 + * + * @genericUse {T} - [$return] + * + * @param {integer} index - [description] + * + * @return {Phaser.GameObjects.GameObject|null} The Game Object at the specified index, or `null` if none found. + */ + getAt: function (index) + { + return this.list[index]; + }, + + /** + * [description] + * + * @method Phaser.GameObjects.Container#getIndex + * @since 3.4.0 + * + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to search for in this Container. + * + * @return {integer} The index of the Game Object in this Container, or -1 if not found. + */ + getIndex: function (child) + { + // Return -1 if given child isn't a child of this display list + return this.list.indexOf(child); + }, + + /** + * Sort the contents of this Container so the items are in order based on the given property. + * For example: `sort('alpha')` would sort the elements based on the value of their `alpha` property. + * + * @method Phaser.GameObjects.Container#sort + * @since 3.4.0 + * + * @genericUse {T[]} - [children,$return] + * + * @param {string} property - The property to lexically sort by. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + sort: function (property) + { + if (property) + { + this._sortKey = property; + + StableSort.inplace(this.list, this.sortHandler); + } + + return this; + }, + + /** + * Internal sort handler method. + * + * @method Phaser.GameObjects.Container#sortHandler + * @private + * @since 3.4.0 + * + * @genericUse {T} - [childA,childB] + * + * @param {Phaser.GameObjects.GameObject} childA - The first child to sort. + * @param {Phaser.GameObjects.GameObject} childB - The second child to sort. + * + * @return {integer} The sort results. + */ + sortHandler: function (childA, childB) + { + return childA[this._sortKey] - childB[this._sortKey]; + }, + + /** + * Searches for the first instance of a child with its `name` property matching the given argument. + * Should more than one child have the same name only the first is returned. + * + * @method Phaser.GameObjects.Container#getByName + * @since 3.4.0 + * + * @genericUse {T | null} - [$return] + * + * @param {string} name - The name to search for. + * + * @return {?Phaser.GameObjects.GameObject} The first child with a matching name, or `null` if none were found. + */ + getByName: function (name) + { + return ArrayUtils.GetFirst(this.list, 'name', name); + }, + + /** + * Returns a random Game Object from this Container. + * + * @method Phaser.GameObjects.Container#getRandom + * @since 3.4.0 + * + * @genericUse {T | null} - [$return] + * + * @param {integer} [startIndex=0] - An optional start index. + * @param {integer} [length] - An optional length, the total number of elements (from the startIndex) to choose from. + * + * @return {?Phaser.GameObjects.GameObject} A random child from the Container, or `null` if the Container is empty. + */ + getRandom: function (startIndex, length) + { + return ArrayUtils.GetRandom(this.list, startIndex, length); + }, + + /** + * Gets the first Game Object in this Container. + * + * You can also specify a property and value to search for, in which case it will return the first + * Game Object in this Container with a matching property and / or value. + * + * For example: `getFirst('visible', true)` would return the first Game Object that had its `visible` property set. + * + * You can limit the search to the `startIndex` - `endIndex` range. + * + * @method Phaser.GameObjects.Container#getFirst + * @since 3.4.0 + * + * @param {string} [property] - The property to test on each Game Object in the Container. + * @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check. + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {?Phaser.GameObjects.GameObject} The first matching Game Object, or `null` if none was found. + */ + getFirst: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetFirstElement(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns all Game Objects in this Container. + * + * You can optionally specify a matching criteria using the `property` and `value` arguments. + * + * For example: `getAll('body')` would return only Game Objects that have a body property. + * + * You can also specify a value to compare the property to: + * + * `getAll('visible', true)` would return only Game Objects that have their visible property set to `true`. + * + * Optionally you can specify a start and end index. For example if this Container had 100 Game Objects, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 Game Objects. + * + * @method Phaser.GameObjects.Container#getAll + * @since 3.4.0 + * + * @param {string} [property] - The property to test on each Game Object in the Container. + * @param {*} [value] - If property is set then the `property` must strictly equal this value to be included in the results. + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {Phaser.GameObjects.GameObject[]} An array of matching Game Objects from this Container. + */ + getAll: function (property, value, startIndex, endIndex) + { + return ArrayUtils.GetAll(this.list, property, value, startIndex, endIndex); + }, + + /** + * Returns the total number of Game Objects in this Container that have a property + * matching the given value. + * + * For example: `count('visible', true)` would count all the elements that have their visible property set. + * + * You can optionally limit the operation to the `startIndex` - `endIndex` range. + * + * @method Phaser.GameObjects.Container#count + * @since 3.4.0 + * + * @param {string} property - [description] + * @param {*} value - [description] + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {integer} The total number of Game Objects in this Container with a property matching the given value. + */ + count: function (property, value, startIndex, endIndex) + { + return ArrayUtils.CountAllMatching(this.list, property, value, startIndex, endIndex); + }, + + /** + * Swaps the position of two Game Objects in this Container. + * Both Game Objects must belong to this Container. + * + * @method Phaser.GameObjects.Container#swap + * @since 3.4.0 + * + * @genericUse {T} - [child1,child2] + * + * @param {Phaser.GameObjects.GameObject} child1 - The first Game Object to swap. + * @param {Phaser.GameObjects.GameObject} child2 - The second Game Object to swap. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + swap: function (child1, child2) + { + ArrayUtils.Swap(this.list, child1, child2); + + return this; + }, + + /** + * Moves a Game Object to a new position within this Container. + * + * The Game Object must already be a child of this Container. + * + * The Game Object is removed from its old position and inserted into the new one. + * Therefore the Container size does not change. Other children will change position accordingly. + * + * @method Phaser.GameObjects.Container#moveTo + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to move. + * @param {integer} index - The new position of the Game Object in this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + moveTo: function (child, index) + { + ArrayUtils.MoveTo(this.list, child, index); + + return this; + }, + + /** + * Removes the given Game Object, or array of Game Objects, from this Container. + * + * The Game Objects must already be children of this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#remove + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to be removed from the Container. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each child successfully removed from this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + remove: function (child, destroyChild) + { + var removed = ArrayUtils.Remove(this.list, child, this.removeHandler, this); + + if (destroyChild && removed) + { + if (!Array.isArray(removed)) + { + removed = [ removed ]; + } + + for (var i = 0; i < removed.length; i++) + { + removed[i].destroy(); + } + } + + return this; + }, + + /** + * Removes the Game Object at the given position in this Container. + * + * You can also optionally call `destroy` on the Game Object, if one is found. + * + * @method Phaser.GameObjects.Container#removeAt + * @since 3.4.0 + * + * @genericUse {T} - [$return] + * + * @param {integer} index - The index of the Game Object to be removed. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + removeAt: function (index) + { + var removed = ArrayUtils.RemoveAt(this.list, index, this.removeHandler, this); + + if (destroyChild && removed) + { + removed.destroy(); + } + + return this; + }, + + /** + * Removes the Game Objects between the given positions in this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#removeBetween + * @since 3.4.0 + * + * @genericUse {T[]} - [$return] + * + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + removeBetween: function (startIndex, endIndex, destroyChild) + { + var removed = ArrayUtils.RemoveBetween(this.list, startIndex, endIndex, this.removeHandler, this); + + if (destroyChild) + { + for (var i = 0; i < removed.length; i++) + { + removed[i].destroy(); + } + } + + return this; + }, + + /** + * Removes all Game Objects from this Container. + * + * You can also optionally call `destroy` on each Game Object that is removed from the Container. + * + * @method Phaser.GameObjects.Container#removeAll + * @since 3.4.0 + * + * @genericUse {Phaser.GameObjects.Container.} - [$return] + * + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + removeAll: function (destroyChild) + { + var removed = ArrayUtils.RemoveBetween(this.list, 0, this.list.length, this.removeHandler, this); + + if (destroyChild) + { + for (var i = 0; i < removed.length; i++) + { + removed[i].destroy(); + } + } + + return this; + }, + + /** + * Brings the given Game Object to the top of this Container. + * This will cause it to render on-top of any other objects in the Container. + * + * @method Phaser.GameObjects.Container#bringToTop + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to bring to the top of the Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + bringToTop: function (child) + { + ArrayUtils.BringToTop(this.list, child); + + return this; + }, + + /** + * Sends the given Game Object to the bottom of this Container. + * This will cause it to render below any other objects in the Container. + * + * @method Phaser.GameObjects.Container#sendToBack + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to send to the bottom of the Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + sendToBack: function (child) + { + ArrayUtils.SendToBack(this.list, child); + + return this; + }, + + /** + * Moves the given Game Object up one place in this Container, unless it's already at the top. + * + * @method Phaser.GameObjects.Container#moveUp + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + moveUp: function (child) + { + ArrayUtils.MoveUp(this.list, child); + + return this; + }, + + /** + * Moves the given Game Object down one place in this Container, unless it's already at the bottom. + * + * @method Phaser.GameObjects.Container#moveDown + * @since 3.4.0 + * + * @genericUse {T} - [child,$return] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + moveDown: function (child) + { + ArrayUtils.MoveDown(this.list, child); + + return this; + }, + + /** + * Reverses the order of all Game Objects in this Container. + * + * @method Phaser.GameObjects.Container#reverse + * @since 3.4.0 + * + * @genericUse {Phaser.GameObjects.Container.} - [$return] + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + reverse: function () + { + this.list.reverse(); + + return this; + }, + + /** + * Shuffles the all Game Objects in this Container using the Fisher-Yates implementation. + * + * @method Phaser.GameObjects.Container#shuffle + * @since 3.4.0 + * + * @genericUse {Phaser.GameObjects.Container.} - [$return] + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + shuffle: function () + { + ArrayUtils.Shuffle(this.list); + + return this; + }, + + /** + * Replaces a Game Object in this Container with the new Game Object. + * The new Game Object cannot already be a child of this Container. + * + * @method Phaser.GameObjects.Container#replace + * @since 3.4.0 + * + * @genericUse {T} - [oldChild,newChild,$return] + * + * @param {Phaser.GameObjects.GameObject} oldChild - The Game Object in this Container that will be replaced. + * @param {Phaser.GameObjects.GameObject} newChild - The Game Object to be added to this Container. + * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + replace: function (oldChild, newChild, destroyChild) + { + var moved = ArrayUtils.Replace(this.list, oldChild, newChild); + + if (moved) + { + this.addHandler(newChild); + this.removeHandler(oldChild); + + if (destroyChild) + { + oldChild.destroy(); + } + } + + return this; + }, + + /** + * Returns `true` if the given Game Object is a direct child of this Container. + * + * This check does not scan nested Containers. + * + * @method Phaser.GameObjects.Container#exists + * @since 3.4.0 + * + * @genericUse {T} - [child] + * + * @param {Phaser.GameObjects.GameObject} child - The Game Object to check for within this Container. + * + * @return {boolean} True if the Game Object is an immediate child of this Container, otherwise false. + */ + exists: function (child) + { + return (this.list.indexOf(child) > -1); + }, + + /** + * Sets the property to the given value on all Game Objects in this Container. + * + * Optionally you can specify a start and end index. For example if this Container had 100 Game Objects, + * and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only + * the first 50 Game Objects. + * + * @method Phaser.GameObjects.Container#setAll + * @since 3.4.0 + * + * @genericUse {T} - [value] + * + * @param {string} property - The property that must exist on the Game Object. + * @param {*} value - The value to get the property to. + * @param {integer} [startIndex=0] - An optional start index to search from. + * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + setAll: function (property, value, startIndex, endIndex) + { + ArrayUtils.SetAll(this.list, property, value, startIndex, endIndex); + + return this; + }, + + /** + * Passes all Game Objects in this Container to the given callback. + * + * A copy of the Container is made before passing each entry to your callback. + * This protects against the callback itself modifying the Container. + * + * If you know for sure that the callback will not change the size of this Container + * then you can use the more performant `Container.iterate` method instead. + * + * @method Phaser.GameObjects.Container#each + * @since 3.4.0 + * + * @genericUse {EachListCallback.} - [callback] + * + * @param {EachListCallback} callback - The function to call. + * @param {*} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + each: function (callback, context) + { + var args = [ null ]; + var i; + var temp = this.list.slice(); + var len = temp.length; + + for (i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < len; i++) + { + args[0] = temp[i]; + + callback.apply(context, args); + } + + return this; + }, + + /** + * Passes all Game Objects in this Container to the given callback. + * + * Only use this method when you absolutely know that the Container will not be modified during + * the iteration, i.e. by removing or adding to its contents. + * + * @method Phaser.GameObjects.Container#iterate + * @since 3.4.0 + * + * @genericUse {EachListCallback.} - [callback] + * + * @param {EachListCallback} callback - The function to call. + * @param {*} [context] - Value to use as `this` when executing callback. + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + * + * @return {Phaser.GameObjects.Container} This Container instance. + */ + iterate: function (callback, context) + { + var args = [ null ]; + var i; + + for (i = 2; i < arguments.length; i++) + { + args.push(arguments[i]); + } + + for (i = 0; i < this.list.length; i++) + { + args[0] = this.list[i]; + + callback.apply(context, args); + } + + return this; + }, + + /** + * The number of Game Objects inside this Container. + * + * @name Phaser.GameObjects.Container#length + * @type {integer} + * @readOnly + * @since 3.4.0 + */ + length: { + + get: function () + { + return this.list.length; + } + + }, + + /** + * Returns the first Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#first + * @type {?Phaser.GameObjects.GameObject} + * @readOnly + * @since 3.4.0 + */ + first: { + + get: function () + { + this.position = 0; + + if (this.list.length > 0) + { + return this.list[0]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the last Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#last + * @type {?Phaser.GameObjects.GameObject} + * @readOnly + * @since 3.4.0 + */ + last: { + + get: function () + { + if (this.list.length > 0) + { + this.position = this.list.length - 1; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the next Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#next + * @type {?Phaser.GameObjects.GameObject} + * @readOnly + * @since 3.4.0 + */ + next: { + + get: function () + { + if (this.position < this.list.length) + { + this.position++; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Returns the previous Game Object within the Container, or `null` if it is empty. + * + * You can move the cursor by calling `Container.next` and `Container.previous`. + * + * @name Phaser.GameObjects.Container#previous + * @type {?Phaser.GameObjects.GameObject} + * @readOnly + * @since 3.4.0 + */ + previous: { + + get: function () + { + if (this.position > 0) + { + this.position--; + + return this.list[this.position]; + } + else + { + return null; + } + } + + }, + + /** + * Destroys this Container, removing it from the Display List. + * + * If `Container.exclusive` is `true` then it will also destroy all children. * * Use this to remove a Container from your game if you don't ever plan to use it again. * As long as no reference to it exists within your own code it should become free for - * garbage collection by the browser. + * garbage collection. * * If you just want to temporarily disable an object then look at using the * Game Object Pool instead of destroying it, as destroyed objects cannot be resurrected. @@ -282,46 +1064,15 @@ var Container = new Class({ */ destroy: function () { - // This Game Object had already been destroyed - if (!this.scene) - { - return; - } + this.removeAll(this.exclusive); - if (this.preDestroy) - { - this.preDestroy.call(this); - } - - this.emit('destroy', this); - - var sys = this.scene.sys; - - sys.displayList.remove(this); - - if (this.data) - { - this.data.destroy(); - - this.data = undefined; - } - - // Tell the Scene to re-sort the children - sys.queueDepthSort(); - - this.active = false; - this.visible = false; - - this.scene = undefined; - - this.removeAllListeners(); - - this.removeAll(); + this.localTransform.destroy(); + this.tempTransformMatrix.destroy(); this.list = []; + this._displayList = null; - this.parent = null; - this.parentContainer = null; + GameObject.prototype.destroy.call(this); } }); From c5cc126a6e15f8cb12ee69dfe49e528a1aa0f89e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 15:55:06 +0100 Subject: [PATCH 54/87] Updated change log --- CHANGELOG.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57048c8c5..62a502932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,13 @@ ### New Features -* A new property was added to Matter.World, `correction` which is used in the Engine.update call and allows you to adjust the time -being passed to the simulation. The default value is 1 to remain consistent with previous releases. -* Group.destroy has a new optional argument `destroyChildren` which will automatically call `destroy` on all children of a Group if set to true (the default is false, hence it doesn't change the public API). Fix #3246 (thanks @DouglasLapsley) +* A new property was added to Matter.World, `correction` which is used in the Engine.update call and allows you to adjust the time being passed to the simulation. The default value is 1 to remain consistent with previous releases. * Matter Physics now has a new config property `getDelta` which allows you to specify your own function to calculate the delta value given to the Matter Engine when it updates. * Matter Physics has two new methods: `set60Hz` and `set30Hz` which will set an Engine update rate of 60Hz and 30Hz respectively. 60Hz being the default. * Matter Physics has a new config and run-time property `autoUpdate`, which defaults to `true`. When enabled the Matter Engine will update in sync with the game step (set by Request Animation Frame). The delta value given to Matter is now controlled by the `getDelta` function. * Matter Physics has a new method `step` which manually advances the physics simulation by one iteration, using whatever delta and correction values you pass in to it. When used in combination with `autoUpdate=false` you can now explicitly control the update frequency of the physics simulation and unbind it from the game step. +* Matter Physics has two new debug properties: `debugShowJoint` and `debugJointColor`. If defined they will display joints in Matter bodies during the postUpdate debug phase (only if debug is enabled) (thanks @OmarShehata) +* Group.destroy has a new optional argument `destroyChildren` which will automatically call `destroy` on all children of a Group if set to true (the default is false, hence it doesn't change the public API). Fix #3246 (thanks @DouglasLapsley) * WebAudioSound.setMute is a chainable way to mute a single Sound instance. * WebAudioSound.setVolume is a chainable way to set the volume of a single Sound instance. * WebAudioSound.setSeek is a chainable way to set seek to a point of a single Sound instance. @@ -20,7 +20,6 @@ being passed to the simulation. The default value is 1 to remain consistent with * HTML5AudioSound.setSeek is a chainable way to set seek to a point of a single Sound instance. * HTML5AudioSound.setLoop is a chainable way to set the loop state of a single Sound instance. * BitmapText has a new property `letterSpacing` which accepts a positive or negative number to add / reduce spacing between characters (thanks @wtravO) -* Matter Physics has two new debug properties: `debugShowJoint` and `debugJointColor`. If defined they will display joints in Matter bodies during the postUpdate debug phase (only if debug is enabled) (thanks @OmarShehata) * You can now pass a Sprite Sheet or Canvas as the Texture key to `Tilemap.addTileset` and it will work in WebGL, where-as before it would display a corrupted tilemap. Fix #3407 (thanks @Zykino) * Graphics.slice allows you to easily draw a Pacman, or slice of pie shape to a Graphics object. * List.addCallback is a new optional callback that is invoked every time a new child is added to the List. You can use this to have a callback fire when children are added to the Display List. From 1eaee870c7334f8d9823eea0a1f3e3a2a9b1f323 Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Tue, 10 Apr 2018 13:25:13 -0300 Subject: [PATCH 55/87] Set rotation of container to be negative at render time. Removed unnecessary call to multiply on TransformMatrix rotate --- src/gameobjects/components/TransformMatrix.js | 12 +++++++++++- src/gameobjects/container/ContainerCanvasRenderer.js | 4 ++-- src/gameobjects/container/ContainerWebGLRenderer.js | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/gameobjects/components/TransformMatrix.js b/src/gameobjects/components/TransformMatrix.js index f0e2523d0..682ab37b9 100644 --- a/src/gameobjects/components/TransformMatrix.js +++ b/src/gameobjects/components/TransformMatrix.js @@ -317,8 +317,18 @@ var TransformMatrix = new Class({ { var radianSin = Math.sin(radian); var radianCos = Math.cos(radian); + var matrix = this.matrix; + var a = matrix[0]; + var b = matrix[1]; + var c = matrix[2]; + var d = matrix[3]; - return this.transform(radianCos, radianSin, -radianSin, radianCos, 0, 0); + matrix[0] = a * radianCos + c * radianSin; + matrix[1] = b * radianCos + d * radianSin; + matrix[2] = a * -radianSin + c * radianCos; + matrix[3] = b * -radianSin + d * radianCos; + + return this; }, /** diff --git a/src/gameobjects/container/ContainerCanvasRenderer.js b/src/gameobjects/container/ContainerCanvasRenderer.js index 9e98f45ed..eebb87896 100644 --- a/src/gameobjects/container/ContainerCanvasRenderer.js +++ b/src/gameobjects/container/ContainerCanvasRenderer.js @@ -34,14 +34,14 @@ var ContainerCanvasRenderer = function (renderer, container, interpolationPercen if (parentMatrix === undefined) { - transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); + transformMatrix.applyITRS(container.x, container.y, -container.rotation, container.scaleX, container.scaleY); } else { transformMatrix.loadIdentity(); transformMatrix.multiply(parentMatrix); transformMatrix.translate(container.x, container.y); - transformMatrix.rotate(container.rotation); + transformMatrix.rotate(-container.rotation); transformMatrix.scale(container.scaleX, container.scaleY); } diff --git a/src/gameobjects/container/ContainerWebGLRenderer.js b/src/gameobjects/container/ContainerWebGLRenderer.js index c00af31f5..7432e6632 100644 --- a/src/gameobjects/container/ContainerWebGLRenderer.js +++ b/src/gameobjects/container/ContainerWebGLRenderer.js @@ -34,14 +34,14 @@ var ContainerWebGLRenderer = function (renderer, container, interpolationPercent if (parentMatrix === undefined) { - transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); + transformMatrix.applyITRS(container.x, container.y, -container.rotation, container.scaleX, container.scaleY); } else { transformMatrix.loadIdentity(); transformMatrix.multiply(parentMatrix); transformMatrix.translate(container.x, container.y); - transformMatrix.rotate(container.rotation); + transformMatrix.rotate(-container.rotation); transformMatrix.scale(container.scaleX, container.scaleY); } From 1fa909081cab0a1bc7590b0cbeee5831d7872ced Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 10 Apr 2018 17:35:14 +0100 Subject: [PATCH 56/87] eslint fixes --- src/gameobjects/container/Container.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 91a2c2b3f..f7e2de55b 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -340,7 +340,7 @@ var Container = new Class({ { this._sortKey = property; - StableSort.inplace(this.list, this.sortHandler); + ArrayUtils.StableSort.inplace(this.list, this.sortHandler); } return this; @@ -577,7 +577,7 @@ var Container = new Class({ * * @return {Phaser.GameObjects.Container} This Container instance. */ - removeAt: function (index) + removeAt: function (index, destroyChild) { var removed = ArrayUtils.RemoveAt(this.list, index, this.removeHandler, this); From 14a651e50918a233ada35476277bf8a0b9a56018 Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Tue, 10 Apr 2018 14:13:23 -0300 Subject: [PATCH 57/87] Fixed inverted rotation on TransformMatrix --- src/gameobjects/components/TransformMatrix.js | 12 ++++++------ src/gameobjects/container/ContainerCanvasRenderer.js | 4 ++-- src/gameobjects/container/ContainerWebGLRenderer.js | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/gameobjects/components/TransformMatrix.js b/src/gameobjects/components/TransformMatrix.js index 682ab37b9..a3d94d3d7 100644 --- a/src/gameobjects/components/TransformMatrix.js +++ b/src/gameobjects/components/TransformMatrix.js @@ -558,18 +558,18 @@ var TransformMatrix = new Class({ { var matrix = this.matrix; - var sr = Math.sin(rotation); - var cr = Math.cos(rotation); + var radianSin = Math.sin(rotation); + var radianCos = Math.cos(rotation); // Translate matrix[4] = x; matrix[5] = y; // Rotate and Scale - matrix[0] = cr * scaleX; - matrix[1] = -sr * scaleX; - matrix[2] = sr * scaleY; - matrix[3] = cr * scaleY; + matrix[0] = radianCos * scaleX; + matrix[1] = radianSin * scaleX; + matrix[2] = -radianSin * scaleY; + matrix[3] = radianCos * scaleY; return this; }, diff --git a/src/gameobjects/container/ContainerCanvasRenderer.js b/src/gameobjects/container/ContainerCanvasRenderer.js index eebb87896..9e98f45ed 100644 --- a/src/gameobjects/container/ContainerCanvasRenderer.js +++ b/src/gameobjects/container/ContainerCanvasRenderer.js @@ -34,14 +34,14 @@ var ContainerCanvasRenderer = function (renderer, container, interpolationPercen if (parentMatrix === undefined) { - transformMatrix.applyITRS(container.x, container.y, -container.rotation, container.scaleX, container.scaleY); + transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); } else { transformMatrix.loadIdentity(); transformMatrix.multiply(parentMatrix); transformMatrix.translate(container.x, container.y); - transformMatrix.rotate(-container.rotation); + transformMatrix.rotate(container.rotation); transformMatrix.scale(container.scaleX, container.scaleY); } diff --git a/src/gameobjects/container/ContainerWebGLRenderer.js b/src/gameobjects/container/ContainerWebGLRenderer.js index 7432e6632..c00af31f5 100644 --- a/src/gameobjects/container/ContainerWebGLRenderer.js +++ b/src/gameobjects/container/ContainerWebGLRenderer.js @@ -34,14 +34,14 @@ var ContainerWebGLRenderer = function (renderer, container, interpolationPercent if (parentMatrix === undefined) { - transformMatrix.applyITRS(container.x, container.y, -container.rotation, container.scaleX, container.scaleY); + transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY); } else { transformMatrix.loadIdentity(); transformMatrix.multiply(parentMatrix); transformMatrix.translate(container.x, container.y); - transformMatrix.rotate(-container.rotation); + transformMatrix.rotate(container.rotation); transformMatrix.scale(container.scaleX, container.scaleY); } From b6480a0db7a67473f705f840ad0cd5a88b85fd5a Mon Sep 17 00:00:00 2001 From: Sean Bohan Date: Wed, 11 Apr 2018 04:51:34 +0800 Subject: [PATCH 58/87] Fix animationcomplete event name typo --- src/gameobjects/components/Animation.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gameobjects/components/Animation.js b/src/gameobjects/components/Animation.js index 8002b105a..daed8c2b9 100644 --- a/src/gameobjects/components/Animation.js +++ b/src/gameobjects/components/Animation.js @@ -8,7 +8,7 @@ var Class = require('../../utils/Class'); /** * This event is dispatched when an animation starts playing. - * + * * @event Phaser.GameObjects.Components.Animation#onStartEvent * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. @@ -16,7 +16,7 @@ var Class = require('../../utils/Class'); /** * This event is dispatched when an animation repeats. - * + * * @event Phaser.GameObjects.Components.Animation#onRepeatEvent * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. @@ -26,7 +26,7 @@ var Class = require('../../utils/Class'); /** * This event is dispatched when an animation updates. This happens when the animation frame changes, * based on the animation frame rate and other factors like timeScale and delay. - * + * * @event Phaser.GameObjects.Components.Animation#onUpdateEvent * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. @@ -34,7 +34,7 @@ var Class = require('../../utils/Class'); /** * This event is dispatched when an animation completes playing, either naturally or via Animation.stop. - * + * * @event Phaser.GameObjects.Components.Animation#onCompleteEvent * @param {Phaser.Animations.Animation} animation - Reference to the currently playing animation. * @param {Phaser.Animations.AnimationFrame} frame - Reference to the current Animation Frame. @@ -281,7 +281,7 @@ var Animation = new Class({ /** * Internal property tracking if this Animation is waiting to stop. - * + * * 0 = No * 1 = Waiting for ms to pass * 2 = Waiting for repeat @@ -625,7 +625,7 @@ var Animation = new Class({ /** * Gets the amount of delay between repeats, if any. - * + * * @method Phaser.GameObjects.Components.Animation#getRepeatDelay * @since 3.4.0 * @@ -700,7 +700,7 @@ var Animation = new Class({ var gameObject = this.parent; - gameObject.emit('animtioncomplete', this.currentAnim, this.currentFrame); + gameObject.emit('animationcomplete', this.currentAnim, this.currentFrame); return gameObject; }, @@ -830,7 +830,7 @@ var Animation = new Class({ return this.currentAnim.completeAnimation(this); } } - + if (this.accumulator >= this.nextTick) { this.currentAnim.setFrame(this); From 97cd94b3de58a304e44d77f6066af2e3b2020f74 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 02:18:30 +0100 Subject: [PATCH 59/87] Updated log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a502932..d90a06b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ * Tween.restart handles removed tweens properly and reads them back into the active queue for the TweenManager (thanks @wtravO) * Tween.resume will now call `Tween.play` on a tween that was paused due to its config object, not as a result of having its paused method called. Fix #3452 (thanks @jazen) * LoaderPlugin.isReady referenced a constant that no longer exists. Fix #3503 (thanks @Twilrom) +* Tween Timeline.destroy was trying to call `destroy` on Tweens instead of `stop` (thanks @Antriel) ### Updates From 8ee98055967301556d1cc4e54280b50089cab409 Mon Sep 17 00:00:00 2001 From: Joe Janiga Date: Wed, 11 Apr 2018 00:16:08 -0400 Subject: [PATCH 60/87] work in progress on Static Body offset functionality... should Sprite.setPosition(x,y) effect Sprites static body? --- src/physics/arcade/StaticBody.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/physics/arcade/StaticBody.js b/src/physics/arcade/StaticBody.js index 9392a88c0..66bf87de6 100644 --- a/src/physics/arcade/StaticBody.js +++ b/src/physics/arcade/StaticBody.js @@ -443,8 +443,14 @@ var StaticBody = new Class({ this.world.staticTree.remove(this); + this.position.x -= this.offset.x; + this.position.y -= this.offset.y; + this.offset.set(x, y); + this.position.x += this.offset.x; + this.position.y += this.offset.y; + this.updateCenter(); this.world.staticTree.insert(this); From d089e16345fbbeea255a18a6d2ec3cd9eb2c6a2b Mon Sep 17 00:00:00 2001 From: jdotrjs Date: Tue, 10 Apr 2018 23:11:14 -0700 Subject: [PATCH 61/87] [fixes #3535] Fix constructed bounding box functions for RTree The previous patch didn't take into account that the accessors passed in as the format array were dot-prefixed due to the previous eval-based construction. The only two uses of RTree that I found were in World.js: ```javascript this.tree = new RTree(this.maxEntries, [ '.left', '.top', '.right', '.bottom' ]); this.staticTree = new RTree(this.maxEntries, [ '.left', '.top', '.right', '.bottom' ]); ``` It's likely that this could be updated to just not pass dotted attribute names but I wasn't super comfortable that they weren't needed in this form elsewhere despite a quick search. I'd honestly say that it might be a better change if we remove the dots before merge but I'll leave that up to the discretion of the reviewers/merger. I'm not super familiar with Phaser's style but I passed lint sooo :D Buyer beware: the only testing I did was on the repo case I left in the bug and I did not verify that this is still within the twitch CSP (though it should be). --- src/structs/RTree.js | 50 +++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/structs/RTree.js b/src/structs/RTree.js index 54bd90917..5d4fba0af 100644 --- a/src/structs/RTree.js +++ b/src/structs/RTree.js @@ -465,31 +465,43 @@ rbush.prototype = { _initFormat: function (format) { - // data format (minX, minY, maxX, maxY accessors) + // format: [minX, minY, maxX, maxY accessors] + // accessors will be dotted names + + // Because we have historically used eval-based function constructor + // the format accerrsors need to have their leading dots stripped to + // obtain the actual accessor + format = format.map( + function (f) + { + return f.substring(1) + } + ) // Do not use string-generated Functions for CSP policies - // Instead a combination of anonymous functions and grabbing - // properties by string is used. - var compareArr = function (accessor) - { - return function (a, b) - { - return this[a + accessor] - this[b + accessor]; - }; - }; + // Instead a combination of anonymous functions and grabbing properties + // by string is used. + // cf. https://github.com/photonstorm/phaser/issues/3441 + // and https://github.com/photonstorm/phaser/issues/3535 - this.compareMinX = compareArr(format[0]); - this.compareMinY = compareArr(format[1]); + var mkCompareFn = function(attr) { + return function(a, b) { + return a[attr] - b[attr] + } + } - this.toBBox = function (a) + this.compareMinX = mkCompareFn(format[0]) + this.compareMinY = mkCompareFn(format[1]) + + this.toBBox = function(a) { return { - minX: a + format[0], - minY: a + format[1], - maxX: a + format[2], - maxy: a + format[3] - }; - }; + minX: a[format[0]], + minY: a[format[1]], + maxX: a[format[2]], + maxY: a[format[3]], + } + } } }; From 6c6d5f4aa17d28c76540916b78affd81b9488683 Mon Sep 17 00:00:00 2001 From: jdotrjs Date: Tue, 10 Apr 2018 23:49:46 -0700 Subject: [PATCH 62/87] somebody forgot their ;s --- src/structs/RTree.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/structs/RTree.js b/src/structs/RTree.js index 5d4fba0af..be6633040 100644 --- a/src/structs/RTree.js +++ b/src/structs/RTree.js @@ -474,9 +474,9 @@ rbush.prototype = { format = format.map( function (f) { - return f.substring(1) + return f.substring(1); } - ) + ); // Do not use string-generated Functions for CSP policies // Instead a combination of anonymous functions and grabbing properties @@ -486,12 +486,12 @@ rbush.prototype = { var mkCompareFn = function(attr) { return function(a, b) { - return a[attr] - b[attr] - } - } + return a[attr] - b[attr]; + }; + }; - this.compareMinX = mkCompareFn(format[0]) - this.compareMinY = mkCompareFn(format[1]) + this.compareMinX = mkCompareFn(format[0]); + this.compareMinY = mkCompareFn(format[1]); this.toBBox = function(a) { @@ -500,8 +500,8 @@ rbush.prototype = { minY: a[format[1]], maxX: a[format[2]], maxY: a[format[3]], - } - } + }; + }; } }; From cd42ce981aeb2bee60b72a74912d4c76bb3021cf Mon Sep 17 00:00:00 2001 From: Hua Date: Wed, 11 Apr 2018 16:29:29 +0800 Subject: [PATCH 63/87] Add destroy event of sound object Add destroy event of sound object --- src/sound/BaseSound.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/BaseSound.js b/src/sound/BaseSound.js index 4959d36cc..942ff4f28 100644 --- a/src/sound/BaseSound.js +++ b/src/sound/BaseSound.js @@ -522,6 +522,7 @@ var BaseSound = new Class({ return; } + this.emit('destroy', this); this.pendingRemove = true; this.manager = null; this.key = ''; From 978c1790545b271527b182410a3bb30424bf547a Mon Sep 17 00:00:00 2001 From: Hua Date: Wed, 11 Apr 2018 16:35:17 +0800 Subject: [PATCH 64/87] Add description of this PR --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d90a06b1c..4896178a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ * Utils.Array.SetAll will set a property on all elements of an array to the given value, with optional range limits. * Utils.Array.Swap will swap the position of two elements in an array. * TransformMatrix.destroy is a new method that will clear out the array and object used by a Matrix internally. +* Add 'destroy' event in sound object. ### Bug Fixes From 3e223211aa8ed95a59120c66359d1e914949e932 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 10:12:31 +0100 Subject: [PATCH 65/87] Updated log --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d90a06b1c..4d4fc7553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,7 +73,7 @@ ### Updates -* The RTree library (rbush) used by Phaser 3 suffered from violating CSP policies by dynamically creating Functions at run-time in an eval-like manner. These are now defined via generators. Fix #3441 (thanks @jamierocks @Colbydude) +* The RTree library (rbush) used by Phaser 3 suffered from violating CSP policies by dynamically creating Functions at run-time in an eval-like manner. These are now defined via generators. Fix #3441 (thanks @jamierocks @Colbydude @jdotrjs) * BaseSound has had its `rate` and `detune` properties removed as they are always set in the overriding class. * BaseSound `setRate` and `setDetune` from the 3.3.0 release have moved to the WebAudioSound and HTML5AudioSound classes respectively, as they each handle the values differently. * The file `InteractiveObject.js` has been renamed to `CreateInteractiveObject.js` to more accurately reflect what it does and to avoid type errors in the docs. From fc6a7e84f74fe69c2d16cdb7675ccb6108c69c98 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 10:22:44 +0100 Subject: [PATCH 66/87] Updated Change Log --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59e2aed57..17931583d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ * Utils.Array.SetAll will set a property on all elements of an array to the given value, with optional range limits. * Utils.Array.Swap will swap the position of two elements in an array. * TransformMatrix.destroy is a new method that will clear out the array and object used by a Matrix internally. -* Add 'destroy' event in sound object. +* BaseSound, and by extension WebAudioSound and HTMLAudioSound, will now emit a `destroy` event when they are destroyed (thanks @rexrainbow) ### Bug Fixes @@ -71,6 +71,7 @@ * Tween.resume will now call `Tween.play` on a tween that was paused due to its config object, not as a result of having its paused method called. Fix #3452 (thanks @jazen) * LoaderPlugin.isReady referenced a constant that no longer exists. Fix #3503 (thanks @Twilrom) * Tween Timeline.destroy was trying to call `destroy` on Tweens instead of `stop` (thanks @Antriel) +* Calling `setOffset` on a Static Arcade Physics Body would break because the method was missing. It has been added and now functions as expected. Fix #3465 (thanks @josephjaniga and @DouglasLapsley) ### Updates From 7aae84a790eeac4a3b9600dab897e78142acc427 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 10:39:20 +0100 Subject: [PATCH 67/87] Calling Impact.World.remove(body) during a Body.updateCallback would cause the internal loop to crash when trying to access a now missing body. Two extra checks are in place to avoid this --- CHANGELOG.md | 1 + src/physics/impact/World.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4062db935..8b204d84f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ * LoaderPlugin.isReady referenced a constant that no longer exists. Fix #3503 (thanks @Twilrom) * Tween Timeline.destroy was trying to call `destroy` on Tweens instead of `stop` (thanks @Antriel) * Calling `setOffset` on a Static Arcade Physics Body would break because the method was missing. It has been added and now functions as expected. Fix #3465 (thanks @josephjaniga and @DouglasLapsley) +* Calling Impact.World.remove(body) during a Body.updateCallback would cause the internal loop to crash when trying to access a now missing body. Two extra checks are in place to avoid this (thanks @iamDecode) ### Updates diff --git a/src/physics/impact/World.js b/src/physics/impact/World.js index 57830ccc6..b12db67c0 100644 --- a/src/physics/impact/World.js +++ b/src/physics/impact/World.js @@ -632,7 +632,7 @@ var World = new Class({ { body = bodies[i]; - if (!body.skipHash()) + if (body && !body.skipHash()) { this.checkHash(body, hash, size); } @@ -648,7 +648,7 @@ var World = new Class({ { body = bodies[i]; - if (body.willDrawDebug()) + if (body && body.willDrawDebug()) { body.drawDebug(graphics); } From e135f132d90c11851785a2e14436007bc39d7f2c Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 11:25:11 +0100 Subject: [PATCH 68/87] Added missing properties needed for input to work --- src/gameobjects/container/Container.js | 48 ++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index f7e2de55b..bcf708e45 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -91,7 +91,7 @@ var Container = new Class({ this.position = 0; /** - * [description] + * Internal Transform Matrix used for local space conversion. * * @name Phaser.GameObjects.Container#localTransform * @type {Phaser.GameObjects.Components.TransformMatrix} @@ -100,7 +100,7 @@ var Container = new Class({ this.localTransform = new Components.TransformMatrix(); /** - * [description] + * Internal temporary Transform Matrix used to avoid object creation. * * @name Phaser.GameObjects.Container#tempTransformMatrix * @type {Phaser.GameObjects.Components.TransformMatrix} @@ -128,6 +128,50 @@ var Container = new Class({ */ this._sortKey = ''; + /** + * Internal value to allow Containers to be used for input. + * Do not change this value. It has no effect other than to break input. + * + * @name Phaser.GameObjects.Container#displayOriginX + * @type {number} + * @private + * @since 3.4.0 + */ + this.displayOriginX = 0; + + /** + * Internal value to allow Containers to be used for input. + * Do not change this value. It has no effect other than to break input. + * + * @name Phaser.GameObjects.Container#displayOriginY + * @type {number} + * @private + * @since 3.4.0 + */ + this.displayOriginY = 0; + + /** + * Internal value to allow Containers to be used for input. + * Do not change this value. It has no effect other than to break input. + * + * @name Phaser.GameObjects.Container#scrollFactorX + * @type {number} + * @private + * @since 3.4.0 + */ + this.scrollFactorX = 1; + + /** + * Internal value to allow Containers to be used for input. + * Do not change this value. It has no effect other than to break input. + * + * @name Phaser.GameObjects.Container#scrollFactorY + * @type {number} + * @private + * @since 3.4.0 + */ + this.scrollFactorY = 1; + this.setPosition(x, y); this.clearAlpha(); From 60cd5ab22bf8b986443866fac740668e6c1f3c85 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 11:25:31 +0100 Subject: [PATCH 69/87] Tighter dropzone test and container warning --- src/input/InputPlugin.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/input/InputPlugin.js b/src/input/InputPlugin.js index fc2ba53ef..6be7bcc9d 100644 --- a/src/input/InputPlugin.js +++ b/src/input/InputPlugin.js @@ -422,7 +422,10 @@ var InputPlugin = new Class({ this.setHitArea(gameObject, shape, callback); } - gameObject.input.dropZone = dropZone; + if (gameObject.input) + { + gameObject.input.dropZone = dropZone; + } return this; }, @@ -1154,6 +1157,13 @@ var InputPlugin = new Class({ for (var i = 0; i < gameObjects.length; i++) { var gameObject = gameObjects[i]; + + if (gameObject.type === 'Container') + { + console.warn('Container.setInteractive() must specify a Shape'); + continue; + } + var frame = gameObject.frame; var width = 0; From 28744bd0a365ba8e310b96cd2010a268094146a0 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 11:25:40 +0100 Subject: [PATCH 70/87] Updated change log --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b204d84f..b04877c63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ * Tween Timeline.destroy was trying to call `destroy` on Tweens instead of `stop` (thanks @Antriel) * Calling `setOffset` on a Static Arcade Physics Body would break because the method was missing. It has been added and now functions as expected. Fix #3465 (thanks @josephjaniga and @DouglasLapsley) * Calling Impact.World.remove(body) during a Body.updateCallback would cause the internal loop to crash when trying to access a now missing body. Two extra checks are in place to avoid this (thanks @iamDecode) +* If `setInteractive` is called on a Game Object that fails to set a hit area, it will no longer try to assign `dropZone` to an undefined `input` property. ### Updates From ffd1d218e61781324e6e2f08930bdbc5381ab4f8 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 12:44:37 +0100 Subject: [PATCH 71/87] Rectangle.Union will now cache all vars internally so you can use one of the input rectangles as the output rectangle without corrupting it. --- CHANGELOG.md | 1 + src/geom/rectangle/Union.js | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b04877c63..b27a4e56c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ * List.sort no longer takes an array as its argument, instead it only sorts the List contents by the defined property. * List.addMultiple has been removed. Used `List.add` instead which offers the exact same functionality. * List is now internally using all of the new Utils.Array functions. +* Rectangle.Union will now cache all vars internally so you can use one of the input rectangles as the output rectangle without corrupting it. ### Animation System Updates diff --git a/src/geom/rectangle/Union.js b/src/geom/rectangle/Union.js index 17b24766a..c73f000d9 100644 --- a/src/geom/rectangle/Union.js +++ b/src/geom/rectangle/Union.js @@ -24,15 +24,13 @@ var Union = function (rectA, rectB, out) { if (out === undefined) { out = new Rectangle(); } + // Cache vars so we can use one of the input rects as the output rect var x = Math.min(rectA.x, rectB.x); var y = Math.min(rectA.y, rectB.y); + var w = Math.max(rectA.right, rectB.right) - x; + var h = Math.max(rectA.bottom, rectB.bottom) - y; - return out.setTo( - x, - y, - Math.max(rectA.right, rectB.right) - x, - Math.max(rectA.bottom, rectB.bottom) - y - ); + return out.setTo(x, y,w, h); }; module.exports = Union; From 9eeef7e33e3f52266a9592fbdb459e924f3c58f7 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:17:16 +0100 Subject: [PATCH 72/87] lint --- src/geom/rectangle/Union.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geom/rectangle/Union.js b/src/geom/rectangle/Union.js index c73f000d9..f9fdaebb6 100644 --- a/src/geom/rectangle/Union.js +++ b/src/geom/rectangle/Union.js @@ -30,7 +30,7 @@ var Union = function (rectA, rectB, out) var w = Math.max(rectA.right, rectB.right) - x; var h = Math.max(rectA.bottom, rectB.bottom) - y; - return out.setTo(x, y,w, h); + return out.setTo(x, y, w, h); }; module.exports = Union; From 2c37ce106d602cc2f8eeb5545edd365c5d63a241 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:17:26 +0100 Subject: [PATCH 73/87] Added default TMs --- src/gameobjects/components/Transform.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gameobjects/components/Transform.js b/src/gameobjects/components/Transform.js index d79f9135d..b725b9d6c 100644 --- a/src/gameobjects/components/Transform.js +++ b/src/gameobjects/components/Transform.js @@ -5,6 +5,7 @@ */ var MATH_CONST = require('../../math/const'); +var TransformMatrix = require('./TransformMatrix'); var WrapAngle = require('../../math/angle/Wrap'); var WrapAngleDegrees = require('../../math/angle/WrapDegrees'); @@ -376,12 +377,14 @@ var Transform = { * @method Phaser.GameObjects.Components.Transform#getLocalTransformMatrix * @since 3.4.0 * - * @param {Phaser.GameObjects.Components.TransformMatrix} tempMatrix - The matrix to populate with the values from this Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object. * * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. */ getLocalTransformMatrix: function (tempMatrix) { + if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); } + return tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY); }, @@ -391,13 +394,21 @@ var Transform = { * @method Phaser.GameObjects.Components.Transform#getWorldTransformMatrix * @since 3.4.0 * - * @param {Phaser.GameObjects.Components.TransformMatrix} tempMatrix - The matrix to populate with the values from this Game Object. + * @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object. * * @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix. */ getWorldTransformMatrix: function (tempMatrix) { + if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); } + var parent = this.parentContainer; + + if (!parent) + { + return tempMatrix(); + } + var parents = []; while (parent) From e2a0a4a5a718fc4c8a745ce01c8e1995a13ba16c Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:17:35 +0100 Subject: [PATCH 74/87] Start of getBounds --- src/gameobjects/container/Container.js | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index bcf708e45..3931f9bea 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -9,7 +9,9 @@ var ArrayUtils = require('../../utils/array'); var Class = require('../../utils/Class'); var Components = require('../components'); var GameObject = require('../GameObject'); +var Rectangle = require('../../geom/rectangle/Rectangle'); var Render = require('./ContainerRender'); +var Union = require('../../geom/rectangle/Union'); var Vector2 = require('../../math/Vector2'); /** @@ -211,6 +213,47 @@ var Container = new Class({ return this; }, + /** + * Gets the bounds of this Container. It works by iterating all children of the Container, + * getting their respective bounds, and then working out a min-max rectangle from that. + * It does not factor in if the children render or not, all are included. + * + * Depending on the quantity of children in this Container it could be a really expensive call, + * so cache it and only poll it as needed. + * + * The values are stored and returned in a Rectangle object. + * + * @method Phaser.GameObjects.Container#getBounds + * @since 3.4.0 + * + * @param {Phaser.Geom.Rectangle} [output] - A Geom.Rectangle object to store the values in. If not provided a new Rectangle will be created. + * + * @return {Phaser.Geom.Rectangle} The values stored in the output object. + */ + getBounds: function (output) + { + if (output === undefined) { output = new Rectangle(); } + + output.setTo(this.x, this.y, 0, 0); + + if (this.list.length > 0) + { + var children = this.list; + var tempRect = new Rectangle(); + + for (var i = 0; i < children.length; i++) + { + var entry = children[i]; + + entry.getBounds(tempRect); + + Union(tempRect, output, output); + } + } + + return output; + }, + /** * Internal add handler. * From 276ae03affbb1b96907e9989f787f76090cb8776 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:17:42 +0100 Subject: [PATCH 75/87] TODO --- src/gameobjects/components/GetBounds.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gameobjects/components/GetBounds.js b/src/gameobjects/components/GetBounds.js index 88413c312..be4a90701 100644 --- a/src/gameobjects/components/GetBounds.js +++ b/src/gameobjects/components/GetBounds.js @@ -192,6 +192,11 @@ var GetBounds = { output.width = Math.max(TLx, TRx, BLx, BRx) - output.x; output.height = Math.max(TLy, TRy, BLy, BRy) - output.y; + if (this.parentContainer) + { + // Clearly something needs to happen here :) + } + return output; } From f80db91429f8dba66c87347ef697b1deb4e28b8e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:17:53 +0100 Subject: [PATCH 76/87] Allowing to work with Containers --- src/physics/arcade/Body.js | 56 +++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index 5ad789870..e4b354dc2 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -7,8 +7,10 @@ var CircleContains = require('../../geom/circle/Contains'); var Class = require('../../utils/Class'); var CONST = require('./const'); +var RadToDeg = require('../../math/RadToDeg'); var Rectangle = require('../../geom/rectangle/Rectangle'); var RectangleContains = require('../../geom/rectangle/Contains'); +var TransformMatrix = require('../../gameobjects/components/TransformMatrix'); var Vector2 = require('../../math/Vector2'); /** @@ -66,6 +68,23 @@ var Body = new Class({ */ this.gameObject = gameObject; + /** + * [description] + * + * @name Phaser.Physics.Arcade.Body#transform + * @type {object} + * @since 3.4.0 + */ + this.transform = { + x: gameObject.x, + y: gameObject.y, + rotation: gameObject.angle, + scaleX: gameObject.scaleX, + scaleY: gameObject.scaleY, + displayOriginX: gameObject.displayOriginX, + displayOriginY: gameObject.displayOriginY + }; + /** * [description] * @@ -709,6 +728,8 @@ var Body = new Class({ * @since 3.0.0 */ this._bounds = new Rectangle(); + + this._tempMatrix = new TransformMatrix(); }, /** @@ -721,6 +742,29 @@ var Body = new Class({ { var sprite = this.gameObject; + // Container? + + var transform = this.transform; + + if (sprite.parentContainer) + { + var matrix = sprite.getWorldTransformMatrix(this._tempMatrix); + + transform.x = matrix.tx; + transform.y = matrix.ty; + transform.rotation = RadToDeg(matrix.rotation); + transform.scaleX = matrix.scaleX; + transform.scaleY = matrix.scaleY; + } + else + { + transform.x = sprite.x; + transform.y = sprite.y; + transform.rotation = sprite.angle; + transform.scaleX = sprite.scaleX; + transform.scaleY = sprite.scaleY; + } + if (this.syncBounds) { var b = sprite.getBounds(this._bounds); @@ -734,8 +778,8 @@ var Body = new Class({ } else { - var asx = Math.abs(sprite.scaleX); - var asy = Math.abs(sprite.scaleY); + var asx = Math.abs(transform.scaleX); + var asy = Math.abs(transform.scaleY); if (asx !== this._sx || asy !== this._sy) { @@ -803,16 +847,17 @@ var Body = new Class({ this.embedded = false; + // Updates the transform values this.updateBounds(); - var sprite = this.gameObject; + var sprite = this.transform; this.position.x = sprite.x + sprite.scaleX * (this.offset.x - sprite.displayOriginX); this.position.y = sprite.y + sprite.scaleY * (this.offset.y - sprite.displayOriginY); this.updateCenter(); - this.rotation = sprite.angle; + this.rotation = sprite.rotation; this.preRotation = this.rotation; @@ -918,6 +963,9 @@ var Body = new Class({ } } + // this.transform.x += this._dx; + // this.transform.y += this._dy; + this.gameObject.x += this._dx; this.gameObject.y += this._dy; From 30d73a0197a92c7c385299bf44056c141b857d5a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:37:38 +0100 Subject: [PATCH 77/87] Container can now be assigned an arcade physics body --- src/gameobjects/container/Container.js | 60 ++++++++++++++++---------- src/physics/arcade/Body.js | 17 +++++--- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 3931f9bea..0514405af 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -26,6 +26,7 @@ var Vector2 = require('../../math/Vector2'); * * @extends Phaser.GameObjects.Components.Alpha * @extends Phaser.GameObjects.Components.BlendMode + * @extends Phaser.GameObjects.Components.ComputedSize * @extends Phaser.GameObjects.Components.Depth * @extends Phaser.GameObjects.Components.Transform * @extends Phaser.GameObjects.Components.Visible @@ -42,6 +43,7 @@ var Container = new Class({ Mixins: [ Components.Alpha, Components.BlendMode, + Components.ComputedSize, Components.Depth, Components.Transform, Components.Visible, @@ -130,28 +132,6 @@ var Container = new Class({ */ this._sortKey = ''; - /** - * Internal value to allow Containers to be used for input. - * Do not change this value. It has no effect other than to break input. - * - * @name Phaser.GameObjects.Container#displayOriginX - * @type {number} - * @private - * @since 3.4.0 - */ - this.displayOriginX = 0; - - /** - * Internal value to allow Containers to be used for input. - * Do not change this value. It has no effect other than to break input. - * - * @name Phaser.GameObjects.Container#displayOriginY - * @type {number} - * @private - * @since 3.4.0 - */ - this.displayOriginY = 0; - /** * Internal value to allow Containers to be used for input. * Do not change this value. It has no effect other than to break input. @@ -184,6 +164,42 @@ var Container = new Class({ } }, + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#displayOriginX + * @type {number} + * @readOnly + * @since 3.4.0 + */ + displayOriginX: { + + get: function () + { + return this.width * 0.5; + } + + }, + + /** + * Internal value to allow Containers to be used for input and physics. + * Do not change this value. It has no effect other than to break things. + * + * @name Phaser.GameObjects.Container#displayOriginY + * @type {number} + * @readOnly + * @since 3.4.0 + */ + displayOriginY: { + + get: function () + { + return this.height * 0.5; + } + + }, + /** * Does this Container exclusively manage its children? * diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index e4b354dc2..209803ff6 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -50,6 +50,9 @@ var Body = new Class({ function Body (world, gameObject) { + var width = (gameObject.width) ? gameObject.width : 64; + var height = (gameObject.height) ? gameObject.height : 64; + /** * [description] * @@ -167,7 +170,7 @@ var Body = new Class({ * @type {Phaser.Math.Vector2} * @since 3.0.0 */ - this.prev = new Vector2(this.position.x, this.position.y); + this.prev = new Vector2(gameObject.x, gameObject.y); /** * [description] @@ -204,7 +207,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.width = gameObject.width; + this.width = width; /** * [description] @@ -213,7 +216,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.height = gameObject.height; + this.height = height; /** * [description] @@ -222,7 +225,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.sourceWidth = gameObject.width; + this.sourceWidth = width; /** * [description] @@ -231,7 +234,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.sourceHeight = gameObject.height; + this.sourceHeight = height; if (gameObject.frame) { @@ -246,7 +249,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.halfWidth = Math.abs(gameObject.width / 2); + this.halfWidth = Math.abs(width / 2); /** * [description] @@ -255,7 +258,7 @@ var Body = new Class({ * @type {number} * @since 3.0.0 */ - this.halfHeight = Math.abs(gameObject.height / 2); + this.halfHeight = Math.abs(height / 2); /** * [description] From 011e67d0f0cea529e695f7c1b02b7fd2e5e7c86e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 13:47:22 +0100 Subject: [PATCH 78/87] The Matter SetBody Component will no longer try to call `setOrigin` unless the Game Object has the origin component (which not all do, like Graphics and Container) --- CHANGELOG.md | 1 + src/physics/matter-js/components/SetBody.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b27a4e56c..909945b72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ * Calling `setOffset` on a Static Arcade Physics Body would break because the method was missing. It has been added and now functions as expected. Fix #3465 (thanks @josephjaniga and @DouglasLapsley) * Calling Impact.World.remove(body) during a Body.updateCallback would cause the internal loop to crash when trying to access a now missing body. Two extra checks are in place to avoid this (thanks @iamDecode) * If `setInteractive` is called on a Game Object that fails to set a hit area, it will no longer try to assign `dropZone` to an undefined `input` property. +* The Matter SetBody Component will no longer try to call `setOrigin` unless the Game Object has the origin component (which not all do, like Graphics and Container) ### Updates diff --git a/src/physics/matter-js/components/SetBody.js b/src/physics/matter-js/components/SetBody.js index 52022f9b8..7838ff5ef 100644 --- a/src/physics/matter-js/components/SetBody.js +++ b/src/physics/matter-js/components/SetBody.js @@ -125,7 +125,10 @@ var SetBody = { this.world.add(this.body); } - this.setOrigin(body.render.sprite.xOffset, body.render.sprite.yOffset); + if (this._originComponent) + { + this.setOrigin(body.render.sprite.xOffset, body.render.sprite.yOffset); + } return this; }, From 70c7732a1ee53ff43ef0fe3aa09485d09aca3355 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 14:00:58 +0100 Subject: [PATCH 79/87] When shutting down a Matter World it will now call MatterEvents.off, clearing all events, and also `removeAllListeners` for any local events. --- CHANGELOG.md | 1 + src/physics/matter-js/World.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 909945b72..b5c34e8ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -108,6 +108,7 @@ * List.addMultiple has been removed. Used `List.add` instead which offers the exact same functionality. * List is now internally using all of the new Utils.Array functions. * Rectangle.Union will now cache all vars internally so you can use one of the input rectangles as the output rectangle without corrupting it. +* When shutting down a Matter World it will now call MatterEvents.off, clearing all events, and also `removeAllListeners` for any local events. ### Animation System Updates diff --git a/src/physics/matter-js/World.js b/src/physics/matter-js/World.js index ac309f968..ceeb85f76 100644 --- a/src/physics/matter-js/World.js +++ b/src/physics/matter-js/World.js @@ -894,6 +894,10 @@ var World = new Class({ */ shutdown: function () { + MatterEvents.off(); + + this.removeAllListeners(); + MatterWorld.clear(this.localWorld, false); Engine.clear(this.engine); From 53425bdae954dca1243cdd1072f2f0037e2fb093 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 14:35:18 +0100 Subject: [PATCH 80/87] Matter Image and Matter Sprite didn't define a `destroy` method, causing an error when trying to destroy the parent Game Object. Fix #3516 --- CHANGELOG.md | 1 + src/physics/matter-js/MatterImage.js | 13 +++---------- src/physics/matter-js/MatterSprite.js | 13 +++---------- src/physics/matter-js/components/SetBody.js | 4 ++-- 4 files changed, 9 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5c34e8ac..f7a845e3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ * Calling Impact.World.remove(body) during a Body.updateCallback would cause the internal loop to crash when trying to access a now missing body. Two extra checks are in place to avoid this (thanks @iamDecode) * If `setInteractive` is called on a Game Object that fails to set a hit area, it will no longer try to assign `dropZone` to an undefined `input` property. * The Matter SetBody Component will no longer try to call `setOrigin` unless the Game Object has the origin component (which not all do, like Graphics and Container) +* Matter Image and Matter Sprite didn't define a `destroy` method, causing an error when trying to destroy the parent Game Object. Fix #3516 (thanks @RollinSafary) ### Updates diff --git a/src/physics/matter-js/MatterImage.js b/src/physics/matter-js/MatterImage.js index a805b1c70..184566e8d 100644 --- a/src/physics/matter-js/MatterImage.js +++ b/src/physics/matter-js/MatterImage.js @@ -113,20 +113,13 @@ var MatterImage = new Class({ var shape = GetFastValue(options, 'shape', null); - if (!shape) + if (shape) { - this.body = Bodies.rectangle(x, y, this.width, this.height, options); - - this.body.gameObject = this; - - if (GetFastValue(options, 'addToWorld', true)) - { - world.add(this.body); - } + this.setBody(shape, options); } else { - this.setBody(shape, options); + this.setRectangle(this.width, this.height, options) } this.setPosition(x, y); diff --git a/src/physics/matter-js/MatterSprite.js b/src/physics/matter-js/MatterSprite.js index 1b3f2308b..e35acb2b8 100644 --- a/src/physics/matter-js/MatterSprite.js +++ b/src/physics/matter-js/MatterSprite.js @@ -120,20 +120,13 @@ var MatterSprite = new Class({ var shape = GetFastValue(options, 'shape', null); - if (!shape) + if (shape) { - this.body = Bodies.rectangle(x, y, this.width, this.height, options); - - this.body.gameObject = this; - - if (GetFastValue(options, 'addToWorld', true)) - { - world.add(this.body); - } + this.setBody(shape, options); } else { - this.setBody(shape, options); + this.setRectangle(this.width, this.height, options) } this.setPosition(x, y); diff --git a/src/physics/matter-js/components/SetBody.js b/src/physics/matter-js/components/SetBody.js index 7838ff5ef..5a4ac9dac 100644 --- a/src/physics/matter-js/components/SetBody.js +++ b/src/physics/matter-js/components/SetBody.js @@ -114,7 +114,7 @@ var SetBody = { var _this = this; - this.body.destroy = function () + body.destroy = function destroy () { _this.world.remove(_this.body); _this.body.gameObject = null; @@ -122,7 +122,7 @@ var SetBody = { if (addToWorld) { - this.world.add(this.body); + this.world.add(body); } if (this._originComponent) From 091d947eae04a8e4138b5f59075a7af42cecf16e Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Wed, 11 Apr 2018 11:02:04 -0300 Subject: [PATCH 81/87] Container scroll factor implemented to the render functions --- src/gameobjects/container/Container.js | 23 ++----------------- .../container/ContainerCanvasRenderer.js | 7 ++++++ .../container/ContainerWebGLRenderer.js | 7 ++++++ 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 0514405af..7e06c5c35 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -45,6 +45,7 @@ var Container = new Class({ Components.BlendMode, Components.ComputedSize, Components.Depth, + Components.ScrollFactor, Components.Transform, Components.Visible, Render @@ -132,27 +133,7 @@ var Container = new Class({ */ this._sortKey = ''; - /** - * Internal value to allow Containers to be used for input. - * Do not change this value. It has no effect other than to break input. - * - * @name Phaser.GameObjects.Container#scrollFactorX - * @type {number} - * @private - * @since 3.4.0 - */ - this.scrollFactorX = 1; - - /** - * Internal value to allow Containers to be used for input. - * Do not change this value. It has no effect other than to break input. - * - * @name Phaser.GameObjects.Container#scrollFactorY - * @type {number} - * @private - * @since 3.4.0 - */ - this.scrollFactorY = 1; + this.setScrollFactor(1.0, 1.0); this.setPosition(x, y); diff --git a/src/gameobjects/container/ContainerCanvasRenderer.js b/src/gameobjects/container/ContainerCanvasRenderer.js index 9e98f45ed..434581252 100644 --- a/src/gameobjects/container/ContainerCanvasRenderer.js +++ b/src/gameobjects/container/ContainerCanvasRenderer.js @@ -46,14 +46,21 @@ var ContainerCanvasRenderer = function (renderer, container, interpolationPercen } var alpha = container._alpha; + var scrollFactorX = container.scrollFactorX; + var scrollFactorY = container.scrollFactorY; for (var index = 0; index < children.length; ++index) { var child = children[index]; var childAlpha = child._alpha; + var childScrollFactorX = child.scrollFactorX; + var childScrollFactorY = child.scrollFactorY; + + child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY); child.setAlpha(childAlpha * alpha); child.renderCanvas(renderer, child, interpolationPercentage, camera, transformMatrix); child.setAlpha(childAlpha); + child.setScrollFactor(childScrollFactorX, childScrollFactorY); } }; diff --git a/src/gameobjects/container/ContainerWebGLRenderer.js b/src/gameobjects/container/ContainerWebGLRenderer.js index c00af31f5..19e114d1a 100644 --- a/src/gameobjects/container/ContainerWebGLRenderer.js +++ b/src/gameobjects/container/ContainerWebGLRenderer.js @@ -46,14 +46,21 @@ var ContainerWebGLRenderer = function (renderer, container, interpolationPercent } var alpha = container._alpha; + var scrollFactorX = container.scrollFactorX; + var scrollFactorY = container.scrollFactorY; for (var index = 0; index < children.length; ++index) { var child = children[index]; var childAlpha = child._alpha; + var childScrollFactorX = child.scrollFactorX; + var childScrollFactorY = child.scrollFactorY; + + child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY); child.setAlpha(childAlpha * alpha); child.renderWebGL(renderer, child, interpolationPercentage, camera, transformMatrix); child.setAlpha(childAlpha); + child.setScrollFactor(childScrollFactorX, childScrollFactorY); } }; From a1e10a4bbc66e35c935f14f6a54856f4423569ec Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 15:39:30 +0100 Subject: [PATCH 82/87] Added missing extends and removed setSF because defaults are 1,1 anyway --- src/gameobjects/container/Container.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 7e06c5c35..5d8dd2b07 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -28,6 +28,7 @@ var Vector2 = require('../../math/Vector2'); * @extends Phaser.GameObjects.Components.BlendMode * @extends Phaser.GameObjects.Components.ComputedSize * @extends Phaser.GameObjects.Components.Depth + * @extends Phaser.GameObjects.Components.ScrollFactor * @extends Phaser.GameObjects.Components.Transform * @extends Phaser.GameObjects.Components.Visible * @@ -133,8 +134,6 @@ var Container = new Class({ */ this._sortKey = ''; - this.setScrollFactor(1.0, 1.0); - this.setPosition(x, y); this.clearAlpha(); From 23cd9868b4dc577e476487e6d163548b8ce7077e Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Wed, 11 Apr 2018 12:55:32 -0300 Subject: [PATCH 83/87] Added getWorldTransformMatrix to Container and added support to parent container transform to GetBounds component. --- src/gameobjects/components/GetBounds.js | 69 +++++++++++++++++++------ src/gameobjects/container/Container.js | 24 +++++++++ 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/src/gameobjects/components/GetBounds.js b/src/gameobjects/components/GetBounds.js index be4a90701..f22cf0866 100644 --- a/src/gameobjects/components/GetBounds.js +++ b/src/gameobjects/components/GetBounds.js @@ -20,6 +20,7 @@ var GetBounds = { /** * Gets the center coordinate of this Game Object, regardless of origin. + * The returned point is calculated in local space and does not factor in any parent containers * * @method Phaser.GameObjects.Components.GetBounds#getCenter * @since 3.0.0 @@ -42,6 +43,7 @@ var GetBounds = { /** * Gets the top-left corner coordinate of this Game Object, regardless of origin. + * The returned point is calculated in local space and does not factor in any parent containers * * @method Phaser.GameObjects.Components.GetBounds#getTopLeft * @since 3.0.0 @@ -69,6 +71,7 @@ var GetBounds = { /** * Gets the top-right corner coordinate of this Game Object, regardless of origin. + * The returned point is calculated in local space and does not factor in any parent containers * * @method Phaser.GameObjects.Components.GetBounds#getTopRight * @since 3.0.0 @@ -96,6 +99,7 @@ var GetBounds = { /** * Gets the bottom-left corner coordinate of this Game Object, regardless of origin. + * The returned point is calculated in local space and does not factor in any parent containers * * @method Phaser.GameObjects.Components.GetBounds#getBottomLeft * @since 3.0.0 @@ -123,6 +127,7 @@ var GetBounds = { /** * Gets the bottom-right corner coordinate of this Game Object, regardless of origin. + * The returned point is calculated in local space and does not factor in any parent containers * * @method Phaser.GameObjects.Components.GetBounds#getBottomRight * @since 3.0.0 @@ -167,36 +172,66 @@ var GetBounds = { // We can use the output object to temporarily store the x/y coords in: - this.getTopLeft(output); + var TLx, TLy, TRx, TRy, BLx, BLy, BRx, BRy; - var TLx = output.x; - var TLy = output.y; + // Instead of doing a check if parent container is + // defined per corner we only do it once. + if (this.parentContainer) + { + var parentMatrix = this.parentContainer.getWorldTransformMatrix(); - this.getTopRight(output); + this.getTopLeft(output); + parentMatrix.transformPoint(output.x, output.y, output); - var TRx = output.x; - var TRy = output.y; + TLx = output.x; + TLy = output.y; - this.getBottomLeft(output); + this.getTopRight(output); + parentMatrix.transformPoint(output.x, output.y, output); - var BLx = output.x; - var BLy = output.y; + TRx = output.x; + TRy = output.y; - this.getBottomRight(output); + this.getBottomLeft(output); + parentMatrix.transformPoint(output.x, output.y, output); - var BRx = output.x; - var BRy = output.y; + BLx = output.x; + BLy = output.y; + + this.getBottomRight(output); + parentMatrix.transformPoint(output.x, output.y, output); + + BRx = output.x; + BRy = output.y; + } + else + { + this.getTopLeft(output); + + TLx = output.x; + TLy = output.y; + + this.getTopRight(output); + + TRx = output.x; + TRy = output.y; + + this.getBottomLeft(output); + + BLx = output.x; + BLy = output.y; + + this.getBottomRight(output); + + BRx = output.x; + BRy = output.y; + } output.x = Math.min(TLx, TRx, BLx, BRx); output.y = Math.min(TLy, TRy, BLy, BRy); output.width = Math.max(TLx, TRx, BLx, BRx) - output.x; output.height = Math.max(TLy, TRy, BLy, BRy) - output.y; - if (this.parentContainer) - { - // Clearly something needs to happen here :) - } - return output; } diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 7e06c5c35..ac30a8ae9 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -329,6 +329,30 @@ var Container = new Class({ return output; }, + /** + * Returns the world transform matrix. + * The returned matrix is a temporal and shouldn't be stored. + * + * @method Phaser.GameObjects.Container#getWorldTransformMatrix + * @since 3.4.0 + * + * @return {Phaser.GameObjects.Components.TransformMatrix} The world transform matrix. + */ + getWorldTransformMatrix: function () + { + var tempMatrix = this.tempTransformMatrix; + + tempMatrix.applyITRS(this.x, this.y, this.rotation, this.scaleX, this.scaleY); + + if (this.parentContainer) + { + var parentMatrix = this.parentContainer.getTransformMatrix(); + tempMatrix.multiply(parentMatrix); + } + + return tempMatrix; + }, + /** * Adds the given Game Object, or array of Game Objects, to this Container. * From 64b07c6ecbf8b2b6e7c60b09bb90c6c8427dc6b1 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 16:58:25 +0100 Subject: [PATCH 84/87] eslint fix --- src/physics/matter-js/MatterImage.js | 3 +-- src/physics/matter-js/MatterSprite.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/physics/matter-js/MatterImage.js b/src/physics/matter-js/MatterImage.js index 184566e8d..309c877a2 100644 --- a/src/physics/matter-js/MatterImage.js +++ b/src/physics/matter-js/MatterImage.js @@ -4,7 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Bodies = require('./lib/factory/Bodies'); var Class = require('../../utils/Class'); var Components = require('./components'); var GameObject = require('../../gameobjects/GameObject'); @@ -119,7 +118,7 @@ var MatterImage = new Class({ } else { - this.setRectangle(this.width, this.height, options) + this.setRectangle(this.width, this.height, options); } this.setPosition(x, y); diff --git a/src/physics/matter-js/MatterSprite.js b/src/physics/matter-js/MatterSprite.js index e35acb2b8..f90e1cec3 100644 --- a/src/physics/matter-js/MatterSprite.js +++ b/src/physics/matter-js/MatterSprite.js @@ -5,7 +5,6 @@ */ var AnimationComponent = require('../../gameobjects/components/Animation'); -var Bodies = require('./lib/factory/Bodies'); var Class = require('../../utils/Class'); var Components = require('./components'); var GameObject = require('../../gameobjects/GameObject'); @@ -126,7 +125,7 @@ var MatterSprite = new Class({ } else { - this.setRectangle(this.width, this.height, options) + this.setRectangle(this.width, this.height, options); } this.setPosition(x, y); From 9bc6237831680cbcea7d630f48335a2a19dda6eb Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 16:58:32 +0100 Subject: [PATCH 85/87] TS defs fix --- src/utils/array/Add.js | 2 +- src/utils/array/AddAt.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/array/Add.js b/src/utils/array/Add.js index 39a118a3a..dba5126e8 100644 --- a/src/utils/array/Add.js +++ b/src/utils/array/Add.js @@ -20,7 +20,7 @@ * @since 3.4.0 * * @param {array} array - The array to be added to. - * @param {*|Array.<*>} item - The item, or array of items, to add to the array. Each item must be unique within the array. + * @param {any|any[]} item - The item, or array of items, to add to the array. Each item must be unique within the array. * @param {integer} [limit] - Optional limit which caps the size of the array. * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. * @param {object} [context] - The context in which the callback is invoked. diff --git a/src/utils/array/AddAt.js b/src/utils/array/AddAt.js index 110ba17cd..f96a1326c 100644 --- a/src/utils/array/AddAt.js +++ b/src/utils/array/AddAt.js @@ -22,7 +22,7 @@ * @since 3.4.0 * * @param {array} array - The array to be added to. - * @param {*} item - The item, or array of items, to add to the array. + * @param {any|any[]} item - The item, or array of items, to add to the array. * @param {integer} [index=0] - The index in the array where the item will be inserted. * @param {integer} [limit] - Optional limit which caps the size of the array. * @param {function} [callback] - A callback to be invoked for each item successfully added to the array. From 0e14b43623cd8dcbf187a06e1dde90844683c0dd Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 16:58:48 +0100 Subject: [PATCH 86/87] Added `maxSize`, jsdocs and ts def fixes --- src/gameobjects/container/Container.js | 139 +++++++++++++------------ 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/src/gameobjects/container/Container.js b/src/gameobjects/container/Container.js index 5d8dd2b07..d4177169e 100644 --- a/src/gameobjects/container/Container.js +++ b/src/gameobjects/container/Container.js @@ -18,6 +18,36 @@ var Vector2 = require('../../math/Vector2'); * @classdesc * A Container Game Object. * + * A Container, as the name implies, can 'contain' other types of Game Object. + * When a Game Object is added to a Container, the Container becomes responsible for the rendering of it. + * By default it will be removed from the Display List and instead added to the Containers own internal list. + * + * The position of the Game Object automatically becomes relative to the position of the Container. + * + * When the Container is rendered, all of its children are rendered as well, in the order in which they exist + * within the Container. Container children can be repositioned using methods such as `MoveUp`, `MoveDown` and `SendToBack`. + * + * If you modify a transform property of the Container, such as `Container.x` or `Container.rotation` then it will + * automatically influence all children as well. + * + * Containers can include other Containers for deeply nested transforms. + * + * Containers can have masks set on them and can be used as a mask too. However, Container children cannot be masked. + * The masks do not 'stack up'. Only a Container on the root of the display list will use its mask. + * + * Containers can be enabled for input. Because they do not have a texture you need to provide a shape for them + * to use as their hit area. Container children can also be enabled for input, independent of the Container. + * + * Containers can be given a physics body for either Arcade Physics, Impact Physics or Matter Physics. However, + * if Container children are enabled for physics you may get unexpected results,such as offset bodies, + * if the Container itself, or any of its ancestors, is positioned anywhere other than at 0x0. + * + * It's important to understand the impact of using Containers. They add additional processing overhead into + * every one of their children. The deeper you nest them, the more the cost escalates. This is especially true + * for input events. You also loose the ability to set the display depth of Container children in the same + * flexible manner as those not within them. In short, don't use them for the sake of it. You pay a small cost + * every time you create one, try to structure your game around avoiding that where possible. + * * @class Container * @extends Phaser.GameObjects.GameObject * @memberOf Phaser.GameObjects @@ -87,6 +117,18 @@ var Container = new Class({ */ this.exclusive = true; + /** + * Containers can have an optional maximum size. If set to anything above 0 it + * will constrict the addition of new Game Objects into the Container, capping off + * the maximum limit the Container can grow in size to. + * + * @name Phaser.GameObjects.Container#maxSize + * @type {integer} + * @default -1 + * @since 3.4.0 + */ + this.maxSize = -1; + /** * The cursor position. * @@ -336,50 +378,48 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#add * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * - * @param {*|Array.<*>} child - The item, or array of items, to add to the array. Each item must be unique within the array. + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container. * * @return {Phaser.GameObjects.Container} This Container instance. */ add: function (child) { - ArrayUtils.Add(this.list, child, 0, this.addHandler, this); + ArrayUtils.Add(this.list, child, this.maxSize, this.addHandler, this); return this; }, /** - * [description] + * Adds the given Game Object, or array of Game Objects, to this Container at the specified position. + * + * Existing Game Objects in the Container are shifted up. + * + * Each Game Object must be unique within the Container. * * @method Phaser.GameObjects.Container#addAt * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * - * @param {*} child - [description] - * @param {integer} [index=0] - [description] + * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container. + * @param {integer} [index=0] - The position to insert the Game Object/s at. * * @return {Phaser.GameObjects.Container} This Container instance. */ addAt: function (child, index) { - ArrayUtils.AddAt(this.list, child, index, 0, this.addHandler, this); + ArrayUtils.AddAt(this.list, child, index, this.maxSize, this.addHandler, this); return this; }, /** - * [description] + * Returns the Game Object at the given position in this Container. * * @method Phaser.GameObjects.Container#getAt * @since 3.4.0 * - * @genericUse {T} - [$return] + * @param {integer} index - The position to get the Game Object from. * - * @param {integer} index - [description] - * - * @return {Phaser.GameObjects.GameObject|null} The Game Object at the specified index, or `null` if none found. + * @return {?Phaser.GameObjects.GameObject} The Game Object at the specified index, or `null` if none found. */ getAt: function (index) { @@ -387,20 +427,17 @@ var Container = new Class({ }, /** - * [description] + * Returns the index of the given Game Object in this Container. * * @method Phaser.GameObjects.Container#getIndex * @since 3.4.0 * - * @genericUse {T} - [child] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to search for in this Container. * * @return {integer} The index of the Game Object in this Container, or -1 if not found. */ getIndex: function (child) { - // Return -1 if given child isn't a child of this display list return this.list.indexOf(child); }, @@ -411,8 +448,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#sort * @since 3.4.0 * - * @genericUse {T[]} - [children,$return] - * * @param {string} property - The property to lexically sort by. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -436,8 +471,6 @@ var Container = new Class({ * @private * @since 3.4.0 * - * @genericUse {T} - [childA,childB] - * * @param {Phaser.GameObjects.GameObject} childA - The first child to sort. * @param {Phaser.GameObjects.GameObject} childB - The second child to sort. * @@ -455,8 +488,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#getByName * @since 3.4.0 * - * @genericUse {T | null} - [$return] - * * @param {string} name - The name to search for. * * @return {?Phaser.GameObjects.GameObject} The first child with a matching name, or `null` if none were found. @@ -472,8 +503,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#getRandom * @since 3.4.0 * - * @genericUse {T | null} - [$return] - * * @param {integer} [startIndex=0] - An optional start index. * @param {integer} [length] - An optional length, the total number of elements (from the startIndex) to choose from. * @@ -528,7 +557,7 @@ var Container = new Class({ * @since 3.4.0 * * @param {string} [property] - The property to test on each Game Object in the Container. - * @param {*} [value] - If property is set then the `property` must strictly equal this value to be included in the results. + * @param {any} [value] - If property is set then the `property` must strictly equal this value to be included in the results. * @param {integer} [startIndex=0] - An optional start index to search from. * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) * @@ -551,7 +580,7 @@ var Container = new Class({ * @since 3.4.0 * * @param {string} property - [description] - * @param {*} value - [description] + * @param {any} value - [description] * @param {integer} [startIndex=0] - An optional start index to search from. * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) * @@ -569,8 +598,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#swap * @since 3.4.0 * - * @genericUse {T} - [child1,child2] - * * @param {Phaser.GameObjects.GameObject} child1 - The first Game Object to swap. * @param {Phaser.GameObjects.GameObject} child2 - The second Game Object to swap. * @@ -594,8 +621,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#moveTo * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to move. * @param {integer} index - The new position of the Game Object in this Container. * @@ -618,8 +643,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#remove * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to be removed from the Container. * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each child successfully removed from this Container. * @@ -653,8 +676,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#removeAt * @since 3.4.0 * - * @genericUse {T} - [$return] - * * @param {integer} index - The index of the Game Object to be removed. * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. * @@ -680,8 +701,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#removeBetween * @since 3.4.0 * - * @genericUse {T[]} - [$return] - * * @param {integer} [startIndex=0] - An optional start index to search from. * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. @@ -711,8 +730,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#removeAll * @since 3.4.0 * - * @genericUse {Phaser.GameObjects.Container.} - [$return] - * * @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -739,8 +756,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#bringToTop * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to bring to the top of the Container. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -759,8 +774,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#sendToBack * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to send to the bottom of the Container. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -778,8 +791,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#moveUp * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -797,8 +808,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#moveDown * @since 3.4.0 * - * @genericUse {T} - [child,$return] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -816,8 +825,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#reverse * @since 3.4.0 * - * @genericUse {Phaser.GameObjects.Container.} - [$return] - * * @return {Phaser.GameObjects.Container} This Container instance. */ reverse: function () @@ -833,8 +840,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#shuffle * @since 3.4.0 * - * @genericUse {Phaser.GameObjects.Container.} - [$return] - * * @return {Phaser.GameObjects.Container} This Container instance. */ shuffle: function () @@ -851,8 +856,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#replace * @since 3.4.0 * - * @genericUse {T} - [oldChild,newChild,$return] - * * @param {Phaser.GameObjects.GameObject} oldChild - The Game Object in this Container that will be replaced. * @param {Phaser.GameObjects.GameObject} newChild - The Game Object to be added to this Container. * @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container. @@ -885,8 +888,6 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#exists * @since 3.4.0 * - * @genericUse {T} - [child] - * * @param {Phaser.GameObjects.GameObject} child - The Game Object to check for within this Container. * * @return {boolean} True if the Game Object is an immediate child of this Container, otherwise false. @@ -906,10 +907,8 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#setAll * @since 3.4.0 * - * @genericUse {T} - [value] - * * @param {string} property - The property that must exist on the Game Object. - * @param {*} value - The value to get the property to. + * @param {any} value - The value to get the property to. * @param {integer} [startIndex=0] - An optional start index to search from. * @param {integer} [endIndex=Container.length] - An optional end index to search up to (but not included) * @@ -922,6 +921,14 @@ var Container = new Class({ return this; }, + /** + * @callback EachContainerCallback + * @generic I - [item] + * + * @param {*} item - [description] + * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. + */ + /** * Passes all Game Objects in this Container to the given callback. * @@ -934,10 +941,8 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#each * @since 3.4.0 * - * @genericUse {EachListCallback.} - [callback] - * - * @param {EachListCallback} callback - The function to call. - * @param {*} [context] - Value to use as `this` when executing callback. + * @param {function} callback - The function to call. + * @param {object} [context] - Value to use as `this` when executing callback. * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. * * @return {Phaser.GameObjects.Container} This Container instance. @@ -973,10 +978,8 @@ var Container = new Class({ * @method Phaser.GameObjects.Container#iterate * @since 3.4.0 * - * @genericUse {EachListCallback.} - [callback] - * - * @param {EachListCallback} callback - The function to call. - * @param {*} [context] - Value to use as `this` when executing callback. + * @param {function} callback - The function to call. + * @param {object} [context] - Value to use as `this` when executing callback. * @param {...*} [args] - Additional arguments that will be passed to the callback, after the child. * * @return {Phaser.GameObjects.Container} This Container instance. From 68d2526d69fc04d565b216c3968cda1ad957f082 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Wed, 11 Apr 2018 17:12:40 +0100 Subject: [PATCH 87/87] Limit fix --- src/utils/array/Add.js | 4 ++-- src/utils/array/AddAt.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/array/Add.js b/src/utils/array/Add.js index dba5126e8..0d2b44bed 100644 --- a/src/utils/array/Add.js +++ b/src/utils/array/Add.js @@ -31,7 +31,7 @@ var Add = function (array, item, limit, callback, context) { if (context === undefined) { context = array; } - if (limit) + if (limit > 0) { var remaining = limit - array.length; @@ -86,7 +86,7 @@ var Add = function (array, item, limit, callback, context) return null; } - if (limit && itemLength > remaining) + if (limit > 0 && itemLength > remaining) { item.splice(remaining); diff --git a/src/utils/array/AddAt.js b/src/utils/array/AddAt.js index f96a1326c..5e4eb2e6e 100644 --- a/src/utils/array/AddAt.js +++ b/src/utils/array/AddAt.js @@ -35,7 +35,7 @@ var AddAt = function (array, item, index, limit, callback, context) if (index === undefined) { index = 0; } if (context === undefined) { context = array; } - if (limit) + if (limit > 0) { var remaining = limit - array.length; @@ -91,7 +91,7 @@ var AddAt = function (array, item, index, limit, callback, context) } // Truncate to the limit - if (limit && itemLength > remaining) + if (limit > 0 && itemLength > remaining) { item.splice(remaining);