< Summary

Line coverage
100%
Covered lines: 1021
Uncovered lines: 0
Coverable lines: 1021
Total lines: 2144
Line coverage: 100%
Branch coverage
100%
Covered branches: 348
Total branches: 348
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: .ctor()100%11100%
File 1: get_IsActive()100%11100%
File 1: set_IsActive(...)100%1414100%
File 1: get_IsTrigger()100%11100%
File 1: set_IsTrigger(...)100%11100%
File 1: get_Id()100%11100%
File 1: get_ReplayOrdinal()100%11100%
File 1: get_LifetimeVersion()100%11100%
File 1: get_IsDeactivationInProgress()100%11100%
File 1: get_ServiceRefreshIndex()100%11100%
File 1: get_AgentOrNull()100%11100%
File 1: get_Context()100%11100%
File 1: get_Body()100%11100%
File 1: get_IsStatic()100%22100%
File 1: get_RequiresServiceSideRefresh()100%22100%
File 1: get_RuntimeShapeVersion()100%11100%
File 1: get_HasHostBinding()100%11100%
File 1: get_CompoundOwner()100%11100%
File 1: get_Position()100%66100%
File 1: set_Position(...)100%22100%
File 1: get_Rotation()100%22100%
File 1: set_Rotation(...)100%22100%
File 1: get_Velocity()100%22100%
File 1: get_World()100%11100%
File 1: get_Transform()100%1212100%
File 1: get_Layer()100%11100%
File 1: set_Layer(...)100%11100%
File 1: get_IgnoredCollisionLayers()100%11100%
File 1: set_IgnoredCollisionLayers(...)100%44100%
File 1: get_Material()100%11100%
File 1: set_Material(...)100%44100%
File 1: get_IsPartitioned()100%11100%
File 1: get_PartitionChanged()100%11100%
File 1: set_PartitionChanged(...)100%11100%
File 1: get_BroadPhaseVersion()100%11100%
File 1: get_LocalOffset()100%11100%
File 1: set_LocalOffset(...)100%22100%
File 1: get_Radius()100%11100%
File 1: set_Radius(...)100%22100%
File 1: get_ScaledRadius()100%11100%
File 1: get_ScaledRadiusSqr()100%11100%
File 1: get_Size()100%11100%
File 1: set_Size(...)100%22100%
File 1: get_LocalScale()100%11100%
File 1: TryGetLocalScale(...)100%22100%
File 1: get_ScaledOffset()100%11100%
File 1: TryGetScaledOffset(...)100%11100%
File 1: get_Center()100%22100%
File 1: get_Bounds()100%11100%
File 1: get_BoundsMin()100%11100%
File 1: get_BoundsMax()100%11100%
File 1: get_PartitionCoordinates()100%11100%
File 1: get_PartitionKind()100%11100%
File 1: get_IsMixedPartitioned()100%11100%
File 1: get_MixedPartitionCoordinates()100%11100%
File 1: get_MixedPartitionKind()100%11100%
File 1: get_RaycastVersion()100%11100%
File 1: set_RaycastVersion(...)100%11100%
File 1: get_CircleQueryVersion()100%11100%
File 1: set_CircleQueryVersion(...)100%11100%
File 1: get_IsChild()100%11100%
File 1: get_IsParent()100%11100%
File 1: get_ParentId()100%11100%
File 1: get_Parent3D()100%11100%
File 1: get_Parent2D()100%11100%
File 1: get_TopParent3D()100%11100%
File 1: get_TopParent2D()100%11100%
File 1: get_HierarchyChildCount()100%11100%
File 1: get_HierarchyKey()100%22100%
File 1: get_ParentKey()100%11100%
File 1: get_TopParentKey()100%11100%
File 1: get_HierarchyState()100%11100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.get_HierarchyKey()100%11100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.get_HierarchyParent()100%11100%
File 1: Initialize(...)100%11100%
File 1: InitializeWithNoBody(...)100%44100%
File 1: PreflightBodyInitialization(...)100%11100%
File 1: PreflightInitialization(...)100%11100%
File 1: InitCore(...)100%11100%
File 1: OnBeforeInitialize(...)100%11100%
File 1: OnInitialize()100%11100%
File 1: ValidateCurrentRuntimeTransform()100%11100%
File 1: InitialPartition()100%44100%
File 1: Simulate()100%88100%
File 1: UpdatePartition()100%44100%
File 1: SetBodylessWorldPose(...)100%1010100%
File 1: SetParent(...)100%11100%
File 1: SetParent(...)100%11100%
File 1: ClearParent()100%11100%
File 1: IsSibling(...)100%11100%
File 1: ExcludesMixedCollisionWith(...)100%11100%
File 1: RebuildRuntimeShapeState(...)100%88100%
File 1: RebuildRuntimeShapeOnly(...)100%11100%
File 1: MarkShapeDirty()100%44100%
File 1: MarkBroadPhaseChanged()100%11100%
File 1: OnRadiusChanged()100%11100%
File 1: OnMaterialChanged()100%11100%
File 1: NormalizeSize(...)100%11100%
File 1: ValidateSize(...)100%44100%
File 1: TryGetPlanarSurfaceNormal(...)100%11100%
File 1: IsPositionInBounds(...)100%1010100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.AddChild(...)100%11100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.RemoveChild(...)100%11100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.ClearParentReference()100%11100%
File 1: Gravitas.Colliders.IColliderHierarchyNode.TryGetHierarchyColliderByKey(...)100%1212100%
File 1: SetPhysicsState(...)100%11100%
File 1: SetServiceIndex(...)100%11100%
File 1: SetReplayOrdinal(...)100%11100%
File 1: SetServiceRefreshIndex(...)100%11100%
File 1: ClearServiceRefreshIndex()100%11100%
File 1: ClearPhysicsState()100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryState(...)100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.get_ServiceIndex()100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.get_ReplayOrder()100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryServiceIndex(...)100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryReplayOrdinal(...)100%11100%
File 1: Gravitas.Colliders.IPhysicsColliderRegistryItem.ClearRegistryState()100%11100%
File 1: GetOrCreateMixedPartitionCoordinates()100%22100%
File 1: MatchesPartitionGridBounds(...)100%66100%
File 1: MarkUnpartitioned()100%11100%
File 1: ClearPartitionCoordinates()100%11100%
File 1: MatchesMixedPartitionGridBounds(...)100%66100%
File 1: MarkMixedPartitioned(...)100%11100%
File 1: MarkMixedUnpartitioned()100%11100%
File 1: ClearMixedPartitionCoordinates()100%11100%
File 1: IgnoresCollisionLayer(...)100%11100%
File 2: get_CollisionPairCount()100%11100%
File 2: get_CollisionPairHolderCount()100%11100%
File 2: get_CollisionPairs()100%11100%
File 2: get_CollisionPairHolders()100%11100%
File 2: NotifyContact(...)100%22100%
File 2: NotifyContact(...)100%5050100%
File 2: NotifyMixedContact(...)100%11100%
File 2: NotifyMixedContact(...)100%4646100%
File 3: GetFrontalArea(...)100%11100%
File 3: CalculateLocalCenterOfMassOffset()100%11100%
File 3: CalculateLocalMassPoint()100%11100%
File 3: CalculatePreparedLocalMassPoint()100%11100%
File 3: get_SupportsMassProperties()100%11100%
File 3: CalculateInertiaTensor(...)100%66100%
File 3: TransformRelativeMassPropertyPointExact(...)100%22100%
File 3: TransformPreparedRelativeMassPropertyPointExact(...)100%22100%
File 3: get_CompoundLocalRotation()100%11100%
File 4: ContributeReplayHash(...)100%22100%
File 4: ContributeShapeReplayHash(...)100%1818100%
File 4: WriteReplayHierarchyKey(...)100%22100%
File 4: TryResolveReplayHierarchyOrdinal(...)100%66100%
File 4: ContributeCompoundPartReplayHash(...)100%22100%
File 4: ContributeShapeDefinitionReplayHash(...)100%66100%
File 4: WriteMaterial(...)100%11100%
File 5: SetPreviousGridBounds()100%11100%
File 5: TryGetCollisionPair(...)100%11100%
File 5: TryAddCollisionPair(...)100%11100%
File 5: TryRemoveCollisionPair(...)100%11100%
File 5: TryAddCollisionPairHolder(...)100%11100%
File 5: TryRemoveCollisionPairHolder(...)100%11100%
File 5: ClearCollisionPairState()100%11100%
File 5: ClearRuntimeRelationships()100%11100%
File 5: Deactivate()100%22100%
File 5: DeactivateRuntimeRegistration()100%22100%
File 5: ClearBindingState()100%11100%
File 5: ClearChildParentReferences()100%66100%
File 5: BindContext(...)100%22100%
File 5: ReserveCompoundPart(...)100%22100%
File 5: ThrowIfCompoundPartLifecycle(...)100%11100%
File 5: SetTrigger(...)100%44100%
File 5: ThrowIfCannotEnableTrigger(...)100%11100%
File 5: ThrowIfTriggerWouldAttachToBody(...)100%11100%
File 5: ThrowIfLoadedTriggerHasBody(...)100%22100%
File 5: TryGetBoundContext(...)100%11100%
File 6: RecordData(...)100%22100%
File 6: ApplyLoadedState()100%1212100%
File 7: .ctor()100%11100%
File 7: get_HasCommittedShape()100%11100%
File 7: get_PreparedContext()100%11100%
File 7: get_PreparedShapeBounds()100%11100%
File 7: get_CanonicalCenteredProxyRadius()100%11100%
File 7: get_CanonicalGroundProbeRadius()100%11100%
File 7: get_CanonicalCenter()100%11100%
File 7: get_CanonicalRotation()100%11100%
File 7: TryGetCommittedOwnerScale(...)100%22100%
File 7: GetCurrentOwnerScale()100%44100%
File 7: GetCurrentPartScale()100%44100%
File 7: GetCurrentShapeScales(...)100%11100%
File 7: TryGetCurrentScaledOffset(...)100%22100%
File 7: GetCurrentScaledOffset()100%11100%
File 7: GetCurrentScaledRadius()100%11100%
File 7: CreateStandaloneSnapshot(...)100%22100%
File 7: CaptureShapeSnapshot()100%22100%
File 7: CreateCompoundPartSnapshot(...)100%11100%
File 7: PrepareRuntimeShape(...)100%66100%
File 7: PublishPreparedShape()100%11100%
File 7: TryPrepareBodyPose(...)100%11100%
File 7: PublishPreparedBodyPose()100%11100%
File 7: PublishPreparedExplicitBodyPose()100%11100%
File 7: PrepareStandaloneInitialization(...)100%11100%
File 7: PrepareCompoundPart(...)100%22100%
File 7: PublishCompoundPart(...)100%11100%
File 7: SetPreparedBounds(...)100%11100%
File 7: ValidateShapeCandidate(...)100%11100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.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 FixedMathSharp.Geometry;
 11using Gravitas.CollisionHandling;
 12using Gravitas.Materials;
 13using Gravitas.Queries;
 14using Gravitas.Support;
 15using GridForge.Grids;
 16using GridForge.Spatial;
 17using SwiftCollections;
 18using System;
 19using System.Runtime.CompilerServices;
 20
 21namespace Gravitas.Colliders;
 22
 23/// <summary>
 24/// Common runtime type for the closed set of Gravitas-owned 3D collider
 25/// shapes. Use <see cref="ColliderShapeDefinition.CreateCollider"/> when
 26/// constructing from engine-adapter shape data.
 27/// </summary>
 28public abstract partial class LSCollider : IRecordable, IColliderHierarchyNode, IPhysicsColliderRegistryItem
 29{
 1220430    internal LSCollider() { }
 31
 32    #region Fields and Properties
 33
 34    /// <summary>Controls collider debug diagnostics.</summary>
 35    protected bool _debug;
 36    /// <summary>Controls collider shape debug drawing.</summary>
 37    protected bool _drawShape;
 38    private bool _drawPartitions;
 39    private bool _drawBoundingBox;
 40
 610241    private bool _active = true;
 42    private bool _deactivationInProgress;
 43    /// <summary>Gets or sets whether this collider participates in runtime physics.</summary>
 44    public bool IsActive
 45    {
 46        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 38345347        get => _active;
 48        set
 49        {
 1850            ThrowIfCompoundPartLifecycle(nameof(IsActive));
 51
 1852            if (_active == value)
 253                return;
 54
 1655            if (_context == null || _id < 0)
 56            {
 257                _active = value;
 258                return;
 59            }
 60
 1461            if (value)
 62            {
 563                RebuildRuntimeShapeState();
 564                _active = true;
 565                InitialPartition();
 566                if (_context.Settings.RuntimeMode.RunsMixedContacts())
 367                    _context.MixedCollisions.Refresh3DColliderPartition(this);
 568                return;
 69            }
 70
 971            _active = false;
 972            if (IsPartitioned)
 873                _context.Collisions.ClearPartitionedObject(this, force: true);
 74
 975            if (IsMixedPartitioned)
 76            {
 377                _context.MixedCollisions.ClearPartitioned3DCollider(this, force: true);
 378                MarkMixedUnpartitioned();
 379                ClearMixedPartitionCoordinates();
 80            }
 981        }
 82    }
 83
 84    private bool _isTrigger;
 85
 86    /// <summary>
 87    /// Gets or sets whether this bodyless collider is a trigger volume.
 88    /// Trigger volumes raise trigger enter/stay/exit callbacks for valid overlap
 89    /// pairs and never apply physical response.
 90    /// </summary>
 91    public bool IsTrigger
 92    {
 93        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 4831394        get => _isTrigger;
 4195        set => SetTrigger(value);
 96    }
 97
 610298    private int _id = -1;
 99    /// <summary>Gets the context-local runtime collider identifier.</summary>
 4807769100    public int Id => _id;
 101
 6102102    private int _serviceIndex = -1;
 103
 6102104    private int _replayOrder = -1;
 105
 6102106    private int _replayOrdinal = -1;
 2390107    internal int ReplayOrdinal => _replayOrdinal;
 108
 109    private long _lifetimeVersion;
 75031110    internal long LifetimeVersion => _lifetimeVersion;
 111
 346783112    internal bool IsDeactivationInProgress => _deactivationInProgress;
 113
 6102114    private int _serviceRefreshIndex = -1;
 4795115    internal int ServiceRefreshIndex => _serviceRefreshIndex;
 116
 117    private IMatterAgent? _agent;
 5253118    internal IMatterAgent? AgentOrNull => _agent;
 119
 120    private GravitasWorldContext? _context;
 121    /// <summary>Gets the world context to which this collider is bound.</summary>
 122    public GravitasWorldContext Context
 123    {
 124        get
 125        {
 137089126            SwiftThrowHelper.ThrowIfTrue(
 137089127                _context == null,
 137089128                nameof(LSCollider),
 137089129                "Collider is not bound to a GravitasWorldContext.");
 137087130            return _context!;
 131        }
 132    }
 133
 134    private SolidBody? _body;
 135    /// <summary>Gets the owning 3D body, or <see langword="null"/> for a bodyless collider.</summary>
 710331136    public SolidBody? Body => _body;
 137
 138    /// <summary>
 139    /// Gets whether this collider is bodyless or belongs to an explicit static
 140    /// body role.
 141    /// </summary>
 102460142    public bool IsStatic => _body == null || _body.IsStatic;
 143
 5749144    internal bool RequiresServiceSideRefresh => _body == null || _body.DynamicId < 0;
 145
 146    private LSCompoundCollider? _compoundOwner;
 6102147    private FixedQuaternion _compoundLocalRotation = FixedQuaternion.Identity;
 6102148    private Vector3d _compoundLocalScale = Vector3d.One;
 149
 6102150    private readonly ColliderRuntimeShapeState<ColliderShapeSnapshot> _runtimeShapeState = new();
 151    private ColliderPartitionState _partitionState;
 152    private ColliderPartitionState _mixedPartitionState;
 153    private ColliderQueryState _queryState;
 154    private ColliderPairState<CollisionPair> _pairState;
 155    private ColliderHierarchyState _hierarchyState;
 156
 1712157    internal uint RuntimeShapeVersion => _runtimeShapeState.RuntimeVersion;
 158
 6066159    internal bool HasHostBinding => _agent != null;
 160
 832161    internal LSCompoundCollider? CompoundOwner => _compoundOwner;
 162
 163    /// <summary>Gets the runtime world position, or sets it for a bodyless collider.</summary>
 164    public Vector3d Position
 165    {
 2261166        get => _compoundOwner?.Center
 2261167            ?? Body?.Position3d
 2261168            ?? _agent?.Transform.WorldPosition
 2261169            ?? throw new InvalidOperationException("Collider has no body or static transform.");
 170        set
 171        {
 14172            SwiftThrowHelper.ThrowIfTrue(
 14173                _compoundOwner != null,
 14174                nameof(Position),
 14175                "Compound collider parts inherit position from their owning compound collider.");
 13176            SwiftThrowHelper.ThrowIfTrue(
 13177                _agent == null,
 13178                nameof(Position),
 13179                "Collider is not bound to a static transform.");
 12180            SwiftThrowHelper.ThrowIfTrue(
 12181                _body != null,
 12182                nameof(Position),
 12183                "Body-owned collider positions must be changed through their SolidBody.");
 184
 11185            if (_agent.Transform.WorldPosition == value)
 1186                return;
 10187            SetBodylessWorldPose(value, default, setRotation: false, nameof(Position));
 7188        }
 189    }
 190
 191    /// <summary>Gets the committed world rotation, or sets it for a bodyless collider.</summary>
 192    public FixedQuaternion Rotation
 193    {
 138403194        get => _hasCommittedShape
 138403195            ? _committedRotation
 138403196            : throw new InvalidOperationException(
 138403197                "Collider has no committed runtime shape.");
 198        set
 199        {
 10200            SwiftThrowHelper.ThrowIfTrue(
 10201                _compoundOwner != null,
 10202                nameof(Rotation),
 10203                "Compound collider parts inherit rotation from their owning compound collider.");
 9204            SwiftThrowHelper.ThrowIfTrue(
 9205                _agent == null,
 9206                nameof(Rotation),
 9207                "Collider is not bound to a static transform.");
 8208            SwiftThrowHelper.ThrowIfTrue(
 8209                _body != null,
 8210                nameof(Rotation),
 8211                "Body-owned collider rotations must be changed through their SolidBody.");
 212
 7213            if (_agent.Transform.WorldRotation == value)
 1214                return;
 6215            SetBodylessWorldPose(default, value, setRotation: true, nameof(Rotation));
 4216        }
 217    }
 218
 219    /// <summary>Gets the owning body's linear velocity, or zero for a bodyless collider.</summary>
 3366220    public Vector3d Velocity => Body?.LinearVelocity ?? Vector3d.Zero;
 221
 222    /// <summary>Gets the GridForge world owned by this collider's context.</summary>
 6223    public GridWorld World => Context.World;
 224
 225    /// <summary>Gets the transform that supplies this collider's runtime pose.</summary>
 306226    public FixedTransform Transform => _compoundOwner?.Transform
 306227        ?? Body?.PositionTransform
 306228        ?? _agent?.Transform
 306229        ?? throw new InvalidOperationException("Collider has no body or static transform.");
 230
 231    private PhysicsLayer _layer = new();
 6102232    private PhysicsLayerMask _ignoredCollisionLayers = PhysicsLayerMask.None;
 233
 234    /// <summary>Gets or sets the single physics layer used for collision and query filtering.</summary>
 235    public PhysicsLayer Layer
 236    {
 237        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 865631238        get => _layer;
 239        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 49240        set => _layer = value;
 241    }
 242
 243    /// <summary>
 244    /// Gets or sets physical layers this collider ignores for collider-to-collider
 245    /// interactions. Public queries continue to use the caller's query mask.
 246    /// </summary>
 247    public PhysicsLayerMask IgnoredCollisionLayers
 248    {
 249        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 9250        get => _ignoredCollisionLayers;
 251        set
 252        {
 22253            if (_ignoredCollisionLayers == value)
 1254                return;
 255
 21256            _ignoredCollisionLayers = value;
 21257            _body?.Wake();
 20258        }
 259    }
 260
 6102261    private PhysicsMaterial _material = PhysicsMaterial.Default;
 262
 263    /// <summary>
 264    /// Gets or sets the deterministic surface material used by collision
 265    /// response for this collider.
 266    /// </summary>
 267    public PhysicsMaterial Material
 268    {
 269        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 22217270        get => _material;
 271        set
 272        {
 1271273            if (_material == value)
 600274                return;
 275
 671276            _material = value;
 671277            OnMaterialChanged();
 671278            _body?.Wake();
 178279        }
 280    }
 281
 282    /// <summary>Gets whether this collider currently has 3D broad-phase partition membership.</summary>
 48163283    public bool IsPartitioned => _partitionState.IsPartitioned;
 284
 285    /// <summary>
 286    /// Used for preventing culling for the first frame this object is added to a new partition node.
 287    /// </summary>
 288    public bool PartitionChanged
 289    {
 290        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 6181291        get => _partitionState.PartitionChanged;
 292        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 27279293        set => _partitionState.PartitionChanged = value;
 294    }
 295
 16022296    internal uint BroadPhaseVersion => _partitionState.BroadPhaseVersion;
 297
 298    /// <summary>
 299    /// Center of collider in local space, used for calculating bounds and offsets. Should be set in the Setup method of
 300    /// </summary>
 301    protected Vector3d _offset;
 302
 303    /// <summary>
 304    /// Gets or sets the unscaled local center offset used by bounds and shape-derived state.
 305    /// </summary>
 306    public Vector3d LocalOffset
 307    {
 308        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 35482309        get => _offset;
 310        set
 311        {
 346312            if (_offset == value)
 84313                return;
 314
 262315            _offset = value;
 262316            MarkShapeDirty();
 262317        }
 318    }
 319
 320    /// <summary>Gets the runtime 3D shape family.</summary>
 321    public abstract ColliderType Shape { get; }
 322    /// <summary>Gets the deterministic narrow-phase ordering priority.</summary>
 323    public abstract int Priority { get; }
 324
 325    /// <summary>Stores the unscaled radius for radius-based collider shapes.</summary>
 6102326    protected Fixed64 _radius = Fixed64.Half;
 327
 328    /// <summary>
 329    /// Gets or sets the unscaled shape radius used by radius-based colliders.
 330    /// </summary>
 331    public Fixed64 Radius
 332    {
 333        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 28334        get => _radius;
 335        set
 336        {
 726337            SwiftThrowHelper.ThrowIfArgument(
 726338                value <= Fixed64.Zero,
 726339                nameof(value),
 726340                "Collider radius must be greater than zero.");
 341
 726342            if (_radius == value)
 266343                return;
 344
 460345            _radius = value;
 460346            OnRadiusChanged();
 460347            MarkShapeDirty();
 460348        }
 349    }
 350
 351    /// <summary>
 352    /// Gets the bounding circle radius.
 353    /// For boxes, this is half of the diagonal length of the cube
 354    /// </summary>
 355    /// <value>The radius.</value>
 5356    public virtual Fixed64 ScaledRadius => GetCurrentScaledRadius();
 357
 358    /// <summary>Gets the squared scaled bounding radius.</summary>
 10094359    public Fixed64 ScaledRadiusSqr => ScaledRadius * ScaledRadius;
 360
 361    /// <summary>Stores the unscaled local collider size.</summary>
 6102362    protected Vector3d _size = Vector3d.One;
 363
 364    /// <summary>
 365    /// Gets or sets the unscaled local size used when rebuilding collider bounds.
 366    /// </summary>
 367    public Vector3d Size
 368    {
 369        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 27370        get => _size;
 371        set
 372        {
 1771373            ValidateSize(value);
 1765374            Vector3d normalizedSize = NormalizeSize(value);
 1765375            if (_size == normalizedSize)
 851376                return;
 377
 914378            _size = normalizedSize;
 914379            MarkShapeDirty();
 914380        }
 381    }
 382
 383    /// <summary>Gets the committed shape-specific measure used as the frontal-area fallback.</summary>
 384    public virtual Fixed64 Area { get; protected set; } = Fixed64.Zero;
 385
 386    #region Grid & Partition Bounds
 387
 388    /// <summary>Gets the combined owner and compound-part scale.</summary>
 389    public virtual Vector3d LocalScale
 390    {
 391        get
 392        {
 3393            bool representable = TryGetLocalScale(out Vector3d scale);
 3394            SwiftThrowHelper.ThrowIfTrue(
 3395                !representable,
 3396                nameof(LocalScale),
 3397                "The combined 3D collider scale is outside the Fixed64 coordinate domain.");
 2398            return scale;
 399        }
 400    }
 401
 402    /// <summary>
 403    /// Attempts to materialize the combined owner and compound-part scale.
 404    /// Shape preparation retains those factors separately and does not require
 405    /// their product to be representable.
 406    /// </summary>
 407    public bool TryGetLocalScale(out Vector3d scale)
 408    {
 6409        GetCurrentShapeScales(
 6410            out Vector3d ownerScale,
 6411            out Vector3d partScale);
 412
 6413        bool representable = Fixed64.TryMultiplyDivide(
 6414                ownerScale.X,
 6415                partScale.X,
 6416                Fixed64.One,
 6417                out Fixed64 x)
 6418            & Fixed64.TryMultiplyDivide(
 6419                ownerScale.Y,
 6420                partScale.Y,
 6421                Fixed64.One,
 6422                out Fixed64 y)
 6423            & Fixed64.TryMultiplyDivide(
 6424                ownerScale.Z,
 6425                partScale.Z,
 6426                Fixed64.One,
 6427                out Fixed64 z);
 6428        scale = representable ? new Vector3d(x, y, z) : default;
 6429        return representable;
 430    }
 431
 432    /// <summary>
 433    /// Gets the component-scaled local offset.
 434    /// </summary>
 435    /// <exception cref="InvalidOperationException">
 436    /// The scaled offset itself is outside the Fixed64 coordinate domain. The
 437    /// collider may still have a representable world center through exact
 438    /// transform cancellation.
 439    /// </exception>
 10440    public Vector3d ScaledOffset => GetCurrentScaledOffset();
 441
 442    /// <summary>
 443    /// Attempts to materialize the component-scaled local offset independently
 444    /// from the collider's complete world transform.
 445    /// </summary>
 446    public bool TryGetScaledOffset(out Vector3d scaledOffset) =>
 2447        TryGetCurrentScaledOffset(out scaledOffset);
 448
 449    /// <summary>
 450    /// Bodies position in world space + collider offset (center) value
 451    /// </summary>
 102582452    public Vector3d Center => _hasCommittedShape
 102582453        ? _committedCenter
 102582454        : throw new InvalidOperationException(
 102582455            "Collider has no committed runtime shape.");
 456
 457    /// <summary>Stores the committed world-space axis-aligned bounds.</summary>
 458    protected FixedBoundBox _bounds;
 459    /// <summary>Gets the committed world-space axis-aligned bounds.</summary>
 16136460    public FixedBoundBox Bounds => _bounds;
 461    /// <summary>Gets the minimum corner of <see cref="Bounds"/>.</summary>
 3594258462    public Vector3d BoundsMin => _bounds.Min;
 463    /// <summary>Gets the maximum corner of <see cref="Bounds"/>.</summary>
 3496650464    public Vector3d BoundsMax => _bounds.Max;
 465
 1034047466    internal SwiftList<WorldVoxelIndex>? PartitionCoordinates => _partitionState.Coordinates;
 467
 19695468    internal int PartitionKind => _partitionState.LastPartitionKind;
 469
 3798470    internal bool IsMixedPartitioned => _mixedPartitionState.IsPartitioned;
 471
 1225472    internal SwiftList<WorldVoxelIndex>? MixedPartitionCoordinates => _mixedPartitionState.Coordinates;
 473
 1943474    internal int MixedPartitionKind => _mixedPartitionState.LastPartitionKind;
 475
 476    #endregion
 477
 478    internal uint RaycastVersion
 479    {
 480        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 215117481        get => _queryState.RaycastVersion;
 482        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 11338483        set => _queryState.RaycastVersion = value;
 484    }
 485
 486    internal uint CircleQueryVersion
 487    {
 488        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 24451489        get => _queryState.CircleQueryVersion;
 490        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 741491        set => _queryState.CircleQueryVersion = value;
 492    }
 493
 494    /// <summary>Gets whether this collider has a hierarchy parent.</summary>
 2495    public bool IsChild => _hierarchyState.IsChild;
 496    /// <summary>Gets whether this collider is configured as or currently owns a hierarchy parent.</summary>
 4497    public bool IsParent => _hierarchyState.IsParent;
 498    /// <summary>Gets the context-local identifier of the parent collider, or -1 when unparented.</summary>
 9499    public int ParentId => ParentKey.Id;
 500    /// <summary>Gets the 3D parent collider, when the parent belongs to the 3D runtime.</summary>
 7501    public LSCollider? Parent3D => _hierarchyState.Parent as LSCollider;
 502    /// <summary>Gets the 2D parent collider, when the parent belongs to the 2D runtime.</summary>
 4503    public LSCollider2D? Parent2D => _hierarchyState.Parent as LSCollider2D;
 17054504    internal LSCollider? TopParent3D => _hierarchyState.TopParent as LSCollider;
 1505    internal LSCollider2D? TopParent2D => _hierarchyState.TopParent as LSCollider2D;
 2257506    internal int HierarchyChildCount => _hierarchyState.ChildCount;
 213504507    internal ColliderHierarchyKey HierarchyKey => Id >= 0 ? ColliderHierarchyKey.Create3D(Id) : ColliderHierarchyKey.Non
 2258508    internal ColliderHierarchyKey ParentKey => _hierarchyState.ParentKey;
 2248509    internal ColliderHierarchyKey TopParentKey => _hierarchyState.TopParentKey;
 1510    internal ColliderHierarchyState HierarchyState => _hierarchyState;
 141511    ColliderHierarchyKey IColliderHierarchyNode.HierarchyKey => HierarchyKey;
 43512    IColliderHierarchyNode? IColliderHierarchyNode.HierarchyParent => _hierarchyState.Parent;
 513
 514    #endregion
 515
 516    internal void Initialize(SolidBody body)
 517    {
 5083518        _body = body;
 5083519        InitCore(body.Agent);
 5083520    }
 521
 522    /// <summary>Binds and registers this collider as a bodyless runtime collider.</summary>
 523    public void InitializeWithNoBody(IMatterAgent agent)
 524    {
 610525        ThrowIfCompoundPartLifecycle(nameof(InitializeWithNoBody));
 610526        SwiftThrowHelper.ThrowIfNull(agent, nameof(agent));
 610527        SwiftThrowHelper.ThrowIfArgument(
 610528            Id >= 0 || (HasHostBinding && !ReferenceEquals(_agent, agent)),
 610529            nameof(agent),
 610530            "Collider is already registered or bound to another host agent.");
 608531        PreflightInitialization(agent);
 589532        InitCore(agent);
 589533    }
 534
 535    internal void PreflightBodyInitialization(
 536        SolidBody body,
 537        Vector3d requestedPosition,
 538        FixedQuaternion requestedRotation)
 539    {
 5089540        ThrowIfCompoundPartLifecycle(nameof(Initialize));
 5089541        SwiftThrowHelper.ThrowIfNull(body, nameof(body));
 5089542        ThrowIfTriggerWouldAttachToBody(nameof(Initialize));
 5088543        PreflightInitialization(
 5088544            body.Agent,
 5088545            useRequestedPose: true,
 5088546            requestedPosition,
 5088547            requestedRotation);
 5082548    }
 549
 550    private void PreflightInitialization(
 551        IMatterAgent agent,
 552        bool useRequestedPose = false,
 553        Vector3d requestedPosition = default,
 554        FixedQuaternion requestedRotation = default)
 555    {
 5696556        SwiftThrowHelper.ThrowIfNull(agent, nameof(agent));
 5696557        OnBeforeInitialize(agent);
 5696558        PrepareStandaloneInitialization(
 5696559            agent,
 5696560            useRequestedPose,
 5696561            requestedPosition,
 5696562            requestedRotation);
 5671563    }
 564
 565    private void InitCore(IMatterAgent agent)
 566    {
 5672567        _lifetimeVersion++;
 568
 5672569        _queryState.Reset();
 570
 5672571        _agent = agent;
 5672572        _active = true;
 5672573        _deactivationInProgress = false;
 5672574        BindContext(agent.Context);
 5672575        PublishPreparedShape();
 5672576        Context.Physics.AssimilateCollider(this);
 5672577        _hierarchyState.Initialize(_agent.IsParent);
 5672578        OnInitialize();
 579
 5672580        _partitionState.SetPreviousGridBounds(Vector3d.Zero, Vector3d.Zero);
 581
 5672582        InitialPartition();
 5672583    }
 584
 585    /// <summary>Validates or prepares derived shape state before runtime registration.</summary>
 5696586    protected virtual void OnBeforeInitialize(IMatterAgent agent) { }
 587
 588    /// <summary>Runs derived initialization after runtime registration.</summary>
 5672589    protected virtual void OnInitialize() { }
 590
 591    internal void ValidateCurrentRuntimeTransform()
 592    {
 112593        ColliderShapeSnapshot snapshot = CaptureShapeSnapshot();
 109594        PrepareRuntimeShape(
 109595            snapshot,
 109596            requireRepresentableMassPoint: true);
 109597    }
 598
 599    private void InitialPartition()
 600    {
 6120601        RebuildRuntimeShapeState();
 6120602        if (!IsActive)
 1603            return;
 604
 6119605        _partitionState.Coordinates ??= new();
 6119606        SwiftList<WorldVoxelIndex> partitionCoordinates = _partitionState.Coordinates!;
 6119607        Context.Collisions.PartitionObject(this, ref partitionCoordinates);
 6119608        _partitionState.Coordinates = partitionCoordinates;
 6119609        SetPreviousGridBounds();
 6119610        _partitionState.MarkPartitioned();
 6119611        MarkBroadPhaseChanged();
 6119612    }
 613
 614    /// <summary>Refreshes bodyless collider shape and broad-phase state for one simulation step.</summary>
 615    public void Simulate()
 616    {
 27700617        ThrowIfCompoundPartLifecycle(nameof(Simulate));
 27699618        if (!IsActive)
 3619            return;
 620
 27696621        if (!IsPartitioned)
 622        {
 438623            InitialPartition();
 438624            return;
 625        }
 626
 27258627        bool refreshPartition = RebuildRuntimeShapeState()
 27258628            || Context.Collisions.IsPartitionRefreshRequired(this);
 27253629        PartitionChanged = false;
 27253630        if (refreshPartition)
 17763631            UpdatePartition();
 27253632    }
 633
 634    private void UpdatePartition()
 635    {
 17817636        MarkBroadPhaseChanged();
 637
 17817638        if (!Context.Collisions.ClearPartitionedObject(this))
 29639            return;
 640
 17788641        SwiftList<WorldVoxelIndex> partitionCoordinates = _partitionState.Coordinates!;
 17788642        bool partitioned = Context.Collisions.PartitionObject(this, ref partitionCoordinates);
 17788643        _partitionState.Coordinates = partitionCoordinates;
 17788644        if (!partitioned)
 485645            return;
 646
 17303647        SetPreviousGridBounds();
 648
 17303649        _partitionState.MarkPartitioned();
 17303650    }
 651
 652    private void SetBodylessWorldPose(
 653        Vector3d position,
 654        FixedQuaternion rotation,
 655        bool setRotation,
 656        string operation)
 657    {
 16658        GravitasWorldContext context = _context!;
 16659        context.ThrowIfFixedStepMutationNotAllowed();
 15660        FixedTransform transform = _agent!.Transform;
 15661        Vector3d localPosition = transform.LocalPosition;
 15662        FixedQuaternion localRotation = transform.LocalRotation;
 15663        bool transformed = setRotation
 15664            ? transform.TrySetWorldPose(transform.WorldPosition, rotation)
 15665            : transform.TrySetWorldPosition(position);
 15666        SwiftThrowHelper.ThrowIfTrue(
 15667            !transformed,
 15668            operation,
 15669            setRotation
 15670                ? "Static collider transform cannot represent the requested world rotation."
 15671                : "Static collider transform cannot represent the requested world position.");
 672
 673        try
 674        {
 13675            RebuildRuntimeShapeState();
 11676        }
 2677        catch
 678        {
 2679            transform.LocalPosition = localPosition;
 2680            transform.LocalRotation = localRotation;
 2681            throw;
 682        }
 683
 11684        if (!IsActive)
 1685            return;
 686
 10687        if (IsPartitioned)
 9688            UpdatePartition();
 689        else
 1690            InitialPartition();
 691
 10692        if (context.Settings.RuntimeMode.RunsMixedContacts())
 2693            context.MixedCollisions.Refresh3DColliderPartition(this);
 10694    }
 695
 696    /// <summary>Assigns a 3D hierarchy parent used for collision exclusion.</summary>
 697    public void SetParent(LSCollider parent)
 698    {
 28699        ThrowIfCompoundPartLifecycle(nameof(SetParent));
 28700        _hierarchyState.SetParent(this, parent);
 25701    }
 702
 703    /// <summary>Assigns a 2D hierarchy parent used for mixed collision exclusion.</summary>
 704    public void SetParent(LSCollider2D parent)
 705    {
 7706        ThrowIfCompoundPartLifecycle(nameof(SetParent));
 7707        _hierarchyState.SetParent(this, parent);
 7708    }
 709
 710    /// <summary>Removes this collider from its current hierarchy parent.</summary>
 711    public void ClearParent()
 712    {
 224713        ThrowIfCompoundPartLifecycle(nameof(ClearParent));
 224714        _hierarchyState.ClearParent(this);
 224715    }
 716
 717    /// <summary>Gets whether hierarchy rules exclude collision with another 3D collider.</summary>
 718    public bool IsSibling(LSCollider other)
 719    {
 102942720        return _hierarchyState.ExcludesCollisionWith(other._hierarchyState, HierarchyKey, other.HierarchyKey);
 721    }
 722
 723    internal bool ExcludesMixedCollisionWith(LSCollider2D other) =>
 5224724        _hierarchyState.ExcludesCollisionWith(other.HierarchyState, HierarchyKey, other.HierarchyKey);
 725
 726    private bool RebuildRuntimeShapeState(bool refreshMassProperties = true)
 727    {
 62178728        ColliderShapeSnapshot snapshot = CaptureShapeSnapshot();
 62173729        if (!_runtimeShapeState.ShouldRebuild(snapshot))
 43095730            return false;
 731
 19078732        PrepareRuntimeShape(
 19078733            snapshot,
 19078734            requireRepresentableMassPoint:
 19078735                _body != null || _compoundOwner != null);
 19076736        PublishPreparedShape();
 19076737        if (refreshMassProperties)
 12269738            _body?.RefreshMassPropertiesFromColliderShape();
 19076739        return true;
 740    }
 741
 742    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 743    internal bool RebuildRuntimeShapeOnly(bool refreshMassProperties = true) =>
 28723744        RebuildRuntimeShapeState(refreshMassProperties);
 745
 746    /// <summary>Marks derived runtime shape state for deterministic rebuilding.</summary>
 747    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 748    protected void MarkShapeDirty()
 749    {
 1637750        _runtimeShapeState.MarkDirty();
 1637751        if (_compoundOwner != null)
 752        {
 1753            _compoundOwner.MarkShapeDirty();
 1754            return;
 755        }
 756
 1636757        _body?.Wake();
 47758    }
 759
 760    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 23936761    private void MarkBroadPhaseChanged() => _partitionState.MarkBroadPhaseChanged();
 762
 763    /// <summary>Updates derived authored dimensions after <see cref="Radius"/> changes.</summary>
 2764    protected virtual void OnRadiusChanged() { }
 765
 766    /// <summary>Updates derived material state after <see cref="Material"/> changes.</summary>
 660767    protected virtual void OnMaterialChanged() { }
 768
 769    /// <summary>Normalizes an authored size for the derived shape.</summary>
 264770    protected virtual Vector3d NormalizeSize(Vector3d value) => value;
 771
 772    private static void ValidateSize(Vector3d value)
 773    {
 1771774        SwiftThrowHelper.ThrowIfArgument(
 1771775            value.X <= Fixed64.Zero || value.Y <= Fixed64.Zero || value.Z <= Fixed64.Zero,
 1771776            nameof(value),
 1771777            "Collider size components must be greater than zero.");
 1765778    }
 779
 780    /// <summary>
 781    /// Gets the point on this collider's surface nearest to a world-space point.
 782    /// </summary>
 783    /// <param name="other"></param>
 784    /// <returns></returns>
 785    public abstract Vector3d ClosestPointOnSurface(Vector3d other);
 786
 787    /// <summary>
 788    /// The direction pointing outward from the surface of the collider at the point
 789    /// </summary>
 790    /// <param name="point"></param>
 791    /// <returns></returns>
 792    public abstract Vector3d GetNormalAtPoint(Vector3d point);
 793
 794    /// <summary>
 795    /// Returns the semantic closest surface feature without requiring its
 796    /// world point or distance to fit in one <see cref="Fixed64"/> vector.
 797    /// </summary>
 798    internal abstract FixedPointAnchor GetClosestSurfaceAnchor(
 799        Vector3d point,
 800        out Vector3d normal);
 801
 802    /// <summary>
 803    /// Tries to resolve a normal that is invariant across the planar surface
 804    /// feature containing <paramref name="point"/>. A successful result must
 805    /// be a nonzero outward normal.
 806    /// </summary>
 807    internal virtual bool TryGetPlanarSurfaceNormal(Vector3d point, out Vector3d normal)
 808    {
 111809        normal = Vector3d.Zero;
 111810        return false;
 811    }
 812
 813    /// <summary>
 814    /// Checks if position is in the padded bounds of the collider, used for broad phase collision detection
 815    /// </summary>
 816    /// <param name="cellPadding">The topology cell edge used to conservatively pad the bounds.</param>
 817    /// <param name="position">The position to check</param>
 818    /// <returns>True if position within bounds</returns>
 819    public bool IsPositionInBounds(Fixed64 cellPadding, Vector3d position)
 820    {
 1258512821        return position.X + cellPadding >= BoundsMin.X
 1258512822            && position.X - cellPadding <= BoundsMax.X
 1258512823            && position.Y + cellPadding >= BoundsMin.Y
 1258512824            && position.Y - cellPadding <= BoundsMax.Y
 1258512825            && position.Z + cellPadding >= BoundsMin.Z
 1258512826            && position.Z - cellPadding <= BoundsMax.Z;
 827    }
 828
 829    /// <summary>
 830    /// Checks if this object overlaps the line formed by p1 and p2
 831    /// </summary>
 832    /// <param name="worker">The prepared ray-axis worker for the owning query service.</param>
 833    /// <param name="outputIntersectionPoints"></param>
 834    /// <returns></returns>
 835    public abstract bool ColliderOverlapsRay(RaycastSegmentWorker worker, ref SwiftList<Vector3d> outputIntersectionPoin
 836
 837    void IColliderHierarchyNode.AddChild(ColliderHierarchyKey key)
 838    {
 30839        ThrowIfCompoundPartLifecycle(nameof(IColliderHierarchyNode.AddChild));
 30840        _hierarchyState.AddChild(key);
 30841    }
 842
 843    void IColliderHierarchyNode.RemoveChild(ColliderHierarchyKey key)
 844    {
 6845        ThrowIfCompoundPartLifecycle(nameof(IColliderHierarchyNode.RemoveChild));
 6846        _hierarchyState.RemoveChild(key);
 6847    }
 848
 2849    void IColliderHierarchyNode.ClearParentReference() => _hierarchyState.ClearParentReference();
 850
 851    bool IColliderHierarchyNode.TryGetHierarchyColliderByKey(ColliderHierarchyKey key, out IColliderHierarchyNode? colli
 852    {
 7853        collider = null;
 7854        if (!key.IsValid || _context == null)
 1855            return false;
 856
 6857        if (key.Is3D && _context.Physics.TryGetColliderById(key.Id, out LSCollider? collider3D))
 858        {
 2859            collider = collider3D;
 2860            return true;
 861        }
 862
 4863        if (key.Is2D && _context.Physics2D.TryGetColliderById(key.Id, out LSCollider2D? collider2D))
 864        {
 2865            collider = collider2D;
 2866            return true;
 867        }
 868
 2869        return false;
 870    }
 871
 872    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 873    internal void SetPhysicsState(int id, int serviceIndex, int replayOrder)
 874    {
 5685875        SwiftThrowHelper.ThrowIfNegative(id, nameof(id));
 5685876        SwiftThrowHelper.ThrowIfNegative(serviceIndex, nameof(serviceIndex));
 5685877        SwiftThrowHelper.ThrowIfNegative(replayOrder, nameof(replayOrder));
 5685878        _id = id;
 5685879        _serviceIndex = serviceIndex;
 5685880        _replayOrder = replayOrder;
 5685881        _replayOrdinal = -1;
 5685882    }
 883
 884    internal void SetServiceIndex(int serviceIndex)
 885    {
 28886        SwiftThrowHelper.ThrowIfNegative(serviceIndex, nameof(serviceIndex));
 28887        _serviceIndex = serviceIndex;
 28888    }
 889
 890    internal void SetReplayOrdinal(int replayOrdinal)
 891    {
 4666892        SwiftThrowHelper.ThrowIfNegative(replayOrdinal, nameof(replayOrdinal));
 4666893        _replayOrdinal = replayOrdinal;
 4666894    }
 895
 896    internal void SetServiceRefreshIndex(int serviceRefreshIndex)
 897    {
 1181898        SwiftThrowHelper.ThrowIfNegative(serviceRefreshIndex, nameof(serviceRefreshIndex));
 1181899        _serviceRefreshIndex = serviceRefreshIndex;
 1181900    }
 901
 902    internal void ClearServiceRefreshIndex()
 903    {
 4793904        _serviceRefreshIndex = -1;
 4793905    }
 906
 907    internal void ClearPhysicsState()
 908    {
 248909        _partitionState.MarkUnpartitioned();
 248910        _partitionState.ClearCoordinates();
 248911        _mixedPartitionState.MarkUnpartitioned();
 248912        _mixedPartitionState.ClearCoordinates();
 248913        _pairState.ClearCollisionPairs();
 248914        _pairState.ClearCollisionPairHolders();
 248915        _id = -1;
 248916        _serviceIndex = -1;
 248917        _replayOrder = -1;
 248918        _replayOrdinal = -1;
 248919        _serviceRefreshIndex = -1;
 248920    }
 921
 922    void IPhysicsColliderRegistryItem.SetRegistryState(int id, int serviceIndex, int replayOrder) =>
 5685923        SetPhysicsState(id, serviceIndex, replayOrder);
 924
 219925    int IPhysicsColliderRegistryItem.ServiceIndex => _serviceIndex;
 926
 6106927    int IPhysicsColliderRegistryItem.ReplayOrder => _replayOrder;
 928
 929    void IPhysicsColliderRegistryItem.SetRegistryServiceIndex(int serviceIndex) =>
 28930        SetServiceIndex(serviceIndex);
 931
 932    void IPhysicsColliderRegistryItem.SetRegistryReplayOrdinal(int replayOrdinal) =>
 4666933        SetReplayOrdinal(replayOrdinal);
 934
 248935    void IPhysicsColliderRegistryItem.ClearRegistryState() => ClearPhysicsState();
 936
 937    internal SwiftList<WorldVoxelIndex> GetOrCreateMixedPartitionCoordinates()
 938    {
 678939        _mixedPartitionState.Coordinates ??= new();
 678940        return _mixedPartitionState.Coordinates;
 941    }
 942
 943    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 944    internal bool MatchesPartitionGridBounds(Vector3d min, Vector3d max, int partitionKind) =>
 37502945        _partitionState.IsPartitioned
 37502946        && _partitionState.LastGridBoundsMin == min
 37502947        && _partitionState.LastGridBoundsMax == max
 37502948        && _partitionState.LastPartitionKind == partitionKind;
 949
 950    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 18026951    internal void MarkUnpartitioned() => _partitionState.MarkUnpartitioned();
 952
 953    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 18026954    internal void ClearPartitionCoordinates() => _partitionState.ClearCoordinates();
 955
 956    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 957    internal bool MatchesMixedPartitionGridBounds(Vector3d min, Vector3d max, int partitionKind) =>
 1569958        _mixedPartitionState.IsPartitioned
 1569959        && _mixedPartitionState.LastGridBoundsMin == min
 1569960        && _mixedPartitionState.LastGridBoundsMax == max
 1569961        && _mixedPartitionState.LastPartitionKind == partitionKind;
 962
 963    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 964    internal void MarkMixedPartitioned(Vector3d min, Vector3d max, int partitionKind)
 965    {
 662966        _mixedPartitionState.SetPreviousGridBounds(min, max, partitionKind);
 662967        _mixedPartitionState.MarkPartitioned();
 662968    }
 969
 970    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 280971    internal void MarkMixedUnpartitioned() => _mixedPartitionState.MarkUnpartitioned();
 972
 973    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 280974    internal void ClearMixedPartitionCoordinates() => _mixedPartitionState.ClearCoordinates();
 975
 976    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 314802977    internal bool IgnoresCollisionLayer(PhysicsLayer layer) => _ignoredCollisionLayers.Includes(layer);
 978}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.Events.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.Events.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 Gravitas.CollisionHandling;
 9using SwiftCollections;
 10
 11namespace Gravitas.Colliders;
 12
 13internal readonly struct ColliderLifetimeToken
 14{
 15    internal ColliderLifetimeToken(LSCollider collider)
 16    {
 17        Collider = collider;
 18        LifetimeVersion = collider.LifetimeVersion;
 19    }
 20
 21    internal LSCollider Collider { get; }
 22
 23    internal long LifetimeVersion { get; }
 24
 25    internal bool IsActive => Collider.IsActive
 26        && !Collider.IsDeactivationInProgress
 27        && IsCurrentLifetime;
 28
 29    internal bool IsCurrentLifetime => Collider.LifetimeVersion == LifetimeVersion;
 30}
 31
 32public abstract partial class LSCollider
 33{
 169234    internal int CollisionPairCount => _pairState.CollisionPairCount;
 35
 169636    internal int CollisionPairHolderCount => _pairState.CollisionPairHolderCount;
 37
 28438    internal SwiftDictionary<int, CollisionPair>? CollisionPairs => _pairState.CollisionPairs;
 39
 28440    internal SwiftHashSet<int>? CollisionPairHolders => _pairState.CollisionPairHolders;
 41
 42    /// <summary>Handles a 3D contact notification for the other body.</summary>
 43    public delegate void BodyCollisionFunc(SolidBody other);
 44    /// <summary>Raised while this collider is touching another collider that owns a 3D body.</summary>
 45    public event BodyCollisionFunc? OnContact;
 46    /// <summary>Raised on the first simulation frame this collider touches another 3D body.</summary>
 47    public event BodyCollisionFunc? OnContactEnter;
 48    /// <summary>Raised when this collider stops touching another 3D body.</summary>
 49    public event BodyCollisionFunc? OnContactExit;
 50
 51    /// <summary>Handles a 3D trigger notification for the other collider.</summary>
 52    public delegate void TriggerCollisionFunc(LSCollider other);
 53
 54    /// <summary>
 55    /// Raised on the first simulation frame this collider participates in a valid trigger pair.
 56    /// </summary>
 57    public event TriggerCollisionFunc? OnTriggerEnter;
 58
 59    /// <summary>
 60    /// Raised each simulation frame this collider participates in an overlapped valid trigger pair.
 61    /// </summary>
 62    public event TriggerCollisionFunc? OnTriggerStay;
 63
 64    /// <summary>
 65    /// Raised when this collider stops participating in a valid trigger pair.
 66    /// </summary>
 67    public event TriggerCollisionFunc? OnTriggerExit;
 68
 69    /// <summary>Handles a mixed contact or trigger notification for the other 2D collider.</summary>
 70    public delegate void MixedCollisionFunc(LSCollider2D other);
 71    /// <summary>Raised while this collider has a physical mixed contact with a 2D collider.</summary>
 72    public event MixedCollisionFunc? OnMixedContact;
 73    /// <summary>Raised when this collider begins a physical mixed contact with a 2D collider.</summary>
 74    public event MixedCollisionFunc? OnMixedContactEnter;
 75    /// <summary>Raised when this collider ends a physical mixed contact with a 2D collider.</summary>
 76    public event MixedCollisionFunc? OnMixedContactExit;
 77
 78    /// <summary>
 79    /// Raised on the first mixed 3D/2D simulation frame this collider participates in a valid trigger pair.
 80    /// </summary>
 81    public event MixedCollisionFunc? OnMixedTriggerEnter;
 82
 83    /// <summary>
 84    /// Raised each mixed 3D/2D simulation frame this collider participates in an overlapped valid trigger pair.
 85    /// </summary>
 86    public event MixedCollisionFunc? OnMixedTriggerStay;
 87
 88    /// <summary>
 89    /// Raised when this collider stops participating in a valid mixed 3D/2D trigger pair.
 90    /// </summary>
 91    public event MixedCollisionFunc? OnMixedTriggerExit;
 92
 93    internal void NotifyContact(LSCollider other, bool isColliding, bool isChanged) =>
 2194        NotifyContact(
 2195            other,
 2196            other.Body,
 2197            isColliding,
 2198            isChanged,
 2199            allowInactive: false,
 21100            new ColliderLifetimeToken(this),
 21101            new ColliderLifetimeToken(other),
 21102            IsTrigger || other.IsTrigger,
 21103            ColliderTriggerEventPolicy.ShouldRaise(this, other));
 104
 105    internal void NotifyContact(
 106        LSCollider other,
 107        SolidBody? otherBody,
 108        bool isColliding,
 109        bool isChanged,
 110        bool allowInactive,
 111        in ColliderLifetimeToken registration,
 112        in ColliderLifetimeToken otherRegistration,
 113        bool isTriggerPair,
 114        bool shouldRaiseTrigger)
 115    {
 5829116        if (isColliding
 5829117            ? !registration.IsActive || !otherRegistration.IsActive
 5829118            : allowInactive ? !registration.IsCurrentLifetime : !registration.IsActive)
 119        {
 2120            return;
 121        }
 122
 5827123        if (isColliding)
 124        {
 5698125            if (isTriggerPair)
 126            {
 21127                if (shouldRaiseTrigger)
 128                {
 18129                    if (isChanged)
 130                    {
 14131                        OnTriggerEnter?.Invoke(other);
 13132                        if (!registration.IsActive || !otherRegistration.IsActive)
 2133                            return;
 134                    }
 135
 15136                    OnTriggerStay?.Invoke(other);
 137                }
 138
 12139                return;
 140            }
 141
 5677142            if (isChanged && otherBody != null)
 143            {
 270144                OnContactEnter?.Invoke(otherBody);
 268145                if (!registration.IsActive || !otherRegistration.IsActive)
 5146                    return;
 147            }
 148
 5670149            if (otherBody != null)
 4024150                OnContact?.Invoke(otherBody);
 151
 1656152            return;
 153        }
 154
 129155        if (!isChanged)
 1156            return;
 157
 128158        if (isTriggerPair)
 159        {
 8160            if (shouldRaiseTrigger)
 6161                OnTriggerExit?.Invoke(other);
 162
 7163            return;
 164        }
 165
 120166        if (otherBody != null)
 119167            OnContactExit?.Invoke(otherBody);
 19168    }
 169
 170    internal void NotifyMixedContact(LSCollider2D other, bool isColliding, bool isChanged, bool isTriggerPair) =>
 14171        NotifyMixedContact(
 14172            other,
 14173            isColliding,
 14174            isChanged,
 14175            isTriggerPair,
 14176            allowInactive: false,
 14177            new ColliderLifetimeToken(this),
 14178            new ColliderLifetimeToken2D(other),
 14179            ColliderTriggerEventPolicy.ShouldRaise(this, other));
 180
 181    internal void NotifyMixedContact(
 182        LSCollider2D other,
 183        bool isColliding,
 184        bool isChanged,
 185        bool isTriggerPair,
 186        bool allowInactive,
 187        in ColliderLifetimeToken registration,
 188        in ColliderLifetimeToken2D otherRegistration,
 189        bool shouldRaiseTrigger)
 190    {
 229191        if (isColliding
 229192            ? !registration.IsActive || !otherRegistration.IsActive
 229193            : allowInactive
 229194                ? !registration.IsCurrentLifetime || !otherRegistration.IsCurrentLifetime
 229195                : !registration.IsActive)
 196        {
 2197            return;
 198        }
 199
 227200        if (isColliding)
 201        {
 191202            if (isTriggerPair)
 203            {
 40204                if (shouldRaiseTrigger)
 205                {
 35206                    if (isChanged)
 207                    {
 30208                        OnMixedTriggerEnter?.Invoke(other);
 30209                        if (!registration.IsActive || !otherRegistration.IsActive)
 2210                            return;
 211                    }
 212
 33213                    OnMixedTriggerStay?.Invoke(other);
 214                }
 215
 16216                return;
 217            }
 218
 151219            if (isChanged)
 220            {
 117221                OnMixedContactEnter?.Invoke(other);
 116222                if (!registration.IsActive || !otherRegistration.IsActive)
 3223                    return;
 224            }
 225
 147226            OnMixedContact?.Invoke(other);
 7227            return;
 228        }
 229
 36230        if (!isChanged)
 1231            return;
 232
 35233        if (isTriggerPair)
 234        {
 12235            if (shouldRaiseTrigger)
 10236                OnMixedTriggerExit?.Invoke(other);
 237
 11238            return;
 239        }
 240
 23241        OnMixedContactExit?.Invoke(other);
 16242    }
 243}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.MassProperties.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.MassProperties.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 FixedMathSharp;
 9using FixedMathSharp.Geometry;
 10using System.Runtime.CompilerServices;
 11
 12namespace Gravitas.Colliders;
 13
 14public abstract partial class LSCollider
 15{
 16    /// <summary>Gets the frontal-area estimate for a world-space direction; the base implementation returns <see cref="
 883717    public virtual Fixed64 GetFrontalArea(Vector3d direction) => Area;
 18
 19    /// <summary>
 20    /// Calculates the body-local center of mass offset implied by this collider's current shape state.
 21    /// </summary>
 22    public virtual Vector3d CalculateLocalCenterOfMassOffset()
 23    {
 2404824        ExactMassPoint3D point = CalculateLocalMassPoint();
 2404725        SwiftThrowHelper.ThrowIfTrue(
 2404726            !point.TryGetPoint(out Vector3d center),
 2404727            nameof(CalculateLocalCenterOfMassOffset),
 2404728            "The collider's body-local center of mass is outside the Fixed64 coordinate domain.");
 2404629        return center;
 30    }
 31
 32    internal virtual ExactMassPoint3D CalculateLocalMassPoint() =>
 3328133        TransformRelativeMassPropertyPointExact(Vector3d.Zero);
 34
 35    internal virtual ExactMassPoint3D CalculatePreparedLocalMassPoint() =>
 3065436        TransformPreparedRelativeMassPropertyPointExact(Vector3d.Zero);
 37
 38    /// <summary>
 39    /// Calculates the deterministic relative measure used to distribute mass
 40    /// when this shape is owned by a compound collider.
 41    /// </summary>
 42    /// <remarks>
 43    /// Solid shapes return volume. Explicit surface-approximation shapes may
 44    /// return a documented shell measure instead.
 45    /// </remarks>
 46    internal abstract ExactMassWeight CalculateMassPropertyWeight();
 47
 48    internal abstract ExactMassWeight CalculatePreparedMassPropertyWeight();
 49
 17950    internal virtual bool SupportsMassProperties => true;
 51
 52    /// <summary>Calculates inertia for a mass about a body-local reference point.</summary>
 53    public virtual Fixed3x3 CalculateInertiaTensor(
 54        Fixed64 mass,
 55        Vector3d localCenterOfMassOffset)
 56    {
 1021357        if (mass <= Fixed64.Zero)
 1258            return Fixed3x3.Zero;
 59
 1020160        Fixed3x3 centerTensor =
 1020161            CalculateCenterOfMassInertiaTensor(mass);
 1019762        ExactMassPoint3D massPoint = CalculateLocalMassPoint();
 1019763        if (massPoint.TryAddParallelAxisTensor(
 1019764                centerTensor,
 1019765                mass,
 1019766                localCenterOfMassOffset,
 1019767                out Fixed3x3 tensor))
 68        {
 1018669            return tensor;
 70        }
 71
 72        // Explicit body center overrides historically use the collider's
 73        // saturating public tensor contract. Semantic child centers have no
 74        // scalar fallback and must remain checked.
 1175        if (!massPoint.TryGetPoint(out Vector3d center))
 76        {
 177            SwiftThrowHelper.ThrowIfTrue(
 178                true,
 179                nameof(localCenterOfMassOffset),
 180                "The requested inertia tensor is outside the Fixed64 scalar domain.");
 81        }
 82
 1083        return InertiaTensorMath.AddParallelAxisTensor(
 1084            centerTensor,
 1085            mass,
 1086            localCenterOfMassOffset - center);
 87    }
 88
 89    internal abstract Fixed3x3 CalculateCenterOfMassInertiaTensor(
 90        Fixed64 mass);
 91
 92    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 93    internal ExactMassPoint3D TransformRelativeMassPropertyPointExact(
 94        Vector3d partRelativePoint) =>
 3466995        _compoundOwner == null
 3466996            ? ExactMassPoint3D.CreateScaledLocalComposition(
 3466997                LocalOffset,
 3466998                GetCurrentOwnerScale(),
 3466999                Vector3d.Zero,
 34669100                Vector3d.One,
 34669101                partRelativePoint,
 34669102                FixedQuaternion.Identity)
 34669103            : ExactMassPoint3D.CreateScaledLocalComposition(
 34669104                _compoundOwner.LocalOffset,
 34669105                GetCurrentOwnerScale(),
 34669106                LocalOffset,
 34669107                GetCurrentOwnerScale(),
 34669108                partRelativePoint,
 34669109                _compoundLocalRotation);
 110
 111    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 112    internal ExactMassPoint3D TransformPreparedRelativeMassPropertyPointExact(
 113        Vector3d partRelativePoint) =>
 32189114        _compoundOwner == null
 32189115            ? ExactMassPoint3D.CreateScaledLocalComposition(
 32189116                _preparedSnapshot.LocalOffset,
 32189117                _preparedSnapshot.OwnerScale,
 32189118                Vector3d.Zero,
 32189119                Vector3d.One,
 32189120                partRelativePoint,
 32189121                FixedQuaternion.Identity)
 32189122            : ExactMassPoint3D.CreateScaledLocalComposition(
 32189123                _compoundOwner._preparedSnapshot.LocalOffset,
 32189124                _preparedSnapshot.OwnerScale,
 32189125                _preparedSnapshot.LocalOffset,
 32189126                _preparedSnapshot.OwnerScale,
 32189127                partRelativePoint,
 32189128                _preparedCompoundLocalRotation);
 129
 185130    internal FixedQuaternion CompoundLocalRotation => _compoundLocalRotation;
 131}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.ReplayHash.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.ReplayHash.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.Chronicler;
 10using Gravitas.Materials;
 11using System;
 12
 13namespace Gravitas.Colliders;
 14
 15public abstract partial class LSCollider
 16{
 17    internal void ContributeReplayHash(
 18        ref ChronicleHashWriter writer,
 19        GravitasReplayHashMode mode)
 20    {
 224821        writer.WriteSection("collider.3d", 4);
 224822        writer.WriteInt32(_replayOrdinal);
 224823        writer.WriteBool(_active);
 224824        writer.WriteBool(_isTrigger);
 224825        writer.WritePhysicsLayer(_layer);
 224826        writer.WritePhysicsLayerMask(_ignoredCollisionLayers);
 224827        WriteMaterial(ref writer, _material);
 224828        writer.WriteEnum(Shape);
 224829        writer.WriteInt32(Priority);
 224830        writer.WriteVector3d(_offset);
 224831        writer.WriteFixed64(_radius);
 224832        writer.WriteVector3d(_size);
 224833        writer.WriteVector3d(Position);
 224834        writer.WriteQuaternion(Rotation);
 224835        writer.WriteVector3d(_committedOwnerScale);
 224836        writer.WriteVector3d(_committedPartScale);
 224837        writer.WriteVector3d(Center);
 224838        writer.WriteInt32(HierarchyChildCount);
 224839        WriteReplayHierarchyKey(ref writer, HierarchyKey);
 224840        WriteReplayHierarchyKey(ref writer, ParentKey);
 224841        WriteReplayHierarchyKey(ref writer, TopParentKey);
 42
 224843        ContributeShapeReplayHash(ref writer);
 44
 224845        if (mode != GravitasReplayHashMode.AuthoritativeWithSolverCaches)
 57946            return;
 47
 166948        writer.WriteSection("collider.3d.caches", 1);
 166949        writer.WriteVector3d(BoundsMin);
 166950        writer.WriteVector3d(BoundsMax);
 166951        writer.WriteUInt32(RuntimeShapeVersion);
 166952        writer.WriteBool(IsPartitioned);
 166953        writer.WriteBool(IsMixedPartitioned);
 166954        writer.WriteInt32(PartitionKind);
 166955        writer.WriteInt32(MixedPartitionKind);
 166956        writer.WriteUInt32(BroadPhaseVersion);
 166957        writer.WriteUInt32(RaycastVersion);
 166958        writer.WriteUInt32(CircleQueryVersion);
 166959        writer.WriteInt32(CollisionPairCount);
 166960        writer.WriteInt32(CollisionPairHolderCount);
 166961    }
 62
 63    private void ContributeShapeReplayHash(ref ChronicleHashWriter writer)
 64    {
 224865        writer.WriteSection("collider.3d.shape", 3);
 224866        switch (this)
 67        {
 68            case LSCapsuleCollider capsule:
 469                writer.WriteVector3d(capsule.Center);
 470                writer.WriteFixed64(capsule.AxisLength);
 471                writer.WriteFixed64(capsule.ScaledRadius);
 472                break;
 73
 74            case LSCylinderCollider cylinder:
 475                writer.WriteVector3d(cylinder.Center);
 476                writer.WriteFixed64(cylinder.Height);
 477                writer.WriteFixed64(cylinder.ScaledRadius);
 478                break;
 79
 80            case LSConeCollider cone:
 481                writer.WriteVector3d(cone.Center);
 482                writer.WriteFixed64(cone.Height);
 483                writer.WriteFixed64(cone.ScaledRadius);
 484                break;
 85
 86            case LSCuboidCollider cuboid:
 9487                writer.WriteVector3d(cuboid.OrientedBox.Center);
 9488                writer.WriteQuaternion(cuboid.OrientedBox.Orientation);
 9489                writer.WriteVector3d(cuboid.OrientedBox.HalfExtents);
 9490                break;
 91
 92            case LSMeshCollider mesh:
 1693                writer.WriteEnum(mesh.Mode);
 1694                writer.WriteEnum(mesh.InertiaPolicy);
 1695                writer.WriteInt32(mesh.Mesh.VertexCount);
 16096                for (int i = 0; i < mesh.Mesh.LocalVertices.Length; i++)
 6497                    writer.WriteVector3d(mesh.Mesh.LocalVertices[i]);
 1698                writer.WriteInt32(mesh.Mesh.Triangles.Length);
 22499                for (int i = 0; i < mesh.Mesh.Triangles.Length; i++)
 96100                    writer.WriteInt32(mesh.Mesh.Triangles[i]);
 16101                break;
 102
 103            case LSCompoundCollider compound:
 31104                writer.WriteInt32(compound.PartCount);
 31105                ReadOnlySpan<CompoundColliderPart> parts = compound.Parts;
 246106                for (int i = 0; i < parts.Length; i++)
 92107                    ContributeCompoundPartReplayHash(ref writer, parts[i]);
 31108                break;
 109
 110            default:
 2095111                writer.WriteFixed64(Area);
 112                break;
 113        }
 2095114    }
 115
 116    private void WriteReplayHierarchyKey(ref ChronicleHashWriter writer, ColliderHierarchyKey key)
 117    {
 6744118        if (!TryResolveReplayHierarchyOrdinal(key, out int replayOrdinal))
 119        {
 4486120            writer.WriteUInt64(0UL);
 4486121            return;
 122        }
 123
 2258124        writer.WriteUInt64(((ulong)key.Dimension << 32) | (uint)replayOrdinal);
 2258125    }
 126
 127    private bool TryResolveReplayHierarchyOrdinal(ColliderHierarchyKey key, out int replayOrdinal)
 128    {
 6744129        replayOrdinal = -1;
 6744130        if (!key.IsValid || _context == null)
 4482131            return false;
 132
 2262133        if (key.Is3D)
 134        {
 2250135            _context.Physics.TryGetColliderById(key.Id, out LSCollider? collider);
 2250136            replayOrdinal = collider!.ReplayOrdinal;
 2250137            return replayOrdinal >= 0;
 138        }
 139
 12140        _context.Physics2D.TryGetColliderById(key.Id, out LSCollider2D? collider2D);
 12141        replayOrdinal = collider2D!.ReplayOrdinal;
 12142        return replayOrdinal >= 0;
 143    }
 144
 145    private static void ContributeCompoundPartReplayHash(
 146        ref ChronicleHashWriter writer,
 147        CompoundColliderPart part)
 148    {
 92149        writer.WriteVector3d(part.LocalOffset);
 92150        writer.WriteQuaternion(part.LocalRotation);
 92151        writer.WriteVector3d(part.LocalScale);
 92152        writer.WriteBool(part.HasMaterial);
 92153        if (part.TryGetMaterial(out PhysicsMaterial material))
 31154            WriteMaterial(ref writer, material);
 92155        ContributeShapeDefinitionReplayHash(ref writer, part.Shape);
 92156    }
 157
 158    private static void ContributeShapeDefinitionReplayHash(
 159        ref ChronicleHashWriter writer,
 160        ColliderShapeDefinition definition)
 161    {
 92162        writer.WriteEnum(definition.Kind);
 92163        writer.WriteBool(definition.HasMaterial);
 92164        if (definition.HasMaterial)
 20165            WriteMaterial(ref writer, definition.Material);
 92166        writer.WriteFixed64(definition.Radius);
 92167        writer.WriteFixed64(definition.Height);
 92168        writer.WriteVector3d(definition.Size);
 92169        writer.WriteEnum(definition.MeshInertiaPolicy);
 92170        writer.WriteInt32(definition.MeshVertexCount);
 256171        for (int i = 0; i < definition.MeshVertexCount; i++)
 36172            writer.WriteVector3d(definition.GetMeshVertex(i));
 92173        writer.WriteInt32(definition.MeshTriangleIndexCount);
 400174        for (int i = 0; i < definition.MeshTriangleIndexCount; i++)
 108175            writer.WriteInt32(definition.GetMeshTriangleIndex(i));
 92176    }
 177
 178    private static void WriteMaterial(ref ChronicleHashWriter writer, PhysicsMaterial material)
 179    {
 2299180        writer.WriteFixed64(material.StaticFriction);
 2299181        writer.WriteFixed64(material.DynamicFriction);
 2299182        writer.WriteFixed64(material.Restitution);
 2299183        writer.WriteEnum(material.FrictionCombine);
 2299184        writer.WriteEnum(material.RestitutionCombine);
 2299185    }
 186}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.RuntimeLifecycle.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.RuntimeLifecycle.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 FixedMathSharp;
 9using Gravitas.CollisionHandling;
 10using SwiftCollections;
 11using System.Runtime.CompilerServices;
 12
 13namespace Gravitas.Colliders;
 14
 15public abstract partial class LSCollider
 16{
 17    /// <summary>Records the current bounds and partition role for broad-phase refresh checks.</summary>
 18    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 19    public void SetPreviousGridBounds() =>
 2342220        _partitionState.SetPreviousGridBounds(BoundsMin, BoundsMax, Context.Collisions.ResolvePartitionKind(this));
 21
 22    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 23    internal bool TryGetCollisionPair(int otherId, out CollisionPair? collisionPair) =>
 10328224        _pairState.TryGetCollisionPair(otherId, out collisionPair);
 25
 26    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 27    internal bool TryAddCollisionPair(int otherId, CollisionPair collisionPair) =>
 26228        _pairState.TryAddCollisionPair(otherId, collisionPair);
 29
 30    internal bool TryRemoveCollisionPair(int otherId) =>
 3931        _pairState.TryRemoveCollisionPair(otherId, out _);
 32
 26133    internal bool TryAddCollisionPairHolder(int otherId) => _pairState.TryAddCollisionPairHolder(otherId);
 34
 3935    internal bool TryRemoveCollisionPairHolder(int otherId) => _pairState.TryRemoveCollisionPairHolder(otherId);
 36
 37    internal void ClearCollisionPairState()
 38    {
 21939        _pairState.ClearCollisionPairs();
 21940        _pairState.ClearCollisionPairHolders();
 21941    }
 42
 43    internal void ClearRuntimeRelationships()
 44    {
 21945        ClearChildParentReferences();
 21946        ClearParent();
 21947    }
 48
 49    /// <summary>Unregisters this collider, or deactivates its owning body.</summary>
 50    public void Deactivate()
 51    {
 14452        ThrowIfCompoundPartLifecycle(nameof(Deactivate));
 14453        if (_body != null)
 54        {
 1555            _body.Deactivate();
 1556            return;
 57        }
 58
 12959        DeactivateRuntimeRegistration();
 12960    }
 61
 62    internal void DeactivateRuntimeRegistration()
 63    {
 22164        _deactivationInProgress = true;
 65        try
 66        {
 22167            if (_id >= 0)
 21868                Context.Physics.DessimilateCollider(this);
 69
 22070            _active = false;
 22071            ClearBindingState();
 22072        }
 73        finally
 74        {
 22175            _deactivationInProgress = false;
 22176        }
 22077    }
 78
 79    private void ClearBindingState()
 80    {
 22081        _body = null;
 22082        _agent = null;
 22083        _context = null;
 22084        _preparedContext = null;
 22085    }
 86
 87    private void ClearChildParentReferences()
 88    {
 21989        SwiftHashSet<ulong>? children = _hierarchyState.Children;
 21990        if (children == null)
 21791            return;
 92
 893        foreach (ulong childPackedKey in children)
 94        {
 295            ColliderHierarchyKey childKey = ColliderHierarchyKey.FromPacked(childPackedKey);
 296            if (((IColliderHierarchyNode)this).TryGetHierarchyColliderByKey(childKey, out IColliderHierarchyNode? child)
 297                child!.ClearParentReference();
 98        }
 99
 2100        _hierarchyState.ClearChildren();
 2101    }
 102
 103    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 104    internal void BindContext(GravitasWorldContext context)
 105    {
 16432106        SwiftThrowHelper.ThrowIfNull(context, nameof(context));
 16432107        SwiftThrowHelper.ThrowIfArgument(
 16432108            _context != null && !ReferenceEquals(_context, context),
 16432109            nameof(context),
 16432110            "Collider is already bound to a different GravitasWorldContext.");
 16432111        _context = context;
 16432112    }
 113
 114    internal void ReserveCompoundPart(
 115        LSCompoundCollider owner,
 116        FixedQuaternion localRotation,
 117        Vector3d localScale)
 118    {
 289119        SwiftThrowHelper.ThrowIfNull(owner, nameof(owner));
 289120        SwiftThrowHelper.ThrowIfArgument(
 289121            HasHostBinding,
 289122            nameof(owner),
 289123            "Compound collider parts cannot be initialized as standalone colliders.");
 288124        SwiftThrowHelper.ThrowIfArgument(
 288125            _compoundOwner != null && !ReferenceEquals(_compoundOwner, owner),
 288126            nameof(owner),
 288127            "Compound collider part is already owned by another compound collider.");
 128
 287129        _compoundOwner = owner;
 287130        _compoundLocalRotation = localRotation;
 287131        _compoundLocalScale = localScale;
 287132    }
 133
 134    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 135    private void ThrowIfCompoundPartLifecycle(string operation)
 136    {
 33856137        SwiftThrowHelper.ThrowIfTrue(
 33856138            _compoundOwner != null,
 33856139            operation,
 33856140            "Compound collider parts are geometry owned by LSCompoundCollider and cannot run standalone lifecycle operat
 33855141    }
 142
 143    private void SetTrigger(bool value)
 144    {
 41145        if (_isTrigger == value)
 7146            return;
 147
 34148        if (value)
 33149            ThrowIfCannotEnableTrigger(nameof(IsTrigger));
 150
 33151        _isTrigger = value;
 33152    }
 153
 154    private void ThrowIfCannotEnableTrigger(string operation)
 155    {
 33156        SwiftThrowHelper.ThrowIfArgument(
 33157            _body != null,
 33158            operation,
 33159            "Trigger colliders must be initialized without a SolidBody. Use InitializeWithNoBody for trigger volumes.");
 32160        SwiftThrowHelper.ThrowIfArgument(
 32161            _compoundOwner != null,
 32162            operation,
 32163            "Compound collider parts are not trigger identities. Set IsTrigger on the owning compound collider.");
 32164    }
 165
 166    private void ThrowIfTriggerWouldAttachToBody(string operation)
 167    {
 5089168        SwiftThrowHelper.ThrowIfArgument(
 5089169            _isTrigger,
 5089170            operation,
 5089171            "Trigger colliders must be initialized without a SolidBody. Use InitializeWithNoBody for trigger volumes.");
 5088172    }
 173
 174    private void ThrowIfLoadedTriggerHasBody(string operation)
 175    {
 70176        SwiftThrowHelper.ThrowIfArgument(
 70177            _isTrigger && _body != null,
 70178            operation,
 70179            "Loaded trigger state is invalid for a collider attached to a SolidBody.");
 68180    }
 181
 182    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 183    internal bool TryGetBoundContext(out GravitasWorldContext? context)
 184    {
 11871185        context = _context;
 11871186        return context != null;
 187    }
 188}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.Serialization.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.Serialization.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.Materials;
 11using Gravitas.Support;
 12
 13namespace Gravitas.Colliders;
 14
 15public abstract partial class LSCollider
 16{
 17    /// <inheritdoc/>
 18    public void RecordData(IChronicler chronicler)
 19    {
 11920        RecordValues.Look(chronicler, ref _debug, "Debug", false);
 11921        RecordValues.Look(chronicler, ref _drawShape, "DrawShape", false);
 11922        RecordValues.Look(chronicler, ref _drawPartitions, "DrawPartitions", false);
 11923        RecordValues.Look(chronicler, ref _drawBoundingBox, "DrawBoundingBox", false);
 11924        RecordValues.Look(chronicler, ref _active, "Active", true);
 11925        RecordValues.Look(chronicler, ref _layer, "Layer", new());
 11926        RecordValues.Look(chronicler, ref _ignoredCollisionLayers, "IgnoredCollisionLayers", PhysicsLayerMask.None);
 11927        RecordValues.Look(chronicler, ref _material, "Material", PhysicsMaterial.Default);
 11928        RecordValues.Look(chronicler, ref _isTrigger, "IsTrigger", false);
 11929        RecordValues.Look(chronicler, ref _offset, "Offset", Vector3d.Zero);
 11930        RecordValues.Look(chronicler, ref _radius, "Radius", Fixed64.Half);
 11931        RecordValues.Look(chronicler, ref _size, "Size", Vector3d.One);
 32
 11933        if (chronicler.Mode == SerializationMode.Loading)
 34        {
 7035            ThrowIfLoadedTriggerHasBody(nameof(IsTrigger));
 6836            ApplyLoadedState();
 37        }
 38        else
 39        {
 4940            _runtimeShapeState.MarkDirty();
 41        }
 4942    }
 43
 44    private void ApplyLoadedState()
 45    {
 6846        _runtimeShapeState.MarkDirty();
 6847        if (_context == null)
 948            return;
 49
 5950        RebuildRuntimeShapeState();
 51
 5952        if (!_active)
 53        {
 1054            if (IsPartitioned)
 655                _context.Collisions.ClearPartitionedObject(this, force: true);
 56
 1057            if (IsMixedPartitioned)
 258                _context.MixedCollisions.ClearPartitioned3DCollider(this, force: true);
 1059            return;
 60        }
 61
 4962        if (IsPartitioned)
 4563            UpdatePartition();
 64        else
 465            InitialPartition();
 4966        if (_context.Settings.RuntimeMode.RunsMixedContacts())
 467            _context.MixedCollisions.Refresh3DColliderPartition(this);
 4968    }
 69}

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Colliders/3D/LSCollider.ShapeTransaction.cs

#LineLine coverage
 1//=======================================================================
 2// LSCollider.ShapeTransaction.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 FixedMathSharp;
 9using FixedMathSharp.Geometry;
 10
 11namespace Gravitas.Colliders;
 12
 13public abstract partial class LSCollider
 14{
 15    private Vector3d _committedCenter;
 610216    private FixedQuaternion _committedRotation = FixedQuaternion.Identity;
 610217    private Vector3d _committedOwnerScale = Vector3d.One;
 610218    private Vector3d _committedPartScale = Vector3d.One;
 19    private bool _hasCommittedShape;
 20
 21    /// <summary>Gets whether this collider has committed runtime shape state.</summary>
 338522    protected bool HasCommittedShape => _hasCommittedShape;
 23
 24    private ColliderShapeSnapshot _preparedSnapshot;
 25    private FixedBoundBox _preparedBounds;
 610226    private Fixed64 _canonicalCenteredProxyRadius = Fixed64.MaxValue;
 27    private Fixed64 _canonicalGroundProbeRadius;
 28    private GravitasWorldContext? _preparedContext;
 610229    private FixedQuaternion _preparedCompoundLocalRotation = FixedQuaternion.Identity;
 30
 62031    private protected GravitasWorldContext PreparedContext => _preparedContext!;
 32
 61833    internal FixedBoundBox PreparedShapeBounds => _preparedBounds;
 34
 35    internal Fixed64 CanonicalCenteredProxyRadius =>
 3413236        _canonicalCenteredProxyRadius;
 37
 38    internal Fixed64 CanonicalGroundProbeRadius =>
 916439        _canonicalGroundProbeRadius;
 40
 1689841    internal Vector3d CanonicalCenter => _committedCenter;
 42
 820043    internal FixedQuaternion CanonicalRotation => _committedRotation;
 44
 45    internal bool TryGetCommittedOwnerScale(out Vector3d scale)
 46    {
 44047        if (_hasCommittedShape)
 48        {
 43649            scale = _committedOwnerScale;
 43650            return true;
 51        }
 52
 453        scale = default;
 454        return false;
 55    }
 56
 57    private Vector3d GetCurrentOwnerScale()
 58    {
 6727559        if (_hasCommittedShape)
 6715860            return _committedOwnerScale;
 11761        if (_compoundOwner != null)
 5362            return _compoundOwner.GetCurrentOwnerScale();
 6463        return Vector3d.One;
 64    }
 65
 66    private Vector3d GetCurrentPartScale() =>
 2967        _hasCommittedShape
 2968            ? _committedPartScale
 2969            : _compoundOwner == null
 2970                ? Vector3d.One
 2971                : _compoundLocalScale;
 72
 73    internal void GetCurrentShapeScales(
 74        out Vector3d ownerScale,
 75        out Vector3d partScale)
 76    {
 2177        ownerScale = GetCurrentOwnerScale();
 2178        partScale = GetCurrentPartScale();
 2179    }
 80
 81    internal bool TryGetCurrentScaledOffset(out Vector3d scaledOffset)
 82    {
 3172983        Vector3d ownerScale = GetCurrentOwnerScale();
 3172984        bool representable = Fixed64.TryMultiplyDivide(
 3172985                _offset.X,
 3172986                ownerScale.X,
 3172987                Fixed64.One,
 3172988                out Fixed64 x)
 3172989            & Fixed64.TryMultiplyDivide(
 3172990                _offset.Y,
 3172991                ownerScale.Y,
 3172992                Fixed64.One,
 3172993                out Fixed64 y)
 3172994            & Fixed64.TryMultiplyDivide(
 3172995                _offset.Z,
 3172996                ownerScale.Z,
 3172997                Fixed64.One,
 3172998                out Fixed64 z);
 3172999        scaledOffset = representable
 31729100            ? new Vector3d(x, y, z)
 31729101            : default;
 31729102        return representable;
 103    }
 104
 105    internal Vector3d GetCurrentScaledOffset()
 106    {
 10107        bool representable =
 10108            TryGetCurrentScaledOffset(out Vector3d scaledOffset);
 10109        SwiftThrowHelper.ThrowIfTrue(
 10110            !representable,
 10111            nameof(ScaledOffset),
 10112            "The scaled collider offset is outside the Fixed64 coordinate domain.");
 10113        return scaledOffset;
 114    }
 115
 116    internal Fixed64 GetCurrentScaledRadius()
 117    {
 8118        Vector3d ownerScale = GetCurrentOwnerScale();
 8119        Vector3d partScale = GetCurrentPartScale();
 8120        return FixedMath.Max(
 8121            ColliderScalePolicy.ScalePositive(
 8122                _radius,
 8123                ownerScale.X,
 8124                partScale.X),
 8125            FixedMath.Max(
 8126                ColliderScalePolicy.ScalePositive(
 8127                    _radius,
 8128                    ownerScale.Y,
 8129                    partScale.Y),
 8130                ColliderScalePolicy.ScalePositive(
 8131                    _radius,
 8132                    ownerScale.Z,
 8133                    partScale.Z)));
 134    }
 135
 136    private ColliderShapeSnapshot CreateStandaloneSnapshot(
 137        IMatterAgent agent,
 138        bool useRequestedPose,
 139        Vector3d requestedPosition,
 140        FixedQuaternion requestedRotation)
 141    {
 142        Vector3d ownerScale;
 143        Vector3d center;
 144        FixedQuaternion rotation;
 74825145        if (useRequestedPose)
 146        {
 72900147            ownerScale = ColliderScalePolicy.CaptureScale(agent.Transform);
 72892148            rotation = requestedRotation;
 72892149            SwiftThrowHelper.ThrowIfArgument(
 72892150                !rotation.TryTransformScaledPoint(
 72892151                    requestedPosition,
 72892152                    _offset,
 72892153                    ownerScale,
 72892154                    out center),
 72892155                nameof(requestedPosition),
 72892156                "Collider center must be representable after applying the requested body pose.");
 157        }
 158        else
 159        {
 1925160            ownerScale = ColliderScalePolicy.Capture(
 1925161                agent.Transform,
 1925162                out Fixed4x4 worldMatrix,
 1925163                out FixedQuaternion matrixRotation);
 1909164            rotation = matrixRotation;
 1909165            SwiftThrowHelper.ThrowIfArgument(
 1909166                !Fixed4x4.TryTransformAffinePoint(worldMatrix, _offset, out center),
 1909167                nameof(agent),
 1909168                "Collider center must be representable after applying the host transform.");
 169        }
 170
 74797171        return new ColliderShapeSnapshot(
 74797172            center,
 74797173            rotation,
 74797174            ownerScale,
 74797175            Vector3d.One,
 74797176            _offset,
 74797177            _size,
 74797178            _radius);
 179    }
 180
 181    private ColliderShapeSnapshot CaptureShapeSnapshot()
 182    {
 62290183        IMatterAgent agent = _agent!;
 62290184        return _body == null
 62290185            ? CreateStandaloneSnapshot(
 62290186                agent,
 62290187                useRequestedPose: false,
 62290188                default,
 62290189                default)
 62290190            : CreateStandaloneSnapshot(
 62290191                agent,
 62290192                useRequestedPose: true,
 62290193                _body.Position3d,
 62290194                _body.Rotation);
 195    }
 196
 197    private ColliderShapeSnapshot CreateCompoundPartSnapshot(
 198        in ColliderShapeSnapshot ownerSnapshot,
 199        FixedQuaternion localRotation,
 200        Vector3d localScale)
 201    {
 314202        ColliderScalePolicy.Validate(localScale);
 314203        SwiftThrowHelper.ThrowIfArgument(
 314204            !ownerSnapshot.Rotation.TryTransformScaledPoint(
 314205                ownerSnapshot.Center,
 314206                _offset,
 314207                ownerSnapshot.OwnerScale,
 314208                out Vector3d center),
 314209            nameof(ownerSnapshot),
 314210            "Compound collider center must be representable after applying its scaled local offset.");
 314211        FixedQuaternion rotation = (ownerSnapshot.Rotation * localRotation).Normalized;
 314212        return new ColliderShapeSnapshot(
 314213            center,
 314214            rotation,
 314215            ownerSnapshot.OwnerScale,
 314216            localScale,
 314217            _offset,
 314218            _size,
 314219            _radius);
 220    }
 221
 222    private void PrepareRuntimeShape(
 223        in ColliderShapeSnapshot snapshot,
 224        bool requireRepresentableMassPoint)
 225    {
 32016226        _preparedContext ??= _context;
 32016227        ValidateShapeCandidate(snapshot);
 32016228        _preparedSnapshot = snapshot;
 32016229        PrepareShape(snapshot);
 31999230        if (requireRepresentableMassPoint
 31999231            && !CalculatePreparedLocalMassPoint().TryGetPoint(out _))
 232        {
 2233            throw new System.InvalidOperationException(
 2234                "The collider's body-local center of mass is outside the Fixed64 coordinate domain.");
 235        }
 31997236    }
 237
 238    private void PublishPreparedShape()
 239    {
 31878240        _committedCenter = _preparedSnapshot.Center;
 31878241        _committedRotation = _preparedSnapshot.Rotation;
 31878242        _committedOwnerScale = _preparedSnapshot.OwnerScale;
 31878243        _committedPartScale = _preparedSnapshot.PartScale;
 31878244        _bounds = _preparedBounds;
 31878245        PublishShape();
 31878246        _canonicalCenteredProxyRadius =
 31878247            ColliderCanonicalBounds.GetCenteredProxyRadius(this);
 31878248        _canonicalGroundProbeRadius =
 31878249            ColliderCanonicalBounds.GetGroundProbeRadius(this);
 31878250        _runtimeShapeState.Commit(_preparedSnapshot);
 31878251        _hasCommittedShape = true;
 31878252    }
 253
 254    internal bool TryPrepareBodyPose(
 255        Vector3d position,
 256        FixedQuaternion rotation)
 257    {
 258        try
 259        {
 6839260            ColliderShapeSnapshot snapshot = CreateStandaloneSnapshot(
 6839261                _agent!,
 6839262                useRequestedPose: true,
 6839263                position,
 6839264                rotation);
 6832265            PrepareRuntimeShape(
 6832266                snapshot,
 6832267                requireRepresentableMassPoint: true);
 6831268            return true;
 269        }
 7270        catch (System.ArgumentException)
 271        {
 7272            return false;
 273        }
 1274        catch (System.InvalidOperationException)
 275        {
 1276            return false;
 277        }
 6839278    }
 279
 280    internal void PublishPreparedBodyPose()
 281    {
 236282        PublishPreparedShape();
 236283    }
 284
 285    internal void PublishPreparedExplicitBodyPose()
 286    {
 6586287        PublishPreparedShape();
 6586288        _body!.RefreshMassPropertiesFromColliderShape();
 6586289    }
 290
 291    private void PrepareStandaloneInitialization(
 292        IMatterAgent agent,
 293        bool useRequestedPose,
 294        Vector3d requestedPosition,
 295        FixedQuaternion requestedRotation)
 296    {
 5696297        ColliderShapeSnapshot snapshot = CreateStandaloneSnapshot(
 5696298            agent,
 5696299            useRequestedPose,
 5696300            requestedPosition,
 5696301            requestedRotation);
 5683302        _preparedContext = agent.Context;
 5683303        PrepareRuntimeShape(
 5683304            snapshot,
 5683305            requireRepresentableMassPoint: useRequestedPose);
 5671306    }
 307
 308    internal void PrepareCompoundPart(
 309        in ColliderShapeSnapshot ownerSnapshot,
 310        FixedQuaternion localRotation,
 311        Vector3d localScale,
 312        GravitasWorldContext context)
 313    {
 314314        SwiftThrowHelper.ThrowIfArgument(
 314315            _context != null && !ReferenceEquals(_context, context),
 314316            nameof(context),
 314317            "Compound collider part is already bound to a different GravitasWorldContext.");
 314318        ColliderShapeSnapshot snapshot = CreateCompoundPartSnapshot(
 314319            ownerSnapshot,
 314320            localRotation,
 314321            localScale);
 314322        _preparedContext = context;
 314323        _preparedCompoundLocalRotation = localRotation;
 314324        PrepareRuntimeShape(
 314325            snapshot,
 314326            requireRepresentableMassPoint: false);
 310327    }
 328
 329    internal void PublishCompoundPart(
 330        FixedQuaternion localRotation,
 331        Vector3d localScale,
 332        GravitasWorldContext context)
 333    {
 308334        _compoundLocalRotation = localRotation;
 308335        _compoundLocalScale = localScale;
 308336        _context = context;
 308337        PublishPreparedShape();
 308338    }
 339
 340    /// <summary>Sets the bounds for the shape transaction being prepared.</summary>
 341    protected void SetPreparedBounds(FixedBoundBox bounds) =>
 31999342        _preparedBounds = bounds;
 343
 32016344    private protected virtual void ValidateShapeCandidate(in ColliderShapeSnapshot snapshot) { }
 345
 346    private protected abstract void PrepareShape(in ColliderShapeSnapshot snapshot);
 347
 348    private protected abstract void PublishShape();
 349}

Methods/Properties

.ctor()
get_IsActive()
set_IsActive(System.Boolean)
get_IsTrigger()
set_IsTrigger(System.Boolean)
get_Id()
get_ReplayOrdinal()
get_LifetimeVersion()
get_IsDeactivationInProgress()
get_ServiceRefreshIndex()
get_AgentOrNull()
get_Context()
get_Body()
get_IsStatic()
get_RequiresServiceSideRefresh()
get_RuntimeShapeVersion()
get_HasHostBinding()
get_CompoundOwner()
get_Position()
set_Position(FixedMathSharp.Vector3d)
get_Rotation()
set_Rotation(FixedMathSharp.FixedQuaternion)
get_Velocity()
get_World()
get_Transform()
get_Layer()
set_Layer(Gravitas.Support.PhysicsLayer)
get_IgnoredCollisionLayers()
set_IgnoredCollisionLayers(Gravitas.Support.PhysicsLayerMask)
get_Material()
set_Material(Gravitas.Materials.PhysicsMaterial)
get_IsPartitioned()
get_PartitionChanged()
set_PartitionChanged(System.Boolean)
get_BroadPhaseVersion()
get_LocalOffset()
set_LocalOffset(FixedMathSharp.Vector3d)
get_Radius()
set_Radius(FixedMathSharp.Fixed64)
get_ScaledRadius()
get_ScaledRadiusSqr()
get_Size()
set_Size(FixedMathSharp.Vector3d)
get_LocalScale()
TryGetLocalScale(FixedMathSharp.Vector3d&)
get_ScaledOffset()
TryGetScaledOffset(FixedMathSharp.Vector3d&)
get_Center()
get_Bounds()
get_BoundsMin()
get_BoundsMax()
get_PartitionCoordinates()
get_PartitionKind()
get_IsMixedPartitioned()
get_MixedPartitionCoordinates()
get_MixedPartitionKind()
get_RaycastVersion()
set_RaycastVersion(System.UInt32)
get_CircleQueryVersion()
set_CircleQueryVersion(System.UInt32)
get_IsChild()
get_IsParent()
get_ParentId()
get_Parent3D()
get_Parent2D()
get_TopParent3D()
get_TopParent2D()
get_HierarchyChildCount()
get_HierarchyKey()
get_ParentKey()
get_TopParentKey()
get_HierarchyState()
Gravitas.Colliders.IColliderHierarchyNode.get_HierarchyKey()
Gravitas.Colliders.IColliderHierarchyNode.get_HierarchyParent()
Initialize(Gravitas.SolidBody)
InitializeWithNoBody(Gravitas.IMatterAgent)
PreflightBodyInitialization(Gravitas.SolidBody,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
PreflightInitialization(Gravitas.IMatterAgent,System.Boolean,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
InitCore(Gravitas.IMatterAgent)
OnBeforeInitialize(Gravitas.IMatterAgent)
OnInitialize()
ValidateCurrentRuntimeTransform()
InitialPartition()
Simulate()
UpdatePartition()
SetBodylessWorldPose(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion,System.Boolean,System.String)
SetParent(Gravitas.Colliders.LSCollider)
SetParent(Gravitas.Colliders.LSCollider2D)
ClearParent()
IsSibling(Gravitas.Colliders.LSCollider)
ExcludesMixedCollisionWith(Gravitas.Colliders.LSCollider2D)
RebuildRuntimeShapeState(System.Boolean)
RebuildRuntimeShapeOnly(System.Boolean)
MarkShapeDirty()
MarkBroadPhaseChanged()
OnRadiusChanged()
OnMaterialChanged()
NormalizeSize(FixedMathSharp.Vector3d)
ValidateSize(FixedMathSharp.Vector3d)
TryGetPlanarSurfaceNormal(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d&)
IsPositionInBounds(FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
Gravitas.Colliders.IColliderHierarchyNode.AddChild(Gravitas.Colliders.ColliderHierarchyKey)
Gravitas.Colliders.IColliderHierarchyNode.RemoveChild(Gravitas.Colliders.ColliderHierarchyKey)
Gravitas.Colliders.IColliderHierarchyNode.ClearParentReference()
Gravitas.Colliders.IColliderHierarchyNode.TryGetHierarchyColliderByKey(Gravitas.Colliders.ColliderHierarchyKey,Gravitas.Colliders.IColliderHierarchyNode&)
SetPhysicsState(System.Int32,System.Int32,System.Int32)
SetServiceIndex(System.Int32)
SetReplayOrdinal(System.Int32)
SetServiceRefreshIndex(System.Int32)
ClearServiceRefreshIndex()
ClearPhysicsState()
Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryState(System.Int32,System.Int32,System.Int32)
Gravitas.Colliders.IPhysicsColliderRegistryItem.get_ServiceIndex()
Gravitas.Colliders.IPhysicsColliderRegistryItem.get_ReplayOrder()
Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryServiceIndex(System.Int32)
Gravitas.Colliders.IPhysicsColliderRegistryItem.SetRegistryReplayOrdinal(System.Int32)
Gravitas.Colliders.IPhysicsColliderRegistryItem.ClearRegistryState()
GetOrCreateMixedPartitionCoordinates()
MatchesPartitionGridBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32)
MarkUnpartitioned()
ClearPartitionCoordinates()
MatchesMixedPartitionGridBounds(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32)
MarkMixedPartitioned(FixedMathSharp.Vector3d,FixedMathSharp.Vector3d,System.Int32)
MarkMixedUnpartitioned()
ClearMixedPartitionCoordinates()
IgnoresCollisionLayer(Gravitas.Support.PhysicsLayer)
get_CollisionPairCount()
get_CollisionPairHolderCount()
get_CollisionPairs()
get_CollisionPairHolders()
NotifyContact(Gravitas.Colliders.LSCollider,System.Boolean,System.Boolean)
NotifyContact(Gravitas.Colliders.LSCollider,Gravitas.SolidBody,System.Boolean,System.Boolean,System.Boolean,Gravitas.Colliders.ColliderLifetimeToken&,Gravitas.Colliders.ColliderLifetimeToken&,System.Boolean,System.Boolean)
NotifyMixedContact(Gravitas.Colliders.LSCollider2D,System.Boolean,System.Boolean,System.Boolean)
NotifyMixedContact(Gravitas.Colliders.LSCollider2D,System.Boolean,System.Boolean,System.Boolean,System.Boolean,Gravitas.Colliders.ColliderLifetimeToken&,Gravitas.Colliders.ColliderLifetimeToken2D&,System.Boolean)
GetFrontalArea(FixedMathSharp.Vector3d)
CalculateLocalCenterOfMassOffset()
CalculateLocalMassPoint()
CalculatePreparedLocalMassPoint()
get_SupportsMassProperties()
CalculateInertiaTensor(FixedMathSharp.Fixed64,FixedMathSharp.Vector3d)
TransformRelativeMassPropertyPointExact(FixedMathSharp.Vector3d)
TransformPreparedRelativeMassPropertyPointExact(FixedMathSharp.Vector3d)
get_CompoundLocalRotation()
ContributeReplayHash(Chronicler.ChronicleHashWriter&,Gravitas.GravitasReplayHashMode)
ContributeShapeReplayHash(Chronicler.ChronicleHashWriter&)
WriteReplayHierarchyKey(Chronicler.ChronicleHashWriter&,Gravitas.Colliders.ColliderHierarchyKey)
TryResolveReplayHierarchyOrdinal(Gravitas.Colliders.ColliderHierarchyKey,System.Int32&)
ContributeCompoundPartReplayHash(Chronicler.ChronicleHashWriter&,Gravitas.Colliders.CompoundColliderPart)
ContributeShapeDefinitionReplayHash(Chronicler.ChronicleHashWriter&,Gravitas.Colliders.ColliderShapeDefinition)
WriteMaterial(Chronicler.ChronicleHashWriter&,Gravitas.Materials.PhysicsMaterial)
SetPreviousGridBounds()
TryGetCollisionPair(System.Int32,Gravitas.CollisionHandling.CollisionPair&)
TryAddCollisionPair(System.Int32,Gravitas.CollisionHandling.CollisionPair)
TryRemoveCollisionPair(System.Int32)
TryAddCollisionPairHolder(System.Int32)
TryRemoveCollisionPairHolder(System.Int32)
ClearCollisionPairState()
ClearRuntimeRelationships()
Deactivate()
DeactivateRuntimeRegistration()
ClearBindingState()
ClearChildParentReferences()
BindContext(Gravitas.GravitasWorldContext)
ReserveCompoundPart(Gravitas.Colliders.LSCompoundCollider,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d)
ThrowIfCompoundPartLifecycle(System.String)
SetTrigger(System.Boolean)
ThrowIfCannotEnableTrigger(System.String)
ThrowIfTriggerWouldAttachToBody(System.String)
ThrowIfLoadedTriggerHasBody(System.String)
TryGetBoundContext(Gravitas.GravitasWorldContext&)
RecordData(Chronicler.IChronicler)
ApplyLoadedState()
.ctor()
get_HasCommittedShape()
get_PreparedContext()
get_PreparedShapeBounds()
get_CanonicalCenteredProxyRadius()
get_CanonicalGroundProbeRadius()
get_CanonicalCenter()
get_CanonicalRotation()
TryGetCommittedOwnerScale(FixedMathSharp.Vector3d&)
GetCurrentOwnerScale()
GetCurrentPartScale()
GetCurrentShapeScales(FixedMathSharp.Vector3d&,FixedMathSharp.Vector3d&)
TryGetCurrentScaledOffset(FixedMathSharp.Vector3d&)
GetCurrentScaledOffset()
GetCurrentScaledRadius()
CreateStandaloneSnapshot(Gravitas.IMatterAgent,System.Boolean,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
CaptureShapeSnapshot()
CreateCompoundPartSnapshot(Gravitas.Colliders.ColliderShapeSnapshot&,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d)
PrepareRuntimeShape(Gravitas.Colliders.ColliderShapeSnapshot&,System.Boolean)
PublishPreparedShape()
TryPrepareBodyPose(FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
PublishPreparedBodyPose()
PublishPreparedExplicitBodyPose()
PrepareStandaloneInitialization(Gravitas.IMatterAgent,System.Boolean,FixedMathSharp.Vector3d,FixedMathSharp.FixedQuaternion)
PrepareCompoundPart(Gravitas.Colliders.ColliderShapeSnapshot&,FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,Gravitas.GravitasWorldContext)
PublishCompoundPart(FixedMathSharp.FixedQuaternion,FixedMathSharp.Vector3d,Gravitas.GravitasWorldContext)
SetPreparedBounds(FixedMathSharp.Geometry.FixedBoundBox)
ValidateShapeCandidate(System.Runtime.InteropServices.InAttribute))