the-world-engine
Version:
three.js based, unity like game engine for browser
624 lines (620 loc) • 17.9 kB
JavaScript
import { Matrix4, Object3D, Quaternion, Vector3 } from "three/src/Three";
import { ObservableEuler } from "../math/ObservableEuler";
import { ObservableQuaternion } from "../math/ObservableQuaternion";
import { ObservableVector3 } from "../math/ObservableVector3";
export class Transform {
static _transformObject3D=class extends Object3D {
updateMatrix() {
this.userData.ts();
}
updateMatrixWorld(t) {
this.userData.ss();
}
updateWorldMatrix(t, s) {
this.userData.ss();
if (s) {
const t = this.children;
for (let s = 0, i = t.length; s < i; ++s) {
t[s].updateWorldMatrix(false, true);
}
}
}
};
es;
bt;
L;
rs;
hs;
os;
ns;
ls;
fs=false;
cs=false;
us=false;
_s=false;
ds=false;
ps=this.vs.bind(this);
bs=this.gs.bind(this);
Rs=this.Ts.bind(this);
Os=this.ws.bind(this);
xs=this.Cs.bind(this);
Ws=this.Ms.bind(this);
Bs=this.Ps.bind(this);
Ls=this.ys.bind(this);
constructor(t, s, i) {
this.L = s;
this.rs = i;
this.es = new Transform._transformObject3D;
this.es.matrixAutoUpdate = true;
this.es.userData = this;
s.scene.unsafeGetThreeScene().add(this.es);
Object.defineProperties(this.es, {
position: {
writable: true
},
rotation: {
writable: true
},
quaternion: {
writable: true
},
scale: {
writable: true
}
});
const e = this.ps;
const r = this.bs;
const h = new ObservableVector3;
h.onBeforeGetComponent(e);
h.onBeforeChange(r);
this.es.position = h;
const o = new ObservableEuler;
o.onBeforeGetComponent(e);
o.onBeforeChange(r);
o._onChange(this.Rs);
this.es.rotation = o;
const n = new ObservableQuaternion;
n.onBeforeGetComponent(e);
n.onBeforeChange(r);
n._onChange(this.Os);
this.es.quaternion = n;
const a = new ObservableVector3(1, 1, 1);
a.onBeforeGetComponent(e);
a.onBeforeChange(r);
this.es.scale = a;
this.bt = t;
const l = this.xs;
const f = this.Ws;
const c = new ObservableVector3;
c.onBeforeGetComponent(l);
c.onBeforeChange(f);
this.hs = c;
const u = new ObservableEuler;
u.onBeforeGetComponent(l);
u.onBeforeChange(f);
u._onChange(this.Bs);
this.os = u;
const _ = new ObservableQuaternion;
_.onBeforeGetComponent(l);
_.onBeforeChange(f);
_._onChange(this.Ls);
this.ns = _;
const d = new ObservableVector3(1, 1, 1);
d.onBeforeGetComponent(l);
d.onBeforeChange(f);
this.ls = d;
this.Fs();
}
js=false;
vs() {
if (this.js) return;
this.Vs();
}
gs() {
if (this.js) return;
this.Vs();
this.Es();
this.ds = false;
this.cs = true;
this.Fs();
this.Ss();
this.Us();
}
Ts() {
if (this.js) return;
this.es.quaternion.setFromEuler(this.es.rotation, false);
}
ws() {
if (this.js) return;
this.es.rotation.setFromQuaternion(this.es.quaternion, undefined, false);
}
Cs() {
if (this.js) return;
this.As();
}
Ms() {
if (this.js) return;
this.As();
this.Es();
this._s = false;
this.ds = true;
this.cs = true;
this.Fs();
this.Ds();
this.Us();
}
Ps() {
if (this.js) return;
this.ns.setFromEuler(this.os, false);
}
ys() {
if (this.js) return;
this.os.setFromQuaternion(this.ns, undefined, false);
}
Ss() {
this._s = true;
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Ss();
}
}
}
Ds() {
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Ss();
}
}
}
Fs() {
this.L.transformMatrixProcessor.enqueueTransformToUpdate(this);
this.Ns();
}
Ns() {
this.us = true;
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Ns();
}
}
}
Us() {
this.fs = true;
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Us();
}
}
}
static _matrix4Buffer=new Matrix4;
Vs() {
if (!this.ds) return;
if (this.cs) {
if (this.us) {
this.js = true;
this.es.matrixWorld.compose(this.hs, this.ns, this.ls);
this.js = false;
this.us = false;
this.bt.gameObjectEventContainer.invokeOnWorldMatrixUpdated();
}
const t = this.parent;
if (t) {
t.ss();
const s = Transform._matrix4Buffer.copy(t.es.matrixWorld).invert();
this.es.matrix.multiplyMatrices(this.es.matrixWorld, s);
} else {
this.es.matrix.copy(this.es.matrixWorld);
}
this.cs = false;
}
this.js = true;
this.es.matrix.decompose(this.localPosition, this.localRotation, this.localScale);
this.localEulerAngles.setFromQuaternion(this.localRotation, undefined, false);
this.js = false;
this.ds = false;
}
As() {
if (!this._s) return;
this.ss();
this.js = true;
this.es.matrixWorld.decompose(this.hs, this.ns, this.ls);
this.os.setFromQuaternion(this.ns, undefined, false);
this.js = false;
this._s = false;
}
ss() {
if (!this.us) return;
const t = this.es.matrix;
if (!this.cs) {
const s = this.parent;
if (s) {
s.ss();
this.es.matrixWorld.multiplyMatrices(s.es.matrixWorld, t);
} else {
this.es.matrixWorld.copy(t);
}
} else if (!this.ds) {
if (this.cs) {
this.js = true;
t.compose(this.localPosition, this.localRotation, this.localScale);
this.js = false;
this.cs = false;
}
const s = this.parent;
if (s) {
s.ss();
this.es.matrixWorld.multiplyMatrices(s.es.matrixWorld, t);
} else {
this.es.matrixWorld.copy(t);
}
} else {
this.js = true;
this.es.matrixWorld.compose(this.hs, this.ns, this.ls);
this.js = false;
}
this.us = false;
this.bt.gameObjectEventContainer.invokeOnWorldMatrixUpdated();
}
ts() {
if (!this.cs) return;
const t = this.es.matrix;
if (!this.us) {
const t = this.parent;
if (t) {
t.ss();
const s = Transform._matrix4Buffer.copy(t.es.matrixWorld).invert();
this.es.matrix.multiplyMatrices(this.es.matrixWorld, s);
} else {
this.es.matrix.copy(this.es.matrixWorld);
}
} else if (!this._s) {
if (this.us) {
this.js = true;
this.es.matrixWorld.compose(this.hs, this.ns, this.ls);
this.js = false;
this.us = false;
this.bt.gameObjectEventContainer.invokeOnWorldMatrixUpdated();
}
const t = this.parent;
if (t) {
t.ss();
const s = Transform._matrix4Buffer.copy(t.es.matrixWorld).invert();
this.es.matrix.multiplyMatrices(this.es.matrixWorld, s);
} else {
this.es.matrix.copy(this.es.matrixWorld);
}
} else {
this.js = true;
t.compose(this.localPosition, this.localRotation, this.localScale);
this.js = false;
}
this.cs = false;
}
Qs() {
this.Vs();
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Qs();
}
}
}
Es() {
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Vs();
i.userData.Es();
}
}
}
isRegisteredToProcessor=false;
tryUpdateWorldMatrixRecursivelyFromThisToChildren() {
if (!this.bt.exists) return false;
return this.Gs();
}
Gs() {
this.ss();
const t = this.es.children;
for (let s = 0, i = t.length; s < i; ++s) {
const i = t[s];
if (i.userData instanceof Transform) {
i.userData.Gs();
}
}
return true;
}
foreachChild(t) {
const s = this.es.children;
for (let i = 0, e = s.length; i < e; ++i) {
const e = s[i];
if (e.userData instanceof Transform) {
t(e.userData);
}
}
}
iterateChild(t) {
const s = this.es.children;
for (let i = 0, e = s.length; i < e; ++i) {
const e = s[i];
if (e.userData instanceof Transform) {
if (!t(e.userData)) break;
}
}
}
get parent() {
if (this.es.parent.isScene) return null;
return this.es.parent.userData;
}
set parent(t) {
this.setParent(t);
}
setParent(t, s = true) {
if (t) {
const i = this.parent;
this.Qs();
this.Fs();
this.Ss();
if (s) {
t.getWorldToLocalMatrix(this.es.matrix).multiply(this.es.matrixWorld);
}
this.es.removeFromParent();
t.es.add(this.es);
this.rs(i, t);
} else {
const t = this.parent;
this.Qs();
this.Fs();
this.Ss();
if (s) {
this.es.matrix.copy(this.es.matrixWorld);
}
this.es.removeFromParent();
this.L.scene.unsafeGetThreeScene().add(this.es);
this.rs(t, null);
}
}
get children() {
const t = [];
const s = this.es.children;
for (let i = 0, e = s.length; i < e; ++i) {
const e = s[i];
if (e.userData instanceof Transform) {
t.push(e.userData);
}
}
return t;
}
get gameObject() {
return this.bt;
}
static _vector3Buffer=new Vector3;
getForward(t) {
this.ss();
const s = this.es.matrixWorld.elements;
return t ? t.set(s[8], s[9], s[10]) : new Vector3(s[8], s[9], s[10]);
}
setForward(t) {
this.L.transformMatrixProcessor.enqueueTransformToUpdate(this);
this.ss();
this.Es();
this.cs = true;
this.ds = true;
this.Ds();
this.Ss();
this._s = true;
const s = this.es.matrixWorld.elements;
const i = Transform._vector3Buffer.copy(t).normalize();
s[8] = i.x;
s[9] = i.y;
s[10] = i.z;
}
getRight(t) {
this.ss();
const s = this.es.matrixWorld.elements;
return t ? t.set(s[0], s[1], s[2]) : new Vector3(s[0], s[1], s[2]);
}
setRight(t) {
this.L.transformMatrixProcessor.enqueueTransformToUpdate(this);
this.ss();
this.Es();
this.cs = true;
this.ds = true;
this.Ds();
this.Ss();
this._s = true;
const s = this.es.matrixWorld.elements;
const i = Transform._vector3Buffer.copy(t).normalize();
s[0] = i.x;
s[1] = i.y;
s[2] = i.z;
}
getUp(t) {
this.ss();
const s = this.es.matrixWorld.elements;
return t ? t.set(s[4], s[5], s[6]) : new Vector3(s[4], s[5], s[6]);
}
setUp(t) {
this.L.transformMatrixProcessor.enqueueTransformToUpdate(this);
this.ss();
this.Es();
this.cs = true;
this.ds = true;
this.Ds();
this.Ss();
this._s = true;
const s = this.es.matrixWorld.elements;
const i = Transform._vector3Buffer.copy(t).normalize();
s[4] = i.x;
s[5] = i.y;
s[6] = i.z;
}
get localPosition() {
return this.es.position;
}
get localEulerAngles() {
return this.es.rotation;
}
get localRotation() {
return this.es.quaternion;
}
get localScale() {
return this.es.scale;
}
get position() {
return this.hs;
}
get eulerAngles() {
return this.os;
}
get rotation() {
return this.ns;
}
get lossyScale() {
return this.ls;
}
get hasChanged() {
return this.fs;
}
set hasChanged(t) {
this.fs = t;
}
getWorldToLocalMatrix(t) {
this.ss();
return t ? t.copy(this.es.matrixWorld).invert() : this.es.matrixWorld.clone().invert();
}
getLocalToWorldMatrix(t) {
this.ss();
return t ? t.copy(this.es.matrixWorld) : this.es.matrixWorld.clone();
}
transformPoint(t) {
this.ss();
return t.applyMatrix4(this.es.matrixWorld);
}
inverseTransformPoint(t) {
this.ss();
return t.applyMatrix4(Transform._matrix4Buffer.copy(this.es.matrixWorld).invert());
}
transformDirection(t) {
const s = Transform._matrix4Buffer.copy(this.es.matrixWorld).makeScale(1, 1, 1);
return t.transformDirection(s);
}
inverseTransformDirection(t) {
const s = Transform._matrix4Buffer.copy(this.es.matrixWorld).makeScale(1, 1, 1).invert();
return t.transformDirection(s);
}
transformVector(t) {
return t.transformDirection(this.es.matrixWorld);
}
inverseTransformVector(t) {
return t.transformDirection(Transform._matrix4Buffer.copy(this.es.matrixWorld).invert());
}
isChildOf(t) {
if (this === t) return true;
const s = this.parent;
if (s) return s.isChildOf(t);
return false;
}
static _quaternionBuffer=new Quaternion;
lookAt(t) {
const s = this.parent;
Transform._vector3Buffer.setFromMatrixPosition(this.es.matrixWorld);
const i = Transform._matrix4Buffer.lookAt(Transform._vector3Buffer, t, this.es.up);
this.es.quaternion.setFromRotationMatrix(i);
if (s) {
i.extractRotation(s.es.matrixWorld);
const t = Transform._quaternionBuffer.setFromRotationMatrix(i);
this.es.quaternion.premultiply(t.invert());
}
}
setRotationFromAxisAngle(t, s) {
this.es.setRotationFromAxisAngle(t, s);
}
setRotationFromEuler(t) {
this.es.setRotationFromEuler(t);
}
setRotationFromMatrix(t) {
this.es.setRotationFromMatrix(t);
}
setRotationFromQuaternion(t) {
this.es.setRotationFromQuaternion(t);
}
rotateOnAxis(t, s) {
this.es.rotateOnAxis(t, s);
return this;
}
rotateOnWorldAxis(t, s) {
this.es.rotateOnWorldAxis(t, s);
return this;
}
rotateX(t) {
this.es.rotateX(t);
return this;
}
rotateY(t) {
this.es.rotateY(t);
return this;
}
rotateZ(t) {
this.es.rotateZ(t);
return this;
}
translateOnAxis(t, s) {
this.es.translateOnAxis(t, s);
return this;
}
translateX(t) {
this.es.translateX(t);
return this;
}
translateY(t) {
this.es.translateY(t);
return this;
}
translateZ(t) {
this.es.translateZ(t);
return this;
}
unsafeGetObject3D() {
return this.es;
}
enqueueRenderAttachedObject3D(t) {
this.L.transformMatrixProcessor.enqueueRenderObject(t);
}
dequeueRenderAttachedObject3D(t) {
this.L.transformMatrixProcessor.dequeueRenderObject(t);
}
static updateRawObject3DWorldMatrixRecursively(t) {
if (t.matrixAutoUpdate) t.updateMatrix();
if (t.parent) {
t.matrixWorld.multiplyMatrices(t.parent.matrixWorld, t.matrix);
} else {
t.matrixWorld.copy(t.matrix);
}
const s = t.children;
for (let t = 0, i = s.length; t < i; ++t) {
Transform.updateRawObject3DWorldMatrixRecursivelyInternal(s[t]);
}
}
static updateRawObject3DWorldMatrixRecursivelyInternal(t) {
if (t.matrixAutoUpdate) t.updateMatrix();
t.matrixWorld.multiplyMatrices(t.parent.matrixWorld, t.matrix);
const s = t.children;
for (let t = 0, i = s.length; t < i; ++t) {
Transform.updateRawObject3DWorldMatrixRecursivelyInternal(s[t]);
}
}
toJSON() {
return {};
}
}