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

166 lines
3.5 KiB
C#

using Godot;
using System.Collections;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/Collider.svg")]
public partial class Collider:Node, iNodeState
{
[Export]
public Area3D area;
[Export]
public CollisionFlag collisionType;
[Export]
public Action onEntered;
[Export]
public Action onInside;
[Export]
public Action onExit;
[Export]
public bool activateAlwaysOnInside = false;
Dictionary<Collidable,System.Action> _inside = new Dictionary<Collidable,System.Action>();
public void OnNodeStateChanged()
{
if ( ! IsProcessing() || ! IsPhysicsProcessing() || Node.ProcessModeEnum.Disabled == this.ProcessMode )
{
// this.LogInfo( "Clearing nodes" );
_inside.Clear();
}
}
public override void _Ready()
{
if ( area == null )
{
return;
}
area.AreaEntered += TriggerOnEnter;
area.BodyEntered += TriggerOnEnter;
area.AreaExited += _TriggerOnExited;
area.BodyExited += _TriggerOnExited;
}
public void TriggerOnCollisionEnter( Projectile p, KinematicCollision3D collision )
{
// this.LogInfo( "Collider:", collision.GetCollider( 0 ), "Shape:", collision.GetColliderShape( 0 ) );
_TriggerOnEnter( (Node) collision.GetCollider( 0 ) );
}
public void TriggerOnCollisionExit( Projectile p, KinematicCollision3D collision )
{
// this.LogInfo( "Collider:", collision.GetCollider( 0 ), "Shape:", collision.GetColliderShape( 0 ) );
_TriggerOnExited( (Node) collision.GetCollider( 0 ) );
}
public void TriggerOnEnter( Node3D node3D )
{
// this.LogInfo( "Collider:", collision.GetCollider( 0 ), "Shape:", collision.GetColliderShape( 0 ) );
_TriggerOnEnter( node3D );
}
public void TriggerOnExited( Node3D node3D )
{
// this.LogInfo( HierarchyName.Of( node3D ) );
_TriggerOnExited( node3D );
}
Collidable GetCollidable( Node n )
{
if ( n is Collidable c && c.IsCollidingWith( this ) )
{
return c;
}
return n.FindDirectChild<Collidable>( c => c.IsCollidingWith( this ) );
}
void _TriggerOnEnter( Node n )
{
if ( n == null )
{
return;
}
if ( area != null && ! Math3D.IsValid( area.GlobalPosition ) )
{
return;
}
var collidable = GetCollidable( n );
if ( collidable == null )
{
return;
}
collidable.Collide( this, CollisionPhase.Entered );
if ( ( ! activateAlwaysOnInside ) && onInside == null )
{
return;
}
var tm = Unique<TimeLineManager>.Get();
if ( tm == null )
{
return;
}
var callback = ()=>
{
collidable.Collide( this, CollisionPhase.Inside );
};
_inside[ collidable ] = callback;
tm.AddProcessCallback( callback );
}
void _TriggerOnExited( Node n )
{
var collidable = GetCollidable( n );
if ( collidable == null )
{
return;
}
collidable.Collide( this, CollisionPhase.Exit );
if ( ! _inside.ContainsKey( collidable ) )
{
return;
}
var tm = Unique<TimeLineManager>.Get();
var callback = _inside[ collidable ];
_inside.Remove( collidable );
if ( tm == null )
{
return;
}
tm.RemoveProcessCallback( callback );
}
}
}