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);
|
||
|
}
|
||
|
}
|
||
|
}
|