diff --git a/packages/core/src/textures/TextureUvs.js b/packages/core/src/textures/TextureUvs.js index c4ca3b2..519842c 100644 --- a/packages/core/src/textures/TextureUvs.js +++ b/packages/core/src/textures/TextureUvs.js @@ -1,7 +1,16 @@ import { GroupD8 } from '@pixi/math'; /** - * A standard object to store the Uvs of a texture + * Stores a texture's frame in UV coordinates, in + * which everything lies in the rectangle `[(0,0), (1,0), + * (1,1), (0,1)]`. + * + * | Corner | Coordinates | + * |--------------|-------------| + * | Top-Left | `(x0,y0)` | + * | Top-Right | `(x1,y1)` | + * | Bottom-Right | `(x2,y2)` | + * | Bottom-Left | `(x3,y3)` | * * @class * @protected @@ -12,56 +21,56 @@ constructor() { /** - * The position of the top-left corner on the x axis. + * X-component of top-left corner `(x0,y0)`. * * @member {number} */ this.x0 = 0; /** - * The position of the top-left corner on the y axis. + * Y-component of top-left corner `(x0,y0)`. * * @member {number} */ this.y0 = 0; /** - * The position of the top-right corner on the x axis. + * X-component of top-right corner `(x1,y1)`. * * @member {number} */ this.x1 = 1; /** - * The position of the top-right corner on the y axis. + * Y-component of top-right corner `(x1,y1)`. * * @member {number} */ this.y1 = 0; /** - * The position of the bottom-right corner on the x axis. + * X-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.x2 = 1; /** - * The position of the bottom-right corner on the y axis. + * Y-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.y2 = 1; /** - * The position of the bottom-left corner on the x axis. + * X-component of bottom-left corner `(x3,y3)`. * * @member {number} */ this.x3 = 0; /** - * The position of the bottom-left corner on the y axis. + * Y-component of bottom-right corner `(x3,y3)`. * * @member {number} */ diff --git a/packages/core/src/textures/TextureUvs.js b/packages/core/src/textures/TextureUvs.js index c4ca3b2..519842c 100644 --- a/packages/core/src/textures/TextureUvs.js +++ b/packages/core/src/textures/TextureUvs.js @@ -1,7 +1,16 @@ import { GroupD8 } from '@pixi/math'; /** - * A standard object to store the Uvs of a texture + * Stores a texture's frame in UV coordinates, in + * which everything lies in the rectangle `[(0,0), (1,0), + * (1,1), (0,1)]`. + * + * | Corner | Coordinates | + * |--------------|-------------| + * | Top-Left | `(x0,y0)` | + * | Top-Right | `(x1,y1)` | + * | Bottom-Right | `(x2,y2)` | + * | Bottom-Left | `(x3,y3)` | * * @class * @protected @@ -12,56 +21,56 @@ constructor() { /** - * The position of the top-left corner on the x axis. + * X-component of top-left corner `(x0,y0)`. * * @member {number} */ this.x0 = 0; /** - * The position of the top-left corner on the y axis. + * Y-component of top-left corner `(x0,y0)`. * * @member {number} */ this.y0 = 0; /** - * The position of the top-right corner on the x axis. + * X-component of top-right corner `(x1,y1)`. * * @member {number} */ this.x1 = 1; /** - * The position of the top-right corner on the y axis. + * Y-component of top-right corner `(x1,y1)`. * * @member {number} */ this.y1 = 0; /** - * The position of the bottom-right corner on the x axis. + * X-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.x2 = 1; /** - * The position of the bottom-right corner on the y axis. + * Y-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.y2 = 1; /** - * The position of the bottom-left corner on the x axis. + * X-component of bottom-left corner `(x3,y3)`. * * @member {number} */ this.x3 = 0; /** - * The position of the bottom-left corner on the y axis. + * Y-component of bottom-right corner `(x3,y3)`. * * @member {number} */ diff --git a/packages/math/src/GroupD8.js b/packages/math/src/GroupD8.js index e6a09e7..4f2f5e7 100644 --- a/packages/math/src/GroupD8.js +++ b/packages/math/src/GroupD8.js @@ -1,46 +1,68 @@ -// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 +// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group +// +// This file implements the dihedral group of order 16, also called +// of degree 8. That's why its called GroupD8. + import Matrix from './Matrix'; +/* + * Transform matrix for operation n is: + * | ux | vx | + * | uy | vy | + */ + const ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; const uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1]; const vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1]; const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1]; -const tempMatrices = []; -const mul = []; +/** + * [Cayley Table]{@link https://en.wikipedia.org/wiki/Cayley_table} + * for the composition of each rotation in the dihederal group D8. + * + * @type number[][] + * @private + */ +const rotationCayley = []; -function signum(x) -{ - if (x < 0) - { - return -1; - } - if (x > 0) - { - return 1; - } +/** + * Matrices for each `GD8Symmetry` rotation. + * + * @type Matrix[] + * @private + */ +const rotationMatrices = []; - return 0; -} +/* + * Alias for {@code Math.sign}. + */ +const signum = Math.sign; +/* + * Initializes `rotationCayley` and `rotationMatrices`. It is called + * only once below. + */ function init() { for (let i = 0; i < 16; i++) { const row = []; - mul.push(row); + rotationCayley.push(row); for (let j = 0; j < 16; j++) { + /* Multiplies rotation matrices i and j. */ const _ux = signum((ux[i] * ux[j]) + (vx[i] * uy[j])); const _uy = signum((uy[i] * ux[j]) + (vy[i] * uy[j])); const _vx = signum((ux[i] * vx[j]) + (vx[i] * vy[j])); const _vy = signum((uy[i] * vx[j]) + (vy[i] * vy[j])); + /* Finds rotation matrix matching the product and pushes it. */ for (let k = 0; k < 16; k++) { - if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy) + if (ux[k] === _ux && uy[k] === _uy + && vx[k] === _vx && vy[k] === _vy) { row.push(k); break; @@ -54,78 +76,262 @@ const mat = new Matrix(); mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0); - tempMatrices.push(mat); + rotationMatrices.push(mat); } } init(); /** - * Implements Dihedral Group D_8, see [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}, - * D8 is the same but with diagonals. Used for texture rotations. + * @memberof PIXI + * @typedef {number} GD8Symmetry + * @see PIXI.GroupD8 + */ + +/** + * Implements the dihedral group D8, which is similar to + * [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}; + * D8 is the same but with diagonals, and it is used for texture + * rotations. * - * Vector xX(i), xY(i) is U-axis of sprite with rotation i - * Vector yY(i), yY(i) is V-axis of sprite with rotation i - * Rotations: 0 grad (0), 90 grad (2), 180 grad (4), 270 grad (6) - * Mirrors: vertical (8), main diagonal (10), horizontal (12), reverse diagonal (14) - * This is the small part of gameofbombs.com portal system. It works. + * The directions the U- and V- axes after rotation + * of an angle of `a: GD8Constant` are the vectors `(uX(a), uY(a))` + * and `(vX(a), vY(a))`. These aren't necessarily unit vectors. * + * **Origin:**
+ * This is the small part of gameofbombs.com portal system. It works. + * + * @see PIXI.GroupD8.E + * @see PIXI.GroupD8.SE + * @see PIXI.GroupD8.S + * @see PIXI.GroupD8.SW + * @see PIXI.GroupD8.W + * @see PIXI.GroupD8.NW + * @see PIXI.GroupD8.N + * @see PIXI.GroupD8.NE * @author Ivan @ivanpopelyshev * @class * @memberof PIXI */ const GroupD8 = { + /** + * | Rotation | Direction | + * |----------|-----------| + * | 0° | East | + * + * @constant {PIXI.GD8Symmetry} + */ E: 0, - SE: 1, - S: 2, - SW: 3, - W: 4, - NW: 5, - N: 6, - NE: 7, - MIRROR_VERTICAL: 8, - MIRROR_HORIZONTAL: 12, - uX: (ind) => ux[ind], - uY: (ind) => uy[ind], - vX: (ind) => vx[ind], - vY: (ind) => vy[ind], - inv: (rotation) => - { - if (rotation & 8) - { - return rotation & 15; - } - - return (-rotation) & 7; - }, - add: (rotationSecond, rotationFirst) => mul[rotationSecond][rotationFirst], - sub: (rotationSecond, rotationFirst) => mul[rotationSecond][GroupD8.inv(rotationFirst)], /** - * Adds 180 degrees to rotation. Commutative operation. + * | Rotation | Direction | + * |----------|-----------| + * | 45°↻ | Southeast | + * + * @constant {PIXI.GD8Symmetry} + */ + SE: 1, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 90°↻ | South | + * + * @constant {PIXI.GD8Symmetry} + */ + S: 2, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 135°↻ | Southwest | + * + * @constant {PIXI.GD8Symmetry} + */ + SW: 3, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 180° | West | + * + * @constant {PIXI.GD8Symmetry} + */ + W: 4, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -135°/225°↻ | Northwest | + * + * @constant {PIXI.GD8Symmetry} + */ + NW: 5, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -90°/270°↻ | North | + * + * @constant {PIXI.GD8Symmetry} + */ + N: 6, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -45°/315°↻ | Northeast | + * + * @constant {PIXI.GD8Symmetry} + */ + NE: 7, + + /** + * Reflection about Y-axis. + * + * @constant {PIXI.GD8Symmetry} + */ + MIRROR_VERTICAL: 8, + + /** + * Reflection about the main diagonal. + * + * @constant {PIXI.GD8Symmetry} + */ + MAIN_DIAGONAL: 10, + + /** + * Reflection about X-axis. + * + * @constant {PIXI.GD8Symmetry} + */ + MIRROR_HORIZONTAL: 12, + + /** + * Reflection about reverse diagonal. + * + * @constant {PIXI.GD8Symmetry} + */ + REVERSE_DIAGONAL: 14, + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The X-component of the U-axis + * after rotating the axes. + */ + uX: (ind) => ux[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The Y-component of the U-axis + * after rotating the axes. + */ + uY: (ind) => uy[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The X-component of the V-axis + * after rotating the axes. + */ + vX: (ind) => vx[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The Y-component of the V-axis + * after rotating the axes. + */ + vY: (ind) => vy[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotation - symmetry whose opposite + * is needed. Only rotations have opposite symmetries while + * reflections don't. + * @return {PIXI.GD8Symmetry} The opposite symmetry of `rotation` + */ + inv: (rotation) => + { + if (rotation & 8)// true only if between 8 & 15 (reflections) + { + return rotation & 15;// or rotation % 16 + } + + return (-rotation) & 7;// or (8 - rotation) % 8 + }, + + /** + * Composes the two D8 operations. + * + * Taking `^` as reflection: + * + * | | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 | + * |-------|-----|-----|-----|-----|------|-------|-------|-------| + * | E=0 | E | S | W | N | E^ | S^ | W^ | N^ | + * | S=2 | S | W | N | E | S^ | W^ | N^ | E^ | + * | W=4 | W | N | E | S | W^ | N^ | E^ | S^ | + * | N=6 | N | E | S | W | N^ | E^ | S^ | W^ | + * | E^=8 | E^ | N^ | W^ | S^ | E | N | W | S | + * | S^=10 | S^ | E^ | N^ | W^ | S | E | N | W | + * | W^=12 | W^ | S^ | E^ | N^ | W | S | E | N | + * | N^=14 | N^ | W^ | S^ | E^ | N | W | S | E | + * + * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table} + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotationSecond - Second operation, which + * is the row in the above cayley table. + * @param {PIXI.GD8Symmetry} rotationFirst - First operation, which + * is the column in the above cayley table. + * @return {PIXI.GD8Symmetry} Composed operation + */ + add: (rotationSecond, rotationFirst) => ( + rotationCayley[rotationSecond][rotationFirst] + ), + + /** + * Reverse of `add`. + * + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotationSecond - Second operation + * @param {PIXI.GD8Symmetry} rotationFirst - First operation + * @return {PIXI.GD8Symmetry} Result + */ + sub: (rotationSecond, rotationFirst) => ( + rotationCayley[rotationSecond][GroupD8.inv(rotationFirst)] + ), + + /** + * Adds 180 degrees to rotation, which is a commutative + * operation. * * @memberof PIXI.GroupD8 * @param {number} rotation - The number to rotate. - * @returns {number} rotated number + * @returns {number} Rotated number */ rotate180: (rotation) => rotation ^ 4, /** - * Direction of main vector can be horizontal, vertical or diagonal. - * Some objects work with vertical directions different. + * Checks if the rotation angle is vertical, i.e. south + * or north. It doesn't work for reflections. * * @memberof PIXI.GroupD8 - * @param {number} rotation - The number to check. + * @param {PIXI.GD8Symmetry} rotation - The number to check. * @returns {boolean} Whether or not the direction is vertical */ - isVertical: (rotation) => (rotation & 3) === 2, + isVertical: (rotation) => (rotation & 3) === 2, // rotation % 4 === 2 /** - * @memberof PIXI.GroupD8 - * @param {number} dx - TODO - * @param {number} dy - TODO + * Approximates the vector `V(dx,dy)` into one of the + * eight directions provided by `GroupD8`. * - * @return {number} TODO + * @memberof PIXI.GroupD8 + * @param {number} dx - X-component of the vector + * @param {number} dy - Y-component of the vector + * @return {PIXI.GD8Symmetry} Approximation of the vector into + * one of the eight symmetries. */ byDirection: (dx, dy) => { @@ -169,14 +375,14 @@ * * @memberof PIXI.GroupD8 * @param {PIXI.Matrix} matrix - sprite world matrix - * @param {number} rotation - The rotation factor to use. + * @param {PIXI.GroupD8Symmetry} rotation - The rotation factor to use. * @param {number} tx - sprite anchoring * @param {number} ty - sprite anchoring */ matrixAppendRotationInv: (matrix, rotation, tx = 0, ty = 0) => { // Packer used "rotation", we use "inv(rotation)" - const mat = tempMatrices[GroupD8.inv(rotation)]; + const mat = rotationMatrices[GroupD8.inv(rotation)]; mat.tx = tx; mat.ty = ty; diff --git a/packages/core/src/textures/TextureUvs.js b/packages/core/src/textures/TextureUvs.js index c4ca3b2..519842c 100644 --- a/packages/core/src/textures/TextureUvs.js +++ b/packages/core/src/textures/TextureUvs.js @@ -1,7 +1,16 @@ import { GroupD8 } from '@pixi/math'; /** - * A standard object to store the Uvs of a texture + * Stores a texture's frame in UV coordinates, in + * which everything lies in the rectangle `[(0,0), (1,0), + * (1,1), (0,1)]`. + * + * | Corner | Coordinates | + * |--------------|-------------| + * | Top-Left | `(x0,y0)` | + * | Top-Right | `(x1,y1)` | + * | Bottom-Right | `(x2,y2)` | + * | Bottom-Left | `(x3,y3)` | * * @class * @protected @@ -12,56 +21,56 @@ constructor() { /** - * The position of the top-left corner on the x axis. + * X-component of top-left corner `(x0,y0)`. * * @member {number} */ this.x0 = 0; /** - * The position of the top-left corner on the y axis. + * Y-component of top-left corner `(x0,y0)`. * * @member {number} */ this.y0 = 0; /** - * The position of the top-right corner on the x axis. + * X-component of top-right corner `(x1,y1)`. * * @member {number} */ this.x1 = 1; /** - * The position of the top-right corner on the y axis. + * Y-component of top-right corner `(x1,y1)`. * * @member {number} */ this.y1 = 0; /** - * The position of the bottom-right corner on the x axis. + * X-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.x2 = 1; /** - * The position of the bottom-right corner on the y axis. + * Y-component of bottom-right corner `(x2,y2)`. * * @member {number} */ this.y2 = 1; /** - * The position of the bottom-left corner on the x axis. + * X-component of bottom-left corner `(x3,y3)`. * * @member {number} */ this.x3 = 0; /** - * The position of the bottom-left corner on the y axis. + * Y-component of bottom-right corner `(x3,y3)`. * * @member {number} */ diff --git a/packages/math/src/GroupD8.js b/packages/math/src/GroupD8.js index e6a09e7..4f2f5e7 100644 --- a/packages/math/src/GroupD8.js +++ b/packages/math/src/GroupD8.js @@ -1,46 +1,68 @@ -// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 +// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group +// +// This file implements the dihedral group of order 16, also called +// of degree 8. That's why its called GroupD8. + import Matrix from './Matrix'; +/* + * Transform matrix for operation n is: + * | ux | vx | + * | uy | vy | + */ + const ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; const uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1]; const vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1]; const vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1]; -const tempMatrices = []; -const mul = []; +/** + * [Cayley Table]{@link https://en.wikipedia.org/wiki/Cayley_table} + * for the composition of each rotation in the dihederal group D8. + * + * @type number[][] + * @private + */ +const rotationCayley = []; -function signum(x) -{ - if (x < 0) - { - return -1; - } - if (x > 0) - { - return 1; - } +/** + * Matrices for each `GD8Symmetry` rotation. + * + * @type Matrix[] + * @private + */ +const rotationMatrices = []; - return 0; -} +/* + * Alias for {@code Math.sign}. + */ +const signum = Math.sign; +/* + * Initializes `rotationCayley` and `rotationMatrices`. It is called + * only once below. + */ function init() { for (let i = 0; i < 16; i++) { const row = []; - mul.push(row); + rotationCayley.push(row); for (let j = 0; j < 16; j++) { + /* Multiplies rotation matrices i and j. */ const _ux = signum((ux[i] * ux[j]) + (vx[i] * uy[j])); const _uy = signum((uy[i] * ux[j]) + (vy[i] * uy[j])); const _vx = signum((ux[i] * vx[j]) + (vx[i] * vy[j])); const _vy = signum((uy[i] * vx[j]) + (vy[i] * vy[j])); + /* Finds rotation matrix matching the product and pushes it. */ for (let k = 0; k < 16; k++) { - if (ux[k] === _ux && uy[k] === _uy && vx[k] === _vx && vy[k] === _vy) + if (ux[k] === _ux && uy[k] === _uy + && vx[k] === _vx && vy[k] === _vy) { row.push(k); break; @@ -54,78 +76,262 @@ const mat = new Matrix(); mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0); - tempMatrices.push(mat); + rotationMatrices.push(mat); } } init(); /** - * Implements Dihedral Group D_8, see [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}, - * D8 is the same but with diagonals. Used for texture rotations. + * @memberof PIXI + * @typedef {number} GD8Symmetry + * @see PIXI.GroupD8 + */ + +/** + * Implements the dihedral group D8, which is similar to + * [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html}; + * D8 is the same but with diagonals, and it is used for texture + * rotations. * - * Vector xX(i), xY(i) is U-axis of sprite with rotation i - * Vector yY(i), yY(i) is V-axis of sprite with rotation i - * Rotations: 0 grad (0), 90 grad (2), 180 grad (4), 270 grad (6) - * Mirrors: vertical (8), main diagonal (10), horizontal (12), reverse diagonal (14) - * This is the small part of gameofbombs.com portal system. It works. + * The directions the U- and V- axes after rotation + * of an angle of `a: GD8Constant` are the vectors `(uX(a), uY(a))` + * and `(vX(a), vY(a))`. These aren't necessarily unit vectors. * + * **Origin:**
+ * This is the small part of gameofbombs.com portal system. It works. + * + * @see PIXI.GroupD8.E + * @see PIXI.GroupD8.SE + * @see PIXI.GroupD8.S + * @see PIXI.GroupD8.SW + * @see PIXI.GroupD8.W + * @see PIXI.GroupD8.NW + * @see PIXI.GroupD8.N + * @see PIXI.GroupD8.NE * @author Ivan @ivanpopelyshev * @class * @memberof PIXI */ const GroupD8 = { + /** + * | Rotation | Direction | + * |----------|-----------| + * | 0° | East | + * + * @constant {PIXI.GD8Symmetry} + */ E: 0, - SE: 1, - S: 2, - SW: 3, - W: 4, - NW: 5, - N: 6, - NE: 7, - MIRROR_VERTICAL: 8, - MIRROR_HORIZONTAL: 12, - uX: (ind) => ux[ind], - uY: (ind) => uy[ind], - vX: (ind) => vx[ind], - vY: (ind) => vy[ind], - inv: (rotation) => - { - if (rotation & 8) - { - return rotation & 15; - } - - return (-rotation) & 7; - }, - add: (rotationSecond, rotationFirst) => mul[rotationSecond][rotationFirst], - sub: (rotationSecond, rotationFirst) => mul[rotationSecond][GroupD8.inv(rotationFirst)], /** - * Adds 180 degrees to rotation. Commutative operation. + * | Rotation | Direction | + * |----------|-----------| + * | 45°↻ | Southeast | + * + * @constant {PIXI.GD8Symmetry} + */ + SE: 1, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 90°↻ | South | + * + * @constant {PIXI.GD8Symmetry} + */ + S: 2, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 135°↻ | Southwest | + * + * @constant {PIXI.GD8Symmetry} + */ + SW: 3, + + /** + * | Rotation | Direction | + * |----------|-----------| + * | 180° | West | + * + * @constant {PIXI.GD8Symmetry} + */ + W: 4, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -135°/225°↻ | Northwest | + * + * @constant {PIXI.GD8Symmetry} + */ + NW: 5, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -90°/270°↻ | North | + * + * @constant {PIXI.GD8Symmetry} + */ + N: 6, + + /** + * | Rotation | Direction | + * |-------------|--------------| + * | -45°/315°↻ | Northeast | + * + * @constant {PIXI.GD8Symmetry} + */ + NE: 7, + + /** + * Reflection about Y-axis. + * + * @constant {PIXI.GD8Symmetry} + */ + MIRROR_VERTICAL: 8, + + /** + * Reflection about the main diagonal. + * + * @constant {PIXI.GD8Symmetry} + */ + MAIN_DIAGONAL: 10, + + /** + * Reflection about X-axis. + * + * @constant {PIXI.GD8Symmetry} + */ + MIRROR_HORIZONTAL: 12, + + /** + * Reflection about reverse diagonal. + * + * @constant {PIXI.GD8Symmetry} + */ + REVERSE_DIAGONAL: 14, + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The X-component of the U-axis + * after rotating the axes. + */ + uX: (ind) => ux[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The Y-component of the U-axis + * after rotating the axes. + */ + uY: (ind) => uy[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The X-component of the V-axis + * after rotating the axes. + */ + vX: (ind) => vx[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} ind - sprite rotation angle. + * @return {PIXI.GD8Symmetry} The Y-component of the V-axis + * after rotating the axes. + */ + vY: (ind) => vy[ind], + + /** + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotation - symmetry whose opposite + * is needed. Only rotations have opposite symmetries while + * reflections don't. + * @return {PIXI.GD8Symmetry} The opposite symmetry of `rotation` + */ + inv: (rotation) => + { + if (rotation & 8)// true only if between 8 & 15 (reflections) + { + return rotation & 15;// or rotation % 16 + } + + return (-rotation) & 7;// or (8 - rotation) % 8 + }, + + /** + * Composes the two D8 operations. + * + * Taking `^` as reflection: + * + * | | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 | + * |-------|-----|-----|-----|-----|------|-------|-------|-------| + * | E=0 | E | S | W | N | E^ | S^ | W^ | N^ | + * | S=2 | S | W | N | E | S^ | W^ | N^ | E^ | + * | W=4 | W | N | E | S | W^ | N^ | E^ | S^ | + * | N=6 | N | E | S | W | N^ | E^ | S^ | W^ | + * | E^=8 | E^ | N^ | W^ | S^ | E | N | W | S | + * | S^=10 | S^ | E^ | N^ | W^ | S | E | N | W | + * | W^=12 | W^ | S^ | E^ | N^ | W | S | E | N | + * | N^=14 | N^ | W^ | S^ | E^ | N | W | S | E | + * + * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table} + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotationSecond - Second operation, which + * is the row in the above cayley table. + * @param {PIXI.GD8Symmetry} rotationFirst - First operation, which + * is the column in the above cayley table. + * @return {PIXI.GD8Symmetry} Composed operation + */ + add: (rotationSecond, rotationFirst) => ( + rotationCayley[rotationSecond][rotationFirst] + ), + + /** + * Reverse of `add`. + * + * @memberof PIXI.GroupD8 + * @param {PIXI.GD8Symmetry} rotationSecond - Second operation + * @param {PIXI.GD8Symmetry} rotationFirst - First operation + * @return {PIXI.GD8Symmetry} Result + */ + sub: (rotationSecond, rotationFirst) => ( + rotationCayley[rotationSecond][GroupD8.inv(rotationFirst)] + ), + + /** + * Adds 180 degrees to rotation, which is a commutative + * operation. * * @memberof PIXI.GroupD8 * @param {number} rotation - The number to rotate. - * @returns {number} rotated number + * @returns {number} Rotated number */ rotate180: (rotation) => rotation ^ 4, /** - * Direction of main vector can be horizontal, vertical or diagonal. - * Some objects work with vertical directions different. + * Checks if the rotation angle is vertical, i.e. south + * or north. It doesn't work for reflections. * * @memberof PIXI.GroupD8 - * @param {number} rotation - The number to check. + * @param {PIXI.GD8Symmetry} rotation - The number to check. * @returns {boolean} Whether or not the direction is vertical */ - isVertical: (rotation) => (rotation & 3) === 2, + isVertical: (rotation) => (rotation & 3) === 2, // rotation % 4 === 2 /** - * @memberof PIXI.GroupD8 - * @param {number} dx - TODO - * @param {number} dy - TODO + * Approximates the vector `V(dx,dy)` into one of the + * eight directions provided by `GroupD8`. * - * @return {number} TODO + * @memberof PIXI.GroupD8 + * @param {number} dx - X-component of the vector + * @param {number} dy - Y-component of the vector + * @return {PIXI.GD8Symmetry} Approximation of the vector into + * one of the eight symmetries. */ byDirection: (dx, dy) => { @@ -169,14 +375,14 @@ * * @memberof PIXI.GroupD8 * @param {PIXI.Matrix} matrix - sprite world matrix - * @param {number} rotation - The rotation factor to use. + * @param {PIXI.GroupD8Symmetry} rotation - The rotation factor to use. * @param {number} tx - sprite anchoring * @param {number} ty - sprite anchoring */ matrixAppendRotationInv: (matrix, rotation, tx = 0, ty = 0) => { // Packer used "rotation", we use "inv(rotation)" - const mat = tempMatrices[GroupD8.inv(rotation)]; + const mat = rotationMatrices[GroupD8.inv(rotation)]; mat.tx = tx; mat.ty = ty; diff --git a/packages/sprite/src/Sprite.js b/packages/sprite/src/Sprite.js index dad76a4..efbc6dd 100644 --- a/packages/sprite/src/Sprite.js +++ b/packages/sprite/src/Sprite.js @@ -44,14 +44,20 @@ super(); /** - * The anchor sets the origin point of the texture. - * 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. + * The anchor point defines the normalized coordinates + * in the texture that map to the position of this + * sprite. * + * By default, this is `(0,0)` (or `texture.defaultAnchor` + * if you have modified that), which means the position + * `(x,y)` of this `Sprite` will be the top-left corner. + * + * Note: Updating `texture.defaultAnchor` after + * constructing a `Sprite` does _not_ update its anchor. + * + * {@link https://docs.cocos2d-x.org/cocos2d-x/en/sprites/manipulation.html} + * + * @default `texture.defaultAnchor` * @member {PIXI.ObservablePoint} * @private */