< Summary

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

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Service()100%11100%
get_IsActive()100%11100%
get_LinkCount()100%11100%
get_JointCount()100%11100%
GetLink(...)100%11100%
GetJoint(...)100%11100%
ActivateDynamic()100%11100%
DeactivateToKinematic()100%11100%
RecordData(...)100%22100%
ApplyActivationState(...)100%1818100%
Invalidate()100%11100%

File(s)

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

#LineLine coverage
 1//=======================================================================
 2// RagdollRuntime2D.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;
 9
 10namespace Gravitas.Constraints;
 11
 12/// <summary>
 13/// Runtime handle for a context-owned pure 2D ragdoll articulation.
 14/// </summary>
 15public sealed class RagdollRuntime2D : IRecordable
 16{
 17    private readonly GravitasConstraint2DService _service;
 18    private readonly SolidBody2D[] _links;
 19    private readonly Joint2D[] _joints;
 20    private bool _isActive;
 21
 3022    internal RagdollRuntime2D(
 3023        GravitasConstraint2DService service,
 3024        int id,
 3025        SolidBody2D[] links,
 3026        Joint2D[] joints,
 3027        RagdollSelfCollisionPolicy selfCollisionPolicy,
 3028        bool startsActive)
 29    {
 3030        _service = service;
 3031        Id = id;
 3032        _links = links;
 3033        _joints = joints;
 3034        SelfCollisionPolicy = selfCollisionPolicy;
 3035        IsRegistered = true;
 3036        ApplyActivationState(startsActive, emitDiagnostics: false);
 3037    }
 38
 439    internal GravitasConstraint2DService Service => _service;
 40
 41    internal RagdollRuntime2D? PreviousRegistered { get; set; }
 42
 43    internal RagdollRuntime2D? NextRegistered { get; set; }
 44
 45    /// <summary>
 46    /// Gets this context-local ragdoll ID.
 47    /// </summary>
 48    public int Id { get; }
 49
 50    /// <summary>
 51    /// Gets ragdoll-internal collision filtering behavior.
 52    /// </summary>
 53    public RagdollSelfCollisionPolicy SelfCollisionPolicy { get; }
 54
 55    /// <summary>
 56    /// Gets whether this articulation remains registered with its owning constraint service.
 57    /// </summary>
 58    public bool IsRegistered { get; private set; }
 59
 60    /// <summary>
 61    /// Gets whether the ragdoll links are currently dynamic.
 62    /// </summary>
 2563    public bool IsActive => _isActive;
 64
 65    /// <summary>
 66    /// Gets the number of links in this ragdoll.
 67    /// </summary>
 5568    public int LinkCount => _links.Length;
 69
 70    /// <summary>
 71    /// Gets the number of joints in this ragdoll.
 72    /// </summary>
 3673    public int JointCount => _joints.Length;
 74
 75    /// <summary>
 76    /// Gets a ragdoll link by runtime index.
 77    /// </summary>
 2378    public SolidBody2D GetLink(int index) => _links[index];
 79
 80    /// <summary>
 81    /// Gets a ragdoll joint by runtime index.
 82    /// </summary>
 1883    public Joint2D GetJoint(int index) => _joints[index];
 84
 85    /// <summary>
 86    /// Switches all links to dynamic simulation and enables ragdoll joints.
 87    /// </summary>
 88    public void ActivateDynamic()
 89    {
 690        ApplyActivationState(isActive: true, emitDiagnostics: true);
 291    }
 92
 93    /// <summary>
 94    /// Switches all links to kinematic host control and disables ragdoll joints.
 95    /// </summary>
 96    public void DeactivateToKinematic()
 97    {
 598        ApplyActivationState(isActive: false, emitDiagnostics: true);
 499    }
 100
 101    /// <summary>
 102    /// Records runtime activation state for deterministic continuation.
 103    /// </summary>
 104    public void RecordData(IChronicler chronicler)
 105    {
 6106        SwiftThrowHelper.ThrowIfTrue(
 6107            !IsRegistered,
 6108            nameof(RagdollRuntime2D),
 6109            "Removed ragdolls cannot participate in serialization.");
 4110        bool isActive = _isActive;
 4111        RecordValues.Look(chronicler, ref isActive, "IsActive", false);
 4112        if (chronicler.Mode != SerializationMode.Loading)
 2113            return;
 114
 2115        ApplyActivationState(isActive, emitDiagnostics: true);
 2116    }
 117
 118    private void ApplyActivationState(bool isActive, bool emitDiagnostics)
 119    {
 43120        SwiftThrowHelper.ThrowIfTrue(
 43121            !IsRegistered,
 43122            nameof(RagdollRuntime2D),
 43123            "Removed ragdolls cannot mutate simulation state.");
 124
 39125        BodyMotionType targetMotionType = isActive
 39126            ? BodyMotionType.Dynamic
 39127            : BodyMotionType.Kinematic;
 128
 129        // Validate every link and publish every required host pose before any
 130        // runtime role or joint state changes. This keeps the ragdoll atomic if
 131        // a host transform cannot represent one of the authoritative poses.
 218132        for (int i = 0; i < _links.Length; i++)
 71133            _links[i].PrepareMotionTypeTransition(targetMotionType);
 134
 214135        for (int i = 0; i < _links.Length; i++)
 136        {
 69137            if (_links[i].MotionType != targetMotionType)
 15138                _links[i].CommitMotionTypeTransition(targetMotionType);
 139
 69140            if (isActive)
 50141                _links[i].Wake();
 142        }
 143
 38144        if (isActive)
 145        {
 100146            for (int i = 0; i < _joints.Length; i++)
 22147                _joints[i].IsEnabled = true;
 148        }
 149        else
 150        {
 38151            for (int i = 0; i < _joints.Length; i++)
 9152                _joints[i].IsEnabled = false;
 153        }
 154
 38155        _isActive = isActive;
 38156        if (emitDiagnostics)
 8157            _links[0].Context.Diagnostics.EmitRagdollActivated(Id, LinkCount, JointCount, isActive);
 38158    }
 159
 160    internal void Invalidate()
 161    {
 30162        IsRegistered = false;
 30163        _isActive = false;
 30164        PreviousRegistered = null;
 30165        NextRegistered = null;
 30166    }
 167}