| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023 | using System.Collections;using System.Collections.Generic;using UnityEngine;//-----------------------------------------------------------------------------// Copyright 2015-2022 RenderHeads Ltd.  All rights reserved.//-----------------------------------------------------------------------------namespace RenderHeads.Media.AVProVideo{	[System.Serializable]	public class MediaPlaylist	{		[System.Serializable]		public class MediaItem		{			public enum SourceType			{				AVProVideoPlayer,				//Texture2D,			}			[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 PlaylistMediaPlayer.Easing.Preset overrideTransitionEasing = PlaylistMediaPlayer.Easing.Preset.Linear;		}		[SerializeField] List<MediaItem> _items = new List<MediaItem>(8);		public List<MediaItem> Items { get { return _items; } }		public bool HasItemAt(int index)		{			return (index >= 0 && index < _items.Count);		}	}	/// <summary>	/// This is a BETA component	/// </summary>	[AddComponentMenu("AVPro Video/Playlist Media Player (BETA)", -80)]	[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,		}		[SerializeField] Shader _transitionShader = null;		[SerializeField] MediaPlayer _playerA = null;		[SerializeField] MediaPlayer _playerB = null;		[SerializeField] bool _playlistAutoProgress = true;		[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;		[SerializeField] PlaylistLoopMode _playlistLoopMode = PlaylistLoopMode.None;		[SerializeField] MediaPlaylist _playlist = new MediaPlaylist();		[Tooltip("Pause the previously playing video. This is useful for systems that will struggle to play 2 videos at once")]		[SerializeField] bool _pausePreviousOnTransition = true;		[SerializeField] Transition _defaultTransition = Transition.None;		[SerializeField] float _defaultTransitionDuration = 1f;		[SerializeField] Easing.Preset _defaultTransitionEasing = Easing.Preset.Linear;		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;		private float _textureTimer;		private float _transitionTimer;		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;			}		}		public MediaPlaylist Playlist { get { return _playlist; } }		public int PlaylistIndex { get { return _playlistIndex; } }		public MediaPlaylist.MediaItem PlaylistItem { get { if (_playlist.HasItemAt(_playlistIndex)) return _playlist.Items[_playlistIndex]; return null; } }		/// <summary>		/// The default transition to use if the transition is not overridden in the MediaItem		/// </summary>		public Transition DefaultTransition { get { return _defaultTransition; } set { _defaultTransition = value; } }				/// <summary>		/// The default duration the transition will take (in seconds) if the transition is not overridden in the MediaItem		/// </summary>		public float DefaultTransitionDuration { get { return _defaultTransitionDuration; } set { _defaultTransitionDuration = value; } }		/// <summary>		/// The default easing the transition will use if the transition is not overridden in the MediaItem		/// </summary>		public Easing.Preset DefaultTransitionEasing { get { return _defaultTransitionEasing; } set { _defaultTransitionEasing = value; } }		/// <summary>		/// Closes videos that aren't playing.  This will save memory but adds extra overhead		/// </summary>		public bool AutoCloseVideo { get { return _autoCloseVideo; } set { _autoCloseVideo = value; } }		/// <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>		public PlaylistLoopMode LoopMode { get { return _playlistLoopMode; } set { _playlistLoopMode = value; } }		/// <summary>		/// Enable the playlist to progress to the next item automatically, or wait for manual trigger via scripting		/// </summary>		public bool AutoProgress { get { return _playlistAutoProgress; } set { _playlistAutoProgress = value; } }		/// <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		{			get { if (CurrentPlayer != null) return CurrentPlayer.Info; return null; }		}		/// <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		{			get { if (CurrentPlayer != null) return CurrentPlayer.Control; return null; }		}		public override ITextureProducer TextureProducer		{			get			{				if (CurrentPlayer != null)				{					if (IsTransitioning())					{						return this;					}					/*if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)					{						return this;					}*/					return CurrentPlayer.TextureProducer;				}				return null;			}		}		[SerializeField, Range(0.0f, 1.0f)] float _playlistAudioVolume = 1.0f;		[SerializeField] bool _playlistAudioMuted = false;		public override float AudioVolume		{			get { return _playlistAudioVolume; }			set { _playlistAudioVolume = Mathf.Clamp01(value); if (!IsTransitioning() && CurrentPlayer != null) CurrentPlayer.AudioVolume = _playlistAudioVolume; }		}		public override bool AudioMuted		{			get { return _playlistAudioMuted; } 			set { _playlistAudioMuted = value; if (!IsTransitioning() && CurrentPlayer != null) CurrentPlayer.AudioMuted = _playlistAudioMuted; } 		}		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;		}		private void SwapPlayers()		{			// 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);			// Start the transition			if (_currentTransition != Transition.None)			{				// Create a new transition texture if required				Texture currentTexture = GetCurrentTexture();				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);					}					Graphics.Blit(currentTexture, _rt);					_material.SetTexture(PropFromTex.Id, currentTexture);					_easeFunc = Easing.GetFunction(_currentTransitionEasing);					_transitionTimer = 0f;				}				else				{					// Immediately complete the transition					_transitionTimer = _currentTransitionDuration;					// 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;		}		private Texture GetCurrentTexture()		{			/*if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)			{				return _currentItem.texture;			}			else*/ if (CurrentPlayer != null && CurrentPlayer.TextureProducer != null)			{				return CurrentPlayer.TextureProducer.GetTexture();			}			return null;		}		private Texture GetNextTexture()		{			/*if (_nextItem != null && _nextItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _nextItem.texture != null)			{				return _nextItem.texture;			}			else*/ if (_nextPlayer != null && _nextPlayer.TextureProducer != null)			{				return _nextPlayer.TextureProducer.GetTexture();			}			return null;		}		private void Awake()		{			#if UNITY_IOS && !UNITY_EDITOR_OSX				Application.targetFrameRate = 60;			#endif			_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)				{					CurrentPlayer.Events.AddListener(OnVideoEvent);					if (NextPlayer)					{						NextPlayer.Events.AddListener(OnVideoEvent);					}				}				JumpToItem(0);			}		}		public void OnVideoEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode)		{			if (mp == CurrentPlayer)			{				Events.Invoke(mp, et, errorCode);			}			switch (et)			{				case MediaPlayerEvent.EventType.FirstFrameReady:					if (mp == NextPlayer)					{						SwapPlayers();						Events.Invoke(mp, et, errorCode);					}					break;				case MediaPlayerEvent.EventType.FinishedPlaying:					if (_playlistAutoProgress && mp == CurrentPlayer && _currentItem.progressMode == ProgressMode.OnFinish)					{						NextItem();					}					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()				SwapPlayers();			}			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()		{			if (_rt != null && _transitionTimer < _currentTransitionDuration && _currentTransition != Transition.None)			{				return true;			}			return false;		}		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()		{			if (!Application.isPlaying) return;			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();					Graphics.Blit(GetCurrentTexture(), _rt, _material);					// 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				{					if (_playlistAutoProgress && _nextItem == null && _currentItem != null && _currentItem.progressMode == ProgressMode.BeforeFinish && Control != null && Control.HasMetaData() && Control.GetCurrentTime() >= (Info.GetDuration() - (_currentItem.progressTimeSeconds)))					{						this.NextItem();					}					else if (_playlistAutoProgress && _currentItem == null)					{						JumpToItem(_playlistIndex);					}				}			}			base.Update();		}#region Implementing ITextureProducer		public Texture GetTexture(int index = 0)		{			// TODO: support iOS YCbCr by supporting multiple textures			/*if (!IsTransitioning())			{				if (_currentItem != null && _currentItem.sourceType == MediaPlaylist.MediaItem.SourceType.Texture2D && _currentItem.texture != null)				{					return _currentItem.texture;				}			}*/			return _rt;		}		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();		}#endregion Implementing ITextureProducer		private static string GetTransitionName(Transition transition)		{			switch (transition)			{				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";			}			return string.Empty;		}#region Easing		/// <summary>		/// Easing functions		/// </summary>		[System.Serializable]		public class Easing		{			public Preset preset = Preset.Linear;			public enum Preset			{				Step,				Linear,				InQuad,				OutQuad,				InOutQuad,				InCubic,				OutCubic,				InOutCubic,				InQuint,				OutQuint,				InOutQuint,				InQuart,				OutQuart,				InOutQuart,				InExpo,				OutExpo,				InOutExpo,				Random,				RandomNotStep,			}			public static System.Func<float, float> GetFunction(Preset preset)			{				System.Func<float, float> result = null;				switch (preset)				{					case Preset.Step:						result = Step;						break;					case Preset.Linear:						result = Linear;						break;					case Preset.InQuad:						result = InQuad;						break;					case Preset.OutQuad:						result = OutQuad;						break;					case Preset.InOutQuad:						result = InOutQuad;						break;					case Preset.InCubic:						result = InCubic;						break;					case Preset.OutCubic:						result = OutCubic;						break;					case Preset.InOutCubic:						result = InOutCubic;						break;					case Preset.InQuint:						result = InQuint;						break;					case Preset.OutQuint:						result = OutQuint;						break;					case Preset.InOutQuint:						result = InOutQuint;						break;					case Preset.InQuart:						result = InQuart;						break;					case Preset.OutQuart:						result = OutQuart;						break;					case Preset.InOutQuart:						result = InOutQuart;						break;					case Preset.InExpo:						result = InExpo;						break;					case Preset.OutExpo:						result = OutExpo;						break;					case Preset.InOutExpo:						result = InOutExpo;						break;					case Preset.Random:						result = GetFunction((Preset)Random.Range(0, (int)Preset.Random));						break;					case Preset.RandomNotStep:						result = GetFunction((Preset)Random.Range((int)Preset.Step+1, (int)Preset.Random));						break;				}				return result;			}			public static float PowerEaseIn(float t, float power)			{				return Mathf.Pow(t, power);			}			public static float PowerEaseOut(float t, float power)			{				return 1f - Mathf.Abs(Mathf.Pow(t - 1f, power));			}			public static float PowerEaseInOut(float t, float power)			{				float result;				if (t < 0.5f)				{					result = PowerEaseIn(t * 2f, power) / 2f;				}				else				{					result = PowerEaseOut(t * 2f - 1f, power) / 2f + 0.5f;				}				return result;			}			public static float Step(float t)			{				float result = 0f;				if (t >= 0.5f)				{					result = 1f;				}				return result;			}			public static float Linear(float t)			{				return t;			}			public static float InQuad(float t)			{				return PowerEaseIn(t, 2f);			}			public static float OutQuad(float t)			{				return PowerEaseOut(t, 2f);				//return t * (2f - t);			}			public static float InOutQuad(float t)			{				return PowerEaseInOut(t, 2f);				//return t < 0.5 ? (2f * t * t) : (-1f + (4f - 2f * t) * t);			}			public static float InCubic(float t)			{				return PowerEaseIn(t, 3f);				//return t * t * t;			}			public static float OutCubic(float t)			{				return PowerEaseOut(t, 3f);				//return (--t) * t * t + 1f;			}			public static float InOutCubic(float t)			{				return PowerEaseInOut(t, 3f);				//return t < .5f ? (4f * t * t * t) : ((t - 1f) * (2f * t - 2f) * (2f * t - 2f) + 1f);			}			public static float InQuart(float t)			{				return PowerEaseIn(t, 4f);				//return t * t * t * t;			}			public static float OutQuart(float t)			{				return PowerEaseOut(t, 4f);				//return 1f - (--t) * t * t * t;			}			public static float InOutQuart(float t)			{				return PowerEaseInOut(t, 4f);				//return t < 0.5f ? (8f * t * t * t * t) : (1f - 8f * (--t) * t * t * t);			}			public static float InQuint(float t)			{				return PowerEaseIn(t, 5f);				//return t * t * t * t * t;			}			public static float OutQuint(float t)			{				return PowerEaseOut(t, 5f);				//return 1f + (--t) * t * t * t * t;			}			public static float InOutQuint(float t)			{				return PowerEaseInOut(t, 5f);				//return t < 0.5f ? (16f * t * t * t * t * t) : (1f + 16f * (--t) * t * t * t * t);			}			public static float InExpo(float t)			{				float result = 0f;				if (t != 0f)				{					result = Mathf.Pow(2f, 10f * (t - 1f));				}				return result;			}			public static float OutExpo(float t)			{				float result = 1f;				if (t != 1f)				{					result = -Mathf.Pow(2f, -10f * t) + 1f;				}				return result;			}			public static float InOutExpo(float t)			{				float result = 0f;				if (t > 0f)				{					result = 1f;					if (t < 1f)					{						t *= 2f;						if (t < 1f)						{							result = 0.5f * Mathf.Pow(2f, 10f * (t - 1f));						}						else						{							t--;							result = 0.5f * (-Mathf.Pow(2f, -10f * t) + 2f);						}					}				}				return result;			}		}#endregion Easing	}}
 |