< Summary

Information
Class: Gravitas.IslandNodeKeyComparer<T>
Assembly: Gravitas
File(s): /home/runner/work/Gravitas/Gravitas/src/Gravitas/Core/IslandGraphUtility.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 177
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Compare(...)100%11100%

File(s)

/home/runner/work/Gravitas/Gravitas/src/Gravitas/Core/IslandGraphUtility.cs

#LineLine coverage
 1//=======================================================================
 2// IslandGraphUtility.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 SwiftCollections;
 9using System.Collections.Generic;
 10
 11namespace Gravitas;
 12
 13internal interface IIslandNodeState
 14{
 15    int BodyKey { get; }
 16
 17    int ParentIndex { get; set; }
 18
 19    int RootKey { get; set; }
 20
 21    bool IsAwakeForCollision { get; }
 22
 23    void WakeFromCollision();
 24}
 25
 26internal sealed class IslandNodeKeyComparer<TNode> : IComparer<TNode>
 27    where TNode : struct, IIslandNodeState
 28{
 29    public int Compare(TNode left, TNode right) =>
 2782830        left.BodyKey.CompareTo(right.BodyKey);
 31}
 32
 33internal static class IslandGraphUtility
 34{
 35    public static void SortAndDeduplicate<TNode>(SwiftList<TNode> nodes, IComparer<TNode> comparer)
 36        where TNode : struct, IIslandNodeState
 37    {
 38        if (nodes.Count == 0)
 39            return;
 40
 41        if (nodes.Count == 1)
 42        {
 43            TNode singleNode = nodes[0];
 44            singleNode.ParentIndex = 0;
 45            singleNode.RootKey = singleNode.BodyKey;
 46            nodes[0] = singleNode;
 47            return;
 48        }
 49
 50        nodes.SortInPlace(comparer);
 51
 52        int writeIndex = 0;
 53        int previousKey = -1;
 54        for (int readIndex = 0; readIndex < nodes.Count; readIndex++)
 55        {
 56            TNode node = nodes[readIndex];
 57            if (node.BodyKey == previousKey)
 58                continue;
 59
 60            node.ParentIndex = writeIndex;
 61            node.RootKey = node.BodyKey;
 62            nodes[writeIndex++] = node;
 63            previousKey = node.BodyKey;
 64        }
 65
 66        while (nodes.Count > writeIndex)
 67            nodes.RemoveAt(nodes.Count - 1);
 68    }
 69
 70    public static int Find<TNode>(SwiftList<TNode> nodes, int key)
 71        where TNode : struct, IIslandNodeState
 72    {
 73        int low = 0;
 74        int high = nodes.Count - 1;
 75        while (low <= high)
 76        {
 77            int mid = low + ((high - low) >> 1);
 78            int midKey = nodes[mid].BodyKey;
 79            if (midKey == key)
 80                return mid;
 81
 82            if (midKey < key)
 83                low = mid + 1;
 84            else
 85                high = mid - 1;
 86        }
 87
 88        return -1;
 89    }
 90
 91    public static void Union<TNode>(SwiftList<TNode> nodes, int nodeA, int nodeB)
 92        where TNode : struct, IIslandNodeState
 93    {
 94        int rootA = FindRoot(nodes, nodeA);
 95        int rootB = FindRoot(nodes, nodeB);
 96        if (rootA == rootB)
 97            return;
 98
 99        int keyA = nodes[rootA].BodyKey;
 100        int keyB = nodes[rootB].BodyKey;
 101        int parent = keyA <= keyB ? rootA : rootB;
 102        int child = parent == rootA ? rootB : rootA;
 103
 104        TNode childNode = nodes[child];
 105        childNode.ParentIndex = parent;
 106        childNode.RootKey = nodes[parent].BodyKey;
 107        nodes[child] = childNode;
 108    }
 109
 110    public static int FindRoot<TNode>(SwiftList<TNode> nodes, int index)
 111        where TNode : struct, IIslandNodeState
 112    {
 113        int root = index;
 114        while (nodes[root].ParentIndex != root)
 115            root = nodes[root].ParentIndex;
 116
 117        while (index != root)
 118        {
 119            TNode node = nodes[index];
 120            int parent = node.ParentIndex;
 121            node.ParentIndex = root;
 122            node.RootKey = nodes[root].BodyKey;
 123            nodes[index] = node;
 124            index = parent;
 125        }
 126
 127        return root;
 128    }
 129
 130    public static void CompressRoots<TNode>(SwiftList<TNode> nodes)
 131        where TNode : struct, IIslandNodeState
 132    {
 133        for (int i = 0; i < nodes.Count; i++)
 134        {
 135            int root = FindRoot(nodes, i);
 136            TNode node = nodes[i];
 137            node.RootKey = nodes[root].BodyKey;
 138            nodes[i] = node;
 139        }
 140    }
 141
 142    public static int ResolveConstraintRootKey<TNode>(SwiftList<TNode> nodes, int nodeA, int nodeB)
 143        where TNode : struct, IIslandNodeState
 144    {
 145        if (nodeA >= 0)
 146            return nodes[nodeA].RootKey;
 147
 148        return nodeB >= 0 ? nodes[nodeB].RootKey : -1;
 149    }
 150
 151    public static bool WakeBodies<TNode>(SwiftList<TNode> nodes, int rootKey)
 152        where TNode : struct, IIslandNodeState
 153    {
 154        bool hasAwakeBody = false;
 155        for (int i = 0; i < nodes.Count; i++)
 156        {
 157            TNode node = nodes[i];
 158            if (node.RootKey == rootKey && node.IsAwakeForCollision)
 159            {
 160                hasAwakeBody = true;
 161                break;
 162            }
 163        }
 164
 165        if (!hasAwakeBody)
 166            return false;
 167
 168        for (int i = 0; i < nodes.Count; i++)
 169        {
 170            TNode node = nodes[i];
 171            if (node.RootKey == rootKey)
 172                node.WakeFromCollision();
 173        }
 174
 175        return true;
 176    }
 177}

Methods/Properties

Compare(TNode,TNode)