using System.Collections; using System.Collections.Generic; using Godot; using System; namespace Rokojori { [Tool] [GlobalClass] public partial class ProjectOnColliders:Scatterer { [ExportGroup("Ray")] [Export] public Vector3 rayDirection = Vector3.Down; [Export] public float rayLength = 10; [Export] public Vector3 rayOffset = Vector3.Zero; [ExportGroup("Normal")] [Export(PropertyHint.Range, "0,1")] public float rotationAlignment = 1; [Export] public bool discardSteepNormals = true; [Export] public Vector3 steepNormalDirection = Vector3.Down; [Export(PropertyHint.Range, "0,180")] public float steepNormalRemovalAngle = 0; [ExportGroup("Collisions")] [Export( PropertyHint.Layers3DPhysics)] public uint collisionLayer = 0; [Export] public bool collideWithAreas = true; [Export] public bool collideWithBodies = true; [Export] public bool hitFromInside = true; [Export] public bool hitBackFaces = true; protected override List _Scatter( List points, Scatterer root ) { var world = GetWorld3D(); var ray = new PhysicsRayQueryParameters3D(); var direction = rayDirection.Normalized(); var normalizedSteepNormalDirection = steepNormalDirection.Normalized(); var steepNormalRemovalTreshold = Mathf.Cos( Mathf.DegToRad( steepNormalRemovalAngle ) ); points.ForEach( p => { if ( ! p.visible ) { return; } ray.From = p.globalPosition; ray.To = ray.From + direction * rayLength; var collisionData = CollisionData.FindCollision( world, ray, ( cd ) => { if ( ! CollisionData.HasCollisionLayer( cd.collider ) ) { return false; } var colliderCollisionLayer = CollisionData.GetCollisionLayer( cd.collider ); var collides = ( colliderCollisionLayer & collisionLayer ) != 0; // RJLog.Log( "Collision With:", "collides", collides, "colliderLayer:", colliderCollisionLayer, "own", collisionLayer, "name:", cd.collider.Name ); return collides; } ); p.visible = collisionData != null; if ( ! p.visible ) { return; } if ( discardSteepNormals ) { var dot = normalizedSteepNormalDirection.Dot( collisionData.normal ); if ( dot >= steepNormalRemovalTreshold ) { p.visible = false; return; } } p.position = collisionData.position; var alginedRotation =Math3D.AlignUp( p.rotation, collisionData.normal ); p.rotation = p.rotation.Slerp( alginedRotation, rotationAlignment ); } ); return points; } } }