using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; using System; namespace Rokojori { public class CollisionData { public bool hasCollision = false; public Node collider; public Vector3 normal; public Vector3 position; public Shape3D shape; public Rid rid; public static bool HasCollisionMask( Node n ) { return n is CsgShape3D || n is CollisionObject3D; } public static uint GetCollisionMask( Node n ) { if ( n is CsgShape3D ) { return ( n as CsgShape3D ).CollisionMask; } if ( n is CollisionObject3D ) { return ( n as CollisionObject3D ).CollisionMask; } return 0; } public static bool HasCollisionLayer( Node n ) { return n is CsgShape3D || n is CollisionObject3D; } public static uint GetCollisionLayer( Node n ) { if ( n is CsgShape3D ) { return ( n as CsgShape3D ).CollisionLayer; } if ( n is CollisionObject3D ) { return ( n as CollisionObject3D ).CollisionLayer; } return 0; } public void Get( PhysicsRayQueryParameters3D ray, PhysicsDirectSpaceState3D physicsState ) { var result = physicsState.IntersectRay( ray ); if ( ! result.ContainsKey( "collider" ) ) { hasCollision = false; return; } hasCollision = true; collider = result[ "collider" ].As(); normal = result[ "normal" ].AsVector3(); position = result[ "position" ].AsVector3(); shape = result[ "shape" ].As(); rid = result[ "rid" ].AsRid(); // RJLog.Log( "Has Collision:", HierarchyName.Of( collider ), ">> at position:", position, "with normal:", normal ); } public static CollisionData FindCollision( World3D world, PhysicsRayQueryParameters3D rayParameters, Func predicate ) { var physics = world.DirectSpaceState; var excludes = new Array(); var maxHits = 10000; for ( int i = 0; i < maxHits; i++ ) { rayParameters.Exclude = excludes; var collisionData = new CollisionData(); collisionData.Get( rayParameters, physics ); if ( ! collisionData.hasCollision ) { return null; } if ( predicate( collisionData ) ) { return collisionData; } excludes.Add( collisionData.rid ); } return null; } public static int MultiRayCast( World3D world, PhysicsRayQueryParameters3D rayParameters, List collisionsOutput ) { var physics = world.DirectSpaceState; var excludes = new Array(); var numCollisions = 0; for ( int i = 0; i < collisionsOutput.Count; i++ ) { rayParameters.Exclude = excludes; var collisionData = collisionsOutput[ i ]; collisionData.Get( rayParameters, physics ); if ( ! collisionData.hasCollision ) { return i; } excludes.Add( collisionData.rid ); numCollisions ++; } return numCollisions; } public static List MultiRayCast( World3D world, PhysicsRayQueryParameters3D rayParameters, int maxHits = 100 ) { var physics = world.DirectSpaceState; var excludes = new Array(); var collisions = new List(); for ( int i = 0; i < maxHits; i++ ) { rayParameters.Exclude = excludes; var collisionData = new CollisionData(); collisionData.Get( rayParameters, physics ); if ( ! collisionData.hasCollision ) { return collisions; } excludes.Add( collisionData.rid ); collisions.Add( collisionData ); } return collisions; } } }