244 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			244 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Linq; | ||
|  | using UnityEngine; | ||
|  | using UnityEngine.Playables; | ||
|  | using UnityEngine.Timeline; | ||
|  | 
 | ||
|  | namespace UnityEditor.Timeline | ||
|  | { | ||
|  |     class SequenceState : ISequenceState | ||
|  |     { | ||
|  |         readonly WindowState m_WindowState; | ||
|  |         readonly SequenceState m_ParentSequence; | ||
|  | 
 | ||
|  |         double m_Time; | ||
|  |         Range? m_CachedEvaluableRange; | ||
|  | 
 | ||
|  |         public TimelineAsset asset { get; } | ||
|  |         public PlayableDirector director { get; } | ||
|  |         public TimelineClip hostClip { get; } | ||
|  |         public double start { get; } | ||
|  |         public double timeScale { get; } | ||
|  | 
 | ||
|  |         public bool isAssetOnly { get; set; } | ||
|  | 
 | ||
|  |         public double duration | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 if (asset == null) | ||
|  |                     return 0.0; | ||
|  | 
 | ||
|  |                 var assetDuration = asset.durationMode == TimelineAsset.DurationMode.FixedLength ? asset.fixedDuration : asset.duration; | ||
|  |                 return hostClip == null ? assetDuration : Math.Min(hostClip.duration, assetDuration); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         [NonSerialized] List<UnityEngine.Object> m_CachedChildAssets; | ||
|  |         public List<UnityEngine.Object> cachedChildAssets | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 if (m_CachedChildAssets == null && asset != null) | ||
|  |                 { | ||
|  |                     m_CachedChildAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(asset)).ToList(); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 return m_CachedChildAssets; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public void InvalidateChildAssetCache() | ||
|  |         { | ||
|  |             m_CachedChildAssets = null; | ||
|  |         } | ||
|  | 
 | ||
|  |         bool? m_IsReadOnly; | ||
|  |         public bool isReadOnly | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 if (!m_IsReadOnly.HasValue) | ||
|  |                     m_IsReadOnly = FileUtility.IsReadOnly(asset); | ||
|  |                 return m_IsReadOnly.Value; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public void ResetIsReadOnly() | ||
|  |         { | ||
|  |             m_IsReadOnly = null; | ||
|  |         } | ||
|  | 
 | ||
|  |         public TimelineAssetViewModel viewModel | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 return TimelineWindowViewPrefs.GetOrCreateViewModel(asset); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public double time | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 if (m_ParentSequence != null) | ||
|  |                     return hostClip.ToLocalTimeUnbound(m_ParentSequence.time); | ||
|  | 
 | ||
|  |                 return GetLocalTime(); | ||
|  |             } | ||
|  |             set | ||
|  |             { | ||
|  |                 var correctedValue = Math.Min(value, TimeUtility.k_MaxTimelineDurationInSeconds); | ||
|  |                 viewModel.windowTime = correctedValue; | ||
|  | 
 | ||
|  |                 if (m_ParentSequence != null) | ||
|  |                     m_ParentSequence.time = hostClip.FromLocalTimeUnbound(correctedValue); | ||
|  |                 else | ||
|  |                     SetLocalTime(correctedValue); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public int frame | ||
|  |         { | ||
|  |             get { return TimeUtility.ToFrames(time, frameRate); } | ||
|  |             set { time = TimeUtility.FromFrames(Mathf.Max(0, value), frameRate); } | ||
|  |         } | ||
|  | 
 | ||
|  |         public double frameRate | ||
|  |         { | ||
|  |             get | ||
|  |             { | ||
|  |                 if (asset != null) | ||
|  |                     return asset.editorSettings.frameRate; | ||
|  | 
 | ||
|  |                 return TimelineAsset.EditorSettings.kDefaultFrameRate; | ||
|  |             } | ||
|  |             set | ||
|  |             { | ||
|  |                 var settings = asset.editorSettings; | ||
|  |                 if (Math.Abs(settings.frameRate - value) > TimeUtility.kFrameRateEpsilon) | ||
|  |                 { | ||
|  |                     settings.frameRate = Math.Max(value, TimeUtility.kFrameRateEpsilon); | ||
|  |                     EditorUtility.SetDirty(asset); | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public SequenceState(WindowState windowState, TimelineAsset asset, PlayableDirector director, TimelineClip hostClip, SequenceState parentSequence) | ||
|  |         { | ||
|  |             m_WindowState = windowState; | ||
|  |             m_ParentSequence = parentSequence; | ||
|  | 
 | ||
|  |             this.asset = asset; | ||
|  |             this.director = director; | ||
|  |             this.hostClip = hostClip; | ||
|  |             isAssetOnly = asset != null && director == null; | ||
|  | 
 | ||
|  |             start = hostClip == null ? 0.0 : hostClip.start; | ||
|  |             timeScale = hostClip == null ? 1.0 : hostClip.timeScale * parentSequence.timeScale; | ||
|  | 
 | ||
|  |             if (asset != null) | ||
|  |             { | ||
|  |                 asset.AssetModifiedOnDisk += AssetOnAssetModifiedOnDisk; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         void AssetOnAssetModifiedOnDisk() | ||
|  |         { | ||
|  |             m_WindowState?.Refresh(); | ||
|  |         } | ||
|  | 
 | ||
|  |         public Range GetEvaluableRange() | ||
|  |         { | ||
|  |             if (hostClip == null) | ||
|  |                 return new Range | ||
|  |                 { | ||
|  |                     start = 0.0, | ||
|  |                     end = duration | ||
|  |                 }; | ||
|  | 
 | ||
|  |             if (!m_CachedEvaluableRange.HasValue) | ||
|  |             { | ||
|  |                 var globalRange = GetGlobalEvaluableRange(); | ||
|  |                 m_CachedEvaluableRange = new Range | ||
|  |                 { | ||
|  |                     start = ToLocalTime(globalRange.start), | ||
|  |                     end = ToLocalTime(globalRange.end) | ||
|  |                 }; | ||
|  |             } | ||
|  | 
 | ||
|  |             return m_CachedEvaluableRange.Value; | ||
|  |         } | ||
|  | 
 | ||
|  |         public double ToGlobalTime(double t) | ||
|  |         { | ||
|  |             if (hostClip == null) | ||
|  |                 return t; | ||
|  | 
 | ||
|  |             return m_ParentSequence.ToGlobalTime(hostClip.FromLocalTimeUnbound(t)); | ||
|  |         } | ||
|  | 
 | ||
|  |         public double ToLocalTime(double t) | ||
|  |         { | ||
|  |             if (hostClip == null) | ||
|  |                 return t; | ||
|  | 
 | ||
|  |             return hostClip.ToLocalTimeUnbound(m_ParentSequence.ToLocalTime(t)); | ||
|  |         } | ||
|  | 
 | ||
|  |         double GetLocalTime() | ||
|  |         { | ||
|  |             if (!m_WindowState.previewMode && !Application.isPlaying) | ||
|  |                 return viewModel.windowTime; | ||
|  | 
 | ||
|  |             // the time needs to always be synchronized with the director | ||
|  |             if (director != null) | ||
|  |                 m_Time = director.time; | ||
|  | 
 | ||
|  |             return m_Time; | ||
|  |         } | ||
|  | 
 | ||
|  |         void SetLocalTime(double newTime) | ||
|  |         { | ||
|  |             // do this prior to the calback, because the callback pulls from the get | ||
|  |             if (director != null) | ||
|  |                 director.time = newTime; | ||
|  | 
 | ||
|  |             if (Math.Abs(m_Time - newTime) > TimeUtility.kTimeEpsilon) | ||
|  |             { | ||
|  |                 m_Time = newTime; | ||
|  |                 m_WindowState.InvokeTimeChangeCallback(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         Range GetGlobalEvaluableRange() | ||
|  |         { | ||
|  |             if (hostClip == null) | ||
|  |                 return new Range | ||
|  |                 { | ||
|  |                     start = 0.0, | ||
|  |                     end = duration | ||
|  |                 }; | ||
|  | 
 | ||
|  |             var currentRange = new Range | ||
|  |             { | ||
|  |                 start = hostClip.ToLocalTimeUnbound(ToGlobalTime(hostClip.start)), | ||
|  |                 end = hostClip.ToLocalTimeUnbound(ToGlobalTime(hostClip.end)) | ||
|  |             }; | ||
|  | 
 | ||
|  |             return Range.Intersection(currentRange, m_ParentSequence.GetGlobalEvaluableRange()); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void Dispose() | ||
|  |         { | ||
|  |             if (asset != null) | ||
|  |             { | ||
|  |                 asset.AssetModifiedOnDisk -= AssetOnAssetModifiedOnDisk; | ||
|  |             } | ||
|  | 
 | ||
|  |             TimelineWindowViewPrefs.SaveViewModel(asset); | ||
|  |         } | ||
|  |     } | ||
|  | } |