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

121 lines
2.3 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;
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;
}
void TriggerOnEnter( Node n )
{
if ( ! Math3D.IsValid( area.GlobalPosition ) )
{
return;
}
var collidable = n.Get<Collidable>();
if ( collidable == null || ! collidable.IsCollidingWith( this ) )
{
return;
}
collidable.Collide( this, CollisionPhase.Entered );
if ( 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 = n.Get<Collidable>();
if ( collidable == null || ! collidable.IsCollidingWith( this ) )
{
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 );
}
}
}