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 _inside = new Dictionary(); 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( 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.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.Get(); var callback = _inside[ collidable ]; _inside.Remove( collidable ); if ( tm == null ) { return; } tm.RemoveProcessCallback( callback ); } } }