< Summary

Information
Class: Trailblazer.Pathing.NavigationSurfaceEdgeRouteWork
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationSurfaceEdgeRouteWork.cs
Line coverage
100%
Covered lines: 243
Uncovered lines: 0
Coverable lines: 243
Total lines: 400
Line coverage: 100%
Branch coverage
100%
Covered branches: 57
Total branches: 57
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Begin(...)100%44100%
Advance(...)100%66100%
get_Cost()100%11100%
get_HasCurrentPoint()100%11100%
get_CurrentPoint()100%77100%
get_CurrentPointIsTargetFootAnchor()100%11100%
ConsumePoint()100%11100%
TryTakeDependencyNode(...)100%22100%
Reset()100%11100%
AdvanceSimple()100%66100%
AdvanceExplicit(...)100%2626100%
Complete(...)100%11100%
SetPoints(...)100%22100%
SetPoints(...)100%22100%
AppendPoints(...)100%22100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Graph/NavigationSurfaceEdgeRouteWork.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationSurfaceEdgeRouteWork.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using FixedMathSharp;
 9using GridForge.Grids.Topology;
 10
 11namespace Trailblazer.Pathing;
 12
 13/// <summary>Reports resumable semantic and swept-geometry edge progress.</summary>
 14internal enum NavigationSurfaceEdgeRouteStatus : byte
 15{
 16    Pending = 0,
 17    Point = 1,
 18    Passable = 2,
 19    Impassable = 3,
 20    BudgetExceeded = 4,
 21    CostOverflow = 5
 22}
 23
 24/// <summary>Evaluates and expands one exact authored surface edge without allocation.</summary>
 25internal struct NavigationSurfaceEdgeRouteWork
 26{
 27    private TraversalEvaluator _evaluator;
 28    private NavigationGraphEdge _edge;
 29    private NavigationNodeRef _source;
 30    private TraversalExplicitEdgeWork _explicitWork;
 31    private GridNavigationPortal _incomingPortal;
 32    private Vector3d _incomingTargetAnchor;
 33    private NavigationNodeRef _dependencyNode;
 34    private Fixed64 _cost;
 35    private NavigationCellAddress _pointAddress0;
 36    private NavigationCellAddress _pointAddress1;
 37    private Vector3d _pointPosition0;
 38    private Vector3d _pointPosition1;
 39    private Vector3d _pointPosition2;
 40    private Vector3d _pointPosition3;
 41    private Vector3d _pointPosition4;
 42    private NavigationSurfaceEdgeRouteStatus _completionStatus;
 43    private int _portalOrdinal;
 44    private int _pointOrdinal;
 45    private int _pointCount;
 46    private int _secondPointAddressOrdinal;
 47    private int _targetPointOrdinal;
 48    private bool _emitPoints;
 49    private bool _explicit;
 50    private bool _hasDependencyNode;
 51
 52    internal NavigationSurfaceEdgeRouteStatus Begin(
 53        TraversalEvaluator evaluator,
 54        NavigationNodeRef source,
 55        in NavigationGraphEdge edge,
 56        bool emitPoints)
 57    {
 1767058        Reset();
 1767059        _evaluator = evaluator;
 1767060        _source = source;
 1767061        _edge = edge;
 1767062        _emitPoints = emitPoints;
 1767063        _completionStatus = NavigationSurfaceEdgeRouteStatus.Pending;
 1767064        if (edge.Kind != NavigationGraphEdgeKind.Explicit)
 1752365            return _completionStatus;
 66
 14767        TraversalExplicitEdgeStatus status = evaluator.BeginExplicitEdge(
 14768            source,
 14769            edge,
 14770            out _explicitWork);
 14771        if (status != TraversalExplicitEdgeStatus.Pending)
 472            return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 14373        _explicit = true;
 14374        return _completionStatus;
 75    }
 76
 77    internal NavigationSurfaceEdgeRouteStatus Advance(
 78        NavigationWorkMeter meter,
 79        ref int connectionStepRemaining)
 80    {
 1997281        if (_pointOrdinal < _pointCount)
 148582            return NavigationSurfaceEdgeRouteStatus.Point;
 1848783        if (_completionStatus != NavigationSurfaceEdgeRouteStatus.Pending)
 54284            return _completionStatus;
 1794585        return _explicit
 1794586            ? AdvanceExplicit(meter, ref connectionStepRemaining)
 1794587            : AdvanceSimple();
 88    }
 89
 1761890    internal Fixed64 Cost => _cost;
 91
 384292    internal bool HasCurrentPoint => _pointOrdinal < _pointCount;
 93
 181594    internal NavigationAStarGuidePoint CurrentPoint => new(
 181595        _pointOrdinal < _secondPointAddressOrdinal
 181596            ? _pointAddress0
 181597            : _pointAddress1,
 181598        _pointOrdinal switch
 181599        {
 604100            0 => _pointPosition0,
 604101            1 => _pointPosition1,
 543102            2 => _pointPosition2,
 32103            3 => _pointPosition3,
 32104            _ => _pointPosition4
 1815105        },
 1815106        TraversalMedium.Solid);
 107
 108    internal bool CurrentPointIsTargetFootAnchor =>
 1815109        _pointOrdinal == _targetPointOrdinal;
 110
 111    internal void ConsumePoint()
 112    {
 113        System.Diagnostics.Debug.Assert(HasCurrentPoint);
 1814114        _pointOrdinal++;
 1814115    }
 116
 117    internal bool TryTakeDependencyNode(out NavigationNodeRef node)
 118    {
 19971119        node = _dependencyNode;
 19971120        if (!_hasDependencyNode)
 19569121            return false;
 402122        _dependencyNode = default;
 402123        _hasDependencyNode = false;
 402124        return true;
 125    }
 126
 127    internal void Reset()
 128    {
 17670129        _evaluator = default;
 17670130        _edge = default;
 17670131        _source = default;
 17670132        _explicitWork = default;
 17670133        _incomingPortal = default;
 17670134        _incomingTargetAnchor = default;
 17670135        _dependencyNode = default;
 17670136        _cost = default;
 17670137        _pointAddress0 = default;
 17670138        _pointAddress1 = default;
 17670139        _pointPosition0 = default;
 17670140        _pointPosition1 = default;
 17670141        _pointPosition2 = default;
 17670142        _pointPosition3 = default;
 17670143        _pointPosition4 = default;
 17670144        _completionStatus = default;
 17670145        _portalOrdinal = 0;
 17670146        _pointOrdinal = 0;
 17670147        _pointCount = 0;
 17670148        _secondPointAddressOrdinal = 0;
 17670149        _targetPointOrdinal = -1;
 17670150        _emitPoints = false;
 17670151        _explicit = false;
 17670152        _hasDependencyNode = false;
 17670153    }
 154
 155    private NavigationSurfaceEdgeRouteStatus AdvanceSimple()
 156    {
 17523157        TraversalEvaluationStatus evaluation = _evaluator.EvaluateEdge(
 17523158            _source,
 17523159            _edge,
 17523160            out TraversalEdgeEvidence evidence);
 17523161        if (evaluation == TraversalEvaluationStatus.CostOverflow)
 2162            return Complete(NavigationSurfaceEdgeRouteStatus.CostOverflow);
 17521163        if (evaluation != TraversalEvaluationStatus.Passable)
 29164            return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 17492165        bool validSourceSegment = GridCellGeometry.IsNavigationBodySegmentValid(
 17492166                evidence.SourcePrism,
 17492167                evidence.SourceFootAnchor,
 17492168                evidence.SourcePortalAnchor,
 17492169                _evaluator.Profile.Shape.Radius,
 17492170                _evaluator.Profile.Shape.Height,
 17492171                default,
 17492172                evidence.Portal,
 17492173                GridNavigationBodySegmentEndpointAllowance.None);
 17492174        bool validTargetSegment = GridCellGeometry.IsNavigationBodySegmentValid(
 17492175                evidence.TargetPrism,
 17492176                evidence.TargetPortalAnchor,
 17492177                evidence.TargetFootAnchor,
 17492178                _evaluator.Profile.Shape.Radius,
 17492179                _evaluator.Profile.Shape.Height,
 17492180                evidence.Portal,
 17492181                default,
 17492182                GridNavigationBodySegmentEndpointAllowance.None);
 183        System.Diagnostics.Debug.Assert(
 184            evidence.Portal.FaceKind != VoxelContactFaceKind.Horizontal
 185            || (GridCellGeometry.TryGetNavigationPortalTraversalParameters(
 186                    evidence.SourcePrism,
 187                    evidence.TargetPrism,
 188                    evidence.Portal,
 189                    evidence.SourcePortalAnchor,
 190                    evidence.TargetPortalAnchor,
 191                    _evaluator.Profile.Shape.Radius,
 192                    _evaluator.Profile.Shape.Height,
 193                    out Fixed64 sourceParameter,
 194                    out Fixed64 targetParameter)
 195                && sourceParameter == Fixed64.Zero
 196                && targetParameter == Fixed64.One),
 197            "published surface portals retain the exact validated profile crossing");
 198        System.Diagnostics.Debug.Assert(validSourceSegment && validTargetSegment);
 199
 17492200        _cost = evidence.Cost;
 17492201        SetPoints(
 17492202            evidence.SourceAddress,
 17492203            evidence.TargetAddress,
 17492204            evidence.SourcePortalAnchor,
 17492205            evidence.TargetPortalAnchor,
 17492206            evidence.TargetFootAnchor);
 17492207        _targetPointOrdinal = 2;
 17492208        _completionStatus = NavigationSurfaceEdgeRouteStatus.Passable;
 17492209        return _pointCount == 0
 17492210            ? _completionStatus
 17492211            : NavigationSurfaceEdgeRouteStatus.Point;
 212    }
 213
 214    private NavigationSurfaceEdgeRouteStatus AdvanceExplicit(
 215        NavigationWorkMeter meter,
 216        ref int connectionStepRemaining)
 217    {
 422218        if (connectionStepRemaining == 0)
 219        {
 16220            return meter.RemainingConnectionLegs == 0
 16221                ? Complete(NavigationSurfaceEdgeRouteStatus.BudgetExceeded)
 16222                : NavigationSurfaceEdgeRouteStatus.Pending;
 223        }
 406224        if (!meter.TryConsumeConnectionLegs(1))
 3225            return Complete(NavigationSurfaceEdgeRouteStatus.BudgetExceeded);
 403226        connectionStepRemaining--;
 227
 403228        TraversalExplicitEdgeStatus semantic = _evaluator.AdvanceExplicitEdge(
 403229            ref _explicitWork,
 403230            out TraversalEdgeEvidence evidence);
 403231        NavigationNodeRef dependencyNode = evidence.DependencyNode;
 232        System.Diagnostics.Debug.Assert(
 233            dependencyNode.IsValid,
 234            "every published explicit corridor leg resolves an immutable graph node");
 403235        _dependencyNode = dependencyNode;
 403236        _hasDependencyNode = true;
 403237        if (semantic == TraversalExplicitEdgeStatus.CostOverflow)
 1238            return Complete(NavigationSurfaceEdgeRouteStatus.CostOverflow);
 402239        if (semantic == TraversalExplicitEdgeStatus.Impassable)
 3240            return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 241
 399242        NavigationExplicitConnectionRecord record = _edge.ExplicitConnection;
 399243        NavigationConnection connection = record.Definition;
 399244        GridNavigationPortal outgoing = evidence.Portal;
 399245        Vector3d sourceAnchor = evidence.SourcePortalAnchor;
 399246        Vector3d targetAnchor = evidence.TargetPortalAnchor;
 247
 399248        if (_portalOrdinal == 0)
 249        {
 136250            if (!GridCellGeometry.IsNavigationBodySegmentValid(
 136251                    evidence.SourcePrism,
 136252                    evidence.SourceFootAnchor,
 136253                    connection.EntryAnchor,
 136254                    _evaluator.Profile.Shape.Radius,
 136255                    _evaluator.Profile.Shape.Height,
 136256                    default,
 136257                    outgoing,
 136258                    GridNavigationBodySegmentEndpointAllowance.None)
 136259                || !GridCellGeometry.IsNavigationBodySegmentValid(
 136260                    evidence.SourcePrism,
 136261                    connection.EntryAnchor,
 136262                    sourceAnchor,
 136263                    _evaluator.Profile.Shape.Radius,
 136264                    _evaluator.Profile.Shape.Height,
 136265                    default,
 136266                    outgoing,
 136267                    GridNavigationBodySegmentEndpointAllowance.None))
 268            {
 1269                return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 270            }
 135271            SetPoints(
 135272                evidence.SourceAddress,
 135273                connection.EntryAnchor,
 135274                sourceAnchor);
 275        }
 276        else
 277        {
 263278            if (!GridCellGeometry.IsNavigationBodySegmentValid(
 263279                    evidence.SourcePrism,
 263280                    _incomingTargetAnchor,
 263281                    sourceAnchor,
 263282                    _evaluator.Profile.Shape.Radius,
 263283                    _evaluator.Profile.Shape.Height,
 263284                    _incomingPortal,
 263285                    outgoing,
 263286                    GridNavigationBodySegmentEndpointAllowance.None))
 287            {
 1288                return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 289            }
 262290            SetPoints(
 262291                evidence.SourceAddress,
 262292                _incomingTargetAnchor,
 262293                sourceAnchor);
 294        }
 295
 397296        _portalOrdinal++;
 397297        _incomingPortal = outgoing;
 397298        _incomingTargetAnchor = targetAnchor;
 397299        if (semantic == TraversalExplicitEdgeStatus.Passable)
 300        {
 129301            if (!GridCellGeometry.IsNavigationBodySegmentValid(
 129302                    evidence.TargetPrism,
 129303                    targetAnchor,
 129304                    connection.ExitAnchor,
 129305                    _evaluator.Profile.Shape.Radius,
 129306                    _evaluator.Profile.Shape.Height,
 129307                    outgoing,
 129308                    default,
 129309                    GridNavigationBodySegmentEndpointAllowance.None)
 129310                || !GridCellGeometry.IsNavigationBodySegmentValid(
 129311                    evidence.TargetPrism,
 129312                    connection.ExitAnchor,
 129313                    evidence.TargetFootAnchor,
 129314                    _evaluator.Profile.Shape.Radius,
 129315                    _evaluator.Profile.Shape.Height,
 129316                    outgoing,
 129317                    default,
 129318                    GridNavigationBodySegmentEndpointAllowance.None))
 319            {
 2320                return Complete(NavigationSurfaceEdgeRouteStatus.Impassable);
 321            }
 127322            AppendPoints(
 127323                evidence.TargetAddress,
 127324                targetAnchor,
 127325                connection.ExitAnchor,
 127326                evidence.TargetFootAnchor);
 127327            _targetPointOrdinal = _pointCount - 1;
 127328            _cost = evidence.Cost;
 127329            _completionStatus = NavigationSurfaceEdgeRouteStatus.Passable;
 330        }
 395331        return _pointCount == 0
 395332            ? _completionStatus
 395333            : NavigationSurfaceEdgeRouteStatus.Point;
 334    }
 335
 336    private NavigationSurfaceEdgeRouteStatus Complete(
 337        NavigationSurfaceEdgeRouteStatus status)
 338    {
 50339        _completionStatus = status;
 50340        return status;
 341    }
 342
 343    private void SetPoints(
 344        NavigationCellAddress address,
 345        Vector3d first,
 346        Vector3d second)
 347    {
 397348        if (!_emitPoints)
 304349            return;
 93350        _pointAddress0 = address;
 93351        _pointAddress1 = default;
 93352        _pointPosition0 = first;
 93353        _pointPosition1 = second;
 93354        _pointPosition2 = default;
 93355        _pointPosition3 = default;
 93356        _pointPosition4 = default;
 93357        _pointOrdinal = 0;
 93358        _pointCount = 2;
 93359        _secondPointAddressOrdinal = 2;
 93360        _targetPointOrdinal = -1;
 93361    }
 362
 363    private void SetPoints(
 364        NavigationCellAddress firstAddress,
 365        NavigationCellAddress secondAddress,
 366        Vector3d first,
 367        Vector3d second,
 368        Vector3d third)
 369    {
 17492370        if (!_emitPoints)
 16981371            return;
 511372        _pointAddress0 = firstAddress;
 511373        _pointAddress1 = secondAddress;
 511374        _pointPosition0 = first;
 511375        _pointPosition1 = second;
 511376        _pointPosition2 = third;
 511377        _pointPosition3 = default;
 511378        _pointPosition4 = default;
 511379        _pointOrdinal = 0;
 511380        _pointCount = 3;
 511381        _secondPointAddressOrdinal = 1;
 511382        _targetPointOrdinal = -1;
 511383    }
 384
 385    private void AppendPoints(
 386        NavigationCellAddress address,
 387        Vector3d first,
 388        Vector3d second,
 389        Vector3d third)
 390    {
 127391        if (!_emitPoints)
 95392            return;
 32393        _pointAddress1 = address;
 32394        _pointPosition2 = first;
 32395        _pointPosition3 = second;
 32396        _pointPosition4 = third;
 32397        _pointCount = 5;
 32398        _secondPointAddressOrdinal = 2;
 32399    }
 400}