gd_core/addons/core/ai/AStarGraph.cs

107 lines
2.1 KiB
C#

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// D E R E L I C T
//
/// // (c) 2003..2025
using Godot;
using gdcoll = Godot.Collections;
//using System.Linq;
[Tool, GlobalClass]
public partial class AStarGraph : Resource
{
[Export]
public gdcoll.Array<Vector3> Points { get; set; } = new();
[Export]
public gdcoll.Array<gdcoll.Array<int>> Connections { get; set; } = new();
private int _nextId = 0;
public int AddPoint( Vector3 position )
{
var id = _nextId++;
if( Points.Count <= _nextId )
{
Points.Resize( _nextId );
Connections.Resize( _nextId );
}
Points[id] = position;
Connections[id] = new gdcoll.Array<int>();
return id;
}
public void ConnectPoints( int idFrom, int idTo, bool bidirectional = true )
{
//if (!Points.ContainsKey(idFrom) || !Points.ContainsKey(idTo)) return;
//if (!Connections.ContainsKey(idFrom)) Connections[idFrom] = new();
Connections[idFrom].Add( idTo );
if( bidirectional )
{
//if (!Connections.ContainsKey(idTo)) Connections[idTo] = new();
Connections[idTo].Add( idFrom );
}
}
public bool ArePointsConnected( int idFrom, int idTo )
{
return Connections[idFrom].Contains( idTo );
}
public int GetAvailablePointId() => _nextId++;
public Vector3 GetPointPosition( int id ) => Points[id];
public gdcoll.Array<int> GetPointConnections( int id ) => Connections[id];
//public int[] GetPointIds() => Points.Keys.ToArray();
public int GetClosestPoint( Vector3 position )
{
int closestId = -1;
float closestDistSq = float.MaxValue;
int curId = 0;
foreach( var pos in Points )
{
if( !pos.IsFinite() )
continue;
float distSq = position.DistanceSquaredTo( pos );
if( distSq < closestDistSq )
{
if( Connections[curId].Count > 0 )
{
closestDistSq = distSq;
closestId = curId;
}
else
{
Points[curId] = Vector3.Inf;
}
}
curId++;
}
return closestId;
}
public void Clear()
{
Points.Clear();
Connections.Clear();
_nextId = 0;
}
}