step-timeline/Scripts/Commands/VideoCmd.cs

125 lines
3.5 KiB
C#

using TriInspector;
using UnityEngine;
using UnityEngine.Video;
namespace R0bbie.Timeline
{
/// <summary>
/// Video StepCmd type, used to control a video
/// </summary>
[AddComponentMenu("Timeline/Commands/Video (Step Command)")]
[RequireComponent(typeof(Step))]
public class VideoCmd : StepCmd, IPausable
{
// Exposed variables
[Title("Video Settings")]
[SerializeField] protected VideoPlayer videoPlayer;
[SerializeField] protected VideoClip clip;
bool eventSubscribed_VideoEndReached;
/// <summary>
/// Initialise command (called before Activate)
/// </summary>
protected override void Init()
{
init = true;
}
public override void Activate(Step _parentStep)
{
base.Activate(_parentStep);
// TODO: Consider what the command itself should control, or pass to an external controller
// What about looping videos etc? Would you want the command to start a video looping and leave it looping once the command was complete?
// Complete conditions - On video end, on number of loops?
// Ensure video player component is active, and set clip to the one we want to play
videoPlayer.gameObject.SetActive(true);
videoPlayer.clip = clip;
// Listen for event when video reaches end
videoPlayer.loopPointReached += VideoEndReached;
eventSubscribed_VideoEndReached = true;
// Play video
videoPlayer.Play();
}
private void VideoEndReached(VideoPlayer _videoPlayer)
{
// Unsubscribe from event
videoPlayer.loopPointReached -= VideoEndReached;
eventSubscribed_VideoEndReached = false;
// Ensure video stopped
videoPlayer.Stop();
// Clear clip
videoPlayer.clip = null;
// Complete command
Complete();
}
protected override void Cleanup()
{
active = false;
}
public void Pause()
{
if (!active)
return;
// Pause video
videoPlayer.Pause();
}
public void Resume(float _elapsedTime)
{
if (!active)
return;
// If the time paused is longer than RepeatOnResumeDelay const, then we'll repeat the animation from the start
if (_elapsedTime >= StepTimeline.RepeatOnResumeDelay && !dontRepeatOnPauseResume)
{
RepeatFromStart();
}
else
{
// Resume video (if currently paused)
if (videoPlayer.isPaused)
{
videoPlayer.Play();
}
}
}
void RepeatFromStart()
{
// Ensure we're still subscribed to video end event
if (!eventSubscribed_VideoEndReached)
{
videoPlayer.loopPointReached += VideoEndReached;
eventSubscribed_VideoEndReached = true;
}
// Reset video player to start then play
videoPlayer.frame = 0;
videoPlayer.Play();
}
}
}