2024-09-05 16:43:17 +02:00
//-----------------------------------------------------------------------------
2025-02-21 10:21:19 +01:00
// Copyright 2015-2025 RenderHeads Ltd. All rights reserved.
2024-09-05 16:43:17 +02:00
//-----------------------------------------------------------------------------
2025-02-21 10:21:19 +01:00
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
2024-09-05 16:43:17 +02:00
namespace RenderHeads.Media.AVProVideo
{
[System.Serializable]
public class MediaPlaylist
{
[System.Serializable]
public class MediaItem
{
public enum SourceType
{
AVProVideoPlayer ,
}
2025-02-21 10:21:19 +01:00
[SerializeField]
public string name = string . Empty ;
[SerializeField]
public SourceType sourceType = SourceType . AVProVideoPlayer ;
[SerializeField]
public MediaPath mediaPath = new MediaPath ( ) ;
[SerializeField]
public Texture2D texture = null ;
[SerializeField]
public float textureDuration ;
[SerializeField]
public bool loop = false ;
[SerializeField]
public PlaylistMediaPlayer . StartMode startMode = PlaylistMediaPlayer . StartMode . Immediate ;
[SerializeField]
public PlaylistMediaPlayer . ProgressMode progressMode = PlaylistMediaPlayer . ProgressMode . OnFinish ;
[SerializeField]
public float progressTimeSeconds = 0.5f ;
[SerializeField]
public bool isOverrideTransition = false ;
[SerializeField]
public PlaylistMediaPlayer . Transition overrideTransition = PlaylistMediaPlayer . Transition . None ;
[SerializeField]
public float overrideTransitionDuration = 1f ;
[SerializeField]
public Easing . Preset overrideTransitionEasing = Easing . Preset . Linear ;
}
[SerializeField]
List < MediaItem > _items = new List < MediaItem > ( 8 ) ;
public List < MediaItem > Items
{
get
{
return _items ;
}
2024-09-05 16:43:17 +02:00
}
public bool HasItemAt ( int index )
{
2025-02-21 10:21:19 +01:00
return index > = 0 & & index < _items . Count ;
2024-09-05 16:43:17 +02:00
}
}
/// <summary>
/// This is a BETA component
/// </summary>
2025-02-21 10:21:19 +01:00
[AddComponentMenu("AVPro Video/Playlist Media Player", -80)]
2024-09-05 16:43:17 +02:00
[HelpURL("https://www.renderheads.com/products/avpro-video/")]
public class PlaylistMediaPlayer : MediaPlayer , ITextureProducer
{
public enum Transition
{
None ,
Fade ,
Black ,
White ,
Transparent ,
Horiz ,
Vert ,
Diag ,
MirrorH ,
MirrorV ,
MirrorD ,
ScrollV ,
ScrollH ,
Circle ,
Diamond ,
Blinds ,
Arrows ,
SlideH ,
SlideV ,
Zoom ,
RectV ,
Random ,
}
public enum PlaylistLoopMode
{
None ,
Loop ,
}
public enum StartMode
{
Immediate ,
//AfterSeconds,
Manual ,
}
public enum ProgressMode
{
OnFinish ,
BeforeFinish ,
//AfterTime,
Manual ,
}
2025-02-21 10:21:19 +01:00
[SerializeField]
Shader _transitionShader = null ;
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
[SerializeField]
MediaPlayer _playerA = null ;
[SerializeField]
MediaPlayer _playerB = null ;
[SerializeField]
bool _playlistAutoProgress = true ;
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
[Tooltip("Close the video on the other MediaPlayer when it is not visible any more. This is useful for freeing up memory and GPU decoding resources.")]
[SerializeField]
bool _autoCloseVideo = true ;
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
[SerializeField]
PlaylistLoopMode _playlistLoopMode = PlaylistLoopMode . None ;
[SerializeField]
MediaPlaylist _playlist = new MediaPlaylist ( ) ;
2024-09-05 16:43:17 +02:00
[Tooltip("Pause the previously playing video. This is useful for systems that will struggle to play 2 videos at once")]
2025-02-21 10:21:19 +01:00
[SerializeField]
bool _pausePreviousOnTransition = true ;
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
[SerializeField]
Transition _defaultTransition = Transition . None ;
[SerializeField]
float _defaultTransitionDuration = 1f ;
[SerializeField]
Easing . Preset _defaultTransitionEasing = Easing . Preset . Linear ;
[SerializeField, Range(0.0f, 1.0f)]
float _playlistAudioVolume = 1.0f ;
[SerializeField]
bool _playlistAudioMuted = false ;
2024-09-05 16:43:17 +02:00
private static readonly LazyShaderProperty PropFromTex = new LazyShaderProperty ( "_FromTex" ) ;
private static readonly LazyShaderProperty PropFade = new LazyShaderProperty ( "_Fade" ) ;
private bool _isPaused = false ;
private int _playlistIndex = 0 ;
private MediaPlayer _nextPlayer ;
private Material _material ;
private Transition _currentTransition = Transition . None ;
private string _currentTransitionName = "LERP_NONE" ;
private float _currentTransitionDuration = 1f ;
private Easing . Preset _currentTransitionEasing = Easing . Preset . Linear ;
2025-02-21 10:21:19 +01:00
private float _transitionTimer = float . MaxValue ;
2024-09-05 16:43:17 +02:00
private System . Func < float , float > _easeFunc ;
private RenderTexture _rt ;
private MediaPlaylist . MediaItem _currentItem ;
private MediaPlaylist . MediaItem _nextItem ;
public MediaPlayer CurrentPlayer
{
get
{
if ( NextPlayer = = _playerA )
{
return _playerB ;
}
return _playerA ;
}
}
public MediaPlayer NextPlayer
{
get
{
return _nextPlayer ;
}
}
2025-02-21 10:21:19 +01:00
public MediaPlaylist Playlist
{
get
{
return _playlist ;
}
}
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
public int PlaylistIndex
{
get
{
return _playlistIndex ;
}
}
2024-09-05 16:43:17 +02:00
2025-02-21 10:21:19 +01:00
public MediaPlaylist . MediaItem PlaylistItem
{
get
{
return _playlist . HasItemAt ( _playlistIndex ) ? _playlist . Items [ _playlistIndex ] : null ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// The default transition to use if the transition is not overridden in the MediaItem
/// </summary>
2025-02-21 10:21:19 +01:00
public Transition DefaultTransition
{
get
{
return _defaultTransition ;
}
set
{
_defaultTransition = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// The default duration the transition will take (in seconds) if the transition is not overridden in the MediaItem
/// </summary>
2025-02-21 10:21:19 +01:00
public float DefaultTransitionDuration
{
get
{
return _defaultTransitionDuration ;
}
set
{
_defaultTransitionDuration = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// The default easing the transition will use if the transition is not overridden in the MediaItem
/// </summary>
2025-02-21 10:21:19 +01:00
public Easing . Preset DefaultTransitionEasing
{
get
{
return _defaultTransitionEasing ;
}
set
{
_defaultTransitionEasing = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// Closes videos that aren't playing. This will save memory but adds extra overhead
/// </summary>
2025-02-21 10:21:19 +01:00
public bool AutoCloseVideo
{
get
{
return _autoCloseVideo ;
}
set
{
_autoCloseVideo = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// None: Do not loop the playlist when the end is reached.<br/>Loop: Rewind the playlist and play again when the each is reached
/// </summary>
2025-02-21 10:21:19 +01:00
public PlaylistLoopMode LoopMode
{
get
{
return _playlistLoopMode ;
}
set
{
_playlistLoopMode = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// Enable the playlist to progress to the next item automatically, or wait for manual trigger via scripting
/// </summary>
2025-02-21 10:21:19 +01:00
public bool AutoProgress
{
get
{
return _playlistAutoProgress ;
}
set
{
_playlistAutoProgress = value ;
}
}
2024-09-05 16:43:17 +02:00
/// <summary>
/// Returns the IMediaInfo interface for the MediaPlayer that is playing the current active item in the playlist (returned by CurrentPlayer property). This will change during each transition.
/// </summary>
public override IMediaInfo Info
{
2025-02-21 10:21:19 +01:00
get
{
return CurrentPlayer ! = null ? CurrentPlayer . Info : null ;
}
2024-09-05 16:43:17 +02:00
}
/// <summary>
/// Returns the IMediaControl interface for the MediaPlayer that is playing the current active item in the playlist (returned by CurrentPlayer property). This will change during each transition.
/// </summary>
public override IMediaControl Control
{
2025-02-21 10:21:19 +01:00
get
{
return CurrentPlayer ! = null ? CurrentPlayer . Control : null ;
}
2024-09-05 16:43:17 +02:00
}
public override ITextureProducer TextureProducer
{
get
{
2025-02-21 10:21:19 +01:00
return this ;
2024-09-05 16:43:17 +02:00
}
}
public override float AudioVolume
{
2025-02-21 10:21:19 +01:00
get
{
return _playlistAudioVolume ;
}
set
{
_playlistAudioVolume = Mathf . Clamp01 ( value ) ;
if ( ! IsTransitioning ( ) & & CurrentPlayer ! = null )
{
CurrentPlayer . AudioVolume = _playlistAudioVolume ;
}
}
2024-09-05 16:43:17 +02:00
}
public override bool AudioMuted
{
2025-02-21 10:21:19 +01:00
get
{
return _playlistAudioMuted ;
}
set
{
_playlistAudioMuted = value ;
if ( ! IsTransitioning ( ) & & CurrentPlayer ! = null )
{
CurrentPlayer . AudioMuted = _playlistAudioMuted ;
}
}
2024-09-05 16:43:17 +02:00
}
public override void Play ( )
{
_isPaused = false ;
if ( Control ! = null )
{
Control . Play ( ) ;
}
if ( IsTransitioning ( ) )
{
if ( ! _pausePreviousOnTransition & & NextPlayer . Control ! = null )
{
NextPlayer . Control . Play ( ) ;
}
}
}
public override void Pause ( )
{
_isPaused = true ;
if ( Control ! = null )
{
Control . Pause ( ) ;
}
if ( IsTransitioning ( ) )
{
if ( NextPlayer . Control ! = null )
{
NextPlayer . Control . Pause ( ) ;
}
}
}
public bool IsPaused ( )
{
return _isPaused ;
}
2025-02-21 10:21:19 +01:00
private WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame ( ) ;
private IEnumerator SwapPlayers ( )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
// Need to wait for rendering to complete before swapping the players
yield return _waitForEndOfFrame ;
2024-09-05 16:43:17 +02:00
// Pause the previously playing video
// This is useful for systems that will struggle to play 2 videos at once
if ( _pausePreviousOnTransition )
{
CurrentPlayer . Pause ( ) ;
}
// Tell listeners that the playlist item has changed
Events . Invoke ( this , MediaPlayerEvent . EventType . PlaylistItemChanged , ErrorCode . None ) ;
2025-02-21 10:21:19 +01:00
2024-09-05 16:43:17 +02:00
// Start the transition
if ( _currentTransition ! = Transition . None )
{
// Create a new transition texture if required
2025-02-21 10:21:19 +01:00
Texture currentTexture = GetCurrentPlayerTexture ( ) ;
2024-09-05 16:43:17 +02:00
Texture nextTexture = GetNextTexture ( ) ;
if ( currentTexture ! = null & & nextTexture ! = null )
{
int maxWidth = Mathf . Max ( nextTexture . width , currentTexture . width ) ;
int maxHeight = Mathf . Max ( nextTexture . height , currentTexture . height ) ;
if ( _rt ! = null )
{
if ( _rt . width ! = maxWidth | | _rt . height ! = maxHeight )
{
RenderTexture . ReleaseTemporary ( _rt ) ;
_rt = null ;
}
}
if ( _rt = = null )
{
_rt = RenderTexture . GetTemporary ( maxWidth , maxHeight , 0 , RenderTextureFormat . Default , RenderTextureReadWrite . Default , 1 ) ;
}
_material . SetTexture ( PropFromTex . Id , currentTexture ) ;
2025-02-21 10:21:19 +01:00
_material . SetFloat ( PropFade . Id , 0.0f ) ;
Graphics . Blit ( nextTexture , _rt , _material ) ;
2024-09-05 16:43:17 +02:00
_easeFunc = Easing . GetFunction ( _currentTransitionEasing ) ;
2025-02-21 10:21:19 +01:00
_transitionTimer = 0.0f ;
2024-09-05 16:43:17 +02:00
}
else
{
// Immediately complete the transition
2025-02-21 10:21:19 +01:00
_transitionTimer = float . MaxValue ;
2024-09-05 16:43:17 +02:00
// Immediately update the audio volume
NextPlayer . AudioVolume = this . AudioVolume ;
CurrentPlayer . AudioVolume = 0f ;
if ( _autoCloseVideo )
{
CurrentPlayer . MediaPath . Path = string . Empty ;
CurrentPlayer . CloseMedia ( ) ;
}
}
}
// Swap the videos
if ( NextPlayer = = _playerA )
{
_nextPlayer = _playerB ;
}
else
{
_nextPlayer = _playerA ;
}
// Swap the items
_currentItem = _nextItem ;
_nextItem = null ;
}
2025-02-21 10:21:19 +01:00
private Texture GetCurrentPlayerTexture ( int index = 0 )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
if ( CurrentPlayer ! = null & & CurrentPlayer . TextureProducer ! = null )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
return CurrentPlayer . TextureProducer . GetTexture ( index ) ;
2024-09-05 16:43:17 +02:00
}
2025-02-21 10:21:19 +01:00
else
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
return null ;
2024-09-05 16:43:17 +02:00
}
}
2025-02-21 10:21:19 +01:00
private Texture GetNextTexture ( int index = 0 )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
if ( _nextPlayer ! = null & & _nextPlayer . TextureProducer ! = null )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
return _nextPlayer . TextureProducer . GetTexture ( index ) ;
2024-09-05 16:43:17 +02:00
}
2025-02-21 10:21:19 +01:00
else
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
return null ;
2024-09-05 16:43:17 +02:00
}
}
private void Awake ( )
{
_nextPlayer = _playerA ;
if ( _transitionShader = = null )
{
_transitionShader = Shader . Find ( "AVProVideo/Internal/Transition" ) ;
if ( _transitionShader = = null )
{
Debug . LogError ( "[AVProVideo] Missing transition shader" ) ;
}
}
_material = new Material ( _transitionShader ) ;
_easeFunc = Easing . GetFunction ( _defaultTransitionEasing ) ;
}
protected override void OnDestroy ( )
{
if ( _rt ! = null )
{
RenderTexture . ReleaseTemporary ( _rt ) ;
_rt = null ;
}
if ( _material ! = null )
{
if ( Application . isPlaying )
{
Material . Destroy ( _material ) ;
}
else
{
Material . DestroyImmediate ( _material ) ;
}
_material = null ;
}
base . OnDestroy ( ) ;
}
private void Start ( )
{
if ( Application . isPlaying )
{
if ( CurrentPlayer )
{
2025-02-21 10:21:19 +01:00
CurrentPlayer . Events . AddListener ( OnMediaPlayerEvent ) ;
2024-09-05 16:43:17 +02:00
if ( NextPlayer )
{
2025-02-21 10:21:19 +01:00
NextPlayer . Events . AddListener ( OnMediaPlayerEvent ) ;
2024-09-05 16:43:17 +02:00
}
}
JumpToItem ( 0 ) ;
}
}
2025-02-21 10:21:19 +01:00
public void OnMediaPlayerEvent ( MediaPlayer mediaPlayer , MediaPlayerEvent . EventType eventType , ErrorCode errorCode )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
if ( mediaPlayer = = CurrentPlayer )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
Events . Invoke ( mediaPlayer , eventType , errorCode ) ;
2024-09-05 16:43:17 +02:00
}
2025-02-21 10:21:19 +01:00
switch ( eventType )
2024-09-05 16:43:17 +02:00
{
case MediaPlayerEvent . EventType . FirstFrameReady :
2025-02-21 10:21:19 +01:00
if ( mediaPlayer = = NextPlayer )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
StartCoroutine ( SwapPlayers ( ) ) ;
Events . Invoke ( mediaPlayer , eventType , errorCode ) ;
2024-09-05 16:43:17 +02:00
}
break ;
2025-02-21 10:21:19 +01:00
2024-09-05 16:43:17 +02:00
case MediaPlayerEvent . EventType . FinishedPlaying :
2025-02-21 10:21:19 +01:00
if ( mediaPlayer = = CurrentPlayer )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
if ( _playlistAutoProgress & & _currentItem . progressMode = = ProgressMode . OnFinish )
{
NextItem ( ) ;
}
2024-09-05 16:43:17 +02:00
}
break ;
}
}
public bool PrevItem ( )
{
return JumpToItem ( _playlistIndex - 1 ) ;
}
public bool NextItem ( )
{
bool result = JumpToItem ( _playlistIndex + 1 ) ;
if ( ! result )
{
Events . Invoke ( this , MediaPlayerEvent . EventType . PlaylistFinished , ErrorCode . None ) ;
}
return result ;
}
public bool CanJumpToItem ( int index )
{
if ( _playlistLoopMode = = PlaylistLoopMode . Loop )
{
if ( _playlist . Items . Count > 0 )
{
index % = _playlist . Items . Count ;
if ( index < 0 )
{
index + = _playlist . Items . Count ;
}
}
}
return _playlist . HasItemAt ( index ) ;
}
public bool JumpToItem ( int index )
{
if ( _playlistLoopMode = = PlaylistLoopMode . Loop )
{
if ( _playlist . Items . Count > 0 )
{
index % = _playlist . Items . Count ;
if ( index < 0 )
{
index + = _playlist . Items . Count ;
}
}
}
if ( _playlist . HasItemAt ( index ) )
{
_playlistIndex = index ;
_nextItem = _playlist . Items [ _playlistIndex ] ;
OpenVideoFile ( _nextItem ) ;
return true ;
}
return false ;
}
public void OpenVideoFile ( MediaPlaylist . MediaItem mediaItem )
{
bool isMediaAlreadyLoaded = false ;
if ( NextPlayer . MediaPath = = mediaItem . mediaPath )
{
isMediaAlreadyLoaded = true ;
}
if ( ! mediaItem . isOverrideTransition )
{
SetTransition ( _defaultTransition , _defaultTransitionDuration , _defaultTransitionEasing ) ;
}
else
{
SetTransition ( mediaItem . overrideTransition , mediaItem . overrideTransitionDuration , mediaItem . overrideTransitionEasing ) ;
}
this . Loop = NextPlayer . Loop = mediaItem . loop ;
NextPlayer . MediaPath = new MediaPath ( mediaItem . mediaPath ) ;
this . MediaPath = new MediaPath ( mediaItem . mediaPath ) ;
NextPlayer . AudioMuted = _playlistAudioMuted ;
NextPlayer . AudioVolume = _playlistAudioVolume ;
if ( _transitionTimer < _currentTransitionDuration & & _currentTransition ! = Transition . None )
{
NextPlayer . AudioVolume = 0f ;
}
if ( isMediaAlreadyLoaded )
{
NextPlayer . Rewind ( false ) ;
if ( _nextItem . startMode = = StartMode . Immediate )
{
NextPlayer . Play ( ) ;
}
// TODO: We probably want to wait until the new frame arrives before swapping after a Rewind()
2025-02-21 10:21:19 +01:00
StartCoroutine ( SwapPlayers ( ) ) ;
2024-09-05 16:43:17 +02:00
}
else
{
if ( string . IsNullOrEmpty ( NextPlayer . MediaPath . Path ) )
{
NextPlayer . CloseMedia ( ) ;
}
else
{
NextPlayer . OpenMedia ( NextPlayer . MediaPath . PathType , NextPlayer . MediaPath . Path , _nextItem . startMode = = StartMode . Immediate ) ;
}
}
}
private bool IsTransitioning ( )
{
2025-02-21 10:21:19 +01:00
bool hasTransition = _currentTransition ! = Transition . None ;
bool inTransition = _transitionTimer < _currentTransitionDuration ;
return hasTransition & & inTransition ;
2024-09-05 16:43:17 +02:00
}
private void SetTransition ( Transition transition , float duration , Easing . Preset easing )
{
if ( transition = = Transition . Random )
{
transition = ( Transition ) Random . Range ( 0 , ( int ) Transition . Random ) ;
}
if ( transition ! = _currentTransition )
{
// Disable the previous transition
if ( ! string . IsNullOrEmpty ( _currentTransitionName ) )
{
_material . DisableKeyword ( _currentTransitionName ) ;
}
// Enable the next transition
_currentTransition = transition ;
_currentTransitionName = GetTransitionName ( transition ) ;
_material . EnableKeyword ( _currentTransitionName ) ;
}
_currentTransitionDuration = duration ;
_currentTransitionEasing = easing ;
}
protected override void Update ( )
{
2025-02-21 10:21:19 +01:00
if ( ! Application . isPlaying )
{
return ;
}
2024-09-05 16:43:17 +02:00
if ( ! IsPaused ( ) )
{
if ( IsTransitioning ( ) )
{
_transitionTimer + = Time . deltaTime ;
float t = _easeFunc ( Mathf . Clamp01 ( _transitionTimer / _currentTransitionDuration ) ) ;
// Fade the audio volume
NextPlayer . AudioVolume = ( 1f - t ) * this . AudioVolume ;
CurrentPlayer . AudioVolume = t * this . AudioVolume ;
// TODO: support going from mono to stereo
// TODO: support videos of different aspect ratios by rendering with scaling to fit
// This can be done by blitting twice, once for each eye
// If the stereo mode is different for playera/b then both should be set to stereo during the transition
// if (CurrentPlayer.m_StereoPacking == StereoPacking.TopBottom)....
_material . SetFloat ( PropFade . Id , t ) ;
_rt . DiscardContents ( ) ;
2025-02-21 10:21:19 +01:00
Graphics . Blit ( GetCurrentPlayerTexture ( ) , _rt , _material ) ;
2024-09-05 16:43:17 +02:00
// After the transition is now complete, close/pause the previous video if required
bool isTransitioning = IsTransitioning ( ) ;
if ( ! isTransitioning )
{
if ( _autoCloseVideo )
{
if ( NextPlayer ! = null )
{
NextPlayer . MediaPath . Path = string . Empty ;
NextPlayer . CloseMedia ( ) ;
}
}
else if ( ! _pausePreviousOnTransition )
{
if ( NextPlayer ! = null & & NextPlayer . Control . IsPlaying ( ) )
{
NextPlayer . Pause ( ) ;
}
}
}
}
else
2025-02-21 10:21:19 +01:00
if ( _playlistAutoProgress )
2024-09-05 16:43:17 +02:00
{
2025-02-21 10:21:19 +01:00
if ( _nextItem = = null & &
_currentItem ! = null & &
_currentItem . progressMode = = ProgressMode . BeforeFinish & &
Control ! = null & &
Control . HasMetaData ( ) & &
Control . GetCurrentTime ( ) > = ( Info . GetDuration ( ) - _currentItem . progressTimeSeconds ) )
2024-09-05 16:43:17 +02:00
{
this . NextItem ( ) ;
}
2025-02-21 10:21:19 +01:00
else
if ( _currentItem = = null )
2024-09-05 16:43:17 +02:00
{
JumpToItem ( _playlistIndex ) ;
}
}
}
base . Update ( ) ;
}
2025-02-21 10:21:19 +01:00
#region Implementing ITextureProducer
2024-09-05 16:43:17 +02:00
public Texture GetTexture ( int index = 0 )
{
2025-02-21 10:21:19 +01:00
bool isTransitioning = IsTransitioning ( ) ;
return isTransitioning ? _rt : CurrentPlayer . TextureProducer . GetTexture ( index ) ;
2024-09-05 16:43:17 +02:00
}
public int GetTextureCount ( )
{
return CurrentPlayer . TextureProducer . GetTextureCount ( ) ;
}
public int GetTextureFrameCount ( )
{
return CurrentPlayer . TextureProducer . GetTextureFrameCount ( ) ;
}
public bool SupportsTextureFrameCount ( )
{
return CurrentPlayer . TextureProducer . SupportsTextureFrameCount ( ) ;
}
public long GetTextureTimeStamp ( )
{
return CurrentPlayer . TextureProducer . GetTextureTimeStamp ( ) ;
}
public float GetTexturePixelAspectRatio ( )
{
return CurrentPlayer . TextureProducer . GetTexturePixelAspectRatio ( ) ;
}
public bool RequiresVerticalFlip ( )
{
return CurrentPlayer . TextureProducer . RequiresVerticalFlip ( ) ;
}
public Matrix4x4 GetYpCbCrTransform ( )
{
return CurrentPlayer . TextureProducer . GetYpCbCrTransform ( ) ;
}
public StereoPacking GetTextureStereoPacking ( )
{
return CurrentPlayer . TextureProducer . GetTextureStereoPacking ( ) ;
}
public TransparencyMode GetTextureTransparency ( )
{
return CurrentPlayer . TextureProducer . GetTextureTransparency ( ) ;
}
public AlphaPacking GetTextureAlphaPacking ( )
{
return CurrentPlayer . TextureProducer . GetTextureAlphaPacking ( ) ;
}
public float [ ] GetAffineTransform ( )
{
return CurrentPlayer . TextureProducer . GetAffineTransform ( ) ;
}
public Matrix4x4 GetTextureMatrix ( )
{
return CurrentPlayer . TextureProducer . GetTextureMatrix ( ) ;
}
2025-02-21 10:21:19 +01:00
public RenderTextureFormat GetCompatibleRenderTextureFormat ( GetCompatibleRenderTextureFormatOptions options , int plane )
{
return CurrentPlayer . TextureProducer . GetCompatibleRenderTextureFormat ( options , plane ) ;
}
#endregion Implementing ITextureProducer
2024-09-05 16:43:17 +02:00
private static string GetTransitionName ( Transition transition )
{
switch ( transition )
{
2025-02-21 10:21:19 +01:00
case Transition . None :
return "LERP_NONE" ;
case Transition . Fade :
return "LERP_FADE" ;
case Transition . Black :
return "LERP_BLACK" ;
case Transition . White :
return "LERP_WHITE" ;
case Transition . Transparent :
return "LERP_TRANSP" ;
case Transition . Horiz :
return "LERP_HORIZ" ;
case Transition . Vert :
return "LERP_VERT" ;
case Transition . Diag :
return "LERP_DIAG" ;
case Transition . MirrorH :
return "LERP_HORIZ_MIRROR" ;
case Transition . MirrorV :
return "LERP_VERT_MIRROR" ;
case Transition . MirrorD :
return "LERP_DIAG_MIRROR" ;
case Transition . ScrollV :
return "LERP_SCROLL_VERT" ;
case Transition . ScrollH :
return "LERP_SCROLL_HORIZ" ;
case Transition . Circle :
return "LERP_CIRCLE" ;
case Transition . Diamond :
return "LERP_DIAMOND" ;
case Transition . Blinds :
return "LERP_BLINDS" ;
case Transition . Arrows :
return "LERP_ARROW" ;
case Transition . SlideH :
return "LERP_SLIDE_HORIZ" ;
case Transition . SlideV :
return "LERP_SLIDE_VERT" ;
case Transition . Zoom :
return "LERP_ZOOM_FADE" ;
case Transition . RectV :
return "LERP_RECTS_VERT" ;
}
2024-09-05 16:43:17 +02:00
return string . Empty ;
}
}
2025-02-21 10:21:19 +01:00
}