121 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
	
	
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<ScatterPoint> _Scatter( List<ScatterPoint> 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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
} |