Files
esengine/source/src/ECS/Transform.ts

507 lines
16 KiB
TypeScript
Raw Normal View History

module transform {
export enum Component {
position,
scale,
rotation,
}
}
2020-07-22 20:07:14 +08:00
module es {
import HashObject = egret.HashObject;
export enum DirtyType {
clean,
positionDirty,
scaleDirty,
rotationDirty,
}
export class Transform extends HashObject {
2020-07-22 20:07:14 +08:00
/** 与此转换关联的实体 */
public readonly entity: Entity;
2020-07-28 16:25:20 +08:00
public hierarchyDirty: DirtyType;
public _localDirty: boolean;
public _localPositionDirty: boolean;
public _localScaleDirty: boolean;
public _localRotationDirty: boolean;
public _positionDirty: boolean;
public _worldToLocalDirty: boolean;
public _worldInverseDirty: boolean;
2020-07-22 20:07:14 +08:00
/**
2020-07-28 16:25:20 +08:00
*
2020-07-22 20:07:14 +08:00
*/
2020-07-28 16:25:20 +08:00
public _localTransform: Matrix2D = Matrix2D.create();
2020-07-22 20:07:14 +08:00
/**
2020-07-28 16:25:20 +08:00
*
2020-07-22 20:07:14 +08:00
*/
2020-07-28 16:25:20 +08:00
public _worldTransform = Matrix2D.create().identity();
2020-08-25 14:21:37 +08:00
public _rotationMatrix: Matrix2D = Matrix2D.create().identity();
public _translationMatrix: Matrix2D = Matrix2D.create().identity();
public _scaleMatrix: Matrix2D = Matrix2D.create().identity();
2020-07-28 16:25:20 +08:00
public _children: Transform[];
constructor(entity: Entity) {
super();
this.entity = entity;
this.scale = Vector2.one;
this._children = [];
2020-07-22 20:07:14 +08:00
}
/**
*
*/
public get childCount() {
return this._children.length;
}
/**
2020-07-28 16:25:20 +08:00
*
2020-07-22 20:07:14 +08:00
*/
2020-07-28 16:25:20 +08:00
public get rotationDegrees(): number {
return MathHelper.toDegrees(this._rotation);
}
/**
2020-07-28 16:25:20 +08:00
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set rotationDegrees(value: number) {
this.setRotation(MathHelper.toRadians(value));
}
/**
2020-07-28 16:25:20 +08:00
*
*/
2020-07-28 16:25:20 +08:00
public get localRotationDegrees(): number {
return MathHelper.toDegrees(this._localRotation);
}
/**
2020-07-28 16:25:20 +08:00
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set localRotationDegrees(value: number) {
this.localRotation = MathHelper.toRadians(value);
}
2020-07-28 16:25:20 +08:00
public get localToWorldTransform(): Matrix2D {
this.updateTransform();
2020-07-28 16:25:20 +08:00
return this._worldTransform;
}
2020-07-28 16:25:20 +08:00
public _parent: Transform;
/**
2020-07-28 16:25:20 +08:00
*
*/
2020-07-28 16:25:20 +08:00
public get parent() {
return this._parent;
}
/**
2020-07-28 16:25:20 +08:00
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set parent(value: Transform) {
this.setParent(value);
}
2020-07-28 16:25:20 +08:00
public _worldToLocalTransform = Matrix2D.create().identity();
public get worldToLocalTransform(): Matrix2D {
if (this._worldToLocalDirty) {
if (!this.parent) {
this._worldToLocalTransform = Matrix2D.create().identity();
} else {
this.parent.updateTransform();
this._worldToLocalTransform = this.parent._worldTransform.invert();
}
this._worldToLocalDirty = false;
}
return this._worldToLocalTransform;
}
public _worldInverseTransform = Matrix2D.create().identity();
public get worldInverseTransform(): Matrix2D {
this.updateTransform();
if (this._worldInverseDirty) {
this._worldInverseTransform = this._worldTransform.invert();
this._worldInverseDirty = false;
}
return this._worldInverseTransform;
}
public _position: Vector2 = Vector2.zero;
2020-07-22 20:07:14 +08:00
/**
2020-07-28 16:25:20 +08:00
*
*/
public get position(): Vector2 {
this.updateTransform();
if (this._positionDirty) {
if (!this.parent) {
this._position = this._localPosition;
} else {
this.parent.updateTransform();
this._position = Vector2Ext.transformR(this._localPosition, this.parent._worldTransform);
}
this._positionDirty = false;
}
return this._position;
}
/**
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set position(value: Vector2) {
this.setPosition(value.x, value.y);
}
2020-07-28 16:25:20 +08:00
public _scale: Vector2 = Vector2.one;
/**
2020-07-28 16:25:20 +08:00
*
2020-07-22 20:07:14 +08:00
*/
2020-07-28 16:25:20 +08:00
public get scale(): Vector2 {
this.updateTransform();
2020-07-28 16:25:20 +08:00
return this._scale;
}
/**
2020-07-28 16:25:20 +08:00
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set scale(value: Vector2) {
this.setScale(value);
}
2020-07-28 16:25:20 +08:00
public _rotation: number = 0;
/**
2020-07-28 16:25:20 +08:00
*
*/
2020-07-28 16:25:20 +08:00
public get rotation(): number {
this.updateTransform();
return this._rotation;
}
/**
2020-07-28 16:25:20 +08:00
*
* @param value
*/
2020-07-28 16:25:20 +08:00
public set rotation(value: number) {
this.setRotation(value);
}
2020-07-28 16:25:20 +08:00
public _localPosition: Vector2 = Vector2.zero;
2020-07-22 20:07:14 +08:00
/**
2020-07-28 16:25:20 +08:00
* transform.position相同
2020-07-22 20:07:14 +08:00
*/
2020-07-28 16:25:20 +08:00
public get localPosition(): Vector2 {
this.updateTransform();
2020-07-28 16:25:20 +08:00
return this._localPosition;
}
/**
2020-07-28 16:25:20 +08:00
* transform.position相同
* @param value
*/
2020-07-28 16:25:20 +08:00
public set localPosition(value: Vector2) {
this.setLocalPosition(value);
}
2020-07-28 16:25:20 +08:00
public _localScale: Vector2 = Vector2.one;
/**
* transform.scale相同
*/
public get localScale(): Vector2 {
this.updateTransform();
return this._localScale;
}
/**
* transform.scale相同
* @param value
*/
2020-07-28 16:25:20 +08:00
public set localScale(value: Vector2) {
this.setLocalScale(value);
}
2020-07-28 16:25:20 +08:00
public _localRotation: number = 0;
2020-07-28 16:25:20 +08:00
/**
* transform.rotation相同
*/
public get localRotation(): number {
this.updateTransform();
2020-07-28 16:25:20 +08:00
return this._localRotation;
}
/**
2020-07-28 16:25:20 +08:00
* transform.rotation相同
* @param value
*/
2020-07-28 16:25:20 +08:00
public set localRotation(value: number) {
this.setLocalRotation(value);
2020-07-22 20:07:14 +08:00
}
/**
*
* @param index
*/
public getChild(index: number): Transform {
return this._children[index];
}
/**
*
* @param parent
*/
public setParent(parent: Transform): Transform {
if (this._parent.equals(parent))
2020-07-22 20:07:14 +08:00
return this;
if (!this._parent) {
this._parent._children.remove(this);
this._parent._children.push(this);
}
this._parent = parent;
this.setDirty(DirtyType.positionDirty);
2020-07-22 20:07:14 +08:00
return this;
}
/**
*
* @param x
* @param y
*/
public setPosition(x: number, y: number): Transform {
let position = new Vector2(x, y);
if (position.equals(this._position))
return this;
this._position = position;
2020-07-28 16:25:20 +08:00
if (this.parent) {
this.localPosition = Vector2Ext.transformR(this._position, this._worldToLocalTransform);
} else {
this.localPosition = position;
}
this._positionDirty = false;
return this;
}
/**
* transform.position相同
* @param localPosition
*/
public setLocalPosition(localPosition: Vector2): Transform {
if (localPosition.equals(this._localPosition))
return this;
this._localPosition = localPosition;
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.positionDirty);
2020-07-22 20:07:14 +08:00
return this;
}
2020-07-22 20:07:14 +08:00
/**
*
* @param radians
2020-07-22 20:07:14 +08:00
*/
public setRotation(radians: number): Transform {
this._rotation = radians;
2020-07-28 16:25:20 +08:00
if (this.parent) {
this.localRotation = this.parent.rotation + radians;
} else {
this.localRotation = radians;
}
2020-07-22 20:07:14 +08:00
return this;
}
/**
*
* @param degrees
2020-07-22 20:07:14 +08:00
*/
public setRotationDegrees(degrees: number): Transform {
return this.setRotation(MathHelper.toRadians(degrees));
2020-07-22 20:07:14 +08:00
}
/**
* 使
* @param pos
*/
public lookAt(pos: Vector2) {
let sign = this.position.x > pos.x ? -1 : 1;
let vectorToAlignTo = Vector2.normalize(Vector2.subtract(this.position, pos));
this.rotation = sign * Math.acos(Vector2.dot(vectorToAlignTo, Vector2.unitY));
}
/**
* transform.rotation相同
* @param radians
*/
2020-07-28 16:25:20 +08:00
public setLocalRotation(radians: number) {
this._localRotation = radians;
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.rotationDirty);
return this;
}
/**
* transform.rotation相同
* @param degrees
*/
public setLocalRotationDegrees(degrees: number): Transform {
return this.setLocalRotation(MathHelper.toRadians(degrees));
}
/**
*
* @param scale
*/
public setScale(scale: Vector2): Transform {
this._scale = scale;
2020-07-28 16:25:20 +08:00
if (this.parent) {
this.localScale = Vector2.divide(scale, this.parent._scale);
2020-07-28 16:25:20 +08:00
} else {
this.localScale = scale;
}
return this;
}
/**
* transform.scale相同
* @param scale
*/
public setLocalScale(scale: Vector2): Transform {
this._localScale = scale;
this._localDirty = this._positionDirty = this._localScaleDirty = true;
this.setDirty(DirtyType.scaleDirty);
return this;
}
2020-07-22 20:07:14 +08:00
/**
*
*/
public roundPosition() {
this.position = this._position.round();
}
2020-07-28 16:25:20 +08:00
public updateTransform() {
if (this.hierarchyDirty != DirtyType.clean) {
if (this.parent)
this.parent.updateTransform();
2020-07-28 16:25:20 +08:00
if (this._localDirty) {
if (this._localPositionDirty) {
this._translationMatrix = Matrix2D.create().translate(this._localPosition.x, this._localPosition.y);
this._localPositionDirty = false;
}
2020-07-28 16:25:20 +08:00
if (this._localRotationDirty) {
this._rotationMatrix = Matrix2D.create().rotate(this._localRotation);
this._localRotationDirty = false;
}
2020-07-28 16:25:20 +08:00
if (this._localScaleDirty) {
this._scaleMatrix = Matrix2D.create().scale(this._localScale.x, this._localScale.y);
this._localScaleDirty = false;
}
this._localTransform = this._scaleMatrix.multiply(this._rotationMatrix);
this._localTransform = this._localTransform.multiply(this._translationMatrix);
2020-07-28 16:25:20 +08:00
if (!this.parent) {
this._worldTransform = this._localTransform;
this._rotation = this._localRotation;
this._scale = this._localScale;
this._worldInverseDirty = true;
}
this._localDirty = false;
}
2020-07-28 16:25:20 +08:00
if (this.parent) {
this._worldTransform = this._localTransform.multiply(this.parent._worldTransform);
this._rotation = this._localRotation + this.parent._rotation;
this._scale = Vector2.multiply(this.parent._scale, this._localScale);
this._worldInverseDirty = true;
}
this._worldToLocalDirty = true;
this._positionDirty = true;
this.hierarchyDirty = DirtyType.clean;
}
2020-07-22 20:07:14 +08:00
}
2020-07-28 16:25:20 +08:00
public setDirty(dirtyFlagType: DirtyType) {
if ((this.hierarchyDirty & dirtyFlagType) == 0) {
this.hierarchyDirty |= dirtyFlagType;
switch (dirtyFlagType) {
case es.DirtyType.positionDirty:
this.entity.onTransformChanged(transform.Component.position);
break;
case es.DirtyType.rotationDirty:
this.entity.onTransformChanged(transform.Component.rotation);
break;
case es.DirtyType.scaleDirty:
this.entity.onTransformChanged(transform.Component.scale);
break;
}
if (!this._children)
this._children = [];
// 告诉子项发生了变换
2020-07-28 16:25:20 +08:00
for (let i = 0; i < this._children.length; i++)
this._children[i].setDirty(dirtyFlagType);
}
}
2020-07-22 20:07:14 +08:00
/**
* transform属性进行拷贝
* @param transform
*/
public copyFrom(transform: Transform) {
this._position = transform.position;
this._localPosition = transform._localPosition;
this._rotation = transform._rotation;
this._localRotation = transform._localRotation;
this._scale = transform._scale;
this._localScale = transform._localScale;
2020-07-22 20:07:14 +08:00
this.setDirty(DirtyType.positionDirty);
this.setDirty(DirtyType.rotationDirty);
this.setDirty(DirtyType.scaleDirty);
}
2020-07-28 16:25:20 +08:00
public toString(): string {
return `[Transform: parent: ${this.parent}, position: ${this.position}, rotation: ${this.rotation},
scale: ${this.scale}, localPosition: ${this._localPosition}, localRotation: ${this._localRotation},
localScale: ${this._localScale}]`;
}
2020-07-28 16:25:20 +08:00
public equals(other: Transform) {
return other.hashCode == this.hashCode;
}
2020-07-22 20:07:14 +08:00
}
}