step-timeline/Scripts/StepSwitches/ExternalTriggerStepSwitch.cs

188 lines
6.7 KiB
C#

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);
triggerSwitch.trigger.AddStep(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);
triggerSwitch.trigger.AddStep(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();
}
}
// 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;
// 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();
}
}
}
}