UNPKG

@box2d/debug-draw

Version:

Debug drawing helper for @box2d

951 lines (950 loc) 34.1 kB
"use strict"; // MIT License Object.defineProperty(exports, "__esModule", { value: true }); exports.b2Body = exports.b2BodyType = void 0; // Copyright (c) 2019 Erin Catto // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // DEBUG: import { b2Assert } from "../common/b2_common"; const b2_math_1 = require("../common/b2_math"); const b2_shape_1 = require("../collision/b2_shape"); const b2_fixture_1 = require("./b2_fixture"); const b2_common_1 = require("../common/b2_common"); /** * The body type. * static: zero mass, zero velocity, may be manually moved * kinematic: zero mass, non-zero velocity set by user, moved by solver * dynamic: positive mass, non-zero velocity determined by forces, moved by solver */ var b2BodyType; (function (b2BodyType) { b2BodyType[b2BodyType["b2_staticBody"] = 0] = "b2_staticBody"; b2BodyType[b2BodyType["b2_kinematicBody"] = 1] = "b2_kinematicBody"; b2BodyType[b2BodyType["b2_dynamicBody"] = 2] = "b2_dynamicBody"; })(b2BodyType || (exports.b2BodyType = b2BodyType = {})); /** * A rigid body. These are created via b2World::CreateBody. */ class b2Body { /** @internal */ constructor(bd, world) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; /** @internal */ this.m_type = b2BodyType.b2_staticBody; /** @internal */ this.m_islandFlag = false; /** @internal */ this.m_awakeFlag = false; /** @internal */ this.m_autoSleepFlag = false; /** @internal */ this.m_bulletFlag = false; /** @internal */ this.m_fixedRotationFlag = false; /** @internal */ this.m_enabledFlag = false; /** @internal */ this.m_toiFlag = false; /** @internal */ this.m_islandIndex = 0; /** @internal */ this.m_xf = new b2_math_1.b2Transform(); // the body origin transform /** @internal */ this.m_sweep = new b2_math_1.b2Sweep(); // the swept motion for CCD /** @internal */ this.m_linearVelocity = new b2_math_1.b2Vec2(); /** @internal */ this.m_angularVelocity = 0; /** @internal */ this.m_force = new b2_math_1.b2Vec2(); /** @internal */ this.m_torque = 0; /** @internal */ this.m_prev = null; /** @internal */ this.m_next = null; /** @internal */ this.m_fixtureList = null; /** @internal */ this.m_fixtureCount = 0; /** @internal */ this.m_jointList = null; /** @internal */ this.m_contactList = null; /** @internal */ this.m_mass = 1; /** @internal */ this.m_invMass = 1; /** * Rotational inertia about the center of mass. * @internal */ this.m_I = 0; /** @internal */ this.m_invI = 0; /** @internal */ this.m_linearDamping = 0; /** @internal */ this.m_angularDamping = 0; /** @internal */ this.m_gravityScale = 1; /** @internal */ this.m_sleepTime = 0; /** @internal */ this.m_userData = {}; this.m_bulletFlag = (_a = bd.bullet) !== null && _a !== void 0 ? _a : false; this.m_fixedRotationFlag = (_b = bd.fixedRotation) !== null && _b !== void 0 ? _b : false; this.m_autoSleepFlag = (_c = bd.allowSleep) !== null && _c !== void 0 ? _c : true; if (((_d = bd.awake) !== null && _d !== void 0 ? _d : true) && ((_e = bd.type) !== null && _e !== void 0 ? _e : b2BodyType.b2_staticBody) !== b2BodyType.b2_staticBody) { this.m_awakeFlag = true; } this.m_enabledFlag = (_f = bd.enabled) !== null && _f !== void 0 ? _f : true; this.m_world = world; this.m_xf.p.Copy((_g = bd.position) !== null && _g !== void 0 ? _g : b2_math_1.b2Vec2.ZERO); this.m_xf.q.Set((_h = bd.angle) !== null && _h !== void 0 ? _h : 0); this.m_sweep.localCenter.SetZero(); this.m_sweep.c0.Copy(this.m_xf.p); this.m_sweep.c.Copy(this.m_xf.p); this.m_sweep.a0 = this.m_sweep.a = this.m_xf.q.GetAngle(); this.m_sweep.alpha0 = 0; this.m_linearVelocity.Copy((_j = bd.linearVelocity) !== null && _j !== void 0 ? _j : b2_math_1.b2Vec2.ZERO); this.m_angularVelocity = (_k = bd.angularVelocity) !== null && _k !== void 0 ? _k : 0; this.m_linearDamping = (_l = bd.linearDamping) !== null && _l !== void 0 ? _l : 0; this.m_angularDamping = (_m = bd.angularDamping) !== null && _m !== void 0 ? _m : 0; this.m_gravityScale = (_o = bd.gravityScale) !== null && _o !== void 0 ? _o : 1; this.m_force.SetZero(); this.m_torque = 0; this.m_sleepTime = 0; this.m_type = (_p = bd.type) !== null && _p !== void 0 ? _p : b2BodyType.b2_staticBody; this.m_mass = 0; this.m_invMass = 0; this.m_I = 0; this.m_invI = 0; if (bd.userData) this.SetUserData(bd.userData); this.m_fixtureList = null; this.m_fixtureCount = 0; } /** * Creates a fixture and attach it to this body. Use this function if you need * to set some fixture parameters, like friction. Otherwise you can create the * fixture directly from a shape. * If the density is non-zero, this function automatically updates the mass of the body. * Contacts are not created until the next time step. * * @param def The fixture definition. * @warning This function is locked during callbacks. */ CreateFixture(def) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); const fixture = new b2_fixture_1.b2Fixture(this, def); if (this.m_enabledFlag) { const broadPhase = this.m_world.m_contactManager.m_broadPhase; fixture.CreateProxies(broadPhase, this.m_xf); } fixture.m_next = this.m_fixtureList; this.m_fixtureList = fixture; ++this.m_fixtureCount; // Adjust mass properties if needed. if (fixture.m_density > 0) { this.ResetMassData(); } // Let the world know we have a new fixture. This will cause new contacts // to be created at the beginning of the next time step. this.m_world.m_newContacts = true; return fixture; } /** * Destroy a fixture. This removes the fixture from the broad-phase and * destroys all contacts associated with this fixture. This will * automatically adjust the mass of the body if the body is dynamic and the * fixture has positive density. * All fixtures attached to a body are implicitly destroyed when the body is destroyed. * * @param fixture The fixture to be removed. * @warning This function is locked during callbacks. */ DestroyFixture(fixture) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); // DEBUG: b2Assert(fixture.m_body === this); // Remove the fixture from this body's singly linked list. // DEBUG: b2Assert(this.m_fixtureCount > 0); let node = this.m_fixtureList; let ppF = null; // DEBUG: let found = false; while (node !== null) { if (node === fixture) { if (ppF) { ppF.m_next = fixture.m_next; } else { this.m_fixtureList = fixture.m_next; } // DEBUG: found = true; break; } ppF = node; node = node.m_next; } // You tried to remove a shape that is not attached to this body. // DEBUG: b2Assert(found); const density = fixture.m_density; // Destroy any contacts associated with the fixture. let edge = this.m_contactList; while (edge) { const c = edge.contact; edge = edge.next; const fixtureA = c.GetFixtureA(); const fixtureB = c.GetFixtureB(); if (fixture === fixtureA || fixture === fixtureB) { // This destroys the contact and removes it from // this body's contact list. this.m_world.m_contactManager.Destroy(c); } } if (this.m_enabledFlag) { const broadPhase = this.m_world.m_contactManager.m_broadPhase; fixture.DestroyProxies(broadPhase); } // fixture.m_body = null; fixture.m_next = null; --this.m_fixtureCount; // Reset the mass data. // Reset the mass data if (density > 0.0) { this.ResetMassData(); } } /** * Set the position of the body's origin and rotation. * This breaks any contacts and wakes the other bodies. * Manipulating a body's transform may cause non-physical behavior. * * @param position The world position of the body's local origin. * @param angle The world rotation in radians. */ SetTransformVec(position, angle) { this.SetTransformXY(position.x, position.y, angle); } SetTransformXY(x, y, angle) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); this.m_xf.q.Set(angle); this.m_xf.p.Set(x, y); b2_math_1.b2Transform.MultiplyVec2(this.m_xf, this.m_sweep.localCenter, this.m_sweep.c); this.m_sweep.a = angle; this.m_sweep.c0.Copy(this.m_sweep.c); this.m_sweep.a0 = angle; const broadPhase = this.m_world.m_contactManager.m_broadPhase; for (let f = this.m_fixtureList; f; f = f.m_next) { f.Synchronize(broadPhase, this.m_xf, this.m_xf); } // Check for new contacts the next step this.m_world.m_newContacts = true; } SetTransform(xf) { this.SetTransformVec(xf.p, xf.GetAngle()); } /** * Get the body transform for the body's origin. * * @returns The world transform of the body's origin. */ GetTransform() { return this.m_xf; } /** * Get the world body origin position. * * @returns The world position of the body's origin. */ GetPosition() { return this.m_xf.p; } /** * Get the angle in radians. * * @returns The current world rotation angle in radians. */ GetAngle() { return this.m_sweep.a; } SetAngle(angle) { this.SetTransformVec(this.GetPosition(), angle); } /** * Get the world position of the center of mass. */ GetWorldCenter() { return this.m_sweep.c; } /** * Get the local position of the center of mass. */ GetLocalCenter() { return this.m_sweep.localCenter; } /** * Set the linear velocity of the center of mass. * * @param v The new linear velocity of the center of mass. */ SetLinearVelocity(v) { if (this.m_type === b2BodyType.b2_staticBody) { return; } if (b2_math_1.b2Vec2.Dot(v, v) > 0) { this.SetAwake(true); } this.m_linearVelocity.Copy(v); } /** * Get the linear velocity of the center of mass. * * @returns The linear velocity of the center of mass. */ GetLinearVelocity() { return this.m_linearVelocity; } /** * Set the angular velocity. * * @param omega The new angular velocity in radians/second. */ SetAngularVelocity(w) { if (this.m_type === b2BodyType.b2_staticBody) { return; } if (w * w > 0) { this.SetAwake(true); } this.m_angularVelocity = w; } /** * Get the angular velocity. * * @returns The angular velocity in radians/second. */ GetAngularVelocity() { return this.m_angularVelocity; } /** * Apply a force at a world point. If the force is not * applied at the center of mass, it will generate a torque and * affect the angular velocity. This wakes up the body. * * @param force The world force vector, usually in Newtons (N). * @param point The world position of the point of application. * @param wake Also wake up the body */ ApplyForce(force, point, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate a force if the body is sleeping if (this.m_awakeFlag) { this.m_force.x += force.x; this.m_force.y += force.y; this.m_torque += (point.x - this.m_sweep.c.x) * force.y - (point.y - this.m_sweep.c.y) * force.x; } } /** * Apply a force to the center of mass. This wakes up the body. * * @param force The world force vector, usually in Newtons (N). * @param wake Also wake up the body */ ApplyForceToCenter(force, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate a force if the body is sleeping if (this.m_awakeFlag) { this.m_force.x += force.x; this.m_force.y += force.y; } } /** * Apply a torque. This affects the angular velocity * without affecting the linear velocity of the center of mass. * * @param torque About the z-axis (out of the screen), usually in N-m. * @param wake Also wake up the body */ ApplyTorque(torque, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate a force if the body is sleeping if (this.m_awakeFlag) { this.m_torque += torque; } } /** * Apply an impulse at a point. This immediately modifies the velocity. * It also modifies the angular velocity if the point of application * is not at the center of mass. This wakes up the body. * * @param impulse The world impulse vector, usually in N-seconds or kg-m/s. * @param point The world position of the point of application. * @param wake Also wake up the body */ ApplyLinearImpulse(impulse, point, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate velocity if the body is sleeping if (this.m_awakeFlag) { this.m_linearVelocity.x += this.m_invMass * impulse.x; this.m_linearVelocity.y += this.m_invMass * impulse.y; this.m_angularVelocity += this.m_invI * ((point.x - this.m_sweep.c.x) * impulse.y - (point.y - this.m_sweep.c.y) * impulse.x); } } /** * Apply an impulse to the center of mass. This immediately modifies the velocity. * * @param impulse The world impulse vector, usually in N-seconds or kg-m/s. * @param wake Also wake up the body */ ApplyLinearImpulseToCenter(impulse, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate velocity if the body is sleeping if (this.m_awakeFlag) { this.m_linearVelocity.x += this.m_invMass * impulse.x; this.m_linearVelocity.y += this.m_invMass * impulse.y; } } /** * Apply an angular impulse. * * @param impulse The angular impulse in units of kg*m*m/s * @param wake Also wake up the body */ ApplyAngularImpulse(impulse, wake = true) { if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } if (wake && !this.m_awakeFlag) { this.SetAwake(true); } // Don't accumulate velocity if the body is sleeping if (this.m_awakeFlag) { this.m_angularVelocity += this.m_invI * impulse; } } /** * Get the total mass of the body. * * @returns The mass, usually in kilograms (kg). */ GetMass() { return this.m_mass; } /** * Get the rotational inertia of the body about the local origin. * * @returns The rotational inertia, usually in kg-m^2. */ GetInertia() { return this.m_I + this.m_mass * b2_math_1.b2Vec2.Dot(this.m_sweep.localCenter, this.m_sweep.localCenter); } /** * Get the mass data of the body. * * @returns A struct containing the mass, inertia and center of the body. */ GetMassData(data) { data.mass = this.m_mass; data.I = this.m_I + this.m_mass * b2_math_1.b2Vec2.Dot(this.m_sweep.localCenter, this.m_sweep.localCenter); data.center.Copy(this.m_sweep.localCenter); return data; } /** * Set the mass properties to override the mass properties of the fixtures. * Note that this changes the center of mass position. * Note that creating or destroying fixtures can also alter the mass. * This function has no effect if the body isn't dynamic. * * @param massData The mass properties. */ SetMassData(massData) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); if (this.m_type !== b2BodyType.b2_dynamicBody) { return; } this.m_invMass = 0; this.m_I = 0; this.m_invI = 0; this.m_mass = massData.mass; if (this.m_mass <= 0) { this.m_mass = 1; } this.m_invMass = 1 / this.m_mass; if (massData.I > 0 && !this.m_fixedRotationFlag) { this.m_I = massData.I - this.m_mass * b2_math_1.b2Vec2.Dot(massData.center, massData.center); // DEBUG: b2Assert(this.m_I > 0); this.m_invI = 1 / this.m_I; } // Move center of mass. const oldCenter = b2Body.SetMassData_s_oldCenter.Copy(this.m_sweep.c); this.m_sweep.localCenter.Copy(massData.center); b2_math_1.b2Transform.MultiplyVec2(this.m_xf, this.m_sweep.localCenter, this.m_sweep.c); this.m_sweep.c0.Copy(this.m_sweep.c); // Update center of mass velocity. b2_math_1.b2Vec2.AddCrossScalarVec2(this.m_linearVelocity, this.m_angularVelocity, b2_math_1.b2Vec2.Subtract(this.m_sweep.c, oldCenter, b2_math_1.b2Vec2.s_t0), this.m_linearVelocity); } /** * This resets the mass properties to the sum of the mass properties of the fixtures. * This normally does not need to be called unless you called SetMassData to override * the mass and you later want to reset the mass. */ ResetMassData() { // Compute mass data from shapes. Each shape has its own density. this.m_mass = 0; this.m_invMass = 0; this.m_I = 0; this.m_invI = 0; this.m_sweep.localCenter.SetZero(); // Static and kinematic bodies have zero mass. if (this.m_type === b2BodyType.b2_staticBody || this.m_type === b2BodyType.b2_kinematicBody) { this.m_sweep.c0.Copy(this.m_xf.p); this.m_sweep.c.Copy(this.m_xf.p); this.m_sweep.a0 = this.m_sweep.a; return; } // DEBUG: b2Assert(this.m_type === b2BodyType.b2_dynamicBody); // Accumulate mass over all fixtures. const localCenter = b2Body.ResetMassData_s_localCenter.SetZero(); for (let f = this.m_fixtureList; f; f = f.m_next) { if (f.m_density === 0) { continue; } const massData = f.GetMassData(b2Body.ResetMassData_s_massData); this.m_mass += massData.mass; localCenter.AddScaled(massData.mass, massData.center); this.m_I += massData.I; } // Compute center of mass. if (this.m_mass > 0) { this.m_invMass = 1 / this.m_mass; localCenter.Scale(this.m_invMass); } if (this.m_I > 0 && !this.m_fixedRotationFlag) { // Center the inertia about the center of mass. this.m_I -= this.m_mass * b2_math_1.b2Vec2.Dot(localCenter, localCenter); // DEBUG: b2Assert(this.m_I > 0); this.m_invI = 1 / this.m_I; } else { this.m_I = 0; this.m_invI = 0; } // Move center of mass. const oldCenter = b2Body.ResetMassData_s_oldCenter.Copy(this.m_sweep.c); this.m_sweep.localCenter.Copy(localCenter); b2_math_1.b2Transform.MultiplyVec2(this.m_xf, this.m_sweep.localCenter, this.m_sweep.c); this.m_sweep.c0.Copy(this.m_sweep.c); // Update center of mass velocity. b2_math_1.b2Vec2.AddCrossScalarVec2(this.m_linearVelocity, this.m_angularVelocity, b2_math_1.b2Vec2.Subtract(this.m_sweep.c, oldCenter, b2_math_1.b2Vec2.s_t0), this.m_linearVelocity); } /** * Get the world coordinates of a point given the local coordinates. * * @param localPoint A point on the body measured relative the the body's origin. * @returns The same point expressed in world coordinates. */ GetWorldPoint(localPoint, out) { return b2_math_1.b2Transform.MultiplyVec2(this.m_xf, localPoint, out); } /** * Get the world coordinates of a vector given the local coordinates. * * @param localVector A vector fixed in the body. * @returns The same vector expressed in world coordinates. */ GetWorldVector(localVector, out) { return b2_math_1.b2Rot.MultiplyVec2(this.m_xf.q, localVector, out); } /** * Gets a local point relative to the body's origin given a world point. * * @param a Point in world coordinates. * @returns The corresponding local point relative to the body's origin. */ GetLocalPoint(worldPoint, out) { return b2_math_1.b2Transform.TransposeMultiplyVec2(this.m_xf, worldPoint, out); } /** * Gets a local vector given a world vector. * * @param a Vector in world coordinates. * @returns The corresponding local vector. */ GetLocalVector(worldVector, out) { return b2_math_1.b2Rot.TransposeMultiplyVec2(this.m_xf.q, worldVector, out); } /** * Get the world linear velocity of a world point attached to this body. * * @param a Point in world coordinates. * @returns The world velocity of a point. */ GetLinearVelocityFromWorldPoint(worldPoint, out) { return b2_math_1.b2Vec2.AddCrossScalarVec2(this.m_linearVelocity, this.m_angularVelocity, b2_math_1.b2Vec2.Subtract(worldPoint, this.m_sweep.c, b2_math_1.b2Vec2.s_t0), out); } /** * Get the world velocity of a local point. * * @param a Point in local coordinates. * @returns The world velocity of a point. */ GetLinearVelocityFromLocalPoint(localPoint, out) { return this.GetLinearVelocityFromWorldPoint(this.GetWorldPoint(localPoint, out), out); } /** * Get the linear damping of the body. */ GetLinearDamping() { return this.m_linearDamping; } /** * Set the linear damping of the body. */ SetLinearDamping(linearDamping) { this.m_linearDamping = linearDamping; } /** * Get the angular damping of the body. */ GetAngularDamping() { return this.m_angularDamping; } /** * Set the angular damping of the body. */ SetAngularDamping(angularDamping) { this.m_angularDamping = angularDamping; } /** * Get the gravity scale of the body. */ GetGravityScale() { return this.m_gravityScale; } /** * Set the gravity scale of the body. */ SetGravityScale(scale) { this.m_gravityScale = scale; } /** * Set the type of this body. This may alter the mass and velocity. */ SetType(type) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); if (this.m_type === type) { return; } this.m_type = type; this.ResetMassData(); if (this.m_type === b2BodyType.b2_staticBody) { this.m_linearVelocity.SetZero(); this.m_angularVelocity = 0; this.m_sweep.a0 = this.m_sweep.a; this.m_sweep.c0.Copy(this.m_sweep.c); this.m_awakeFlag = false; this.SynchronizeFixtures(); } this.SetAwake(true); this.m_force.SetZero(); this.m_torque = 0; // Delete the attached contacts. let ce = this.m_contactList; while (ce) { const ce0 = ce; ce = ce.next; this.m_world.m_contactManager.Destroy(ce0.contact); } this.m_contactList = null; // Touch the proxies so that new contacts will be created (when appropriate) const broadPhase = this.m_world.m_contactManager.m_broadPhase; for (let f = this.m_fixtureList; f; f = f.m_next) { for (const proxy of f.m_proxies) { broadPhase.TouchProxy(proxy.treeNode); } } } /** * Get the type of this body. */ GetType() { return this.m_type; } /** * Should this body be treated like a bullet for continuous collision detection? */ SetBullet(flag) { this.m_bulletFlag = flag; } /** * Is this body treated like a bullet for continuous collision detection? */ IsBullet() { return this.m_bulletFlag; } /** * You can disable sleeping on this body. If you disable sleeping, the * body will be woken. */ SetSleepingAllowed(flag) { this.m_autoSleepFlag = flag; if (!flag) { this.SetAwake(true); } } /** * Is this body allowed to sleep */ IsSleepingAllowed() { return this.m_autoSleepFlag; } /** * Set the sleep state of the body. A sleeping body has very * low CPU cost. * * @param flag Set to true to wake the body, false to put it to sleep. */ SetAwake(flag) { if (this.m_type === b2BodyType.b2_staticBody) { return; } if (flag) { this.m_awakeFlag = true; this.m_sleepTime = 0; } else { this.m_awakeFlag = false; this.m_sleepTime = 0; this.m_linearVelocity.SetZero(); this.m_angularVelocity = 0; this.m_force.SetZero(); this.m_torque = 0; } } /** * Get the sleeping state of this body. * * @returns true if the body is awake. */ IsAwake() { return this.m_awakeFlag; } /** * Allow a body to be disabled. A disabled body is not simulated and cannot * be collided with or woken up. * If you pass a flag of true, all fixtures will be added to the broad-phase. * If you pass a flag of false, all fixtures will be removed from the * broad-phase and all contacts will be destroyed. * Fixtures and joints are otherwise unaffected. You may continue * to create/destroy fixtures and joints on disabled bodies. * Fixtures on a disabled body are implicitly disabled and will * not participate in collisions, ray-casts, or queries. * Joints connected to a disabled body are implicitly disabled. * An disabled body is still owned by a b2World object and remains * in the body list. */ SetEnabled(flag) { (0, b2_common_1.b2Assert)(!this.m_world.IsLocked()); if (flag === this.IsEnabled()) { return; } this.m_enabledFlag = flag; const broadPhase = this.m_world.m_contactManager.m_broadPhase; if (flag) { // Create all proxies. for (let f = this.m_fixtureList; f; f = f.m_next) { f.CreateProxies(broadPhase, this.m_xf); } // Contacts are created at the beginning of the next this.m_world.m_newContacts = true; } else { // Destroy all proxies. for (let f = this.m_fixtureList; f; f = f.m_next) { f.DestroyProxies(broadPhase); } // Destroy the attached contacts. let ce = this.m_contactList; while (ce) { const ce0 = ce; ce = ce.next; this.m_world.m_contactManager.Destroy(ce0.contact); } this.m_contactList = null; } } /** * Get the active state of the body. */ IsEnabled() { return this.m_enabledFlag; } /** * Set this body to have fixed rotation. This causes the mass * to be reset. */ SetFixedRotation(flag) { if (this.m_fixedRotationFlag === flag) { return; } this.m_fixedRotationFlag = flag; this.m_angularVelocity = 0; this.ResetMassData(); } /** * Does this body have fixed rotation? */ IsFixedRotation() { return this.m_fixedRotationFlag; } /** * Get the list of all fixtures attached to this body. */ GetFixtureList() { return this.m_fixtureList; } /** * Get the list of all joints attached to this body. */ GetJointList() { return this.m_jointList; } /** * Get the list of all contacts attached to this body. * * @warning this list changes during the time step and you may * miss some collisions if you don't use b2ContactListener. */ GetContactList() { return this.m_contactList; } /** * Get the next body in the world's body list. */ GetNext() { return this.m_next; } /** * Get the user data reference that was provided in the body definition. */ GetUserData() { return this.m_userData; } /** * Set the user data. Use this to store your application specific data. * This is a merge operation. Only specified keys will be overridden. */ SetUserData(data) { Object.assign(this.m_userData, data); } /** * Get the parent world of this body. */ GetWorld() { return this.m_world; } /** @internal */ SynchronizeFixtures() { const broadPhase = this.m_world.m_contactManager.m_broadPhase; if (this.m_awakeFlag) { const xf1 = b2Body.SynchronizeFixtures_s_xf1; xf1.q.Set(this.m_sweep.a0); b2_math_1.b2Rot.MultiplyVec2(xf1.q, this.m_sweep.localCenter, xf1.p); b2_math_1.b2Vec2.Subtract(this.m_sweep.c0, xf1.p, xf1.p); for (let f = this.m_fixtureList; f; f = f.m_next) { f.Synchronize(broadPhase, xf1, this.m_xf); } } else { for (let f = this.m_fixtureList; f; f = f.m_next) { f.Synchronize(broadPhase, this.m_xf, this.m_xf); } } } /** @internal */ SynchronizeTransform() { this.m_xf.q.Set(this.m_sweep.a); b2_math_1.b2Rot.MultiplyVec2(this.m_xf.q, this.m_sweep.localCenter, this.m_xf.p); b2_math_1.b2Vec2.Subtract(this.m_sweep.c, this.m_xf.p, this.m_xf.p); } /** * This is used to prevent connected bodies from colliding. * It may lie, depending on the collideConnected flag. * * @internal */ ShouldCollide(other) { // At least one body should be dynamic. if (this.m_type !== b2BodyType.b2_dynamicBody && other.m_type !== b2BodyType.b2_dynamicBody) { return false; } return this.ShouldCollideConnected(other); } ShouldCollideConnected(other) { // Does a joint prevent collision? for (let jn = this.m_jointList; jn; jn = jn.next) { if (jn.other === other) { if (!jn.joint.m_collideConnected) { return false; } } } return true; } /** @internal */ Advance(alpha) { // Advance to the new safe time. This doesn't sync the broad-phase. this.m_sweep.Advance(alpha); this.m_sweep.c.Copy(this.m_sweep.c0); this.m_sweep.a = this.m_sweep.a0; this.m_xf.q.Set(this.m_sweep.a); b2_math_1.b2Rot.MultiplyVec2(this.m_xf.q, this.m_sweep.localCenter, this.m_xf.p); b2_math_1.b2Vec2.Subtract(this.m_sweep.c, this.m_xf.p, this.m_xf.p); } } exports.b2Body = b2Body; b2Body.SetMassData_s_oldCenter = new b2_math_1.b2Vec2(); b2Body.ResetMassData_s_localCenter = new b2_math_1.b2Vec2(); b2Body.ResetMassData_s_oldCenter = new b2_math_1.b2Vec2(); b2Body.ResetMassData_s_massData = new b2_shape_1.b2MassData(); b2Body.SynchronizeFixtures_s_xf1 = new b2_math_1.b2Transform();