< Summary

Information
Class: Gravitas.GravitasConstraint2DService
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/2D/GravitasConstraint2DService.cs
Line coverage
100%
Covered lines: 359
Uncovered lines: 0
Coverable lines: 359
Total lines: 640
Line coverage: 100%
Branch coverage
100%
Covered branches: 150
Total branches: 150
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/2D/GravitasConstraint2DService.cs

#LineLine coverage
 1//=======================================================================
 2// GravitasConstraint2DService.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2026-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using Chronicler;
 9using FixedMathSharp;
 10using Gravitas.Colliders;
 11using Gravitas.Constraints;
 12using SwiftCollections;
 13using System;
 14
 15namespace Gravitas;
 16
 17/// <summary>
 18/// Owns deterministic pure 2D joints and ragdoll articulation state for one world context.
 19/// </summary>
 20public sealed class GravitasConstraint2DService
 21{
 22    private const int DefaultJointCapacity = 64;
 23
 24    private readonly GravitasWorldContext _context;
 508325    private readonly ConstraintEndpointJointIndex<SolidBody2D> _jointIdsByBody = new();
 508326    private readonly SwiftDictionary<SolidBody2D, RagdollRuntime2D> _ragdollByBody = new();
 508327    private readonly SwiftDictionary<int, RagdollRuntime2D> _ragdollsById = new();
 508328    private readonly SwiftDictionary<ulong, int> _suppressedColliderPairs = new();
 508329    private Joint2D?[] _joints = new Joint2D?[DefaultJointCapacity];
 30    private RagdollRuntime2D? _firstRagdoll;
 31    private RagdollRuntime2D? _lastRagdoll;
 32    private int _nextRagdollId;
 33    private int _registeredRagdollCount;
 34    private int _enabledJointCount;
 35
 508336    internal GravitasConstraint2DService(GravitasWorldContext context)
 37    {
 508338        SwiftThrowHelper.ThrowIfNull(context, nameof(context));
 508339        _context = context;
 508340    }
 41
 42    /// <summary>
 43    /// Gets the owning world context.
 44    /// </summary>
 19545    public GravitasWorldContext Context => _context;
 46
 47    /// <summary>
 48    /// Gets the highest joint ID allocated in this context.
 49    /// </summary>
 50    public int PeakJointCount { get; private set; }
 51
 52    /// <summary>
 53    /// Gets the number of registered active joints.
 54    /// </summary>
 55    public int RegisteredJointCount { get; private set; }
 56
 57    /// <summary>
 58    /// Gets the number of registered ragdoll runtimes.
 59    /// </summary>
 1160    public int RegisteredRagdollCount => _registeredRagdollCount;
 61
 2162    internal int EnabledJointCount => _enabledJointCount;
 63
 100364    internal bool HasActiveJoints => _enabledJointCount > 0;
 65
 66    internal void ClearSolverCachesForBody(SolidBody2D body)
 67    {
 7868        if (!_jointIdsByBody.TryGetLast(body, out int jointId))
 6369            return;
 70
 171        while (true)
 72        {
 1673            _joints[jointId]!.ClearSolverCache();
 1674            if (!_jointIdsByBody.TryGetPrevious(body, jointId, out int previousJointId))
 1575                return;
 76
 177            jointId = previousJointId;
 78        }
 79    }
 80
 81    /// <summary>
 82    /// Registers a context-owned deterministic pure 2D joint.
 83    /// </summary>
 84    public Joint2D RegisterJoint(in JointDefinition2D definition)
 85    {
 20386        _context.ThrowIfDisposed();
 20287        ValidateDefinition(definition);
 88
 19589        int id = ++PeakJointCount;
 19590        EnsureJointCapacity(id + 1);
 19591        var joint = new Joint2D(this, id, definition);
 19592        _joints[id] = joint;
 19593        _jointIdsByBody.Add(joint.BodyA, joint.BodyB, id);
 19594        RegisteredJointCount++;
 19595        _enabledJointCount++;
 96
 19597        if (joint.CollisionPolicy == JointCollisionPolicy.SuppressLinked)
 16998            AddSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 99
 195100        _context.Diagnostics.EmitJointRegistered(joint);
 195101        return joint;
 102    }
 103
 104    /// <summary>
 105    /// Removes a context-owned pure 2D joint and releases its filter state.
 106    /// </summary>
 107    public bool RemoveJoint(int jointId)
 108    {
 13109        _context.ThrowIfDisposed();
 12110        if (!TryGetJoint(jointId, out Joint2D? joint))
 1111            return false;
 112
 11113        SwiftThrowHelper.ThrowIfTrue(
 11114            joint!.OwningRagdoll?.IsRegistered == true,
 11115            nameof(jointId),
 11116            "Ragdoll-owned joints cannot be removed independently. Remove the owning ragdoll instead.");
 10117        return RemoveJointCore(joint);
 118    }
 119
 120    private bool RemoveJointCore(Joint2D joint)
 121    {
 28122        int jointId = joint.Id;
 28123        _joints[jointId] = null;
 28124        _jointIdsByBody.Remove(jointId);
 28125        RegisteredJointCount--;
 28126        if (joint.IsEnabled)
 27127            _enabledJointCount--;
 28128        joint.IsActive = false;
 28129        joint.ClearSolverCache();
 28130        if (joint.CollisionPolicy == JointCollisionPolicy.SuppressLinked)
 27131            RemoveSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 132
 28133        _context.Diagnostics.EmitJointRemoved(joint);
 28134        return true;
 135    }
 136
 137    /// <summary>
 138    /// Gets a registered pure 2D joint by context-local ID.
 139    /// </summary>
 140    public Joint2D GetJoint(int jointId)
 141    {
 21142        if (!TryGetJoint(jointId, out Joint2D? joint))
 1143            throw new ArgumentOutOfRangeException(nameof(jointId), "No active 2D joint exists with the supplied ID.");
 144
 20145        return joint!;
 146    }
 147
 148    /// <summary>
 149    /// Tries to get a registered pure 2D joint by context-local ID.
 150    /// </summary>
 151    public bool TryGetJoint(int jointId, out Joint2D? joint)
 152    {
 657153        if ((uint)jointId >= (uint)_joints.Length)
 154        {
 4155            joint = null;
 4156            return false;
 157        }
 158
 653159        joint = _joints[jointId];
 653160        return joint != null && joint.IsActive;
 161    }
 162
 163    /// <summary>
 164    /// Registers a pure 2D ragdoll articulation and its owned joints.
 165    /// </summary>
 166    public RagdollRuntime2D RegisterRagdoll(RagdollDefinition2D definition)
 167    {
 34168        _context.ThrowIfDisposed();
 34169        ValidateRagdollDefinition(definition);
 170
 30171        int linkCount = definition.Links.Length;
 30172        var links = new SolidBody2D[linkCount];
 168173        for (int i = 0; i < linkCount; i++)
 54174            links[i] = definition.Links[i].Body;
 175
 30176        int jointCount = definition.Joints.Length;
 30177        var joints = new Joint2D[jointCount];
 108178        for (int i = 0; i < jointCount; i++)
 179        {
 24180            RagdollJointDefinition2D authoredJoint = definition.Joints[i];
 24181            SolidBody2D bodyA = ResolveRagdollLink(definition.Links, authoredJoint.LinkAId);
 24182            SolidBody2D bodyB = ResolveRagdollLink(definition.Links, authoredJoint.LinkBId);
 24183            JointCollisionPolicy collisionPolicy = definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.CollideA
 24184                ? JointCollisionPolicy.Collide
 24185                : authoredJoint.CollisionPolicy;
 186
 24187            joints[i] = RegisterJoint(new JointDefinition2D(
 24188                bodyA,
 24189                bodyB,
 24190                authoredJoint.LocalFrameA,
 24191                authoredJoint.LocalFrameB,
 24192                authoredJoint.Type,
 24193                authoredJoint.Limits,
 24194                authoredJoint.Motor,
 24195                collisionPolicy));
 196        }
 197
 30198        if (definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.SuppressAllLinks)
 2199            AddAllRagdollPairSuppressions(links);
 200
 30201        var runtime = new RagdollRuntime2D(
 30202            this,
 30203            ++_nextRagdollId,
 30204            links,
 30205            joints,
 30206            definition.SelfCollisionPolicy,
 30207            startsActive: !HasKinematicLink(links));
 30208        AppendRagdoll(runtime);
 30209        _ragdollsById.Add(runtime.Id, runtime);
 168210        for (int i = 0; i < links.Length; i++)
 54211            _ragdollByBody.Add(links[i], runtime);
 108212        for (int i = 0; i < joints.Length; i++)
 24213            joints[i].OwningRagdoll = runtime;
 30214        return runtime;
 215    }
 216
 217    /// <summary>
 218    /// Removes a registered pure 2D ragdoll and every joint and collision suppression it owns.
 219    /// </summary>
 220    public bool RemoveRagdoll(int ragdollId)
 221    {
 9222        _context.ThrowIfDisposed();
 9223        if (!_ragdollsById.TryGetValue(ragdollId, out RagdollRuntime2D? ragdoll))
 2224            return false;
 225
 7226        RemoveRagdollCore(ragdoll);
 7227        return true;
 228    }
 229
 230    /// <summary>
 231    /// Updates a pure 2D joint motor target while preserving the motor's gains and impulse cap.
 232    /// </summary>
 233    public bool SetJointMotorTarget(int jointId, Fixed64 target)
 234    {
 3235        _context.ThrowIfDisposed();
 3236        if (!TryGetJoint(jointId, out Joint2D? joint))
 1237            return false;
 238
 2239        JointMotor2D current = joint!.Motor;
 2240        JointMotor2D replacement = current.Kind == JointMotorKind2D.Linear
 2241            ? JointMotor2D.Linear(target, current.DriveStrength, current.Damping, current.MaximumMotorImpulse)
 2242            : JointMotor2D.Angular(target, current.DriveStrength, current.Damping, current.MaximumMotorImpulse);
 2243        joint.SetMotor(replacement);
 2244        return true;
 245    }
 246
 247    /// <summary>
 248    /// Disables a pure 2D joint motor target and clears its cached solver impulses.
 249    /// </summary>
 250    public bool ClearJointMotorTarget(int jointId)
 251    {
 2252        _context.ThrowIfDisposed();
 2253        if (!TryGetJoint(jointId, out Joint2D? joint))
 1254            return false;
 255
 1256        joint!.ClearMotor();
 1257        return true;
 258    }
 259
 260    /// <summary>
 261    /// Applies caller-owned motor payloads to every joint in a pure 2D ragdoll runtime.
 262    /// </summary>
 263    public void SetRagdollPoseTargets(RagdollRuntime2D ragdoll, ReadOnlySpan<JointMotor2D> motors)
 264    {
 4265        _context.ThrowIfDisposed();
 4266        SwiftThrowHelper.ThrowIfNull(ragdoll, nameof(ragdoll));
 4267        SwiftThrowHelper.ThrowIfArgument(
 4268            !ReferenceEquals(ragdoll.Service, this),
 4269            nameof(ragdoll),
 4270            "Ragdoll targets must be applied through the owning 2D constraint service.");
 3271        SwiftThrowHelper.ThrowIfTrue(
 3272            !ragdoll.IsRegistered,
 3273            nameof(ragdoll),
 3274            "Removed ragdolls cannot mutate simulation state.");
 1275        SwiftThrowHelper.ThrowIfArgument(
 1276            motors.Length != ragdoll.JointCount,
 1277            nameof(motors),
 1278            "Ragdoll pose target count must match the ragdoll joint count.");
 279
 4280        for (int i = 0; i < motors.Length; i++)
 281        {
 1282            Joint2D joint = ragdoll.GetJoint(i);
 1283            joint.SetMotor(motors[i]);
 284        }
 1285    }
 286
 287    /// <summary>
 288    /// Gets whether the supplied pure 2D colliders should be excluded because a registered articulation links them.
 289    /// </summary>
 290    public bool ShouldExcludeLinkedCollision(LSCollider2D colliderA, LSCollider2D colliderB)
 291    {
 8798292        if (colliderA == null || colliderB == null)
 2293            return false;
 8796294        if (colliderA.Id < 0 || colliderB.Id < 0 || colliderA.Id == colliderB.Id)
 4295            return false;
 296
 8792297        return _suppressedColliderPairs.ContainsKey(CreateColliderPairKey(colliderA.Id, colliderB.Id));
 298    }
 299
 300    internal bool TryGetJointForSolver(int jointId, out Joint2D? joint)
 301    {
 601302        if (!TryGetJoint(jointId, out joint))
 12303            return false;
 304
 589305        if (!joint!.IsEnabled || !joint.HasSolverParticipant())
 306        {
 3307            joint = null;
 3308            return false;
 309        }
 310
 586311        return true;
 312    }
 313
 314    internal void RemoveJointsForBody(SolidBody2D body)
 315    {
 123316        if (_ragdollByBody.TryGetValue(body, out RagdollRuntime2D? ragdoll))
 3317            RemoveRagdollCore(ragdoll);
 318
 135319        while (_jointIdsByBody.TryGetLast(body, out int jointId))
 12320            RemoveJointCore(GetJoint(jointId));
 123321    }
 322
 323    internal void UpdateJointCollisionPolicy(
 324        Joint2D joint,
 325        JointCollisionPolicy oldPolicy,
 326        JointCollisionPolicy newPolicy)
 327    {
 10328        if (!joint.IsActive || oldPolicy == newPolicy)
 3329            return;
 330
 7331        if (oldPolicy == JointCollisionPolicy.SuppressLinked)
 6332            RemoveSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 7333        if (newPolicy == JointCollisionPolicy.SuppressLinked)
 1334            AddSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 7335    }
 336
 337    internal void UpdateJointEnabledState(
 338        Joint2D joint,
 339        bool oldEnabled,
 340        bool newEnabled)
 341    {
 19342        if (!joint.IsActive || oldEnabled == newEnabled)
 1343            return;
 344
 18345        _enabledJointCount += newEnabled ? 1 : -1;
 18346    }
 347
 348    internal void Reset()
 349    {
 5114350        RagdollRuntime2D? ragdoll = _firstRagdoll;
 5134351        while (ragdoll != null)
 352        {
 20353            RagdollRuntime2D? next = ragdoll.NextRegistered;
 20354            ragdoll.Invalidate();
 20355            ragdoll = next;
 356        }
 357
 10618358        for (int i = 1; i <= PeakJointCount && i < _joints.Length; i++)
 359        {
 195360            Joint2D? joint = _joints[i];
 195361            if (joint == null)
 362                continue;
 363
 167364            joint.IsActive = false;
 167365            joint.ClearSolverCache();
 167366            joint.OwningRagdoll = null;
 167367            _joints[i] = null;
 368        }
 369
 5114370        _suppressedColliderPairs.Clear();
 5114371        _jointIdsByBody.Clear();
 5114372        _ragdollByBody.Clear();
 5114373        _ragdollsById.Clear();
 5114374        _firstRagdoll = null;
 5114375        _lastRagdoll = null;
 5114376        PeakJointCount = 0;
 5114377        RegisteredJointCount = 0;
 5114378        _registeredRagdollCount = 0;
 5114379        _enabledJointCount = 0;
 5114380        _nextRagdollId = 0;
 5114381    }
 382
 383    internal void ContributeReplayHash(
 384        ref ChronicleHashWriter writer,
 385        GravitasReplayHashMode mode)
 386    {
 997387        writer.WriteSection("constraints.2d", 1);
 997388        writer.WriteInt32(PeakJointCount);
 997389        writer.WriteInt32(RegisteredJointCount);
 2022390        for (int jointId = 1; jointId <= PeakJointCount; jointId++)
 391        {
 14392            bool hasJoint = TryGetJoint(jointId, out Joint2D? joint);
 14393            writer.WriteBool(hasJoint);
 14394            if (hasJoint)
 7395                joint!.ContributeReplayHash(ref writer, mode);
 396        }
 397
 997398        writer.WriteInt32(_registeredRagdollCount);
 997399        for (RagdollRuntime2D? ragdoll = _firstRagdoll;
 1007400             ragdoll != null;
 10401             ragdoll = ragdoll.NextRegistered)
 402        {
 10403            writer.WriteInt32(ragdoll.Id);
 10404            writer.WriteEnum(ragdoll.SelfCollisionPolicy);
 10405            writer.WriteBool(ragdoll.IsActive);
 10406            writer.WriteInt32(ragdoll.LinkCount);
 10407            writer.WriteInt32(ragdoll.JointCount);
 408        }
 997409    }
 410
 411    internal static ulong CreateColliderPairKey(int colliderAId, int colliderBId)
 412    {
 9004413        uint min = (uint)(colliderAId <= colliderBId ? colliderAId : colliderBId);
 9004414        uint max = (uint)(colliderAId <= colliderBId ? colliderBId : colliderAId);
 9004415        return ((ulong)min << 32) | max;
 416    }
 417
 418    private void EnsureJointCapacity(int required)
 419    {
 195420        if (required <= _joints.Length)
 194421            return;
 422
 1423        int newSize = _joints.Length;
 2424        while (newSize < required)
 1425            newSize *= 2;
 426
 1427        Array.Resize(ref _joints, newSize);
 1428    }
 429
 430    private void ValidateDefinition(in JointDefinition2D definition)
 431    {
 228432        SwiftThrowHelper.ThrowIfNull(definition.BodyA, nameof(definition.BodyA));
 228433        SwiftThrowHelper.ThrowIfNull(definition.BodyB, nameof(definition.BodyB));
 228434        SwiftThrowHelper.ThrowIfArgument(
 228435            ReferenceEquals(definition.BodyA, definition.BodyB),
 228436            nameof(definition),
 228437            "A 2D joint cannot link a body to itself.");
 227438        SwiftThrowHelper.ThrowIfArgument(
 227439            !ReferenceEquals(definition.BodyA.Context, _context) || !ReferenceEquals(definition.BodyB.Context, _context)
 227440            nameof(definition),
 227441            "Both 2D joint bodies must belong to this constraint service context.");
 225442        SwiftThrowHelper.ThrowIfArgument(
 225443            !definition.BodyA.Active || !definition.BodyB.Active,
 225444            nameof(definition),
 225445            "2D joint bodies must be active before registration.");
 223446        SwiftThrowHelper.ThrowIfArgument(
 223447            !Joint2D.IsSupportedType(definition.Type),
 223448            nameof(definition.Type),
 223449            "Unsupported 2D joint type.");
 222450        SwiftThrowHelper.ThrowIfArgument(
 222451            definition.CollisionPolicy != JointCollisionPolicy.SuppressLinked
 222452                && definition.CollisionPolicy != JointCollisionPolicy.Collide,
 222453            nameof(definition.CollisionPolicy),
 222454            "Unsupported joint collision policy.");
 221455        definition.Limits.Validate();
 221456        definition.Motor.Validate();
 221457        Joint2D.ValidatePayload(definition.Type, definition.Limits, definition.Motor);
 220458    }
 459
 460    private void ValidateRagdollDefinition(RagdollDefinition2D definition)
 461    {
 34462        SwiftThrowHelper.ThrowIfNull(definition, nameof(definition));
 34463        SwiftThrowHelper.ThrowIfNull(definition.Links, nameof(definition.Links));
 34464        SwiftThrowHelper.ThrowIfNull(definition.Joints, nameof(definition.Joints));
 34465        SwiftThrowHelper.ThrowIfArgument(definition.Links.Length == 0, nameof(definition.Links), "A 2D ragdoll must cont
 34466        SwiftThrowHelper.ThrowIfArgument(
 34467            definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.SuppressAdjacentLinks
 34468                && definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.CollideAllLinks
 34469                && definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.SuppressAllLinks,
 34470            nameof(definition.SelfCollisionPolicy),
 34471            "Unsupported ragdoll self-collision policy.");
 472
 186473        for (int i = 0; i < definition.Links.Length; i++)
 474        {
 61475            RagdollLinkDefinition2D link = definition.Links[i];
 61476            SwiftThrowHelper.ThrowIfNull(link.Body, nameof(definition.Links));
 61477            SwiftThrowHelper.ThrowIfNull(link.Collider, nameof(definition.Links));
 61478            SwiftThrowHelper.ThrowIfArgument(
 61479                !ReferenceEquals(link.Body.Context, _context),
 61480                nameof(definition.Links),
 61481                "All 2D ragdoll links must belong to this context.");
 61482            SwiftThrowHelper.ThrowIfArgument(
 61483                !link.Body.Active,
 61484                nameof(definition.Links),
 61485                "2D ragdoll links must have active 2D colliders.");
 61486            SwiftThrowHelper.ThrowIfArgument(
 61487                !ReferenceEquals(link.Body.Collider, link.Collider),
 61488                nameof(definition.Links),
 61489                "2D ragdoll link collider must match the link body's collider.");
 61490            SwiftThrowHelper.ThrowIfArgument(
 61491                _ragdollByBody.ContainsKey(link.Body),
 61492                nameof(definition.Links),
 61493                "A 2D body cannot belong to more than one registered ragdoll.");
 494
 184495            for (int j = i + 1; j < definition.Links.Length; j++)
 496            {
 33497                SwiftThrowHelper.ThrowIfArgument(
 33498                    link.LinkId == definition.Links[j].LinkId,
 33499                    nameof(definition.Links),
 33500                    "2D ragdoll link IDs must be unique.");
 33501                SwiftThrowHelper.ThrowIfArgument(
 33502                    ReferenceEquals(link.Body, definition.Links[j].Body),
 33503                    nameof(definition.Links),
 33504                    "2D ragdoll bodies must be unique.");
 505            }
 506        }
 507
 114508        for (int i = 0; i < definition.Joints.Length; i++)
 509        {
 27510            RagdollJointDefinition2D joint = definition.Joints[i];
 27511            SolidBody2D bodyA = ResolveRagdollLink(definition.Links, joint.LinkAId);
 27512            SolidBody2D bodyB = ResolveRagdollLink(definition.Links, joint.LinkBId);
 26513            SwiftThrowHelper.ThrowIfArgument(
 26514                joint.LinkAId == joint.LinkBId,
 26515                nameof(definition.Joints),
 26516                "A 2D ragdoll joint cannot link a body to itself.");
 26517            JointCollisionPolicy collisionPolicy = definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.CollideA
 26518                ? JointCollisionPolicy.Collide
 26519                : joint.CollisionPolicy;
 26520            ValidateDefinition(new JointDefinition2D(
 26521                bodyA,
 26522                bodyB,
 26523                joint.LocalFrameA,
 26524                joint.LocalFrameB,
 26525                joint.Type,
 26526                joint.Limits,
 26527                joint.Motor,
 26528                collisionPolicy));
 529        }
 30530    }
 531
 532    private static bool HasKinematicLink(SolidBody2D[] links)
 533    {
 154534        for (int i = 0; i < links.Length; i++)
 535        {
 51536            if (links[i].IsKinematic)
 4537                return true;
 538        }
 539
 26540        return false;
 541    }
 542
 543    private static SolidBody2D ResolveRagdollLink(RagdollLinkDefinition2D[] links, int linkId)
 544    {
 344545        for (int i = 0; i < links.Length; i++)
 546        {
 171547            if (links[i].LinkId == linkId)
 101548                return links[i].Body;
 549        }
 550
 1551        throw new ArgumentException("2D ragdoll joint references an unknown link ID.", nameof(linkId));
 552    }
 553
 554    private void AddAllRagdollPairSuppressions(SolidBody2D[] links)
 555    {
 16556        for (int i = 0; i < links.Length; i++)
 557        {
 24558            for (int j = i + 1; j < links.Length; j++)
 6559                AddSuppressedColliderPair(links[i].Collider, links[j].Collider);
 560        }
 2561    }
 562
 563    private void RemoveRagdollCore(RagdollRuntime2D ragdoll)
 564    {
 10565        _ragdollsById.Remove(ragdoll.Id);
 52566        for (int i = 0; i < ragdoll.LinkCount; i++)
 16567            _ragdollByBody.Remove(ragdoll.GetLink(i));
 568
 10569        if (ragdoll.SelfCollisionPolicy == RagdollSelfCollisionPolicy.SuppressAllLinks)
 570        {
 8571            for (int i = 0; i < ragdoll.LinkCount; i++)
 572            {
 12573                for (int j = i + 1; j < ragdoll.LinkCount; j++)
 574                {
 3575                    RemoveSuppressedColliderPair(
 3576                        ragdoll.GetLink(i).Collider,
 3577                        ragdoll.GetLink(j).Collider);
 578                }
 579            }
 580        }
 581
 10582        UnlinkRagdoll(ragdoll);
 10583        ragdoll.Invalidate();
 584
 32585        for (int i = 0; i < ragdoll.JointCount; i++)
 586        {
 6587            Joint2D joint = ragdoll.GetJoint(i);
 6588            joint.OwningRagdoll = null;
 6589            RemoveJointCore(joint);
 590        }
 10591    }
 592
 593    private void AppendRagdoll(RagdollRuntime2D ragdoll)
 594    {
 30595        ragdoll.PreviousRegistered = _lastRagdoll;
 30596        if (_lastRagdoll == null)
 23597            _firstRagdoll = ragdoll;
 598        else
 7599            _lastRagdoll.NextRegistered = ragdoll;
 600
 30601        _lastRagdoll = ragdoll;
 30602        _registeredRagdollCount++;
 30603    }
 604
 605    private void UnlinkRagdoll(RagdollRuntime2D ragdoll)
 606    {
 10607        if (ragdoll.PreviousRegistered == null)
 9608            _firstRagdoll = ragdoll.NextRegistered;
 609        else
 1610            ragdoll.PreviousRegistered.NextRegistered = ragdoll.NextRegistered;
 611
 10612        if (ragdoll.NextRegistered == null)
 5613            _lastRagdoll = ragdoll.PreviousRegistered;
 614        else
 5615            ragdoll.NextRegistered.PreviousRegistered = ragdoll.PreviousRegistered;
 616
 10617        _registeredRagdollCount--;
 10618    }
 619
 620    private void AddSuppressedColliderPair(LSCollider2D colliderA, LSCollider2D colliderB)
 621    {
 176622        ulong key = CreateColliderPairKey(colliderA.Id, colliderB.Id);
 176623        if (_suppressedColliderPairs.TryGetValue(key, out int count))
 79624            _suppressedColliderPairs[key] = count + 1;
 625        else
 97626            _suppressedColliderPairs.Add(key, 1);
 97627    }
 628
 629    private void RemoveSuppressedColliderPair(LSCollider2D colliderA, LSCollider2D colliderB)
 630    {
 36631        ulong key = CreateColliderPairKey(colliderA.Id, colliderB.Id);
 36632        if (!_suppressedColliderPairs.TryGetValue(key, out int count))
 1633            return;
 634
 35635        if (count <= 1)
 29636            _suppressedColliderPairs.Remove(key);
 637        else
 6638            _suppressedColliderPairs[key] = count - 1;
 6639    }
 640}

Methods/Properties

.ctor(Gravitas.GravitasWorldContext)
get_Context()
get_RegisteredRagdollCount()
get_EnabledJointCount()
get_HasActiveJoints()
ClearSolverCachesForBody(Gravitas.SolidBody2D)
RegisterJoint(Gravitas.Constraints.JointDefinition2D&)
RemoveJoint(System.Int32)
RemoveJointCore(Gravitas.Constraints.Joint2D)
GetJoint(System.Int32)
TryGetJoint(System.Int32,Gravitas.Constraints.Joint2D&)
RegisterRagdoll(Gravitas.Constraints.RagdollDefinition2D)
RemoveRagdoll(System.Int32)
SetJointMotorTarget(System.Int32,FixedMathSharp.Fixed64)
ClearJointMotorTarget(System.Int32)
SetRagdollPoseTargets(Gravitas.Constraints.RagdollRuntime2D,System.ReadOnlySpan`1<Gravitas.Constraints.JointMotor2D>)
ShouldExcludeLinkedCollision(Gravitas.Colliders.LSCollider2D,Gravitas.Colliders.LSCollider2D)
TryGetJointForSolver(System.Int32,Gravitas.Constraints.Joint2D&)
RemoveJointsForBody(Gravitas.SolidBody2D)
UpdateJointCollisionPolicy(Gravitas.Constraints.Joint2D,Gravitas.Constraints.JointCollisionPolicy,Gravitas.Constraints.JointCollisionPolicy)
UpdateJointEnabledState(Gravitas.Constraints.Joint2D,System.Boolean,System.Boolean)
Reset()
ContributeReplayHash(Chronicler.ChronicleHashWriter&,Gravitas.GravitasReplayHashMode)
CreateColliderPairKey(System.Int32,System.Int32)
EnsureJointCapacity(System.Int32)
ValidateDefinition(Gravitas.Constraints.JointDefinition2D&)
ValidateRagdollDefinition(Gravitas.Constraints.RagdollDefinition2D)
HasKinematicLink(Gravitas.SolidBody2D[])
ResolveRagdollLink(Gravitas.Constraints.RagdollLinkDefinition2D[],System.Int32)
AddAllRagdollPairSuppressions(Gravitas.SolidBody2D[])
RemoveRagdollCore(Gravitas.Constraints.RagdollRuntime2D)
AppendRagdoll(Gravitas.Constraints.RagdollRuntime2D)
UnlinkRagdoll(Gravitas.Constraints.RagdollRuntime2D)
AddSuppressedColliderPair(Gravitas.Colliders.LSCollider2D,Gravitas.Colliders.LSCollider2D)
RemoveSuppressedColliderPair(Gravitas.Colliders.LSCollider2D,Gravitas.Colliders.LSCollider2D)