210 lines
9.4 KiB
JavaScript
210 lines
9.4 KiB
JavaScript
"use strict";
|
|
var _const = require("./const.js"), Point = require("./Point.js");
|
|
class Matrix {
|
|
/**
|
|
* @param a - x scale
|
|
* @param b - y skew
|
|
* @param c - x skew
|
|
* @param d - y scale
|
|
* @param tx - x translation
|
|
* @param ty - y translation
|
|
*/
|
|
constructor(a = 1, b = 0, c = 0, d = 1, tx = 0, ty = 0) {
|
|
this.array = null, this.a = a, this.b = b, this.c = c, this.d = d, this.tx = tx, this.ty = ty;
|
|
}
|
|
/**
|
|
* Creates a Matrix object based on the given array. The Element to Matrix mapping order is as follows:
|
|
*
|
|
* a = array[0]
|
|
* b = array[1]
|
|
* c = array[3]
|
|
* d = array[4]
|
|
* tx = array[2]
|
|
* ty = array[5]
|
|
* @param array - The array that the matrix will be populated from.
|
|
*/
|
|
fromArray(array) {
|
|
this.a = array[0], this.b = array[1], this.c = array[3], this.d = array[4], this.tx = array[2], this.ty = array[5];
|
|
}
|
|
/**
|
|
* Sets the matrix properties.
|
|
* @param a - Matrix component
|
|
* @param b - Matrix component
|
|
* @param c - Matrix component
|
|
* @param d - Matrix component
|
|
* @param tx - Matrix component
|
|
* @param ty - Matrix component
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
set(a, b, c, d, tx, ty) {
|
|
return this.a = a, this.b = b, this.c = c, this.d = d, this.tx = tx, this.ty = ty, this;
|
|
}
|
|
/**
|
|
* Creates an array from the current Matrix object.
|
|
* @param transpose - Whether we need to transpose the matrix or not
|
|
* @param [out=new Float32Array(9)] - If provided the array will be assigned to out
|
|
* @returns The newly created array which contains the matrix
|
|
*/
|
|
toArray(transpose, out) {
|
|
this.array || (this.array = new Float32Array(9));
|
|
const array = out || this.array;
|
|
return transpose ? (array[0] = this.a, array[1] = this.b, array[2] = 0, array[3] = this.c, array[4] = this.d, array[5] = 0, array[6] = this.tx, array[7] = this.ty, array[8] = 1) : (array[0] = this.a, array[1] = this.c, array[2] = this.tx, array[3] = this.b, array[4] = this.d, array[5] = this.ty, array[6] = 0, array[7] = 0, array[8] = 1), array;
|
|
}
|
|
/**
|
|
* Get a new position with the current transformation applied.
|
|
* Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering)
|
|
* @param pos - The origin
|
|
* @param {PIXI.Point} [newPos] - The point that the new position is assigned to (allowed to be same as input)
|
|
* @returns {PIXI.Point} The new point, transformed through this matrix
|
|
*/
|
|
apply(pos, newPos) {
|
|
newPos = newPos || new Point.Point();
|
|
const x = pos.x, y = pos.y;
|
|
return newPos.x = this.a * x + this.c * y + this.tx, newPos.y = this.b * x + this.d * y + this.ty, newPos;
|
|
}
|
|
/**
|
|
* Get a new position with the inverse of the current transformation applied.
|
|
* Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input)
|
|
* @param pos - The origin
|
|
* @param {PIXI.Point} [newPos] - The point that the new position is assigned to (allowed to be same as input)
|
|
* @returns {PIXI.Point} The new point, inverse-transformed through this matrix
|
|
*/
|
|
applyInverse(pos, newPos) {
|
|
newPos = newPos || new Point.Point();
|
|
const id = 1 / (this.a * this.d + this.c * -this.b), x = pos.x, y = pos.y;
|
|
return newPos.x = this.d * id * x + -this.c * id * y + (this.ty * this.c - this.tx * this.d) * id, newPos.y = this.a * id * y + -this.b * id * x + (-this.ty * this.a + this.tx * this.b) * id, newPos;
|
|
}
|
|
/**
|
|
* Translates the matrix on the x and y.
|
|
* @param x - How much to translate x by
|
|
* @param y - How much to translate y by
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
translate(x, y) {
|
|
return this.tx += x, this.ty += y, this;
|
|
}
|
|
/**
|
|
* Applies a scale transformation to the matrix.
|
|
* @param x - The amount to scale horizontally
|
|
* @param y - The amount to scale vertically
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
scale(x, y) {
|
|
return this.a *= x, this.d *= y, this.c *= x, this.b *= y, this.tx *= x, this.ty *= y, this;
|
|
}
|
|
/**
|
|
* Applies a rotation transformation to the matrix.
|
|
* @param angle - The angle in radians.
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
rotate(angle) {
|
|
const cos = Math.cos(angle), sin = Math.sin(angle), a1 = this.a, c1 = this.c, tx1 = this.tx;
|
|
return this.a = a1 * cos - this.b * sin, this.b = a1 * sin + this.b * cos, this.c = c1 * cos - this.d * sin, this.d = c1 * sin + this.d * cos, this.tx = tx1 * cos - this.ty * sin, this.ty = tx1 * sin + this.ty * cos, this;
|
|
}
|
|
/**
|
|
* Appends the given Matrix to this Matrix.
|
|
* @param matrix - The matrix to append.
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
append(matrix) {
|
|
const a1 = this.a, b1 = this.b, c1 = this.c, d1 = this.d;
|
|
return this.a = matrix.a * a1 + matrix.b * c1, this.b = matrix.a * b1 + matrix.b * d1, this.c = matrix.c * a1 + matrix.d * c1, this.d = matrix.c * b1 + matrix.d * d1, this.tx = matrix.tx * a1 + matrix.ty * c1 + this.tx, this.ty = matrix.tx * b1 + matrix.ty * d1 + this.ty, this;
|
|
}
|
|
/**
|
|
* Sets the matrix based on all the available properties
|
|
* @param x - Position on the x axis
|
|
* @param y - Position on the y axis
|
|
* @param pivotX - Pivot on the x axis
|
|
* @param pivotY - Pivot on the y axis
|
|
* @param scaleX - Scale on the x axis
|
|
* @param scaleY - Scale on the y axis
|
|
* @param rotation - Rotation in radians
|
|
* @param skewX - Skew on the x axis
|
|
* @param skewY - Skew on the y axis
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
setTransform(x, y, pivotX, pivotY, scaleX, scaleY, rotation, skewX, skewY) {
|
|
return this.a = Math.cos(rotation + skewY) * scaleX, this.b = Math.sin(rotation + skewY) * scaleX, this.c = -Math.sin(rotation - skewX) * scaleY, this.d = Math.cos(rotation - skewX) * scaleY, this.tx = x - (pivotX * this.a + pivotY * this.c), this.ty = y - (pivotX * this.b + pivotY * this.d), this;
|
|
}
|
|
/**
|
|
* Prepends the given Matrix to this Matrix.
|
|
* @param matrix - The matrix to prepend
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
prepend(matrix) {
|
|
const tx1 = this.tx;
|
|
if (matrix.a !== 1 || matrix.b !== 0 || matrix.c !== 0 || matrix.d !== 1) {
|
|
const a1 = this.a, c1 = this.c;
|
|
this.a = a1 * matrix.a + this.b * matrix.c, this.b = a1 * matrix.b + this.b * matrix.d, this.c = c1 * matrix.a + this.d * matrix.c, this.d = c1 * matrix.b + this.d * matrix.d;
|
|
}
|
|
return this.tx = tx1 * matrix.a + this.ty * matrix.c + matrix.tx, this.ty = tx1 * matrix.b + this.ty * matrix.d + matrix.ty, this;
|
|
}
|
|
/**
|
|
* Decomposes the matrix (x, y, scaleX, scaleY, and rotation) and sets the properties on to a transform.
|
|
* @param transform - The transform to apply the properties to.
|
|
* @returns The transform with the newly applied properties
|
|
*/
|
|
decompose(transform) {
|
|
const a = this.a, b = this.b, c = this.c, d = this.d, pivot = transform.pivot, skewX = -Math.atan2(-c, d), skewY = Math.atan2(b, a), delta = Math.abs(skewX + skewY);
|
|
return delta < 1e-5 || Math.abs(_const.PI_2 - delta) < 1e-5 ? (transform.rotation = skewY, transform.skew.x = transform.skew.y = 0) : (transform.rotation = 0, transform.skew.x = skewX, transform.skew.y = skewY), transform.scale.x = Math.sqrt(a * a + b * b), transform.scale.y = Math.sqrt(c * c + d * d), transform.position.x = this.tx + (pivot.x * a + pivot.y * c), transform.position.y = this.ty + (pivot.x * b + pivot.y * d), transform;
|
|
}
|
|
/**
|
|
* Inverts this matrix
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
invert() {
|
|
const a1 = this.a, b1 = this.b, c1 = this.c, d1 = this.d, tx1 = this.tx, n = a1 * d1 - b1 * c1;
|
|
return this.a = d1 / n, this.b = -b1 / n, this.c = -c1 / n, this.d = a1 / n, this.tx = (c1 * this.ty - d1 * tx1) / n, this.ty = -(a1 * this.ty - b1 * tx1) / n, this;
|
|
}
|
|
/**
|
|
* Resets this Matrix to an identity (default) matrix.
|
|
* @returns This matrix. Good for chaining method calls.
|
|
*/
|
|
identity() {
|
|
return this.a = 1, this.b = 0, this.c = 0, this.d = 1, this.tx = 0, this.ty = 0, this;
|
|
}
|
|
/**
|
|
* Creates a new Matrix object with the same values as this one.
|
|
* @returns A copy of this matrix. Good for chaining method calls.
|
|
*/
|
|
clone() {
|
|
const matrix = new Matrix();
|
|
return matrix.a = this.a, matrix.b = this.b, matrix.c = this.c, matrix.d = this.d, matrix.tx = this.tx, matrix.ty = this.ty, matrix;
|
|
}
|
|
/**
|
|
* Changes the values of the given matrix to be the same as the ones in this matrix
|
|
* @param matrix - The matrix to copy to.
|
|
* @returns The matrix given in parameter with its values updated.
|
|
*/
|
|
copyTo(matrix) {
|
|
return matrix.a = this.a, matrix.b = this.b, matrix.c = this.c, matrix.d = this.d, matrix.tx = this.tx, matrix.ty = this.ty, matrix;
|
|
}
|
|
/**
|
|
* Changes the values of the matrix to be the same as the ones in given matrix
|
|
* @param {PIXI.Matrix} matrix - The matrix to copy from.
|
|
* @returns {PIXI.Matrix} this
|
|
*/
|
|
copyFrom(matrix) {
|
|
return this.a = matrix.a, this.b = matrix.b, this.c = matrix.c, this.d = matrix.d, this.tx = matrix.tx, this.ty = matrix.ty, this;
|
|
}
|
|
/**
|
|
* A default (identity) matrix
|
|
* @readonly
|
|
*/
|
|
static get IDENTITY() {
|
|
return new Matrix();
|
|
}
|
|
/**
|
|
* A temp matrix
|
|
* @readonly
|
|
*/
|
|
static get TEMP_MATRIX() {
|
|
return new Matrix();
|
|
}
|
|
}
|
|
Matrix.prototype.toString = function() {
|
|
return `[@pixi/math:Matrix a=${this.a} b=${this.b} c=${this.c} d=${this.d} tx=${this.tx} ty=${this.ty}]`;
|
|
};
|
|
exports.Matrix = Matrix;
|
|
//# sourceMappingURL=Matrix.js.map
|