using Godot; using System.Collections.Generic; namespace Rokojori { [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Parallel.svg") ] public partial class Parallel : SequenceAction { public enum Mode { First_Finishes_Sequence, Wait_For_All_To_Finish } [Export] public Mode mode = Mode.Wait_For_All_To_Finish; [Export] public Action[] actions = new Action[ 0 ]; [Export] public bool triggerDirectChildren = true; [Export] public bool ignoreNonSequenceActions = true; [Export] public bool errorsCountAsFinished = false; protected override void _OnTrigger() { var actions = new List( this.actions ); if ( triggerDirectChildren ) { Nodes.ForEachDirectChild( this, a => actions.Add( a ) ); } var sequenceActions = Lists.FilterAndMap( actions, ( a, i ) => a is SequenceAction, a => (SequenceAction) a ); var sequenceID = DispatchStart(); if ( ! ignoreNonSequenceActions && sequenceActions.Count != actions.Count && Mode.First_Finishes_Sequence == mode ) { actions.ForEach( a => Action.Trigger( a ) ); DispatchEnd( sequenceID ); return; } var numFinished = 0; var running = true; sequenceActions.ForEach( sa => { sa.onSequenceDone.Once( ( fe )=> { if ( ! running ) { return; } if ( fe.success || errorsCountAsFinished ) { numFinished ++; if ( Mode.First_Finishes_Sequence == mode ) { running = false; DispatchEnd( sequenceID ); } else if ( Mode.Wait_For_All_To_Finish == mode ) { if ( numFinished == sequenceActions.Count ) { running = false; DispatchEnd( sequenceID ); } } } else { running = false; DispatchCancelled( sequenceID ); } } ); } ); actions.ForEach( a => Action.Trigger( a ) ); } } }