using System.Collections.Generic; using Godot; using Rokojori; namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/OnEvent.svg") ] public partial class OnCollision:Node,iNodeState { [Export] public Area3D area; [Export] public Selector selector; [Export] public Action onEntered; [Export] public Action onInside; [Export] public Action onExit; Dictionary _inside = new Dictionary(); List _nodes = new List(); public List GetNodesInside() { _nodes = _nodes.Filter( n => n != null && IsInstanceValid( n ) ); return _nodes; } public void OnNodeStateChanged( bool processEnabled, bool inputEnabled, bool physicsEnabled, bool signalsEnabled, Node.ProcessModeEnum processMode, bool visible ) { if ( ! processEnabled || ! physicsEnabled || Node.ProcessModeEnum.Disabled == processMode ) { this.LogInfo( "Clearing nodes" ); _nodes.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; } if ( ! Selector.IsSelecting( selector, n ) ) { return; } if ( ! _nodes.Contains( n ) ) { _nodes.Add( n ); } // this.LogInfo( "Selecting Enter", area.GlobalPosition, HierarchyName.Of( n ), ( (Node3D)n ).GlobalPosition ); Action.Trigger( onEntered ); if ( onInside == null ) { return; } var tm = Unique.Get(); if ( tm == null ) { return; } var callback = ()=>{ Action.Trigger( onInside ); }; _inside[ n ] = callback; tm.AddProcessCallback( callback ); } void TriggerOnExited( Node n ) { _nodes.Remove( n ); if ( ! Selector.IsSelecting( selector, n ) ) { return; } Action.Trigger( onExit ); if ( ! _inside.ContainsKey( n ) ) { return; } var tm = Unique.Get(); if ( tm == null ) { return; } var callback = _inside[ n ]; tm.RemoveProcessCallback( callback ); _inside.Remove( n ); } } }