< Summary

Information
Class: Gravitas.GravitasConstraint3DService
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Constraints/3D/GravitasConstraint3DService.cs
Line coverage
100%
Covered lines: 364
Uncovered lines: 0
Coverable lines: 364
Total lines: 645
Line coverage: 100%
Branch coverage
100%
Covered branches: 148
Total branches: 148
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/3D/GravitasConstraint3DService.cs

#LineLine coverage
 1//=======================================================================
 2// GravitasConstraint3DService.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 3D joints and ragdoll articulation state for one world context.
 19/// </summary>
 20public sealed class GravitasConstraint3DService
 21{
 22    private const int DefaultJointCapacity = 64;
 23
 24    private readonly GravitasWorldContext _context;
 508325    private readonly ConstraintEndpointJointIndex<SolidBody> _jointIdsByBody = new();
 508326    private readonly SwiftDictionary<SolidBody, RagdollRuntime3D> _ragdollByBody = new();
 508327    private readonly SwiftDictionary<int, RagdollRuntime3D> _ragdollsById = new();
 508328    private readonly SwiftDictionary<ulong, int> _suppressedColliderPairs = new();
 508329    private Joint3D?[] _joints = new Joint3D?[DefaultJointCapacity];
 30    private RagdollRuntime3D? _firstRagdoll;
 31    private RagdollRuntime3D? _lastRagdoll;
 32    private int _nextRagdollId;
 33    private int _registeredRagdollCount;
 34    private int _enabledJointCount;
 35
 508336    internal GravitasConstraint3DService(GravitasWorldContext context)
 37    {
 508338        SwiftThrowHelper.ThrowIfNull(context, nameof(context));
 508339        _context = context;
 508340    }
 41
 42    /// <summary>
 43    /// Gets the owning world context.
 44    /// </summary>
 31245    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
 1262    internal int EnabledJointCount => _enabledJointCount;
 63
 218164    internal bool HasActiveJoints => _enabledJointCount > 0;
 65
 66    internal void ClearSolverCachesForBody(SolidBody body)
 67    {
 6468        if (!_jointIdsByBody.TryGetLast(body, out int jointId))
 4869            return;
 70
 171        while (true)
 72        {
 1773            _joints[jointId]!.ClearSolverCache();
 1774            if (!_jointIdsByBody.TryGetPrevious(body, jointId, out int previousJointId))
 1675                return;
 76
 177            jointId = previousJointId;
 78        }
 79    }
 80
 81    /// <summary>
 82    /// Registers a context-owned deterministic 3D joint.
 83    /// </summary>
 84    public Joint3D RegisterJoint(in JointDefinition3D definition)
 85    {
 32186        _context.ThrowIfDisposed();
 32087        ValidateDefinition(definition);
 31288        JointFrame3D frameA = JointFrame3D.FromTransform(definition.LocalFrameA, nameof(definition.LocalFrameA));
 31289        JointFrame3D frameB = JointFrame3D.FromTransform(definition.LocalFrameB, nameof(definition.LocalFrameB));
 90
 31291        int id = ++PeakJointCount;
 31292        EnsureJointCapacity(id + 1);
 31293        var joint = new Joint3D(this, id, definition, frameA, frameB);
 31294        _joints[id] = joint;
 31295        _jointIdsByBody.Add(joint.BodyA, joint.BodyB, id);
 31296        RegisteredJointCount++;
 31297        _enabledJointCount++;
 98
 31299        if (joint.CollisionPolicy == JointCollisionPolicy.SuppressLinked)
 299100            AddSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 101
 312102        _context.Diagnostics.EmitJointRegistered(joint);
 312103        return joint;
 104    }
 105
 106    /// <summary>
 107    /// Removes a context-owned joint and releases its filter state.
 108    /// </summary>
 109    public bool RemoveJoint(int jointId)
 110    {
 14111        _context.ThrowIfDisposed();
 13112        if (!TryGetJoint(jointId, out Joint3D? joint))
 1113            return false;
 114
 12115        SwiftThrowHelper.ThrowIfTrue(
 12116            joint!.OwningRagdoll?.IsRegistered == true,
 12117            nameof(jointId),
 12118            "Ragdoll-owned joints cannot be removed independently. Remove the owning ragdoll instead.");
 11119        return RemoveJointCore(joint);
 120    }
 121
 122    private bool RemoveJointCore(Joint3D joint)
 123    {
 29124        int jointId = joint.Id;
 29125        _joints[jointId] = null;
 29126        _jointIdsByBody.Remove(jointId);
 29127        RegisteredJointCount--;
 29128        if (joint.IsEnabled)
 28129            _enabledJointCount--;
 29130        joint.IsActive = false;
 29131        joint.ClearSolverCache();
 29132        if (joint.CollisionPolicy == JointCollisionPolicy.SuppressLinked)
 28133            RemoveSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 134
 29135        _context.Diagnostics.EmitJointRemoved(joint);
 29136        return true;
 137    }
 138
 139    /// <summary>
 140    /// Gets a registered joint by context-local ID.
 141    /// </summary>
 142    public Joint3D GetJoint(int jointId)
 143    {
 18144        if (!TryGetJoint(jointId, out Joint3D? joint))
 1145            throw new ArgumentOutOfRangeException(nameof(jointId), "No active joint exists with the supplied ID.");
 146
 17147        return joint!;
 148    }
 149
 150    /// <summary>
 151    /// Tries to get a registered joint by context-local ID.
 152    /// </summary>
 153    public bool TryGetJoint(int jointId, out Joint3D? joint)
 154    {
 16368155        if ((uint)jointId >= (uint)_joints.Length)
 156        {
 4157            joint = null;
 4158            return false;
 159        }
 160
 16364161        joint = _joints[jointId];
 16364162        return joint != null && joint.IsActive;
 163    }
 164
 165    /// <summary>
 166    /// Registers a ragdoll articulation and its owned joints.
 167    /// </summary>
 168    public RagdollRuntime3D RegisterRagdoll(RagdollDefinition3D definition)
 169    {
 41170        _context.ThrowIfDisposed();
 41171        ValidateRagdollDefinition(definition);
 172
 37173        int linkCount = definition.Links.Length;
 37174        var links = new SolidBody[linkCount];
 264175        for (int i = 0; i < linkCount; i++)
 95176            links[i] = definition.Links[i].Body;
 177
 37178        int jointCount = definition.Joints.Length;
 37179        var joints = new Joint3D[jointCount];
 190180        for (int i = 0; i < jointCount; i++)
 181        {
 58182            RagdollJointDefinition3D authoredJoint = definition.Joints[i];
 58183            SolidBody bodyA = ResolveRagdollLink(definition.Links, authoredJoint.LinkAId);
 58184            SolidBody bodyB = ResolveRagdollLink(definition.Links, authoredJoint.LinkBId);
 58185            JointCollisionPolicy collisionPolicy = definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.CollideA
 58186                ? JointCollisionPolicy.Collide
 58187                : authoredJoint.CollisionPolicy;
 188
 58189            joints[i] = RegisterJoint(new JointDefinition3D(
 58190                bodyA,
 58191                bodyB,
 58192                authoredJoint.LocalFrameA,
 58193                authoredJoint.LocalFrameB,
 58194                authoredJoint.Type,
 58195                authoredJoint.Limits,
 58196                authoredJoint.Motor,
 58197                collisionPolicy));
 198        }
 199
 37200        if (definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.SuppressAllLinks)
 6201            AddAllRagdollPairSuppressions(links);
 202
 37203        var runtime = new RagdollRuntime3D(
 37204            this,
 37205            ++_nextRagdollId,
 37206            links,
 37207            joints,
 37208            definition.SelfCollisionPolicy,
 37209            startsActive: !HasKinematicLink(links));
 37210        AppendRagdoll(runtime);
 37211        _ragdollsById.Add(runtime.Id, runtime);
 264212        for (int i = 0; i < links.Length; i++)
 95213            _ragdollByBody.Add(links[i], runtime);
 190214        for (int i = 0; i < joints.Length; i++)
 58215            joints[i].OwningRagdoll = runtime;
 37216        return runtime;
 217    }
 218
 219    /// <summary>
 220    /// Removes a registered ragdoll and every joint and collision suppression it owns.
 221    /// </summary>
 222    public bool RemoveRagdoll(int ragdollId)
 223    {
 9224        _context.ThrowIfDisposed();
 9225        if (!_ragdollsById.TryGetValue(ragdollId, out RagdollRuntime3D? ragdoll))
 2226            return false;
 227
 7228        RemoveRagdollCore(ragdoll);
 7229        return true;
 230    }
 231
 232    /// <summary>
 233    /// Updates a joint motor target while preserving the joint's authored motor gains and impulse cap.
 234    /// </summary>
 235    public bool SetJointMotorTarget(int jointId, FixedQuaternion targetLocalRotation)
 236    {
 2237        _context.ThrowIfDisposed();
 2238        if (!TryGetJoint(jointId, out Joint3D? joint))
 1239            return false;
 240
 1241        JointMotor3D current = joint!.Motor;
 1242        joint.SetMotor(new JointMotor3D(
 1243            targetLocalRotation,
 1244            current.AngularDriveStrength,
 1245            current.AngularDriveDamping,
 1246            current.MaximumMotorImpulse));
 1247        return true;
 248    }
 249
 250    /// <summary>
 251    /// Disables a joint motor target and clears its cached solver impulses.
 252    /// </summary>
 253    public bool ClearJointMotorTarget(int jointId)
 254    {
 2255        _context.ThrowIfDisposed();
 2256        if (!TryGetJoint(jointId, out Joint3D? joint))
 1257            return false;
 258
 1259        joint!.ClearMotor();
 1260        return true;
 261    }
 262
 263    /// <summary>
 264    /// Applies caller-owned motor payloads to every joint in a ragdoll runtime.
 265    /// </summary>
 266    public void SetRagdollPoseTargets(RagdollRuntime3D ragdoll, ReadOnlySpan<JointMotor3D> motors)
 267    {
 4268        _context.ThrowIfDisposed();
 4269        SwiftThrowHelper.ThrowIfNull(ragdoll, nameof(ragdoll));
 4270        SwiftThrowHelper.ThrowIfArgument(
 4271            !ReferenceEquals(ragdoll.Service, this),
 4272            nameof(ragdoll),
 4273            "Ragdoll targets must be applied through the owning constraint service.");
 3274        SwiftThrowHelper.ThrowIfTrue(
 3275            !ragdoll.IsRegistered,
 3276            nameof(ragdoll),
 3277            "Removed ragdolls cannot mutate simulation state.");
 1278        SwiftThrowHelper.ThrowIfArgument(
 1279            motors.Length != ragdoll.JointCount,
 1280            nameof(motors),
 1281            "Ragdoll pose target count must match the ragdoll joint count.");
 282
 4283        for (int i = 0; i < motors.Length; i++)
 284        {
 1285            Joint3D joint = ragdoll.GetJoint(i);
 1286            joint.SetMotor(motors[i]);
 287        }
 1288    }
 289
 290    /// <summary>
 291    /// Gets whether the supplied 3D colliders should be excluded because a registered articulation links them.
 292    /// </summary>
 293    public bool ShouldExcludeLinkedCollision(LSCollider colliderA, LSCollider colliderB)
 294    {
 394058295        if (colliderA == null || colliderB == null)
 2296            return false;
 394056297        if (colliderA.Id < 0 || colliderB.Id < 0 || colliderA.Id == colliderB.Id)
 6640298            return false;
 299
 387416300        return _suppressedColliderPairs.ContainsKey(CreateColliderPairKey(colliderA.Id, colliderB.Id));
 301    }
 302
 303    internal bool TryGetJointForSolver(int jointId, out Joint3D? joint)
 304    {
 15040305        if (!TryGetJoint(jointId, out joint))
 12306            return false;
 307
 15028308        if (!joint!.IsEnabled || !joint.HasSolverParticipant())
 309        {
 3310            joint = null;
 3311            return false;
 312        }
 313
 15025314        return true;
 315    }
 316
 317    internal void RemoveJointsForBody(SolidBody body)
 318    {
 92319        if (_ragdollByBody.TryGetValue(body, out RagdollRuntime3D? ragdoll))
 3320            RemoveRagdollCore(ragdoll);
 321
 104322        while (_jointIdsByBody.TryGetLast(body, out int jointId))
 12323            RemoveJointCore(GetJoint(jointId));
 92324    }
 325
 326    internal void UpdateJointCollisionPolicy(
 327        Joint3D joint,
 328        JointCollisionPolicy oldPolicy,
 329        JointCollisionPolicy newPolicy)
 330    {
 8331        if (!joint.IsActive || oldPolicy == newPolicy)
 3332            return;
 333
 5334        if (oldPolicy == JointCollisionPolicy.SuppressLinked)
 4335            RemoveSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 5336        if (newPolicy == JointCollisionPolicy.SuppressLinked)
 1337            AddSuppressedColliderPair(joint.BodyA.Collider, joint.BodyB.Collider);
 5338    }
 339
 340    internal void UpdateJointEnabledState(
 341        Joint3D joint,
 342        bool oldEnabled,
 343        bool newEnabled)
 344    {
 21345        if (!joint.IsActive || oldEnabled == newEnabled)
 1346            return;
 347
 20348        _enabledJointCount += newEnabled ? 1 : -1;
 20349    }
 350
 351    internal void Reset()
 352    {
 5114353        RagdollRuntime3D? ragdoll = _firstRagdoll;
 5141354        while (ragdoll != null)
 355        {
 27356            RagdollRuntime3D? next = ragdoll.NextRegistered;
 27357            ragdoll.Invalidate();
 27358            ragdoll = next;
 359        }
 360
 10852361        for (int i = 1; i <= PeakJointCount && i < _joints.Length; i++)
 362        {
 312363            Joint3D? joint = _joints[i];
 312364            if (joint == null)
 365                continue;
 366
 283367            joint.IsActive = false;
 283368            joint.ClearSolverCache();
 283369            joint.OwningRagdoll = null;
 283370            _joints[i] = null;
 371        }
 372
 5114373        _suppressedColliderPairs.Clear();
 5114374        _jointIdsByBody.Clear();
 5114375        _ragdollByBody.Clear();
 5114376        _ragdollsById.Clear();
 5114377        _firstRagdoll = null;
 5114378        _lastRagdoll = null;
 5114379        PeakJointCount = 0;
 5114380        RegisteredJointCount = 0;
 5114381        _registeredRagdollCount = 0;
 5114382        _enabledJointCount = 0;
 5114383        _nextRagdollId = 0;
 5114384    }
 385
 386    internal void ContributeReplayHash(
 387        ref ChronicleHashWriter writer,
 388        GravitasReplayHashMode mode)
 389    {
 995390        writer.WriteSection("constraints.3d", 1);
 995391        writer.WriteInt32(PeakJointCount);
 995392        writer.WriteInt32(RegisteredJointCount);
 4564393        for (int jointId = 1; jointId <= PeakJointCount; jointId++)
 394        {
 1287395            bool hasJoint = TryGetJoint(jointId, out Joint3D? joint);
 1287396            writer.WriteBool(hasJoint);
 1287397            if (hasJoint)
 1282398                joint!.ContributeReplayHash(ref writer, mode);
 399        }
 400
 995401        writer.WriteInt32(_registeredRagdollCount);
 995402        for (RagdollRuntime3D? ragdoll = _firstRagdoll;
 1004403             ragdoll != null;
 9404             ragdoll = ragdoll.NextRegistered)
 405        {
 9406            writer.WriteInt32(ragdoll.Id);
 9407            writer.WriteEnum(ragdoll.SelfCollisionPolicy);
 9408            writer.WriteBool(ragdoll.IsActive);
 9409            writer.WriteInt32(ragdoll.LinkCount);
 9410            writer.WriteInt32(ragdoll.JointCount);
 411        }
 995412    }
 413
 414    internal static ulong CreateColliderPairKey(int colliderAId, int colliderBId)
 415    {
 387821416        uint min = (uint)(colliderAId <= colliderBId ? colliderAId : colliderBId);
 387821417        uint max = (uint)(colliderAId <= colliderBId ? colliderBId : colliderAId);
 387821418        return ((ulong)min << 32) | max;
 419    }
 420
 421    private void EnsureJointCapacity(int required)
 422    {
 312423        if (required <= _joints.Length)
 311424            return;
 425
 1426        int newSize = _joints.Length;
 2427        while (newSize < required)
 1428            newSize *= 2;
 429
 1430        Array.Resize(ref _joints, newSize);
 1431    }
 432
 433    private void ValidateDefinition(in JointDefinition3D definition)
 434    {
 380435        SwiftThrowHelper.ThrowIfNull(definition.BodyA, nameof(definition.BodyA));
 380436        SwiftThrowHelper.ThrowIfNull(definition.BodyB, nameof(definition.BodyB));
 380437        SwiftThrowHelper.ThrowIfNull(definition.LocalFrameA, nameof(definition.LocalFrameA));
 379438        SwiftThrowHelper.ThrowIfNull(definition.LocalFrameB, nameof(definition.LocalFrameB));
 379439        SwiftThrowHelper.ThrowIfArgument(
 379440            ReferenceEquals(definition.BodyA, definition.BodyB),
 379441            nameof(definition),
 379442            "A joint cannot link a body to itself.");
 378443        SwiftThrowHelper.ThrowIfArgument(
 378444            !ReferenceEquals(definition.BodyA.Context, _context) || !ReferenceEquals(definition.BodyB.Context, _context)
 378445            nameof(definition),
 378446            "Both joint bodies must belong to this constraint service context.");
 376447        SwiftThrowHelper.ThrowIfArgument(
 376448            !definition.BodyA.Active || !definition.BodyB.Active,
 376449            nameof(definition),
 376450            "Joint bodies must be active before registration.");
 374451        SwiftThrowHelper.ThrowIfArgument(
 374452            !Joint3D.IsSupportedType(definition.Type),
 374453            nameof(definition.Type),
 374454            "Unsupported 3D joint type.");
 374455        SwiftThrowHelper.ThrowIfArgument(
 374456            definition.CollisionPolicy != JointCollisionPolicy.SuppressLinked
 374457                && definition.CollisionPolicy != JointCollisionPolicy.Collide,
 374458            nameof(definition.CollisionPolicy),
 374459            "Unsupported joint collision policy.");
 373460        definition.Limits.Validate();
 373461        definition.Motor.Validate();
 373462        Joint3D.ValidatePayload(definition.Type, definition.Limits);
 371463    }
 464
 465    private void ValidateRagdollDefinition(RagdollDefinition3D definition)
 466    {
 41467        SwiftThrowHelper.ThrowIfNull(definition, nameof(definition));
 41468        SwiftThrowHelper.ThrowIfNull(definition.Links, nameof(definition.Links));
 41469        SwiftThrowHelper.ThrowIfNull(definition.Joints, nameof(definition.Joints));
 41470        SwiftThrowHelper.ThrowIfArgument(definition.Links.Length == 0, nameof(definition.Links), "A ragdoll must contain
 41471        SwiftThrowHelper.ThrowIfArgument(
 41472            definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.SuppressAdjacentLinks
 41473                && definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.CollideAllLinks
 41474                && definition.SelfCollisionPolicy != RagdollSelfCollisionPolicy.SuppressAllLinks,
 41475            nameof(definition.SelfCollisionPolicy),
 41476            "Unsupported ragdoll self-collision policy.");
 477
 282478        for (int i = 0; i < definition.Links.Length; i++)
 479        {
 102480            RagdollLinkDefinition3D link = definition.Links[i];
 102481            SwiftThrowHelper.ThrowIfNull(link.Body, nameof(definition.Links));
 102482            SwiftThrowHelper.ThrowIfNull(link.Collider, nameof(definition.Links));
 102483            SwiftThrowHelper.ThrowIfArgument(
 102484                !ReferenceEquals(link.Body.Context, _context),
 102485                nameof(definition.Links),
 102486                "All ragdoll links must belong to this context.");
 102487            SwiftThrowHelper.ThrowIfArgument(
 102488                !link.Body.Active,
 102489                nameof(definition.Links),
 102490                "Ragdoll links must have active 3D colliders.");
 102491            SwiftThrowHelper.ThrowIfArgument(
 102492                !ReferenceEquals(link.Body.Collider, link.Collider),
 102493                nameof(definition.Links),
 102494                "Ragdoll link collider must match the link body's collider.");
 102495            SwiftThrowHelper.ThrowIfArgument(
 102496                _ragdollByBody.ContainsKey(link.Body),
 102497                nameof(definition.Links),
 102498                "A body cannot belong to more than one registered ragdoll.");
 499
 484500            for (int j = i + 1; j < definition.Links.Length; j++)
 501            {
 142502                SwiftThrowHelper.ThrowIfArgument(
 142503                    link.LinkId == definition.Links[j].LinkId,
 142504                    nameof(definition.Links),
 142505                    "Ragdoll link IDs must be unique.");
 142506                SwiftThrowHelper.ThrowIfArgument(
 142507                    ReferenceEquals(link.Body, definition.Links[j].Body),
 142508                    nameof(definition.Links),
 142509                    "Ragdoll bodies must be unique.");
 510            }
 511        }
 512
 196513        for (int i = 0; i < definition.Joints.Length; i++)
 514        {
 61515            RagdollJointDefinition3D joint = definition.Joints[i];
 61516            SolidBody bodyA = ResolveRagdollLink(definition.Links, joint.LinkAId);
 61517            SolidBody bodyB = ResolveRagdollLink(definition.Links, joint.LinkBId);
 60518            SwiftThrowHelper.ThrowIfArgument(
 60519                joint.LinkAId == joint.LinkBId,
 60520                nameof(definition.Joints),
 60521                "A ragdoll joint cannot link a body to itself.");
 60522            JointCollisionPolicy collisionPolicy = definition.SelfCollisionPolicy == RagdollSelfCollisionPolicy.CollideA
 60523                ? JointCollisionPolicy.Collide
 60524                : joint.CollisionPolicy;
 60525            ValidateDefinition(new JointDefinition3D(
 60526                bodyA,
 60527                bodyB,
 60528                joint.LocalFrameA,
 60529                joint.LocalFrameB,
 60530                joint.Type,
 60531                joint.Limits,
 60532                joint.Motor,
 60533                collisionPolicy));
 534        }
 37535    }
 536
 537    private static SolidBody ResolveRagdollLink(RagdollLinkDefinition3D[] links, int linkId)
 538    {
 1232539        for (int i = 0; i < links.Length; i++)
 540        {
 615541            if (links[i].LinkId == linkId)
 237542                return links[i].Body;
 543        }
 544
 1545        throw new ArgumentException("Ragdoll joint references an unknown link ID.", nameof(linkId));
 546    }
 547
 548    private static bool HasKinematicLink(SolidBody[] links)
 549    {
 250550        for (int i = 0; i < links.Length; i++)
 551        {
 92552            if (links[i].IsKinematic)
 4553                return true;
 554        }
 555
 33556        return false;
 557    }
 558
 559    private void AddAllRagdollPairSuppressions(SolidBody[] links)
 560    {
 70561        for (int i = 0; i < links.Length; i++)
 562        {
 198563            for (int j = i + 1; j < links.Length; j++)
 70564                AddSuppressedColliderPair(links[i].Collider, links[j].Collider);
 565        }
 6566    }
 567
 568    private void RemoveRagdollCore(RagdollRuntime3D ragdoll)
 569    {
 10570        _ragdollsById.Remove(ragdoll.Id);
 52571        for (int i = 0; i < ragdoll.LinkCount; i++)
 16572            _ragdollByBody.Remove(ragdoll.GetLink(i));
 573
 10574        if (ragdoll.SelfCollisionPolicy == RagdollSelfCollisionPolicy.SuppressAllLinks)
 575        {
 8576            for (int i = 0; i < ragdoll.LinkCount; i++)
 577            {
 12578                for (int j = i + 1; j < ragdoll.LinkCount; j++)
 579                {
 3580                    RemoveSuppressedColliderPair(
 3581                        ragdoll.GetLink(i).Collider,
 3582                        ragdoll.GetLink(j).Collider);
 583                }
 584            }
 585        }
 586
 10587        UnlinkRagdoll(ragdoll);
 10588        ragdoll.Invalidate();
 589
 32590        for (int i = 0; i < ragdoll.JointCount; i++)
 591        {
 6592            Joint3D joint = ragdoll.GetJoint(i);
 6593            joint.OwningRagdoll = null;
 6594            RemoveJointCore(joint);
 595        }
 10596    }
 597
 598    private void AppendRagdoll(RagdollRuntime3D ragdoll)
 599    {
 37600        ragdoll.PreviousRegistered = _lastRagdoll;
 37601        if (_lastRagdoll == null)
 30602            _firstRagdoll = ragdoll;
 603        else
 7604            _lastRagdoll.NextRegistered = ragdoll;
 605
 37606        _lastRagdoll = ragdoll;
 37607        _registeredRagdollCount++;
 37608    }
 609
 610    private void UnlinkRagdoll(RagdollRuntime3D ragdoll)
 611    {
 10612        if (ragdoll.PreviousRegistered == null)
 9613            _firstRagdoll = ragdoll.NextRegistered;
 614        else
 1615            ragdoll.PreviousRegistered.NextRegistered = ragdoll.NextRegistered;
 616
 10617        if (ragdoll.NextRegistered == null)
 5618            _lastRagdoll = ragdoll.PreviousRegistered;
 619        else
 5620            ragdoll.NextRegistered.PreviousRegistered = ragdoll.PreviousRegistered;
 621
 10622        _registeredRagdollCount--;
 10623    }
 624
 625    private void AddSuppressedColliderPair(LSCollider colliderA, LSCollider colliderB)
 626    {
 370627        ulong key = CreateColliderPairKey(colliderA.Id, colliderB.Id);
 370628        if (_suppressedColliderPairs.TryGetValue(key, out int count))
 102629            _suppressedColliderPairs[key] = count + 1;
 630        else
 268631            _suppressedColliderPairs.Add(key, 1);
 268632    }
 633
 634    private void RemoveSuppressedColliderPair(LSCollider colliderA, LSCollider colliderB)
 635    {
 35636        ulong key = CreateColliderPairKey(colliderA.Id, colliderB.Id);
 35637        if (!_suppressedColliderPairs.TryGetValue(key, out int count))
 1638            return;
 639
 34640        if (count <= 1)
 27641            _suppressedColliderPairs.Remove(key);
 642        else
 7643            _suppressedColliderPairs[key] = count - 1;
 7644    }
 645}

Methods/Properties

.ctor(Gravitas.GravitasWorldContext)
get_Context()
get_RegisteredRagdollCount()
get_EnabledJointCount()
get_HasActiveJoints()
ClearSolverCachesForBody(Gravitas.SolidBody)
RegisterJoint(Gravitas.Constraints.JointDefinition3D&)
RemoveJoint(System.Int32)
RemoveJointCore(Gravitas.Constraints.Joint3D)
GetJoint(System.Int32)
TryGetJoint(System.Int32,Gravitas.Constraints.Joint3D&)
RegisterRagdoll(Gravitas.Constraints.RagdollDefinition3D)
RemoveRagdoll(System.Int32)
SetJointMotorTarget(System.Int32,FixedMathSharp.FixedQuaternion)
ClearJointMotorTarget(System.Int32)
SetRagdollPoseTargets(Gravitas.Constraints.RagdollRuntime3D,System.ReadOnlySpan`1<Gravitas.Constraints.JointMotor3D>)
ShouldExcludeLinkedCollision(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider)
TryGetJointForSolver(System.Int32,Gravitas.Constraints.Joint3D&)
RemoveJointsForBody(Gravitas.SolidBody)
UpdateJointCollisionPolicy(Gravitas.Constraints.Joint3D,Gravitas.Constraints.JointCollisionPolicy,Gravitas.Constraints.JointCollisionPolicy)
UpdateJointEnabledState(Gravitas.Constraints.Joint3D,System.Boolean,System.Boolean)
Reset()
ContributeReplayHash(Chronicler.ChronicleHashWriter&,Gravitas.GravitasReplayHashMode)
CreateColliderPairKey(System.Int32,System.Int32)
EnsureJointCapacity(System.Int32)
ValidateDefinition(Gravitas.Constraints.JointDefinition3D&)
ValidateRagdollDefinition(Gravitas.Constraints.RagdollDefinition3D)
ResolveRagdollLink(Gravitas.Constraints.RagdollLinkDefinition3D[],System.Int32)
HasKinematicLink(Gravitas.SolidBody[])
AddAllRagdollPairSuppressions(Gravitas.SolidBody[])
RemoveRagdollCore(Gravitas.Constraints.RagdollRuntime3D)
AppendRagdoll(Gravitas.Constraints.RagdollRuntime3D)
UnlinkRagdoll(Gravitas.Constraints.RagdollRuntime3D)
AddSuppressedColliderPair(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider)
RemoveSuppressedColliderPair(Gravitas.Colliders.LSCollider,Gravitas.Colliders.LSCollider)