2023-12-14 22:59:25 +00:00
using UnityEngine ;
using System.Collections.Generic ;
using TriInspector ;
namespace R0bbie.Timeline
{
/// <summary>
/// Toggle between step option based on what external TimelineTrigger is received
/// </summary>
[AddComponentMenu("Timeline/StepSwitches/External Trigger (Step Switch)")]
public class ExternalTriggerStepSwitch : StepSwitch
{
enum IfStepAlreadyPlayedAction
{
PlayAgain ,
DoNothing ,
SkipSwitch
}
[System.Serializable]
struct TriggerSwitch
{
[SerializeField] public TimelineTrigger trigger ;
[SerializeField] public Step stepOption ;
[SerializeField] public IfStepAlreadyPlayedAction ifStepPrevPlayed ;
}
[Title("Switch Options")]
[SerializeField] List < TriggerSwitch > triggerSwitches = new List < TriggerSwitch > ( ) ;
[Title("Adjust Trigger Behaviour")]
[SerializeField, Tooltip("If a trigger attached to this switch was triggered previously, set the corresponding step option as active immediately, rather than waiting for a live trigger.")] private bool switchImmediatelyIfPrevTriggered ;
[ShowIf(nameof(switchImmediatelyIfPrevTriggered))]
[SerializeField, Tooltip("If no triggers attached to this switch have been triggered previously, just skip this switch altogether.")] private bool skipImmediatelyIfNotPrevTriggered ;
/// <summary>
/// Initialise the StepSwitch by Timeline
/// </summary>
public override void Init ( StepTimeline _stepTimeline )
{
// Setup necessary refs such as parent timeline
attachedStepTimeline = _stepTimeline ;
// Inactive by default
activeMode = Mode . Inactive ;
// Init all step switch options
foreach ( TriggerSwitch triggerSwitch in triggerSwitches )
{
triggerSwitch . stepOption . Init ( attachedStepTimeline , this ) ;
}
init = true ;
}
/// <summary>
/// Initialise the StepSwitch by StepController
/// </summary>
public override void Init ( StepController _controller )
{
// Setup necessary refs such as parent controller
attachedController = _controller ;
// Inactive by default
activeMode = Mode . Inactive ;
// Init all step switch options
foreach ( TriggerSwitch triggerSwitch in triggerSwitches )
{
triggerSwitch . stepOption . Init ( attachedController , this ) ;
}
init = true ;
}
/// <summary>
/// Play this StepSwitch, in turn playing whichever step its conditions point to
/// </summary>
public override void Play ( )
{
Debug . Log ( name + " - Started" ) ;
isActive = true ;
activeMode = Mode . WaitingForEvent ;
// Option to play a child option immediately if the paired trigger was triggered previously
if ( switchImmediatelyIfPrevTriggered )
{
// Loop through all triggers and check if any were triggered before
foreach ( TriggerSwitch triggerSwitch in triggerSwitches )
{
// If so we've got our step option to play
if ( triggerSwitch . trigger . triggered )
{
activeStepOption = triggerSwitch . stepOption ;
break ;
}
}
// If no triggers were previously triggered, option to just skip over this switch altogether, and inform the timeline to play the next step
if ( skipImmediatelyIfNotPrevTriggered )
{
SkipSwitch ( ) ;
return ;
}
// If active step is now setup, play it!
if ( activeStepOption )
{
activeMode = Mode . PlayingChildStep ;
activeStepOption . Play ( ) ;
}
}
2024-02-28 18:16:58 +00:00
// Listen for triggers..
foreach ( TriggerSwitch triggerSwitch in triggerSwitches )
{
triggerSwitch . trigger . onTrigger . AddListener ( TriggerContinue ) ;
}
2023-12-14 22:59:25 +00:00
// If we've got here then we want to wait for an external trigger to send instruction to this switch..
}
void SkipSwitch ( )
{
activeMode = Mode . Inactive ;
Continue ( ) ;
}
/// <summary>
/// Trigger command received from external TimelineTrigger
/// </summary>
public override void TriggerContinue ( TimelineTrigger _trigger )
{
if ( ! isActive | | activeMode ! = Mode . WaitingForEvent )
return ;
2024-02-28 18:16:58 +00:00
// Remove listeners
foreach ( TriggerSwitch triggerSwitch in triggerSwitches )
{
triggerSwitch . trigger . onTrigger . RemoveListener ( TriggerContinue ) ;
}
2023-12-14 22:59:25 +00:00
// Find this trigger in the list, and set the corresponding child step as active
int switchIndexInList = triggerSwitches . FindIndex ( x = > x . trigger = = _trigger ) ;
// If this trigger wasn't found in the list, we can't play any child step. Don't do anything
if ( switchIndexInList = = - 1 )
{
Debug . LogWarning ( "ExternalTriggerStepSwitch received a command from a trigger not in the switch list, can't do anything." ) ;
return ;
}
// With the trigger found in the list, set active step option to corresponding step
activeStepOption = triggerSwitches [ switchIndexInList ] . stepOption ;
// Check if step was previously played, and if we want to execute any custom action here if so
if ( activeStepOption . wasCompleted )
{
if ( triggerSwitches [ switchIndexInList ] . ifStepPrevPlayed = = IfStepAlreadyPlayedAction . DoNothing )
{
activeStepOption = null ;
return ;
}
else if ( triggerSwitches [ switchIndexInList ] . ifStepPrevPlayed = = IfStepAlreadyPlayedAction . SkipSwitch )
{
SkipSwitch ( ) ;
return ;
}
}
// Target step option to play is now definitely set..
// Play the selected option, unless it's null (in which case just play next step in timeline)
if ( activeStepOption )
{
activeMode = Mode . PlayingChildStep ;
activeStepOption . Play ( ) ;
}
else
{
Debug . Log ( "The option selected by the step switch was null, so just proceeding to next step in timeline." ) ;
SkipSwitch ( ) ;
}
}
}
}