2020-06-08 17:18:21 +08:00
|
|
|
enum DirtyType{
|
|
|
|
|
clean,
|
|
|
|
|
positionDirty,
|
|
|
|
|
scaleDirty,
|
|
|
|
|
rotationDirty,
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 23:04:57 +08:00
|
|
|
enum ComponentTransform{
|
|
|
|
|
position,
|
|
|
|
|
scale,
|
|
|
|
|
rotation
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 11:49:45 +08:00
|
|
|
class Transform {
|
|
|
|
|
/** 相关联的实体 */
|
|
|
|
|
public readonly entity: Entity;
|
|
|
|
|
private _children: Transform[];
|
|
|
|
|
private _parent: Transform;
|
|
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
private _localPosition: Vector2;
|
|
|
|
|
private _localRotation: number = 0;
|
|
|
|
|
private _localScale: Vector2;
|
|
|
|
|
|
|
|
|
|
private _translationMatrix: Matrix2D;
|
|
|
|
|
private _rotationMatrix: Matrix2D;
|
|
|
|
|
private _scaleMatrix: Matrix2D;
|
|
|
|
|
|
|
|
|
|
private _worldTransform = Matrix2D.identity;
|
|
|
|
|
private _worldToLocalTransform = Matrix2D.identity;
|
|
|
|
|
private _worldInverseTransform = Matrix2D.identity;
|
|
|
|
|
|
|
|
|
|
private _rotation: number = 0;
|
|
|
|
|
private _position: Vector2;
|
|
|
|
|
private _scale: Vector2;
|
|
|
|
|
|
|
|
|
|
private _localTransform;
|
2020-06-08 17:18:21 +08:00
|
|
|
private _hierachyDirty: DirtyType;
|
|
|
|
|
private _localDirty: boolean;
|
|
|
|
|
private _localPositionDirty: boolean;
|
|
|
|
|
private _localScaleDirty: boolean;
|
|
|
|
|
private _localRotationDirty: boolean;
|
|
|
|
|
private _positionDirty: boolean;
|
|
|
|
|
private _worldToLocalDirty: boolean;
|
|
|
|
|
private _worldInverseDirty: boolean;
|
2020-06-08 16:23:48 +08:00
|
|
|
|
2020-06-08 11:49:45 +08:00
|
|
|
public get childCount(){
|
|
|
|
|
return this._children.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
constructor(entity: Entity){
|
|
|
|
|
this.entity = entity;
|
2020-06-08 16:23:48 +08:00
|
|
|
this._scale = this._localScale = Vector2.One;
|
2020-06-08 11:49:45 +08:00
|
|
|
this._children = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getChild(index: number){
|
|
|
|
|
return this._children[index];
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 11:09:26 +08:00
|
|
|
public get worldInverseTransform(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
if (this._worldInverseDirty){
|
|
|
|
|
this._worldInverseTransform = Matrix2D.invert(this._worldTransform, this._worldInverseTransform);
|
|
|
|
|
this._worldInverseDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this._worldInverseTransform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get localToWorldTransform(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._worldTransform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get worldToLocalTransform(){
|
|
|
|
|
if (this._worldToLocalDirty){
|
|
|
|
|
if (!this.parent){
|
|
|
|
|
this._worldInverseTransform = Matrix2D.identity;
|
|
|
|
|
} else{
|
|
|
|
|
this.parent.updateTransform();
|
|
|
|
|
this._worldToLocalTransform = Matrix2D.invert(this.parent._worldTransform, this._worldToLocalTransform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._worldToLocalDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this._worldToLocalTransform;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 11:49:45 +08:00
|
|
|
public get parent(){
|
|
|
|
|
return this._parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set parent(value: Transform){
|
|
|
|
|
this.setParent(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setParent(parent: Transform){
|
|
|
|
|
if (this._parent == parent)
|
|
|
|
|
return this;
|
|
|
|
|
|
|
|
|
|
if (this._parent)
|
|
|
|
|
this._parent._children.remove(this);
|
|
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
|
parent._children.push(this);
|
|
|
|
|
|
|
|
|
|
this._parent = parent;
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2020-06-08 16:23:48 +08:00
|
|
|
|
2020-06-09 11:09:26 +08:00
|
|
|
public get rotation() {
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._rotation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set rotation(value: number){
|
|
|
|
|
this.setRotation(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get localRotation(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._localRotation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set localRotation(value: number){
|
|
|
|
|
this.setLocalRotation(value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
public get position(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
if (!this.parent){
|
|
|
|
|
this._position = this._localPosition;
|
|
|
|
|
}else{
|
|
|
|
|
this.parent.updateTransform();
|
|
|
|
|
this._position = Vector2.transform(this._localPosition, this.parent._worldTransform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this._position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set position(value: Vector2){
|
|
|
|
|
this.setPosition(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get localPosition(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._localPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set localPosition(value: Vector2){
|
|
|
|
|
this.setLocalPosition(value);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 11:09:26 +08:00
|
|
|
public get scale(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set scale(value: Vector2){
|
|
|
|
|
this.setScale(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get localScale(){
|
|
|
|
|
this.updateTransform();
|
|
|
|
|
return this._localScale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set localScale(value: Vector2){
|
|
|
|
|
this.setLocalScale(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get rotationDegrees(){
|
|
|
|
|
return MathHelper.toDegrees(this._rotation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set rotationDegrees(value: number){
|
|
|
|
|
this.setRotation(MathHelper.toRadians(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public get localRotationDegrees(){
|
|
|
|
|
return MathHelper.toDegrees(this._localRotation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public set localRotationDegrees(value: number){
|
|
|
|
|
this.localRotation = MathHelper.toRadians(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setLocalScale(scale: Vector2){
|
|
|
|
|
this._localScale = scale;
|
|
|
|
|
this._localDirty = this._positionDirty = this._localScaleDirty = true;
|
|
|
|
|
this.setDirty(DirtyType.scaleDirty);
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setScale(scale: Vector2){
|
|
|
|
|
this._scale = scale;
|
|
|
|
|
if (this.parent){
|
|
|
|
|
this.localScale = Vector2.divide(scale, this.parent._scale);
|
|
|
|
|
}else{
|
|
|
|
|
this.localScale = scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setLocalRotationDegrees(degrees: number){
|
|
|
|
|
return this.setLocalRotation(MathHelper.toRadians(degrees));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setLocalRotation(radians: number){
|
|
|
|
|
this._localRotation = radians;
|
|
|
|
|
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
|
|
|
|
|
this.setDirty(DirtyType.rotationDirty);
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setRotation(radians: number){
|
|
|
|
|
this._rotation = radians;
|
|
|
|
|
if (this.parent){
|
|
|
|
|
this.localRotation = this.parent.rotation + radians;
|
|
|
|
|
} else {
|
|
|
|
|
this.localRotation = radians;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setRotationDegrees(degrees: number){
|
|
|
|
|
return this.setRotation(MathHelper.toRadians(degrees));
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
public setLocalPosition(localPosition: Vector2){
|
|
|
|
|
if (localPosition == this._localPosition)
|
|
|
|
|
return this;
|
|
|
|
|
|
|
|
|
|
this._localPosition = localPosition;
|
2020-06-08 17:18:21 +08:00
|
|
|
this._localDirty = this._positionDirty = this._localPositionDirty = this._localRotationDirty = this._localScaleDirty = true;
|
2020-06-08 23:04:57 +08:00
|
|
|
this.setDirty(DirtyType.positionDirty);
|
2020-06-08 17:18:21 +08:00
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public setPosition(position: Vector2){
|
|
|
|
|
if (position == this._position)
|
|
|
|
|
return this;
|
|
|
|
|
|
|
|
|
|
this._position = position;
|
|
|
|
|
if (this.parent){
|
|
|
|
|
this.localPosition = Vector2.transform(this._position, this._worldToLocalTransform);
|
|
|
|
|
}else{
|
|
|
|
|
this.localPosition = position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 23:04:57 +08:00
|
|
|
public setDirty(dirtyFlagType: DirtyType){
|
|
|
|
|
if ((this._hierachyDirty & dirtyFlagType) == 0){
|
|
|
|
|
this._hierachyDirty |= dirtyFlagType;
|
|
|
|
|
|
|
|
|
|
switch (dirtyFlagType){
|
|
|
|
|
case DirtyType.positionDirty:
|
|
|
|
|
this.entity.onTransformChanged(ComponentTransform.position);
|
|
|
|
|
break;
|
|
|
|
|
case DirtyType.rotationDirty:
|
|
|
|
|
this.entity.onTransformChanged(ComponentTransform.rotation);
|
|
|
|
|
break;
|
|
|
|
|
case DirtyType.scaleDirty:
|
|
|
|
|
this.entity.onTransformChanged(ComponentTransform.scale);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this._children == null)
|
|
|
|
|
this._children = [];
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < this._children.length; i ++){
|
|
|
|
|
this._children[i].setDirty(dirtyFlagType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
public updateTransform(){
|
2020-06-08 17:18:21 +08:00
|
|
|
if (this._hierachyDirty != DirtyType.clean){
|
|
|
|
|
if (this.parent)
|
|
|
|
|
this.parent.updateTransform();
|
|
|
|
|
|
|
|
|
|
if (this._localDirty){
|
|
|
|
|
if (this._localPositionDirty){
|
|
|
|
|
this._translationMatrix = Matrix2D.createTranslation(this._localPosition.x, this._localPosition.y);
|
|
|
|
|
this._localPositionDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this._localRotationDirty){
|
|
|
|
|
this._rotationMatrix = Matrix2D.createRotation(this._localRotation);
|
|
|
|
|
this._localRotationDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this._localScaleDirty){
|
|
|
|
|
this._scaleMatrix = Matrix2D.createScale(this._localScale.x, this._localScale.y);
|
|
|
|
|
this._localScaleDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._localTransform = Matrix2D.multiply(this._scaleMatrix, this._rotationMatrix);
|
|
|
|
|
this._localTransform = Matrix2D.multiply(this._localTransform, this._translationMatrix);
|
|
|
|
|
|
|
|
|
|
if (!this.parent){
|
|
|
|
|
this._worldTransform = this._localTransform;
|
|
|
|
|
this._rotation = this._localRotation;
|
|
|
|
|
this._scale = this._localScale;
|
|
|
|
|
this._worldInverseDirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._localDirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.parent){
|
|
|
|
|
this._worldTransform = Matrix2D.multiply(this._localTransform, 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._hierachyDirty = DirtyType.clean;
|
2020-06-08 16:23:48 +08:00
|
|
|
}
|
2020-06-08 17:18:21 +08:00
|
|
|
|
2020-06-08 16:23:48 +08:00
|
|
|
}
|
2020-06-08 11:49:45 +08:00
|
|
|
}
|