/* * Farseer Physics Engine: * Copyright (c) 2012 Ian Qvist * * Original source Box2D: * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * PhysicsComponent is heavily modified from Box2D. */ using System.Collections.Generic; using System.Numerics; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Maths; using Robust.Shared.Physics.Dynamics.Contacts; using Robust.Shared.Physics.Systems; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Robust.Shared.Physics.Components; [RegisterComponent, NetworkedComponent] public sealed partial class PhysicsComponent : Component { /// /// Has this body been added to an island previously in this tick. /// [Access(typeof(SharedPhysicsSystem))] public bool Island; /// /// Store the body's index within the island so we can lookup its data. /// Key is Island's ID and value is our index. /// [Access(typeof(SharedPhysicsSystem))] public Dictionary IslandIndex = new(); [ViewVariables] public int ContactCount => Contacts.Count; /// /// Linked-list of all of our contacts. /// internal readonly LinkedList Contacts = new(); [DataField("ignorePaused"), ViewVariables(VVAccess.ReadWrite)] public bool IgnorePaused; [DataField("bodyType"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public BodyType BodyType = BodyType.Static; // We'll also block Static bodies from ever being awake given they don't need to move. [ViewVariables(VVAccess.ReadWrite), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public bool Awake; /// /// You can disable sleeping on this body. If you disable sleeping, the /// body will be woken. /// /// true if sleeping is allowed; otherwise, false. [ViewVariables(VVAccess.ReadWrite), DataField("sleepingAllowed"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public bool SleepingAllowed = true; [ViewVariables(VVAccess.ReadWrite), DataField("sleepTime"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float SleepTime = 0f; /// /// Enables or disabled collision processing of this component. /// /// /// Also known as Enabled in Box2D /// [ViewVariables(VVAccess.ReadWrite), DataField("canCollide"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public bool CanCollide = true; /// /// Non-hard physics bodies will not cause action collision (e.g. blocking of movement) /// while still raising collision events. Recommended you use the fixture hard values directly /// /// /// This is useful for triggers or such to detect collision without actually causing a blockage. /// [ViewVariables, Access(typeof(SharedPhysicsSystem), typeof(FixtureSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public bool Hard { get; internal set; } /// /// Bitmask of the collision layers this component is a part of. /// [ViewVariables, Access(typeof(SharedPhysicsSystem), typeof(FixtureSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public int CollisionLayer { get; internal set; } /// /// Bitmask of the layers this component collides with. /// [ViewVariables, Access(typeof(SharedPhysicsSystem), typeof(FixtureSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public int CollisionMask { get; internal set; } /// /// The current total mass of the entities fixtures in kilograms. Ignores the body type. /// [ViewVariables] public float FixturesMass => _mass; // I made Mass read-only just because overwriting it doesn't touch inertia. /// /// Current mass of the entity in kilograms. This may be 0 depending on the body type. /// [ViewVariables(VVAccess.ReadOnly)] public float Mass => (BodyType & (BodyType.Dynamic | BodyType.KinematicController)) != 0 ? _mass : 0.0f; internal float _mass; /// /// Inverse mass of the entity in kilograms (1 / Mass). /// [ViewVariables] public float InvMass => (BodyType & (BodyType.Dynamic | BodyType.KinematicController)) != 0 ? _invMass : 0.0f; internal float _invMass; /// /// Moment of inertia, or angular mass, in kg * m^2. /// /// /// https://en.wikipedia.org/wiki/Moment_of_inertia /// [ViewVariables] public float Inertia => _inertia + _mass * Vector2.Dot(_localCenter, _localCenter); [ViewVariables(VVAccess.ReadWrite), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] // ReSharper disable once InconsistentNaming internal float _inertia; /// /// Indicates whether this body ignores gravity /// [ViewVariables(VVAccess.ReadWrite)] public bool IgnoreGravity; /// /// Inverse moment of inertia (1 / I). /// [ViewVariables(VVAccess.ReadWrite), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float InvI; /// /// Is the body allowed to have angular velocity. /// [ViewVariables(VVAccess.ReadWrite), DataField("fixedRotation"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public bool FixedRotation = true; /// /// Get this body's center of mass offset to world position. /// [ViewVariables] public Vector2 LocalCenter => _localCenter; [Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] // ReSharper disable once InconsistentNaming internal Vector2 _localCenter = Vector2.Zero; /// /// Current Force being applied to this entity in Newtons. /// /// /// The force is applied to the center of mass. /// https://en.wikipedia.org/wiki/Force /// [ViewVariables(VVAccess.ReadWrite), DataField("force"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public Vector2 Force; /// /// Current torque being applied to this entity in N*m. /// /// /// The torque rotates around the Z axis on the object. /// https://en.wikipedia.org/wiki/Torque /// [ViewVariables(VVAccess.ReadWrite), DataField("torque"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float Torque; /// /// Contact friction between 2 bodies. /// [ViewVariables, Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float Friction => _friction; internal float _friction; /// /// This is a set amount that the body's linear velocity is reduced by every tick. /// Combined with the tile friction. /// [ViewVariables(VVAccess.ReadWrite), DataField("linearDamping"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float LinearDamping = 0.2f; /// /// This is a set amount that the body's angular velocity is reduced every tick. /// Combined with the tile friction. /// /// [ViewVariables(VVAccess.ReadWrite), DataField("angularDamping"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public float AngularDamping = 0.2f; // TODO: Datafield /// /// Current linear velocity of the entity in meters per second. /// /// /// This is the velocity relative to the parent, but is defined in terms of map coordinates. I.e., if the /// entity's parents are all stationary, this is the rate of change of this entity's world position (not /// local position). /// [ViewVariables(VVAccess.ReadWrite), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.ReadExecute)] public Vector2 LinearVelocity; /// /// Current angular velocity of the entity in radians per sec. /// [ViewVariables(VVAccess.ReadWrite), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.ReadExecute)] public float AngularVelocity; /// /// Current momentum of the entity in kilogram meters per second /// [ViewVariables] public Vector2 Momentum => LinearVelocity * Mass; /// /// The current status of the object /// [ViewVariables(VVAccess.ReadWrite), DataField("bodyStatus"), Access(typeof(SharedPhysicsSystem), Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.Read)] public BodyStatus BodyStatus { get; set; } [ViewVariables, Access(typeof(SharedPhysicsSystem))] public bool Predict; }