the-world-engine
Version:
three.js based, unity like game engine for browser
200 lines (195 loc) • 5.91 kB
JavaScript
import { Vector2 } from "three/src/Three";
import { Filter, FixtureDef, WorldManifold } from "../../../../box2d.ts/build/index";
import { Component } from "../../../hierarchy_object/Component";
import { ContactPoint2D } from "../../../physics/2d/ContactPoint2D";
import { PhysicsMaterial2D } from "../../../physics/2d/PhysicsMaterial2D";
export class Collider2D extends Component {
fl=null;
yl=1;
wl=null;
xl=false;
Za=new Vector2;
Oo=null;
onEnable() {
this.Cl();
this.fl.body.SetAwake(true);
}
onDisable() {
this.fl?.body.SetAwake(true);
this.Fl();
}
onDestroy() {
this.wl?.onChanged.removeListener(this.updateFixturesMaterialInfo);
}
Cl() {
if (this.fl) return;
this.fl = this.engine.physics2DProcessor.addCollider(this.gameObject, this);
const t = this.createShapes();
for (let i = 0; i < t.length; ++i) {
const s = t[i];
const e = new FixtureDef;
e.userData = this;
e.density = this.yl;
e.isSensor = this.xl;
e.shape = s;
this.fl.add(e);
}
this.updateFixturesMaterialInfo();
this.updateFixturesFilter();
this.fl.physicObject.rigidbody?.updateMass();
}
Fl() {
if (this.fl) {
this.engine.physics2DProcessor.removeCollider(this.gameObject, this, this.fl);
this.fl.physicObject.rigidbody?.updateMass();
this.fl = null;
}
}
updateFixture() {
if (this.fl) {
this.Fl();
this.Cl();
this.fl.body.SetAwake(true);
}
}
static _filterBuffer=new Filter;
updateFixturesFilter() {
if (!this.fl) return;
const t = Collider2D._filterBuffer;
const i = this.fl.physicObject;
const s = i.rigidbody;
let e;
if (this.Oo) {
e = this.Oo;
} else {
if (s) {
e = s.layer;
} else {
e = 1;
}
}
t.categoryBits = e;
if (s && !s.simulated) {
t.maskBits = 0;
} else {
t.maskBits = this.engine.physics.collisionLayerMask.getMaskFromLayer(e);
}
this.fl.foreachFixture((i => i.SetFilterData(t)));
}
updateFixturesMaterialInfo=() => {
if (this.fl) {
let t = null;
if (this.wl) {
t = this.wl;
} else if (this.fl) {
const i = this.fl.physicObject.sharedMaterial;
if (i) t = i;
}
if (!t) t = new PhysicsMaterial2D;
this.fl.foreachFixture((i => {
i.SetFriction(t.friction);
i.SetRestitution(t.bounciness);
}));
}
};
createShapes() {
throw new Error("You should not use Collider2D directly but one of its subclasses. e.g. BoxCollider2D");
}
get density() {
return this.yl;
}
set density(t) {
if (this.fl) {
const t = this.fl.physicObject;
if (t && t.rigidbody && !t.rigidbody.useAutoMass) {
throw new Error("You cannot change the density of a collider when the rigid body is not using auto mass.");
}
}
this.yl = t;
if (this.fl) {
this.fl.foreachFixture((i => i.SetDensity(t)));
}
}
get material() {
return this.wl;
}
set material(t) {
if (t) {
if (!this.wl) {
this.wl = new PhysicsMaterial2D(t.friction, t.bounciness);
this.wl.onChanged.addListener(this.updateFixturesMaterialInfo);
} else {
this.wl.copy(t);
}
} else {
this.wl?.onChanged.removeListener(this.updateFixturesMaterialInfo);
this.wl = null;
}
this.updateFixturesMaterialInfo();
}
get isTrigger() {
return this.xl;
}
set isTrigger(t) {
this.xl = t;
if (this.fl) {
this.fl.foreachFixture((i => i.SetSensor(t)));
}
}
get offset() {
return this.Za;
}
set offset(t) {
this.Za.copy(t);
this.updateFixture();
}
getLayerToName() {
return this.Oo ? this.engine.physics.collisionLayerMask.layerToName(this.Oo) : null;
}
setLayerFromName(t) {
this.Oo = t ? this.engine.physics.collisionLayerMask.nameToLayer(t) : null;
this.updateFixturesFilter();
}
get layer() {
return this.Oo;
}
set layer(t) {
this.Oo = t;
this.updateFixturesFilter();
}
getThisOrRigidBodyLayerToName() {
if (this.Oo) {
return this.engine.physics.collisionLayerMask.layerToName(this.Oo);
} else {
return this.fl?.physicObject.rigidbody?.getLayerToName() ?? "default";
}
}
getThisOrRigidBodyLayer() {
if (this.Oo) {
return this.Oo;
} else {
return this.fl?.physicObject.rigidbody?.layer ?? 1;
}
}
fi=new WorldManifold;
getContacts(t) {
if (!this.fl) return 0;
let i = 0;
let s = this.fl.body.GetContactList();
while (s) {
const e = s;
s = s.next;
if (!this.fl.contains(e.contact.GetFixtureA()) && !this.fl.contains(e.contact.GetFixtureB())) {
continue;
}
const r = e.contact.GetManifold();
for (let s = 0; s < r.pointCount; ++s) {
if (!t[i]) t[i] = new ContactPoint2D;
e.contact.GetWorldManifold(this.fi);
t[i].setData(e.contact, r.points[s], this.fi.normal, this.fi.points[s], this.fi.separations[s]);
i += 1;
}
}
return i;
}
}