diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/test/core/resources/src/sheet.tps b/test/core/resources/src/sheet.tps
new file mode 100644
index 0000000..d08b10c
--- /dev/null
+++ b/test/core/resources/src/sheet.tps
@@ -0,0 +1,262 @@
+
+
+
+ fileFormatVersion
+ 4
+ texturePackerVersion
+ 4.8.1
+ autoSDSettings
+
+
+ scale
+ 1
+ extension
+ @2x
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ scale
+ 0.5
+ extension
+
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ allowRotation
+
+ shapeDebug
+
+ dpi
+ 72
+ dataFormat
+ pixijs4
+ textureFileName
+
+ flipPVR
+
+ pvrCompressionQuality
+ PVR_QUALITY_NORMAL
+ atfCompressData
+
+ mipMapMinSize
+ 32768
+ etc1CompressionQuality
+ ETC1_QUALITY_LOW_PERCEPTUAL
+ etc2CompressionQuality
+ ETC2_QUALITY_LOW_PERCEPTUAL
+ dxtCompressionMode
+ DXT_PERCEPTUAL
+ jxrColorFormat
+ JXR_YUV444
+ jxrTrimFlexBits
+ 0
+ jxrCompressionLevel
+ 0
+ ditherType
+ NearestNeighbour
+ backgroundColor
+ 0
+ libGdx
+
+ filtering
+
+ x
+ Linear
+ y
+ Linear
+
+
+ shapePadding
+ 0
+ jpgQuality
+ 80
+ pngOptimizationLevel
+ 1
+ webpQualityLevel
+ 101
+ textureSubPath
+
+ atfFormats
+
+ textureFormat
+ png
+ borderPadding
+ 0
+ maxTextureSize
+
+ width
+ 2048
+ height
+ 2048
+
+ fixedTextureSize
+
+ width
+ -1
+ height
+ -1
+
+ algorithmSettings
+
+ algorithm
+ MaxRects
+ freeSizeMode
+ Best
+ sizeConstraints
+ AnySize
+ forceSquared
+
+ maxRects
+
+ heuristic
+ Best
+
+ basic
+
+ sortBy
+ Best
+ order
+ Ascending
+
+ polygon
+
+ alignToGrid
+ 1
+
+
+ dataFileNames
+
+ multiPack
+
+ forceIdenticalLayout
+
+ outputFormat
+ RGBA8888
+ alphaHandling
+ ClearTransparentPixels
+ contentProtection
+
+ key
+
+
+ autoAliasEnabled
+
+ trimSpriteNames
+
+ prependSmartFolderName
+
+ autodetectAnimations
+
+ globalSpriteSettings
+
+ scale
+ 1
+ scaleMode
+ Smooth
+ extrude
+ 1
+ trimThreshold
+ 1
+ trimMargin
+ 1
+ trimMode
+ Trim
+ tracerTolerance
+ 200
+ heuristicMask
+
+ defaultPivotPoint
+ 0,0
+ writePivotPoints
+
+
+ individualSpriteSettings
+
+ fileList
+
+ goldmine_10_5.png
+ star1.png
+ star2.png
+ star3.png
+ star4.png
+
+ ignoreFileList
+
+ replaceList
+
+ ignoredWarnings
+
+ commonDivisorX
+ 1
+ commonDivisorY
+ 1
+ packNormalMaps
+
+ autodetectNormalMaps
+
+ normalMapFilter
+
+ normalMapSuffix
+
+ normalMapSheetFileName
+
+ exporterProperties
+
+
+
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/test/core/resources/src/sheet.tps b/test/core/resources/src/sheet.tps
new file mode 100644
index 0000000..d08b10c
--- /dev/null
+++ b/test/core/resources/src/sheet.tps
@@ -0,0 +1,262 @@
+
+
+
+ fileFormatVersion
+ 4
+ texturePackerVersion
+ 4.8.1
+ autoSDSettings
+
+
+ scale
+ 1
+ extension
+ @2x
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ scale
+ 0.5
+ extension
+
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ allowRotation
+
+ shapeDebug
+
+ dpi
+ 72
+ dataFormat
+ pixijs4
+ textureFileName
+
+ flipPVR
+
+ pvrCompressionQuality
+ PVR_QUALITY_NORMAL
+ atfCompressData
+
+ mipMapMinSize
+ 32768
+ etc1CompressionQuality
+ ETC1_QUALITY_LOW_PERCEPTUAL
+ etc2CompressionQuality
+ ETC2_QUALITY_LOW_PERCEPTUAL
+ dxtCompressionMode
+ DXT_PERCEPTUAL
+ jxrColorFormat
+ JXR_YUV444
+ jxrTrimFlexBits
+ 0
+ jxrCompressionLevel
+ 0
+ ditherType
+ NearestNeighbour
+ backgroundColor
+ 0
+ libGdx
+
+ filtering
+
+ x
+ Linear
+ y
+ Linear
+
+
+ shapePadding
+ 0
+ jpgQuality
+ 80
+ pngOptimizationLevel
+ 1
+ webpQualityLevel
+ 101
+ textureSubPath
+
+ atfFormats
+
+ textureFormat
+ png
+ borderPadding
+ 0
+ maxTextureSize
+
+ width
+ 2048
+ height
+ 2048
+
+ fixedTextureSize
+
+ width
+ -1
+ height
+ -1
+
+ algorithmSettings
+
+ algorithm
+ MaxRects
+ freeSizeMode
+ Best
+ sizeConstraints
+ AnySize
+ forceSquared
+
+ maxRects
+
+ heuristic
+ Best
+
+ basic
+
+ sortBy
+ Best
+ order
+ Ascending
+
+ polygon
+
+ alignToGrid
+ 1
+
+
+ dataFileNames
+
+ multiPack
+
+ forceIdenticalLayout
+
+ outputFormat
+ RGBA8888
+ alphaHandling
+ ClearTransparentPixels
+ contentProtection
+
+ key
+
+
+ autoAliasEnabled
+
+ trimSpriteNames
+
+ prependSmartFolderName
+
+ autodetectAnimations
+
+ globalSpriteSettings
+
+ scale
+ 1
+ scaleMode
+ Smooth
+ extrude
+ 1
+ trimThreshold
+ 1
+ trimMargin
+ 1
+ trimMode
+ Trim
+ tracerTolerance
+ 200
+ heuristicMask
+
+ defaultPivotPoint
+ 0,0
+ writePivotPoints
+
+
+ individualSpriteSettings
+
+ fileList
+
+ goldmine_10_5.png
+ star1.png
+ star2.png
+ star3.png
+ star4.png
+
+ ignoreFileList
+
+ replaceList
+
+ ignoredWarnings
+
+ commonDivisorX
+ 1
+ commonDivisorY
+ 1
+ packNormalMaps
+
+ autodetectNormalMaps
+
+ normalMapFilter
+
+ normalMapSuffix
+
+ normalMapSheetFileName
+
+ exporterProperties
+
+
+
diff --git a/test/core/resources/src/star1.png b/test/core/resources/src/star1.png
new file mode 100644
index 0000000..32824fd
--- /dev/null
+++ b/test/core/resources/src/star1.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/test/core/resources/src/sheet.tps b/test/core/resources/src/sheet.tps
new file mode 100644
index 0000000..d08b10c
--- /dev/null
+++ b/test/core/resources/src/sheet.tps
@@ -0,0 +1,262 @@
+
+
+
+ fileFormatVersion
+ 4
+ texturePackerVersion
+ 4.8.1
+ autoSDSettings
+
+
+ scale
+ 1
+ extension
+ @2x
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ scale
+ 0.5
+ extension
+
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ allowRotation
+
+ shapeDebug
+
+ dpi
+ 72
+ dataFormat
+ pixijs4
+ textureFileName
+
+ flipPVR
+
+ pvrCompressionQuality
+ PVR_QUALITY_NORMAL
+ atfCompressData
+
+ mipMapMinSize
+ 32768
+ etc1CompressionQuality
+ ETC1_QUALITY_LOW_PERCEPTUAL
+ etc2CompressionQuality
+ ETC2_QUALITY_LOW_PERCEPTUAL
+ dxtCompressionMode
+ DXT_PERCEPTUAL
+ jxrColorFormat
+ JXR_YUV444
+ jxrTrimFlexBits
+ 0
+ jxrCompressionLevel
+ 0
+ ditherType
+ NearestNeighbour
+ backgroundColor
+ 0
+ libGdx
+
+ filtering
+
+ x
+ Linear
+ y
+ Linear
+
+
+ shapePadding
+ 0
+ jpgQuality
+ 80
+ pngOptimizationLevel
+ 1
+ webpQualityLevel
+ 101
+ textureSubPath
+
+ atfFormats
+
+ textureFormat
+ png
+ borderPadding
+ 0
+ maxTextureSize
+
+ width
+ 2048
+ height
+ 2048
+
+ fixedTextureSize
+
+ width
+ -1
+ height
+ -1
+
+ algorithmSettings
+
+ algorithm
+ MaxRects
+ freeSizeMode
+ Best
+ sizeConstraints
+ AnySize
+ forceSquared
+
+ maxRects
+
+ heuristic
+ Best
+
+ basic
+
+ sortBy
+ Best
+ order
+ Ascending
+
+ polygon
+
+ alignToGrid
+ 1
+
+
+ dataFileNames
+
+ multiPack
+
+ forceIdenticalLayout
+
+ outputFormat
+ RGBA8888
+ alphaHandling
+ ClearTransparentPixels
+ contentProtection
+
+ key
+
+
+ autoAliasEnabled
+
+ trimSpriteNames
+
+ prependSmartFolderName
+
+ autodetectAnimations
+
+ globalSpriteSettings
+
+ scale
+ 1
+ scaleMode
+ Smooth
+ extrude
+ 1
+ trimThreshold
+ 1
+ trimMargin
+ 1
+ trimMode
+ Trim
+ tracerTolerance
+ 200
+ heuristicMask
+
+ defaultPivotPoint
+ 0,0
+ writePivotPoints
+
+
+ individualSpriteSettings
+
+ fileList
+
+ goldmine_10_5.png
+ star1.png
+ star2.png
+ star3.png
+ star4.png
+
+ ignoreFileList
+
+ replaceList
+
+ ignoredWarnings
+
+ commonDivisorX
+ 1
+ commonDivisorY
+ 1
+ packNormalMaps
+
+ autodetectNormalMaps
+
+ normalMapFilter
+
+ normalMapSuffix
+
+ normalMapSheetFileName
+
+ exporterProperties
+
+
+
diff --git a/test/core/resources/src/star1.png b/test/core/resources/src/star1.png
new file mode 100644
index 0000000..32824fd
--- /dev/null
+++ b/test/core/resources/src/star1.png
Binary files differ
diff --git a/test/core/resources/src/star2.png b/test/core/resources/src/star2.png
new file mode 100644
index 0000000..8432cb5
--- /dev/null
+++ b/test/core/resources/src/star2.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/test/core/resources/src/sheet.tps b/test/core/resources/src/sheet.tps
new file mode 100644
index 0000000..d08b10c
--- /dev/null
+++ b/test/core/resources/src/sheet.tps
@@ -0,0 +1,262 @@
+
+
+
+ fileFormatVersion
+ 4
+ texturePackerVersion
+ 4.8.1
+ autoSDSettings
+
+
+ scale
+ 1
+ extension
+ @2x
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ scale
+ 0.5
+ extension
+
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ allowRotation
+
+ shapeDebug
+
+ dpi
+ 72
+ dataFormat
+ pixijs4
+ textureFileName
+
+ flipPVR
+
+ pvrCompressionQuality
+ PVR_QUALITY_NORMAL
+ atfCompressData
+
+ mipMapMinSize
+ 32768
+ etc1CompressionQuality
+ ETC1_QUALITY_LOW_PERCEPTUAL
+ etc2CompressionQuality
+ ETC2_QUALITY_LOW_PERCEPTUAL
+ dxtCompressionMode
+ DXT_PERCEPTUAL
+ jxrColorFormat
+ JXR_YUV444
+ jxrTrimFlexBits
+ 0
+ jxrCompressionLevel
+ 0
+ ditherType
+ NearestNeighbour
+ backgroundColor
+ 0
+ libGdx
+
+ filtering
+
+ x
+ Linear
+ y
+ Linear
+
+
+ shapePadding
+ 0
+ jpgQuality
+ 80
+ pngOptimizationLevel
+ 1
+ webpQualityLevel
+ 101
+ textureSubPath
+
+ atfFormats
+
+ textureFormat
+ png
+ borderPadding
+ 0
+ maxTextureSize
+
+ width
+ 2048
+ height
+ 2048
+
+ fixedTextureSize
+
+ width
+ -1
+ height
+ -1
+
+ algorithmSettings
+
+ algorithm
+ MaxRects
+ freeSizeMode
+ Best
+ sizeConstraints
+ AnySize
+ forceSquared
+
+ maxRects
+
+ heuristic
+ Best
+
+ basic
+
+ sortBy
+ Best
+ order
+ Ascending
+
+ polygon
+
+ alignToGrid
+ 1
+
+
+ dataFileNames
+
+ multiPack
+
+ forceIdenticalLayout
+
+ outputFormat
+ RGBA8888
+ alphaHandling
+ ClearTransparentPixels
+ contentProtection
+
+ key
+
+
+ autoAliasEnabled
+
+ trimSpriteNames
+
+ prependSmartFolderName
+
+ autodetectAnimations
+
+ globalSpriteSettings
+
+ scale
+ 1
+ scaleMode
+ Smooth
+ extrude
+ 1
+ trimThreshold
+ 1
+ trimMargin
+ 1
+ trimMode
+ Trim
+ tracerTolerance
+ 200
+ heuristicMask
+
+ defaultPivotPoint
+ 0,0
+ writePivotPoints
+
+
+ individualSpriteSettings
+
+ fileList
+
+ goldmine_10_5.png
+ star1.png
+ star2.png
+ star3.png
+ star4.png
+
+ ignoreFileList
+
+ replaceList
+
+ ignoredWarnings
+
+ commonDivisorX
+ 1
+ commonDivisorY
+ 1
+ packNormalMaps
+
+ autodetectNormalMaps
+
+ normalMapFilter
+
+ normalMapSuffix
+
+ normalMapSheetFileName
+
+ exporterProperties
+
+
+
diff --git a/test/core/resources/src/star1.png b/test/core/resources/src/star1.png
new file mode 100644
index 0000000..32824fd
--- /dev/null
+++ b/test/core/resources/src/star1.png
Binary files differ
diff --git a/test/core/resources/src/star2.png b/test/core/resources/src/star2.png
new file mode 100644
index 0000000..8432cb5
--- /dev/null
+++ b/test/core/resources/src/star2.png
Binary files differ
diff --git a/test/core/resources/src/star3.png b/test/core/resources/src/star3.png
new file mode 100644
index 0000000..a91eadc
--- /dev/null
+++ b/test/core/resources/src/star3.png
Binary files differ
diff --git a/packages/core/src/textures/Texture.js b/packages/core/src/textures/Texture.js
index 9148656..f9bb8bc 100644
--- a/packages/core/src/textures/Texture.js
+++ b/packages/core/src/textures/Texture.js
@@ -4,7 +4,7 @@
import TextureUvs from './TextureUvs';
import EventEmitter from 'eventemitter3';
import { settings } from '@pixi/settings';
-import { Rectangle } from '@pixi/math';
+import { Rectangle, Point } from '@pixi/math';
import { uid, TextureCache, getResolutionOfUrl } from '@pixi/utils';
/**
@@ -41,8 +41,9 @@
* @param {PIXI.Rectangle} [orig] - The area of original texture
* @param {PIXI.Rectangle} [trim] - Trimmed rectangle of original texture
* @param {number} [rotate] - indicates how the texture was rotated by texture packer. See {@link PIXI.GroupD8}
+ * @param {PIXI.Point} [anchor] - Default anchor point used for sprite placement / rotation
*/
- constructor(baseTexture, frame, orig, trim, rotate)
+ constructor(baseTexture, frame, orig, trim, rotate, anchor)
{
super();
@@ -153,6 +154,14 @@
}
/**
+ * Anchor point that is used as default if sprite is created with this texture.
+ * Changing the `defaultAnchor` at a later point of time will not update Sprite's anchor point.
+ * @member {PIXI.Point}
+ * @default {0,0}
+ */
+ this.defaultAnchor = anchor ? new Point(anchor.x, anchor.y) : new Point(0, 0);
+
+ /**
* Update ID is observed by sprites and TextureMatrix instances.
* Call updateUvs() to increment it.
*
diff --git a/packages/sprite-animated/src/AnimatedSprite.js b/packages/sprite-animated/src/AnimatedSprite.js
index d5f5fce..330c683 100644
--- a/packages/sprite-animated/src/AnimatedSprite.js
+++ b/packages/sprite-animated/src/AnimatedSprite.js
@@ -22,7 +22,20 @@
* textureArray.push(texture);
* };
*
- * let mc = new PIXI.AnimatedSprite(textureArray);
+ * let animatedSprite = new PIXI.extras.AnimatedSprite(textureArray);
+ * ```
+ *
+ * The more efficient and simpler way to create an animated sprite is using a {@link PIXI.Spritesheet}
+ * containing the animation definitions:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * animatedSprite = new PIXI.extras.AnimatedSprite(sheet.animations["image_sequence"]);
+ * ...
+ * }
* ```
*
* @class
diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js
index ebf1f6f..91546cf 100644
--- a/packages/sprite/src/Sprite.js
+++ b/packages/sprite/src/Sprite.js
@@ -15,6 +15,18 @@
* let sprite = new PIXI.Sprite.from('assets/image.png');
* ```
*
+ * The more efficient way to create sprites is using a {@link PIXI.Spritesheet}:
+ *
+ * ```js
+ * PIXI.loader.add("assets/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["assets/spritesheet.json"].spritesheet;
+ * let sprite = new PIXI.Sprite(sheet.textures["image.png"]);
+ * ...
+ * }
+ * ```
+ *
* @class
* @extends PIXI.Container
* @memberof PIXI
@@ -30,14 +42,22 @@
/**
* The anchor sets the origin point of the texture.
- * The default is 0,0 this means the texture's origin is the top left.
+ * The default is 0,0 or taken from the {@link PIXI.Texture#defaultAnchor|Texture}
+ * passed to the constructor. A value of 0,0 means the texture's origin is the top left.
* Setting the anchor to 0.5,0.5 means the texture's origin is centered.
* Setting the anchor to 1,1 would mean the texture's origin point will be the bottom right corner.
+ * Note: Updating the {@link PIXI.Texture#defaultAnchor} after a Texture is
+ * created does _not_ update the Sprite's anchor values.
*
* @member {PIXI.ObservablePoint}
* @private
*/
- this._anchor = new ObservablePoint(this._onAnchorUpdate, this);
+ this._anchor = new ObservablePoint(
+ this._onAnchorUpdate,
+ this,
+ (texture ? texture.defaultAnchor.x : 0),
+ (texture ? texture.defaultAnchor.y : 0)
+ );
/**
* The texture that the sprite is using
@@ -484,7 +504,8 @@
}
/**
- * The anchor sets the origin point of the text.
+ * The anchor sets the origin point of the text. The default value is taken from the {@link PIXI.Texture|Texture}
+ * and passed to the constructor.
*
* The default is `(0,0)`, this means the text's origin is the top left.
*
diff --git a/packages/spritesheet/src/Spritesheet.js b/packages/spritesheet/src/Spritesheet.js
index 64d932d..28597d7 100644
--- a/packages/spritesheet/src/Spritesheet.js
+++ b/packages/spritesheet/src/Spritesheet.js
@@ -6,6 +6,23 @@
* Utility class for maintaining reference to a collection
* of Textures on a single Spritesheet.
*
+ * To access a sprite sheet from your code pass its JSON data file to Pixi's loader:
+ *
+ * ```js
+ * PIXI.loader.add("images/spritesheet.json").load(setup);
+ *
+ * function setup() {
+ * let sheet = PIXI.loader.resources["images/spritesheet.json"].spritesheet;
+ * ...
+ * }
+ * ```
+ * With the `sheet.textures` you can create Sprite objects,`sheet.animations` can be used to create an AnimatedSprite.
+ *
+ * Sprite sheets can be packed using tools like {@link https://codeandweb.com/texturepacker|TexturePacker},
+ * {@link https://renderhjs.net/shoebox/|Shoebox} or {@link https://github.com/krzysztof-o/spritesheet.js|Spritesheet.js}.
+ * Default anchor points (see {@link PIXI.Texture#defaultAnchor}) and grouping of animation sprites are currently only
+ * supported by TexturePacker.
+ *
* @class
* @memberof PIXI
*/
@@ -38,12 +55,26 @@
this.baseTexture = baseTexture;
/**
- * Map of spritesheet textures.
- * @type {Object}
+ * A map containing all textures of the sprite sheet.
+ * Can be used to create a {@link PIXI.Sprite|Sprite}:
+ * ```js
+ * new PIXI.Sprite(sheet.textures["image.png"]);
+ * ```
+ * @member {Object}
*/
this.textures = {};
/**
+ * A map containing the textures for each animation.
+ * Can be used to create an {@link PIXI.extras.AnimatedSprite|AnimatedSprite}:
+ * ```js
+ * new PIXI.extras.AnimatedSprite(sheet.animations["anim_name"])
+ * ```
+ * @member {Object}
+ */
+ this.animations = {};
+
+ /**
* Reference to the original JSON data.
* @type {Object}
*/
@@ -134,6 +165,7 @@
if (this._frameKeys.length <= Spritesheet.BATCH_SIZE)
{
this._processFrames(0);
+ this._processAnimations();
this._parseComplete();
}
else
@@ -208,7 +240,8 @@
frame,
orig,
trim,
- data.rotated ? 2 : 0
+ data.rotated ? 2 : 0,
+ data.anchor
);
// lets also add the frame to pixi's global cache for fromFrame and fromImage functions
@@ -220,6 +253,27 @@
}
/**
+ * Parse animations config
+ *
+ * @private
+ */
+ _processAnimations()
+ {
+ const animations = this.data.animations || {};
+
+ for (const animName in animations)
+ {
+ this.animations[animName] = [];
+ for (let i = 0; i < animations[animName].length; i++)
+ {
+ const frameName = animations[animName][i];
+
+ this.animations[animName].push(this.textures[frameName]);
+ }
+ }
+ }
+
+ /**
* The parse has completed.
*
* @private
@@ -250,6 +304,7 @@
}
else
{
+ this._processAnimations();
this._parseComplete();
}
}, 0);
diff --git a/packages/spritesheet/test/Spritesheet.js b/packages/spritesheet/test/Spritesheet.js
index b168fe0..5063a45 100644
--- a/packages/spritesheet/test/Spritesheet.js
+++ b/packages/spritesheet/test/Spritesheet.js
@@ -15,12 +15,20 @@
const width = Math.floor(spritesheet.data.frames[id].frame.w);
const height = Math.floor(spritesheet.data.frames[id].frame.h);
- expect(Object.keys(textures).length).to.equal(1);
- expect(Object.keys(spritesheet.textures).length).to.equal(1);
+ expect(Object.keys(textures).length).to.equal(5);
+ expect(Object.keys(spritesheet.textures).length).to.equal(5);
expect(textures[id]).to.be.an.instanceof(Texture);
expect(textures[id].width).to.equal(width / spritesheet.resolution);
expect(textures[id].height).to.equal(height / spritesheet.resolution);
+ expect(textures[id].defaultAnchor.x).to.equal(0);
+ expect(textures[id].defaultAnchor.y).to.equal(0);
expect(textures[id].textureCacheIds.indexOf(id)).to.equal(0);
+
+ expect(this.animations).to.have.property('star').that.is.an('array');
+ expect(this.animations.star.length).to.equal(4);
+ expect(this.animations.star[0].defaultAnchor.x).to.equal(0.5);
+ expect(this.animations.star[0].defaultAnchor.y).to.equal(0.5);
+
spritesheet.destroy(true);
expect(spritesheet.textures).to.be.null;
expect(spritesheet.baseTexture).to.be.null;
diff --git a/packages/spritesheet/test/SpritesheetLoader.js b/packages/spritesheet/test/SpritesheetLoader.js
index 2797100..932064c 100644
--- a/packages/spritesheet/test/SpritesheetLoader.js
+++ b/packages/spritesheet/test/SpritesheetLoader.js
@@ -75,6 +75,19 @@
.with.keys(Object.keys(getJsonSpritesheet().frames))
.and.has.property('0.png')
.that.is.an.instanceof(Texture);
+
+ expect(res.textures['0.png'].frame.x).to.equal(14);
+ expect(res.textures['0.png'].frame.y).to.equal(28);
+ expect(res.textures['0.png'].defaultAnchor.x).to.equal(0.3);
+ expect(res.textures['0.png'].defaultAnchor.y).to.equal(0.4);
+ expect(res.textures['1.png'].defaultAnchor.x).to.equal(0.0); // default of defaultAnchor is 0,0
+ expect(res.textures['1.png'].defaultAnchor.y).to.equal(0.0);
+
+ expect(res).to.have.property('spritesheet')
+ .to.have.property('animations')
+ .to.have.property('png123');
+ expect(res.spritesheet.animations.png123.length).to.equal(3);
+ expect(res.spritesheet.animations.png123[0]).to.equal(res.textures['1.png']);
});
it('should not load binary images as an image loader type', function (done)
@@ -188,7 +201,8 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
- "sourceSize": {"w":14,"h":14}
+ "sourceSize": {"w":14,"h":14},
+ "anchor": {"x":0.3,"y":0.4}
},
"1.png":
{
@@ -262,6 +276,9 @@
"spriteSourceSize": {"x":0,"y":0,"w":14,"h":14},
"sourceSize": {"w":14,"h":14}
}},
+ "animations": {
+ "png123": [ "1.png", "2.png", "3.png" ]
+ },
"meta": {
"app": "http://www.texturepacker.com",
"version": "1.0",
diff --git a/packages/spritesheet/test/resources/building1.json b/packages/spritesheet/test/resources/building1.json
old mode 100755
new mode 100644
index 03fa5c1..d8fbfe1
--- a/packages/spritesheet/test/resources/building1.json
+++ b/packages/spritesheet/test/resources/building1.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":95,"h":115},
- "sourceSize": {"w":95,"h":115},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":95,"h":115}
+},
+"star1.png":
+{
+ "frame": {"x":98,"y":33,"w":28,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":2,"y":2,"w":28,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":98,"y":95,"w":26,"h":30},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":3,"y":1,"w":26,"h":30},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":98,"y":1,"w":30,"h":29},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":2,"w":30,"h":29},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":98,"y":63,"w":30,"h":27},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":1,"y":3,"w":30,"h":27},
+ "sourceSize": {"w":32,"h":32},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1.png",
"format": "RGBA8888",
- "size": {"w":128,"h":128},
+ "size": {"w":128,"h":126},
"scale": "0.5",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1.png b/packages/spritesheet/test/resources/building1.png
old mode 100755
new mode 100644
index 7e1e114..7e16cda
--- a/packages/spritesheet/test/resources/building1.png
+++ b/packages/spritesheet/test/resources/building1.png
Binary files differ
diff --git a/packages/spritesheet/test/resources/building1@2x.json b/packages/spritesheet/test/resources/building1@2x.json
old mode 100755
new mode 100644
index 24e25ff..c8cb7bf
--- a/packages/spritesheet/test/resources/building1@2x.json
+++ b/packages/spritesheet/test/resources/building1@2x.json
@@ -6,16 +6,54 @@
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":190,"h":229},
- "sourceSize": {"w":190,"h":229},
- "pivot": {"x":0.5,"y":0.5}
+ "sourceSize": {"w":190,"h":229}
+},
+"star1.png":
+{
+ "frame": {"x":193,"y":59,"w":54,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":5,"y":5,"w":54,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star2.png":
+{
+ "frame": {"x":193,"y":115,"w":50,"h":57},
+ "rotated": false,
+ "trimmed": true,
+ "spriteSourceSize": {"x":7,"y":4,"w":50,"h":57},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star3.png":
+{
+ "frame": {"x":193,"y":1,"w":56,"h":55},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":5,"w":56,"h":55},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
+},
+"star4.png":
+{
+ "frame": {"x":193,"y":174,"w":56,"h":50},
+ "rotated": true,
+ "trimmed": true,
+ "spriteSourceSize": {"x":4,"y":8,"w":56,"h":50},
+ "sourceSize": {"w":64,"h":64},
+ "anchor": {"x":0.5,"y":0.5}
}},
+"animations": {
+ "star": ["star1.png","star2.png","star3.png","star4.png"]
+},
"meta": {
- "app": "http://www.codeandweb.com/texturepacker",
+ "app": "https://www.codeandweb.com/texturepacker",
"version": "1.0",
"image": "building1@2x.png",
"format": "RGBA8888",
- "size": {"w":256,"h":256},
+ "size": {"w":249,"h":231},
"scale": "1",
- "smartupdate": "$TexturePacker:SmartUpdate:d7a5e54c8f8a3fecd508baf190c44807:99a0e3a4dc0f441e4aad77614191ab38:6046b8eb706ddefaa771c33ceb7cb6d5$"
+ "smartupdate": "$TexturePacker:SmartUpdate:1cb0f14cbdd5e7bcecd332ecd0eaa9f7:8acde9d234ecca966a410602c71bffad:6046b8eb706ddefaa771c33ceb7cb6d5$"
}
}
diff --git a/packages/spritesheet/test/resources/building1@2x.png b/packages/spritesheet/test/resources/building1@2x.png
old mode 100755
new mode 100644
index d5ecd04..06e613f
--- a/packages/spritesheet/test/resources/building1@2x.png
+++ b/packages/spritesheet/test/resources/building1@2x.png
Binary files differ
diff --git a/test/core/resources/src/goldmine_10_5.png b/test/core/resources/src/goldmine_10_5.png
new file mode 100755
index 0000000..de2ba5a
--- /dev/null
+++ b/test/core/resources/src/goldmine_10_5.png
Binary files differ
diff --git a/test/core/resources/src/sheet.tps b/test/core/resources/src/sheet.tps
new file mode 100644
index 0000000..d08b10c
--- /dev/null
+++ b/test/core/resources/src/sheet.tps
@@ -0,0 +1,262 @@
+
+
+
+ fileFormatVersion
+ 4
+ texturePackerVersion
+ 4.8.1
+ autoSDSettings
+
+
+ scale
+ 1
+ extension
+ @2x
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ scale
+ 0.5
+ extension
+
+ spriteFilter
+
+ acceptFractionalValues
+
+ maxTextureSize
+
+ width
+ -1
+ height
+ -1
+
+
+
+ allowRotation
+
+ shapeDebug
+
+ dpi
+ 72
+ dataFormat
+ pixijs4
+ textureFileName
+
+ flipPVR
+
+ pvrCompressionQuality
+ PVR_QUALITY_NORMAL
+ atfCompressData
+
+ mipMapMinSize
+ 32768
+ etc1CompressionQuality
+ ETC1_QUALITY_LOW_PERCEPTUAL
+ etc2CompressionQuality
+ ETC2_QUALITY_LOW_PERCEPTUAL
+ dxtCompressionMode
+ DXT_PERCEPTUAL
+ jxrColorFormat
+ JXR_YUV444
+ jxrTrimFlexBits
+ 0
+ jxrCompressionLevel
+ 0
+ ditherType
+ NearestNeighbour
+ backgroundColor
+ 0
+ libGdx
+
+ filtering
+
+ x
+ Linear
+ y
+ Linear
+
+
+ shapePadding
+ 0
+ jpgQuality
+ 80
+ pngOptimizationLevel
+ 1
+ webpQualityLevel
+ 101
+ textureSubPath
+
+ atfFormats
+
+ textureFormat
+ png
+ borderPadding
+ 0
+ maxTextureSize
+
+ width
+ 2048
+ height
+ 2048
+
+ fixedTextureSize
+
+ width
+ -1
+ height
+ -1
+
+ algorithmSettings
+
+ algorithm
+ MaxRects
+ freeSizeMode
+ Best
+ sizeConstraints
+ AnySize
+ forceSquared
+
+ maxRects
+
+ heuristic
+ Best
+
+ basic
+
+ sortBy
+ Best
+ order
+ Ascending
+
+ polygon
+
+ alignToGrid
+ 1
+
+
+ dataFileNames
+
+ multiPack
+
+ forceIdenticalLayout
+
+ outputFormat
+ RGBA8888
+ alphaHandling
+ ClearTransparentPixels
+ contentProtection
+
+ key
+
+
+ autoAliasEnabled
+
+ trimSpriteNames
+
+ prependSmartFolderName
+
+ autodetectAnimations
+
+ globalSpriteSettings
+
+ scale
+ 1
+ scaleMode
+ Smooth
+ extrude
+ 1
+ trimThreshold
+ 1
+ trimMargin
+ 1
+ trimMode
+ Trim
+ tracerTolerance
+ 200
+ heuristicMask
+
+ defaultPivotPoint
+ 0,0
+ writePivotPoints
+
+
+ individualSpriteSettings
+
+ fileList
+
+ goldmine_10_5.png
+ star1.png
+ star2.png
+ star3.png
+ star4.png
+
+ ignoreFileList
+
+ replaceList
+
+ ignoredWarnings
+
+ commonDivisorX
+ 1
+ commonDivisorY
+ 1
+ packNormalMaps
+
+ autodetectNormalMaps
+
+ normalMapFilter
+
+ normalMapSuffix
+
+ normalMapSheetFileName
+
+ exporterProperties
+
+
+
diff --git a/test/core/resources/src/star1.png b/test/core/resources/src/star1.png
new file mode 100644
index 0000000..32824fd
--- /dev/null
+++ b/test/core/resources/src/star1.png
Binary files differ
diff --git a/test/core/resources/src/star2.png b/test/core/resources/src/star2.png
new file mode 100644
index 0000000..8432cb5
--- /dev/null
+++ b/test/core/resources/src/star2.png
Binary files differ
diff --git a/test/core/resources/src/star3.png b/test/core/resources/src/star3.png
new file mode 100644
index 0000000..a91eadc
--- /dev/null
+++ b/test/core/resources/src/star3.png
Binary files differ
diff --git a/test/core/resources/src/star4.png b/test/core/resources/src/star4.png
new file mode 100644
index 0000000..c629571
--- /dev/null
+++ b/test/core/resources/src/star4.png
Binary files differ