mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Initial commit
This commit is contained in:
commit
3c7cc0c973
8391 changed files with 704313 additions and 0 deletions
|
@ -0,0 +1,106 @@
|
|||
using System;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
interface ISequenceState : IDisposable
|
||||
{
|
||||
TimelineAsset asset { get; }
|
||||
PlayableDirector director { get; }
|
||||
TimelineClip hostClip { get; }
|
||||
double start { get; }
|
||||
double timeScale { get; }
|
||||
double duration { get; }
|
||||
bool isReadOnly { get; }
|
||||
TimelineAssetViewModel viewModel { get; }
|
||||
double time { get; set; }
|
||||
int frame { get; set; }
|
||||
float frameRate { get; set; }
|
||||
|
||||
Range GetEvaluableRange();
|
||||
string TimeAsString(double timeValue, string format = "F2");
|
||||
double ToGlobalTime(double t);
|
||||
double ToLocalTime(double t);
|
||||
void ResetIsReadOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to hold default values for an implementation of ISequenceState.
|
||||
* It could be removed in a phase 2, but it is currently used to limit the scope of
|
||||
* this refactoring: it allows client code to access sequence info without having to
|
||||
* worry about `currentSequence` being null.
|
||||
* In the future this should be removed and we should pass around the correct data
|
||||
* structure (i.e. SequenceState OR WindowState) based on the situation.
|
||||
*/
|
||||
class NullSequenceState : ISequenceState
|
||||
{
|
||||
public TimelineAsset asset { get { return null; } }
|
||||
public PlayableDirector director { get { return null; } }
|
||||
public TimelineClip hostClip { get { return null; } }
|
||||
public double start { get { return 0.0; } }
|
||||
public double timeScale { get { return 1.0; } }
|
||||
public double duration { get { return 0.0; } }
|
||||
public bool isReadOnly { get { return false; } }
|
||||
|
||||
TimelineAssetViewModel m_ViewModel;
|
||||
|
||||
public TimelineAssetViewModel viewModel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_ViewModel == null)
|
||||
m_ViewModel = TimelineWindowViewPrefs.CreateUnassociatedViewModel();
|
||||
return m_ViewModel;
|
||||
}
|
||||
}
|
||||
|
||||
public double time
|
||||
{
|
||||
get { return 0.0; }
|
||||
set { /* NO-OP*/ }
|
||||
}
|
||||
|
||||
public int frame
|
||||
{
|
||||
get { return 0; }
|
||||
set { /* NO-OP*/ }
|
||||
}
|
||||
|
||||
public float frameRate
|
||||
{
|
||||
get { return TimelineAsset.EditorSettings.kDefaultFps; }
|
||||
set { /* NO-OP*/ }
|
||||
}
|
||||
|
||||
public Range GetEvaluableRange()
|
||||
{
|
||||
return new Range();
|
||||
}
|
||||
|
||||
public string TimeAsString(double timeValue, string format = "F2")
|
||||
{
|
||||
return TimeUtility.TimeAsTimeCode(timeValue, frameRate, format);
|
||||
}
|
||||
|
||||
public double ToGlobalTime(double t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
public double ToLocalTime(double t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
public void ResetIsReadOnly()
|
||||
{
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// NO-OP
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 167329c8289a3a14a9e342df49fc4104
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,298 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class SequenceHierarchy : ScriptableObject
|
||||
{
|
||||
readonly List<ISequenceState> m_Sequences = new List<ISequenceState>();
|
||||
|
||||
WindowState m_WindowState;
|
||||
|
||||
[SerializeField]
|
||||
SequencePath m_SerializedPath;
|
||||
|
||||
public ISequenceState masterSequence
|
||||
{
|
||||
get { return m_Sequences.FirstOrDefault(); }
|
||||
}
|
||||
|
||||
public ISequenceState editSequence
|
||||
{
|
||||
get { return m_Sequences.LastOrDefault(); }
|
||||
}
|
||||
|
||||
public int count
|
||||
{
|
||||
get { return m_Sequences.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<ISequenceState> allSequences
|
||||
{
|
||||
get { return m_Sequences; }
|
||||
}
|
||||
|
||||
public static SequenceHierarchy CreateInstance()
|
||||
{
|
||||
var hierarchy = ScriptableObject.CreateInstance<SequenceHierarchy>();
|
||||
hierarchy.hideFlags = HideFlags.HideAndDontSave;
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
public void Init(WindowState owner)
|
||||
{
|
||||
m_WindowState = owner;
|
||||
}
|
||||
|
||||
// This is called when performing Undo operations.
|
||||
// It needs to be called here since some operations are not
|
||||
// allowed (EditorUtility.InstanceIDToObject, for example)
|
||||
// during the ISerializationCallbackReceiver methods.
|
||||
void OnValidate()
|
||||
{
|
||||
if (m_SerializedPath == null || m_WindowState == null || m_WindowState.GetWindow() == null)
|
||||
return;
|
||||
|
||||
m_WindowState.SetCurrentSequencePath(m_SerializedPath, true);
|
||||
}
|
||||
|
||||
public void Add(TimelineAsset asset, PlayableDirector director, TimelineClip hostClip)
|
||||
{
|
||||
if (hostClip == null)
|
||||
AddToCurrentUndoGroup(this); // Merge with selection undo
|
||||
else
|
||||
TimelineUndo.PushUndo(this, "Edit Sub-Timeline");
|
||||
|
||||
Add_Internal(asset, director, hostClip);
|
||||
|
||||
UpdateSerializedPath();
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
if (m_Sequences.Count == 0) return;
|
||||
|
||||
TimelineUndo.PushUndo(this, "Go to Sub-Timeline");
|
||||
|
||||
Remove_Internal();
|
||||
|
||||
UpdateSerializedPath();
|
||||
}
|
||||
|
||||
public ISequenceState GetStateAtIndex(int index)
|
||||
{
|
||||
return m_Sequences[index];
|
||||
}
|
||||
|
||||
public void RemoveUntilCount(int expectedCount)
|
||||
{
|
||||
if (expectedCount < 0 || m_Sequences.Count <= expectedCount) return;
|
||||
|
||||
TimelineUndo.PushUndo(this, "Go to Sub-Timeline");
|
||||
|
||||
RemoveUntilCount_Internal(expectedCount);
|
||||
|
||||
UpdateSerializedPath();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (m_Sequences.Count == 0) return;
|
||||
|
||||
AddToCurrentUndoGroup(this);
|
||||
Clear_Internal();
|
||||
UpdateSerializedPath();
|
||||
}
|
||||
|
||||
public SequencePath ToSequencePath()
|
||||
{
|
||||
var path = new SequencePath();
|
||||
|
||||
if (m_Sequences.Count == 0)
|
||||
return path;
|
||||
|
||||
var rootSequence = m_Sequences[0];
|
||||
var root = 0;
|
||||
if (rootSequence.director != null && rootSequence.director.gameObject != null)
|
||||
root = rootSequence.director.gameObject.GetInstanceID();
|
||||
else if (rootSequence.asset != null)
|
||||
root = rootSequence.asset.GetInstanceID();
|
||||
|
||||
path.SetSelectionRoot(root);
|
||||
|
||||
var resolver = rootSequence.director;
|
||||
|
||||
if (m_Sequences.Count > 1)
|
||||
{
|
||||
for (int i = 1, n = m_Sequences.Count; i < n; ++i)
|
||||
{
|
||||
path.AddSubSequence(m_Sequences[i], resolver);
|
||||
resolver = m_Sequences[i].director;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public bool NeedsUpdate(SequencePath path, bool forceRebuild)
|
||||
{
|
||||
return forceRebuild || !SequencePath.AreEqual(m_SerializedPath, path);
|
||||
}
|
||||
|
||||
public void FromSequencePath(SequencePath path, bool forceRebuild)
|
||||
{
|
||||
if (!NeedsUpdate(path, forceRebuild))
|
||||
return;
|
||||
|
||||
Clear_Internal();
|
||||
|
||||
var rootObject = EditorUtility.InstanceIDToObject(path.selectionRoot);
|
||||
if (rootObject == null)
|
||||
{
|
||||
UpdateSerializedPath();
|
||||
return;
|
||||
}
|
||||
|
||||
var candidateAsset = rootObject as TimelineAsset;
|
||||
if (candidateAsset != null)
|
||||
{
|
||||
Add_Internal(candidateAsset, null, null);
|
||||
UpdateSerializedPath();
|
||||
return;
|
||||
}
|
||||
|
||||
var candidateGameObject = rootObject as GameObject;
|
||||
if (candidateGameObject == null)
|
||||
{
|
||||
UpdateSerializedPath();
|
||||
return;
|
||||
}
|
||||
|
||||
var director = TimelineUtility.GetDirectorComponentForGameObject(candidateGameObject);
|
||||
var asset = TimelineUtility.GetTimelineAssetForDirectorComponent(director);
|
||||
Add_Internal(asset, director, null);
|
||||
|
||||
if (!path.subElements.Any())
|
||||
{
|
||||
UpdateSerializedPath();
|
||||
return;
|
||||
}
|
||||
|
||||
List<SequenceBuildingBlock> buildingBlocks;
|
||||
if (ValidateSubElements(path.subElements, director, out buildingBlocks))
|
||||
{
|
||||
foreach (var buildingBlock in buildingBlocks)
|
||||
Add_Internal(buildingBlock.asset, buildingBlock.director, buildingBlock.hostClip);
|
||||
}
|
||||
|
||||
UpdateSerializedPath();
|
||||
}
|
||||
|
||||
void Add_Internal(TimelineAsset asset, PlayableDirector director, TimelineClip hostClip)
|
||||
{
|
||||
if (hostClip == null)
|
||||
Clear_Internal();
|
||||
|
||||
var parent = m_Sequences.Count > 0 ? editSequence : null;
|
||||
m_Sequences.Add(new SequenceState(m_WindowState, asset, director, hostClip, (SequenceState)parent));
|
||||
}
|
||||
|
||||
void Remove_Internal()
|
||||
{
|
||||
m_Sequences.Last().Dispose();
|
||||
m_Sequences.RemoveAt(m_Sequences.Count - 1);
|
||||
}
|
||||
|
||||
void RemoveUntilCount_Internal(int expectedCount)
|
||||
{
|
||||
while (m_Sequences.Count > expectedCount)
|
||||
{
|
||||
Remove_Internal();
|
||||
}
|
||||
}
|
||||
|
||||
void Clear_Internal()
|
||||
{
|
||||
RemoveUntilCount_Internal(0);
|
||||
}
|
||||
|
||||
void UpdateSerializedPath()
|
||||
{
|
||||
m_SerializedPath = ToSequencePath();
|
||||
}
|
||||
|
||||
static bool ValidateSubElements(List<SequencePathSubElement> subElements, PlayableDirector director, out List<SequenceBuildingBlock> buildingBlocks)
|
||||
{
|
||||
buildingBlocks = new List<SequenceBuildingBlock>(subElements.Count);
|
||||
var currentDirector = director;
|
||||
|
||||
foreach (var element in subElements)
|
||||
{
|
||||
var timeline = currentDirector.playableAsset as TimelineAsset;
|
||||
if (timeline == null)
|
||||
return false;
|
||||
if (timeline.trackObjects == null)
|
||||
return false;
|
||||
|
||||
var track = timeline.GetOutputTracks().FirstOrDefault(t => t.GetInstanceID() == element.trackInstanceID);
|
||||
if (track == null)
|
||||
return false;
|
||||
if (track.Hash() != element.trackHash)
|
||||
return false;
|
||||
if (track.clips == null)
|
||||
return false;
|
||||
if (track.clips.Length <= element.clipIndex)
|
||||
return false;
|
||||
|
||||
var clip = track.clips[element.clipIndex];
|
||||
if (clip == null)
|
||||
return false;
|
||||
if (clip.Hash() != element.clipHash)
|
||||
return false;
|
||||
|
||||
var candidateDirectors = TimelineUtility.GetSubTimelines(clip, director);
|
||||
|
||||
if (element.subDirectorIndex < 0 || element.subDirectorIndex >= candidateDirectors.Count)
|
||||
return false;
|
||||
|
||||
var candidateDirector = candidateDirectors[element.subDirectorIndex];
|
||||
|
||||
if (candidateDirector == null || !(candidateDirector.playableAsset is TimelineAsset))
|
||||
return false;
|
||||
|
||||
currentDirector = candidateDirector;
|
||||
|
||||
buildingBlocks.Add(
|
||||
new SequenceBuildingBlock
|
||||
{
|
||||
asset = currentDirector.playableAsset as TimelineAsset,
|
||||
director = currentDirector,
|
||||
hostClip = clip
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SequenceBuildingBlock
|
||||
{
|
||||
public TimelineAsset asset;
|
||||
public PlayableDirector director;
|
||||
public TimelineClip hostClip;
|
||||
}
|
||||
|
||||
static void AddToCurrentUndoGroup(Object target)
|
||||
{
|
||||
if (target == null) return;
|
||||
|
||||
var group = Undo.GetCurrentGroup();
|
||||
var groupName = Undo.GetCurrentGroupName();
|
||||
EditorUtility.SetDirty(target);
|
||||
Undo.RegisterCompleteObjectUndo(target, groupName);
|
||||
Undo.CollapseUndoOperations(group);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6901fab4d5157ac48b9f263730387c03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,131 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
[Serializable]
|
||||
class SequencePath
|
||||
{
|
||||
[SerializeField] int m_SelectionRoot;
|
||||
|
||||
public int selectionRoot
|
||||
{
|
||||
get { return m_SelectionRoot; }
|
||||
}
|
||||
|
||||
[SerializeField] List<SequencePathSubElement> m_SubElements;
|
||||
|
||||
public List<SequencePathSubElement> subElements
|
||||
{
|
||||
get { return m_SubElements ?? (m_SubElements = new List<SequencePathSubElement>()); }
|
||||
}
|
||||
|
||||
public void SetSelectionRoot(int instanceID)
|
||||
{
|
||||
m_SelectionRoot = instanceID;
|
||||
subElements.Clear();
|
||||
}
|
||||
|
||||
public void AddSubSequence(ISequenceState state, IExposedPropertyTable resolver)
|
||||
{
|
||||
subElements.Add(SequencePathSubElement.Create(state, resolver));
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
m_SelectionRoot = 0;
|
||||
subElements.Clear();
|
||||
}
|
||||
|
||||
public static bool AreEqual(SequencePath lhs, SequencePath rhs)
|
||||
{
|
||||
if (ReferenceEquals(lhs, null) && ReferenceEquals(rhs, null)) return true;
|
||||
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null)) return false;
|
||||
if (ReferenceEquals(lhs, rhs)) return true;
|
||||
|
||||
var result = lhs.selectionRoot == rhs.selectionRoot &&
|
||||
lhs.subElements.Count == rhs.subElements.Count;
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
for (int i = 0, n = lhs.subElements.Count; i < n; ++i)
|
||||
result = result && SequencePathSubElement.AreEqual(lhs.subElements[i], rhs.subElements[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendFormat("[{0}]", m_SelectionRoot.ToString());
|
||||
|
||||
if (m_SubElements != null && m_SubElements.Count > 0)
|
||||
{
|
||||
foreach (var element in m_SubElements)
|
||||
{
|
||||
sb.Append(" > ");
|
||||
sb.Append(element.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
class SequencePathSubElement
|
||||
{
|
||||
public int trackInstanceID;
|
||||
public int trackHash;
|
||||
public int clipIndex;
|
||||
public int clipHash;
|
||||
public int subDirectorIndex;
|
||||
|
||||
public static SequencePathSubElement Create(ISequenceState state, IExposedPropertyTable resolver)
|
||||
{
|
||||
var clip = state.hostClip;
|
||||
Debug.Assert(clip != null);
|
||||
var track = clip.parentTrack;
|
||||
Debug.Assert(track != null);
|
||||
var asset = track.timelineAsset;
|
||||
Debug.Assert(asset != null);
|
||||
var directors = TimelineUtility.GetSubTimelines(clip, resolver as PlayableDirector);
|
||||
|
||||
return new SequencePathSubElement
|
||||
{
|
||||
trackInstanceID = track.GetInstanceID(),
|
||||
trackHash = track.Hash(),
|
||||
clipIndex = Array.IndexOf(track.clips, clip),
|
||||
clipHash = clip.Hash(),
|
||||
subDirectorIndex = directors.IndexOf(state.director)
|
||||
};
|
||||
}
|
||||
|
||||
public static bool AreEqual(SequencePathSubElement lhs, SequencePathSubElement rhs)
|
||||
{
|
||||
if (ReferenceEquals(lhs, null) && ReferenceEquals(rhs, null)) return true;
|
||||
if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null)) return false;
|
||||
if (ReferenceEquals(lhs, rhs)) return true;
|
||||
|
||||
return lhs.trackInstanceID == rhs.trackInstanceID &&
|
||||
lhs.trackHash == rhs.trackHash &&
|
||||
lhs.clipIndex == rhs.clipIndex &&
|
||||
lhs.clipHash == rhs.clipHash &&
|
||||
lhs.subDirectorIndex == rhs.subDirectorIndex;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(
|
||||
"[track[{0}] ({1}) > clip[{2}] ({3})]",
|
||||
trackInstanceID.ToString(), trackHash.ToString(),
|
||||
clipIndex.ToString(), clipHash.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d1207768d96c479488b6b81f3483e0c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,212 @@
|
|||
using System;
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
bool? m_IsReadOnly;
|
||||
public bool isReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!m_IsReadOnly.HasValue)
|
||||
m_IsReadOnly = FileUtil.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 float frameRate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (asset != null)
|
||||
return asset.editorSettings.fps;
|
||||
|
||||
return TimelineAsset.EditorSettings.kDefaultFps;
|
||||
}
|
||||
set
|
||||
{
|
||||
TimelineAsset.EditorSettings settings = asset.editorSettings;
|
||||
if (Math.Abs(settings.fps - value) > TimeUtility.kFrameRateEpsilon)
|
||||
{
|
||||
settings.fps = Mathf.Max(value, (float)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;
|
||||
|
||||
start = hostClip == null ? 0.0 : hostClip.start;
|
||||
timeScale = hostClip == null ? 1.0 : hostClip.timeScale * parentSequence.timeScale;
|
||||
}
|
||||
|
||||
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 string TimeAsString(double timeValue, string format = "F2")
|
||||
{
|
||||
if (viewModel.timeInFrames)
|
||||
return TimeUtility.TimeAsFrames(timeValue, frameRate, format);
|
||||
|
||||
return TimeUtility.TimeAsTimeCode(timeValue, frameRate, format);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TimelineWindowViewPrefs.SaveViewModel(asset);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 09f4db536a377bc40a9ac110af702bfa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: df8df80bb65e9ec4280229a9921c4f3c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue