/// Unity default Start function, called the first time the script is activated. Used here to check if timeline should auto-play or just be initialised ready for play
/// </summary>
voidStart()
{
// If playOnStart then start playing first step in timeline, otherwise just initialise everything ready for play, and wait for Play to be called externally
if(playOnStart)
Play();
else
Init();
}
/// <summary>
/// Initialise timeline ready for play
/// </summary>
voidInit()
{
// Avoid duplicated initialisation
if(init)
return;
// Get refs to all child steps (only 1 level deep to avoid getting children of StepGroups and StepSwitches etc, as these will initialise their own children)
foreach(Transformtintransform)
{
if(t.GetComponent<Step>())
{
steps.Add(t.GetComponent<Step>());
}
}
// Initialise Steps (and StepGroups and StepSwitches)
foreach(varstepinsteps)
{
step.Init(this);
}
init=true;
}
/// <summary>
/// Play the timeline
/// </summary>
publicvoidPlay()
{
if(!init)
Init();
// Don't try and start playing the timeline if it's already playing
// Check if timeline is already playing, and if we need to take any action first
if(isPlaying)
{
if(!_skipToIfPlaying)
{
// Don't try and start playing the timeline if it's already playing
return;
}
else
{
// Otherwise, before we play from this step, end the current step, if one is active
if(activeStep)
activeStep.ForceEnd();
// TODO: Possibly don't allow if step requested is earlier than the active step?
}
}
isPlaying=true;
isComplete=false;
StepTimelineManager.activeStepTimeline=this;
// Invoke timeline play event
onTimelinePlayEvent?.Invoke();
// Play the requested step
GoToStepAndPlay(_playFromStep);
}
/// <summary>
/// Play the next step in timeline. Called by Continue function on Step, which should ensure the previously active step is tidied up and set inactive before playing asking the timeline to play the next one
/// </summary>
publicvoidPlayNextStep()
{
// If the controller is playing force the step to end as the timeline has been resumed and has priority on the level
if(StepTimelineManager.activeController)
{
StepTimelineManager.activeController.ForceEnd();
}
activeStepIndex++;
// Check we've not reached the end of the timeline, before playing the next step (if there is one)
if(activeStepIndex>=steps.Count)
{
TimelineCompleted();
}
else
{
SetActiveStep(activeStepIndex);
activeStep.Play();
}
}
/// <summary>
/// Internal only function to set activeStep and associated vars
/// </summary>
/// <param name="_newActiveStepIndex">New active step index on the main timeline</param>
voidSetActiveStep(int_newActiveStepIndex)
{
activeStep=steps[_newActiveStepIndex];
activeStepIsGroup=(activeStepisStepGroup);
activeStepHasVariants=(activeStepisStepSwitch);
}
publicvoidStepContinuedEvent()
{
// Invoke step continued event
onStepContinued?.Invoke();
}
/// <summary>
/// Play a specific step which may not be the "next" one (may mean replaying an already played step or jumping to a future one), and update activeStepIndex to the desired one
/// </summary>
/// <param name="_step">Reference to the Step the timeline should now play</param>
publicvoidGoToStepAndPlay(Step_step)
{
// Make absolutely sure previously active step has been set inactive before setting the new active one and playing
if(activeStep&&activeStep.isActive)
activeStep.ForceEnd();
// Make sure requested step isn't a child of a step switch - only step switches should play a sub-option
if(_step.parentStepSwitch)
{
Debug.LogError("Can't 'GoTo' a step which is a child of a step switch. Use the step switch to switch between options, or move the step outwith the switch!");
return;
}
// If requested step has a parent step group, we want to activate the step group first, then jump to it
if(_step.parentStepGroup)
{
// Tell the direct parent step group to jump to the step and play it (will handle any other intermediary step groups between the timeline root and the step there)
_step.parentStepGroup.GoToStepAndPlay(_step);
// GoToStepAndPlay will in turn recurse upwards and find the highest level group before the root timeline, and call back into Timeline via BLAAA to set it active
}
else// Otherwise this is just a normal step with no parent step group, play it directly
// If this command implements ISingleInstance make sure there are no existing ISingleInstances in the active list (there can only be one active at a time..)
if(_commandToAddToListisISingleInstance)
{
// remove all existing ISingleInstance from list before adding another. iterate through all current pausable commands backwards to check
for(inti=activePausableCommands.Count-1;i>=0;i--)
{
if(activePausableCommands[i]isISingleInstance)
activePausableCommands.RemoveAt(i);
}
}
// Add to list
activePausableCommands.Add(_commandToAddToList);
}
/// <summary>
/// When a pausable command is deactivated, remove it from list