rj-action-library/Runtime/Interactions/MultiRayCaster.cs

158 lines
2.9 KiB
C#

using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class MultiRayCaster:Caster
{
public enum UpdateMode
{
Process,
Physics_Process
}
[Export]
public float rayLength = 10;
[Export]
public int maxHits = 3;
List<CollisionData> collisions = new List<CollisionData>();
int numCollisions = 0;
[Export]
public Vector3 to;
[Export]
public UpdateMode updateMode = UpdateMode.Physics_Process;
[Export]
public Action beforeProcess;
[Export]
public Action afterProcess;
[ExportGroup( "Debugging")]
[Export]
public Node collider;
[Export]
public bool printColliderNames = false;
PhysicsRayQueryParameters3D rayParameters = new PhysicsRayQueryParameters3D();
public override void _PhysicsProcess( double delta )
{
if ( UpdateMode.Physics_Process != updateMode )
{
return;
}
Update( delta );
}
public override void _Process( double delta )
{
if ( UpdateMode.Process != updateMode )
{
return;
}
Update( delta );
}
[Export]
public bool runInEditor = false;
void Update( double delta )
{
if ( Engine.IsEditorHint() && ! runInEditor )
{
return;
}
Action.Trigger( beforeProcess );
ResolveCollisions();
SortCollisions();
var nextCollider = NumColliders() == 0 ? null : GetCollider( 0 );
if ( nextCollider != collider )
{
collider = nextCollider;
if ( printColliderNames )
{
this.LogInfo( "New Collider:", HierarchyName.Of( collider ) );
}
}
Action.Trigger( afterProcess );
}
CollisionData GetCollisionData( int i )
{
while ( collisions.Count <= i )
{
collisions.Add( new CollisionData() );
}
return collisions[ i ];
}
void ResolveCollisions()
{
var physics = GetWorld3D().DirectSpaceState;
var excludes = new Array<Rid>();
var from = GlobalPosition;
var to = from + this.GlobalForward().Normalized() * rayLength;
this.to = to;
rayParameters.From = from;
rayParameters.To = to;
numCollisions = 0;
for ( int i = 0; i < maxHits; i++ )
{
rayParameters.Exclude = excludes;
var collisionData = GetCollisionData( numCollisions );
collisionData.Get( rayParameters, physics );
if ( ! collisionData.hasCollision || this.DistanceTo( collisionData.position ) > rayLength )
{
return;
}
excludes.Add( collisionData.rid );
if ( IsSelected( collisionData ) )
{
numCollisions ++;
}
}
}
}
}