You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.3 KiB
121 lines
4.3 KiB
using UnityEngine; |
|
using UnityEngine.Playables; |
|
using UnityEngine.Video; |
|
|
|
namespace Timeline.Samples |
|
{ |
|
// The runtime instance of a video clip player in Timeline. |
|
public sealed class VideoPlayableBehaviour : PlayableBehaviour |
|
{ |
|
public VideoPlayer videoPlayer; |
|
|
|
public double preloadTime; |
|
public double clipInTime; |
|
public double startTime; |
|
|
|
private bool preparing; |
|
|
|
// Called by the mixer (VideoSchedulerPlayableBehaviour) when this is nearly active to |
|
// give the video time to load. |
|
public void PrepareVideo() |
|
{ |
|
if (videoPlayer == null || videoPlayer.isPrepared || preparing) |
|
return; |
|
|
|
videoPlayer.targetCameraAlpha = 0.0f; |
|
videoPlayer.time = clipInTime; |
|
videoPlayer.Prepare(); |
|
preparing = true; |
|
} |
|
|
|
// Called each frame the clip is active. |
|
// |
|
public override void PrepareFrame(Playable playable, FrameData info) |
|
{ |
|
if (videoPlayer == null) |
|
return; |
|
|
|
// Pause or Play the video to match whether the graph is being scrubbed or playing |
|
// If we need to hold the last frame, this will treat the last frame as a pause |
|
bool shouldBePlaying = info.evaluationType == FrameData.EvaluationType.Playback; |
|
if (!videoPlayer.isLooping && playable.GetTime() >= videoPlayer.clip.length) |
|
shouldBePlaying = false; |
|
|
|
if (shouldBePlaying) |
|
{ |
|
// this will use the timeline time to prevent drift |
|
videoPlayer.timeReference = VideoTimeReference.ExternalTime; |
|
if (!videoPlayer.isPlaying) |
|
videoPlayer.Play(); |
|
videoPlayer.externalReferenceTime = playable.GetTime() / videoPlayer.playbackSpeed; |
|
} |
|
else |
|
{ |
|
videoPlayer.timeReference = VideoTimeReference.Freerun; |
|
if (!videoPlayer.isPaused) |
|
videoPlayer.Pause(); |
|
SyncVideoToPlayable(playable); |
|
} |
|
|
|
// use the accumulated blend value to set the alpha and the audio volume |
|
videoPlayer.targetCameraAlpha = info.effectiveWeight; |
|
if (videoPlayer.audioOutputMode == VideoAudioOutputMode.Direct) |
|
{ |
|
for (ushort i = 0; i < videoPlayer.clip.audioTrackCount; ++i) |
|
videoPlayer.SetDirectAudioVolume(i, info.effectiveWeight); |
|
} |
|
} |
|
|
|
// Called when the clip becomes active. |
|
public override void OnBehaviourPlay(Playable playable, FrameData info) |
|
{ |
|
if (videoPlayer == null) |
|
return; |
|
|
|
SyncVideoToPlayable(playable); |
|
videoPlayer.playbackSpeed = Mathf.Clamp(info.effectiveSpeed, 1 / 10f, 10f); |
|
videoPlayer.Play(); |
|
preparing = false; |
|
} |
|
|
|
// Called when the clip becomes inactive OR the timeline is 'paused' |
|
public override void OnBehaviourPause(Playable playable, FrameData info) |
|
{ |
|
if (videoPlayer == null) |
|
return; |
|
|
|
preparing = false; |
|
|
|
// The effective weight will be greater than 0 if the graph is paused and the playhead is still on this clip. |
|
if (info.effectiveWeight <= 0) |
|
videoPlayer.Stop(); |
|
else |
|
videoPlayer.Pause(); |
|
} |
|
|
|
// Called when the playable is destroyed. |
|
public override void OnPlayableDestroy(Playable playable) |
|
{ |
|
if (videoPlayer != null) |
|
{ |
|
videoPlayer.Stop(); |
|
if (Application.isPlaying) |
|
Object.Destroy(videoPlayer.gameObject); |
|
else |
|
Object.DestroyImmediate(videoPlayer.gameObject); |
|
} |
|
} |
|
|
|
// Syncs the video player time to playable time |
|
private void SyncVideoToPlayable(Playable playable) |
|
{ |
|
if (videoPlayer == null || videoPlayer.clip == null) |
|
return; |
|
|
|
if (videoPlayer.isLooping) |
|
videoPlayer.time = playable.GetTime() % videoPlayer.clip.length; |
|
else |
|
videoPlayer.time = System.Math.Min(playable.GetTime(), videoPlayer.clip.length); |
|
} |
|
} |
|
}
|
|
|