@awayjs/core
Version:
AwayJS core classes
626 lines (625 loc) • 23 kB
JavaScript
import { __extends } from "tslib";
import { EventDispatcher } from '../events/EventDispatcher';
import { TransformEvent } from '../events/TransformEvent';
import { Matrix } from '../geom/Matrix';
import { Matrix3D } from '../geom/Matrix3D';
import { Vector3D } from '../geom/Vector3D';
import { ColorTransform } from './ColorTransform';
/**
* The Transform class provides access to color adjustment properties and two-
* or three-dimensional transformation objects that can be applied to a display
* object. During the transformation, the color or the orientation and position
* of a display object is adjusted(offset) from the current values or
* coordinates to new values or coordinates. The Transform class also collects
* data about color and two-dimensional matrix transformations that are applied
* to a display object and all of its parent objects. You can access these
* combined transformations through the `concatenatedColorTransform` and
* `concatenatedMatrix` properties.
*
* To apply color transformations: create a ColorTransform object, set the color
* adjustments using the object's methods and properties, and then assign the
* `colorTransformation` property of the `transform` property of the display
* object to the new ColorTransformation object.
*
* To apply two-dimensional transformations: create a Matrix object, set the
* matrix's two-dimensional transformation, and then assign the
* `transform.matrix` property of the display object to the new Matrix object.
*
* To apply three-dimensional transformations: start with a three-dimensional
* display object. A three-dimensional display object has a `z` property value
* other than zero. You do not need to create the Matrix3D object. For all
* three-dimensional objects, a Matrix3D object is created automatically when
* you assign a `z` value to a display object. You can access the display
* object's Matrix3D object through the display object's `transform` property.
* Using the methods of the Matrix3D class, you can add to or modify the
* existing transformation settings. Also, you can create a custom Matrix3D
* object, set the custom Matrix3D object's transformation elements, and then
* assign the new Matrix3D object to the display object using the
* `transform.matrix` property.
*
* To modify a perspective projection of the stage or root object: use the
* `transform.matrix` property of the root display object to gain access to the
* PerspectiveProjection object. Or, apply different perspective projection
* properties to a display object by setting the perspective projection
* properties of the display object's parent. The child display object inherits
* the new properties. Specifically, create a PerspectiveProjection object and
* set its properties, then assign the PerspectiveProjection object to the
* `perspectiveProjection` property of the parent display object's `transform`
* property. The specified projection transformation then applies to all the
* display object's three-dimensional children.
*
* Since both PerspectiveProjection and Matrix3D objects perform perspective
* transformations, do not assign both to a display object at the same time. Use
* the PerspectiveProjection object for focal length and projection center
* changes. For more control over the perspective transformation, create a
* perspective projection Matrix3D object.
*/
var Transform = /** @class */ (function (_super) {
__extends(Transform, _super);
function Transform(rawData) {
if (rawData === void 0) { rawData = null; }
var _this = _super.call(this) || this;
_this._componentsDirty = true;
_this._inverseMatrix3DDirty = true;
_this._rawData = rawData || new Float32Array(24);
//create the view for matrix3D
_this._matrix3D = new Matrix3D(new Float32Array(_this._rawData.buffer, 0, 16));
//create the view for colorTransform
_this._colorTransform = new ColorTransform(new Float32Array(_this._rawData.buffer, 64, 8));
if (rawData == null) {
_this._matrix3D.identity();
_this._colorTransform.clear();
}
return _this;
}
Object.defineProperty(Transform.prototype, "backVector", {
/**
*
*/
get: function () {
if (!this._backVector)
this._backVector = new Vector3D();
this._matrix3D.copyColumnTo(2, this._backVector, true);
return this._backVector;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "colorTransform", {
/**
* A ColorTransform object containing values that universally adjust the
* colors in the display object.
*
* @throws TypeError The colorTransform is null when being set
*/
get: function () {
return this._colorTransform;
},
set: function (val) {
if (val) {
this._rawData.set(val._rawData, 16);
}
else {
this._colorTransform.clear();
}
this.invalidateColorTransform();
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "inverseMatrix3D", {
/**
*
*/
get: function () {
if (!this._inverseMatrix3D)
this._inverseMatrix3D = new Matrix3D();
if (this._inverseMatrix3DDirty) {
this._inverseMatrix3DDirty = false;
this._inverseMatrix3D.copyFrom(this.matrix3D);
this._inverseMatrix3D.invert();
}
return this._inverseMatrix3D;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "downVector", {
/**
*
*/
get: function () {
if (!this._downVector)
this._downVector = new Vector3D();
this._matrix3D.copyColumnTo(1, this._downVector, true);
return this._downVector;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "forwardVector", {
/**
*
*/
get: function () {
if (!this._forwardVector)
this._forwardVector = new Vector3D();
this._matrix3D.copyColumnTo(2, this._forwardVector);
return this._forwardVector;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "leftVector", {
/**
*
*/
get: function () {
if (!this._leftVector)
this._leftVector = new Vector3D();
this._matrix3D.copyColumnTo(0, this._backVector, true);
return this._leftVector;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "matrix", {
/**
* A Matrix object containing values that alter the scaling, rotation, and
* translation of the display object. If the `matrix` property is set to a
* value (not `null`), the `matrix3D` property is `null`. And if the
* `matrix3D` property is set to a value(not `null`), the `matrix` property
* is `null`.
*
* @throws TypeError The matrix is null when being set
*/
get: function () {
if (!this._matrix)
this._matrix = new Matrix();
if (this._matrix3DDirty)
this.updateMatrix3D();
this._matrix.a = this._matrix3D._rawData[0];
this._matrix.b = this._matrix3D._rawData[1];
this._matrix.c = this._matrix3D._rawData[4];
this._matrix.d = this._matrix3D._rawData[5];
this._matrix.tx = this._matrix3D._rawData[12];
this._matrix.ty = this._matrix3D._rawData[13];
return this._matrix;
},
set: function (value) {
if (!value)
return;
this._matrix3D.identity();
this._matrix3D._rawData[0] = value.a;
this._matrix3D._rawData[1] = value.b;
this._matrix3D._rawData[4] = value.c;
this._matrix3D._rawData[5] = value.d;
this._matrix3D._rawData[12] = value.tx;
this._matrix3D._rawData[13] = value.ty;
this.invalidateComponents();
this._matrix3DDirty = false;
this._inverseMatrix3DDirty = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "matrix3D", {
/**
* Provides access to the Matrix3D object of a three-dimensional display
* object. The Matrix3D object represents a transformation matrix that
* determines the display object's position and orientation. A Matrix3D
* object can also perform perspective projection.
*
* If the `matrix` property is set to a value(not `null`), the `matrix3D`
* property is `null`. And if the `matrix3D` property is set to a value(not
* `null`), the `matrix` property is `null`.
*/
get: function () {
if (this._matrix3DDirty)
this.updateMatrix3D();
return this._matrix3D;
},
set: function (val) {
if (!val) {
this._matrix3D.identity();
}
else {
this._rawData.set(val._rawData);
}
this.invalidateComponents();
this._matrix3DDirty = false;
this._inverseMatrix3DDirty = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "pixelBounds", {
/**
* A Rectangle object that defines the bounding rectangle of the display
* object on the stage.
*/
get: function () {
return this._pixelBounds;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "position", {
/**
* Defines the position of the 3d object, relative to the local coordinates
* of the parent `ObjectContainer3D`.
*/
get: function () {
return this._matrix3D.position;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "rightVector", {
/**
*
*/
get: function () {
if (!this._rightVector)
this._rightVector = new Vector3D();
this._matrix3D.copyColumnTo(0, this._rightVector);
return this._rightVector;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "rotation", {
/**
* Defines the rotation of the 3d object, relative to the local coordinates
* of the parent `ObjectContainer3D` .
*/
get: function () {
if (this._componentsDirty)
this._updateComponents();
return this._rotation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "scale", {
/**
* Defines the scale of the 3d object, relative to the local coordinates of
* the parent `ObjectContainer3D` .
*/
get: function () {
if (this._componentsDirty)
this._updateComponents();
return this._scale;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "skew", {
/**
* Defines the scale of the 3d object, relative to the local coordinates of
* the parent `ObjectContainer3D` .
*/
get: function () {
if (this._componentsDirty)
this._updateComponents();
return this._skew;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Transform.prototype, "upVector", {
/**
*
*/
get: function () {
if (!this._upVector)
this._upVector = new Vector3D();
this._matrix3D.copyColumnTo(1, this._upVector);
return this._upVector;
},
enumerable: false,
configurable: true
});
/**
*
* @param value
*/
Transform.prototype.append = function (value) {
console.log("append(".concat(value, ") is not implemented yet in core/Transform"));
};
/**
*
*/
Transform.prototype.clearColorTransform = function () {
if (!this._colorTransform)
return;
this._colorTransform.clear();
this.invalidateColorTransform();
};
/**
*
*/
Transform.prototype.clearMatrix3D = function () {
this._matrix3D.identity();
this.invalidateComponents();
};
/**
*
*/
Transform.prototype.clone = function () {
var transform = new Transform();
this.copyRawDataTo(transform);
return transform;
};
/**
*
* @param transform
*/
Transform.prototype.copyRawDataTo = function (transform) {
if (this._matrix3DDirty)
this.updateMatrix3D();
transform._rawData.set(this._rawData);
this.invalidateComponents();
this.invalidateColorTransform();
};
/**
*
*/
Transform.prototype.dispose = function () {
};
Transform.prototype.invalidateColorTransform = function () {
if (!this._invalidateColorTransform) {
this._invalidateColorTransform = new TransformEvent(TransformEvent.INVALIDATE_COLOR_TRANSFORM, this);
}
this.dispatchEvent(this._invalidateColorTransform);
};
Transform.prototype.invalidateComponents = function () {
this.invalidatePosition();
this._componentsDirty = true;
};
/**
* Invalidates the 3D transformation matrix, causing it to be updated upon the next request
*
* @private
*/
Transform.prototype.invalidateMatrix3D = function () {
this._inverseMatrix3DDirty = true;
if (this._matrix3DDirty)
return;
this._matrix3DDirty = true;
if (!this._invalidateMatrix3D)
this._invalidateMatrix3D = new TransformEvent(TransformEvent.INVALIDATE_MATRIX3D, this);
this.dispatchEvent(this._invalidateMatrix3D);
};
/**
*
*/
Transform.prototype.invalidatePosition = function () {
this._inverseMatrix3DDirty = true;
if (!this._invalidateMatrix3D)
this._invalidateMatrix3D = new TransformEvent(TransformEvent.INVALIDATE_MATRIX3D, this);
this.dispatchEvent(this._invalidateMatrix3D);
};
/**
* Rotates the 3d object around to face a point defined relative to the
* local coordinates of the parent `ObjectContainer3D` .
*
* @param target The vector defining the point to be looked at.
* @param upAxis An optional vector used to define the desired up
* orientation of the 3d object after rotation has occurred.
*/
Transform.prototype.lookAt = function (position, upAxis) {
if (upAxis === void 0) { upAxis = null; }
if (upAxis == null)
upAxis = Vector3D.Y_AXIS;
var vec = Matrix3D.getPointAtMatrix(new Vector3D(), position.subtract(this._matrix3D.position), upAxis, Matrix3D.CALCULATION_MATRIX)
.decompose()[1];
this.rotateTo(vec.x, vec.y, vec.z);
};
/**
* Moves the 3d object backwards along it's local z axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveBackward = function (distance) {
this.translateLocal(Vector3D.Z_AXIS, -distance);
};
/**
* Moves the 3d object backwards along it's local y axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveDown = function (distance) {
this.translateLocal(Vector3D.Y_AXIS, -distance);
};
/**
* Moves the 3d object forwards along it's local z axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveForward = function (distance) {
this.translateLocal(Vector3D.Z_AXIS, distance);
};
/**
* Moves the 3d object backwards along it's local x axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveLeft = function (distance) {
this.translateLocal(Vector3D.X_AXIS, -distance);
};
/**
* Moves the 3d object forwards along it's local x axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveRight = function (distance) {
this.translateLocal(Vector3D.X_AXIS, distance);
};
/**
* Moves the 3d object directly to a point in space
*
* @param dx The amount of movement along the local x axis.
* @param dy The amount of movement along the local y axis.
* @param dz The amount of movement along the local z axis.
*/
Transform.prototype.moveTo = function (dx, dy, dz) {
this._matrix3D._rawData[12] = dx;
this._matrix3D._rawData[13] = dy;
this._matrix3D._rawData[14] = dz;
this.invalidatePosition();
};
/**
* Moves the 3d object forwards along it's local y axis
*
* @param distance The length of the movement
*/
Transform.prototype.moveUp = function (distance) {
this.translateLocal(Vector3D.Y_AXIS, distance);
};
/**
* Rotates the 3d object around it's local x-axis
*
* @param angle The amount of rotation in degrees
*/
Transform.prototype.pitch = function (angle) {
this.rotate(Vector3D.X_AXIS, angle);
};
/**
* Rotates the 3d object around it's local z-axis
*
* @param angle The amount of rotation in degrees
*/
Transform.prototype.roll = function (angle) {
this.rotate(Vector3D.Z_AXIS, angle);
};
/**
* Rotates the 3d object around an axis by a defined angle
*
* @param axis The vector defining the axis of rotation
* @param angle The amount of rotation in degrees
*/
Transform.prototype.rotate = function (axis, angle) {
this.matrix3D.prependRotation(angle, axis);
this.invalidateComponents();
};
/**
* Rotates the 3d object directly to a euler angle
*
* @param ax The angle in degrees of the rotation around the x axis.
* @param ay The angle in degrees of the rotation around the y axis.
* @param az The angle in degrees of the rotation around the z axis.
*/
Transform.prototype.rotateTo = function (ax, ay, az) {
if (this._componentsDirty)
this._updateComponents();
this._rotation.x = ax;
this._rotation.y = ay;
this._rotation.z = az;
this.invalidateMatrix3D();
};
/**
*
* @param sx
* @param sy
* @param sz
*/
Transform.prototype.scaleTo = function (sx, sy, sz) {
if (this._componentsDirty)
this._updateComponents();
this._scale.x = sx;
this._scale.y = sy;
this._scale.z = sz;
this.invalidateMatrix3D();
};
/**
*
* @param sx
* @param sy
* @param sz
*/
Transform.prototype.skewTo = function (sx, sy, sz) {
if (this._componentsDirty)
this._updateComponents();
this._skew.x = sx;
this._skew.y = sy;
this._skew.z = sz;
this.invalidateMatrix3D();
};
/**
* Moves the 3d object along a vector by a defined length.
*
* @param axis The vector defining the axis of movement.
* @param distance The length of the movement.
*/
Transform.prototype.translate = function (axis, distance) {
var x = axis.x, y = axis.y, z = axis.z;
var len = distance / Math.sqrt(x * x + y * y + z * z);
this.matrix3D.appendTranslation(x * len, y * len, z * len);
this.invalidatePosition();
};
/**
* Moves the 3d object along a vector by a defined length.
*
* @param axis The vector defining the axis of movement.
* @param distance The length of the movement.
*/
Transform.prototype.translateLocal = function (axis, distance) {
var x = axis.x, y = axis.y, z = axis.z;
var len = distance / Math.sqrt(x * x + y * y + z * z);
this.matrix3D.prependTranslation(x * len, y * len, z * len);
this.invalidatePosition();
};
/**
*
*/
Transform.prototype.updateMatrix3D = function () {
Transform._tempVector.copyFrom(this._matrix3D.position);
this._matrix3D.recompose(this._components);
this._matrix3DDirty = false;
};
/**
* Rotates the 3d object around it's local y-axis
*
* @param angle The amount of rotation in degrees
*/
Transform.prototype.yaw = function (angle) {
this.rotate(Vector3D.Y_AXIS, angle);
};
Transform.prototype._updateComponents = function () {
if (!this._components) {
// Cached vector of transformation components used when
// recomposing the transform matrix in updateTransform()
this._components = new Array(4);
this._rawDataComponents = new Float32Array(12);
this._rawDataComponents[3] = 1;
this._rawDataComponents[7] = 1;
this._rawDataComponents[11] = 1;
this._rotation = new Vector3D(new Float32Array(this._rawDataComponents.buffer, 0, 4));
this._skew = new Vector3D(new Float32Array(this._rawDataComponents.buffer, 16, 4));
this._scale = new Vector3D(new Float32Array(this._rawDataComponents.buffer, 32, 4));
this._components[0] = Transform._tempVector;
this._components[1] = this._rotation;
this._components[2] = this._skew;
this._components[3] = this._scale;
}
var elements = this._matrix3D.decompose();
var vec;
vec = elements[1];
this._rotation.x = vec.x;
this._rotation.y = vec.y;
this._rotation.z = vec.z;
vec = elements[2];
this._skew.x = vec.x;
this._skew.y = vec.y;
this._skew.z = vec.z;
vec = elements[3];
this._scale.x = vec.x;
this._scale.y = vec.y;
this._scale.z = vec.z;
this._componentsDirty = false;
};
Transform._tempVector = new Vector3D();
return Transform;
}(EventDispatcher));
export { Transform };