namespace GodotHelpers.Raycasts;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Godot;
using Godot.Collections;
using SJK.Functional;
///
/// Extensions for .
/// Allows for an static way of casting an godot Raycast3D.
///
public static class RaycastExtensions
{
// --- 3D ---
public static RaycastResult3D? RaycastEx(this PhysicsDirectSpaceState3D space, Vector3 from, Vector3 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
{
var query = new PhysicsRayQueryParameters3D
{
From = from,
To = to,
CollisionMask = collisionMask,
HitFromInside = hitFromInside,
};
if (exclude != null)
query.Exclude = new Array(exclude);
var result = space.IntersectRay(query);
if (result.Count == 0)
return null;
return new RaycastResult3D(
Collider: result["collider"].AsGodotObject(),
ColliderId: result["collider_id"].AsInt32(),
Rid: (Rid)result["rid"],
Shape: result["shape"].AsInt32(),
Position: result["position"].AsVector3(),
Normal: result["normal"].AsVector3()
);
}
public static bool RaycastHitEx(this PhysicsDirectSpaceState3D space, Vector3 from, Vector3 to, [NotNullWhen(true)] out RaycastResult3D hit, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
{
hit = space.RaycastEx(from, to, collisionMask, exclude, hitFromInside)!;
return hit is not null;
}
// --- 2D ---
///
/// Extensions for .
/// Allows for an static way of casting an godot Raycast3D.
///
public static RaycastResult2D? RaycastEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
{
var query = new PhysicsRayQueryParameters2D
{
From = from,
To = to,
CollisionMask = collisionMask,
HitFromInside = hitFromInside,
};
if (exclude != null)
query.Exclude = new Array(exclude);
var result = space.IntersectRay(query);
if (result.Count == 0)
return null;
return new RaycastResult2D(
Collider: result["collider"].AsGodotObject(),
ColliderId: result["collider_id"].AsInt32(),
Rid: (Rid)result["rid"],
Shape: result["shape"].AsInt32(),
Position: result["position"].AsVector2(),
Normal: result["normal"].AsVector2()
);
}
public static IOption RaycastOptionEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
=> RaycastEx(space, from, to, collisionMask, exclude, hitFromInside).ToOption();
public static bool RaycastHitEx(this PhysicsDirectSpaceState2D space, Vector2 from, Vector2 to, out RaycastResult2D hit, uint collisionMask = uint.MaxValue, Rid[]? exclude = null, bool hitFromInside = false)
{
hit = space.RaycastEx(from, to, collisionMask, exclude, hitFromInside)!;
return hit is not null;
}
// 3D Shape Cast
public static List IntersectShapeEx(this PhysicsDirectSpaceState3D space, PhysicsShapeQueryParameters3D query, int maxResults = 32)
{
var results = space.IntersectShape(query, maxResults);
var list = new List(results.Count);
foreach (var dict in results)
{
list.Add(new CollisionResultBase(
Collider: dict["collider"].AsGodotObject(),
ColliderId: dict["collider_id"].AsInt32(),
Rid: (Rid)dict["rid"],
Shape: dict["shape"].AsInt32()
));
}
return list;
}
// 2D Shape Cast
public static List IntersectShapeEx(this PhysicsDirectSpaceState2D space, PhysicsShapeQueryParameters2D query, int maxResults = 32)
{
var results = space.IntersectShape(query, maxResults);
var list = new List(results.Count);
foreach (var dict in results)
{
list.Add(new CollisionResultBase(
Collider: dict["collider"].AsGodotObject(),
ColliderId: dict["collider_id"].AsInt32(),
Rid: (Rid)dict["rid"],
Shape: dict["shape"].AsInt32()
));
}
return list;
}
}