summaryrefslogtreecommitdiff
path: root/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables
diff options
context:
space:
mode:
authorAndrew Lee <alee14498@protonmail.com>2020-04-19 17:19:32 -0400
committerAndrew Lee <alee14498@protonmail.com>2020-04-19 17:19:32 -0400
commitc55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 (patch)
treeee4d51c7c1d633e11f46453ef1edd3c77c4ef9f7 /Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables
downloadProject-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.gz
Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.bz2
Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.zip
Inital commit
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables')
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs140
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs91
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs206
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs27
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs31
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs177
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs158
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs85
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs.meta11
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs254
-rw-r--r--Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs.meta11
18 files changed, 1268 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs
new file mode 100644
index 0000000..3efb818
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs
@@ -0,0 +1,140 @@
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Playable that controls the active state of a GameObject.
+ /// </summary>
+ public class ActivationControlPlayable : PlayableBehaviour
+ {
+ /// <summary>
+ /// The state of a GameObject's activeness when a PlayableGraph stops.
+ /// </summary>
+ public enum PostPlaybackState
+ {
+ /// <summary>
+ /// Set the GameObject to active when the PlayableGraph stops.
+ /// </summary>
+ Active,
+
+ /// <summary>
+ /// Set the GameObject to inactive when the [[PlayableGraph]] stops.
+ /// </summary>
+ Inactive,
+
+ /// <summary>
+ /// Revert the GameObject to the active state it was before the [[PlayableGraph]] started.
+ /// </summary>
+ Revert
+ }
+
+ enum InitialState
+ {
+ Unset,
+ Active,
+ Inactive
+ }
+
+ public GameObject gameObject = null;
+ public PostPlaybackState postPlayback = PostPlaybackState.Revert;
+ InitialState m_InitialState;
+
+ /// <summary>
+ /// Creates a ScriptPlayable with an ActivationControlPlayable behaviour attached
+ /// </summary>
+ /// <param name="graph">PlayableGraph that will own the playable</param>
+ /// <param name="gameObject">The GameObject that triggered the graph build</param>
+ /// <param name="postPlaybackState">The state to leave the gameObject after the graph is stopped</param>
+ /// <returns>Returns a playable that controls activation of a game object</returns>
+ public static ScriptPlayable<ActivationControlPlayable> Create(PlayableGraph graph, GameObject gameObject, ActivationControlPlayable.PostPlaybackState postPlaybackState)
+ {
+ if (gameObject == null)
+ return ScriptPlayable<ActivationControlPlayable>.Null;
+
+ var handle = ScriptPlayable<ActivationControlPlayable>.Create(graph);
+ var playable = handle.GetBehaviour();
+ playable.gameObject = gameObject;
+ playable.postPlayback = postPlaybackState;
+
+ return handle;
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">The information about this frame</param>
+ public override void OnBehaviourPlay(Playable playable, FrameData info)
+ {
+ if (gameObject == null)
+ return;
+
+ gameObject.SetActive(true);
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to PlayState.Paused.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">The information about this frame</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
+ // the effectivePlayState will test if the pause is due to the clip being out of bounds
+ if (gameObject != null && info.effectivePlayState == PlayState.Paused)
+ {
+ gameObject.SetActive(false);
+ }
+ }
+
+ /// <summary>
+ /// This function is called during the ProcessFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ /// <param name="userData">unused</param>
+ public override void ProcessFrame(Playable playable, FrameData info, object userData)
+ {
+ if (gameObject != null)// && !gameObject.activeSelf)
+ gameObject.SetActive(true);
+ }
+
+ /// <summary>
+ /// This function is called when the PlayableGraph that owns this PlayableBehaviour starts.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ public override void OnGraphStart(Playable playable)
+ {
+ if (gameObject != null)
+ {
+ if (m_InitialState == InitialState.Unset)
+ m_InitialState = gameObject.activeSelf ? InitialState.Active : InitialState.Inactive;
+ }
+ }
+
+ /// <summary>
+ /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ public override void OnPlayableDestroy(Playable playable)
+ {
+ if (gameObject == null || m_InitialState == InitialState.Unset)
+ return;
+
+ switch (postPlayback)
+ {
+ case PostPlaybackState.Active:
+ gameObject.SetActive(true);
+ break;
+
+ case PostPlaybackState.Inactive:
+ gameObject.SetActive(false);
+ break;
+
+ case PostPlaybackState.Revert:
+ gameObject.SetActive(m_InitialState == InitialState.Active);
+ break;
+ }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs.meta
new file mode 100644
index 0000000..a7763a6
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ActivationControlPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d20e4e177b86a2843805dd3894f41b42
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs
new file mode 100644
index 0000000..0157958
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// This class is deprecated. It is recommended to use Playable Asset and Playable Behaviour derived classes instead.
+ /// </summary>
+ [Serializable]
+ [Obsolete("For best performance use PlayableAsset and PlayableBehaviour.")]
+ public class BasicPlayableBehaviour : ScriptableObject, IPlayableAsset, IPlayableBehaviour
+ {
+ public BasicPlayableBehaviour() {}
+
+ /// <summary>
+ /// The playback duration in seconds of the instantiated Playable.
+ /// </summary>
+ public virtual double duration { get { return PlayableBinding.DefaultDuration; } }
+
+ /// <summary>
+ ///A description of the outputs of the instantiated Playable.
+ /// </summary>
+ public virtual IEnumerable<PlayableBinding> outputs { get { return PlayableBinding.None; } }
+
+ /// <summary>
+ /// <para>This function is called when the PlayableGraph that owns this PlayableBehaviour starts.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ public virtual void OnGraphStart(Playable playable) {}
+
+ /// <summary>
+ /// <para>This function is called when the PlayableGraph that owns this PlayableBehaviour stops.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ public virtual void OnGraphStop(Playable playable) {}
+
+ /// <summary>
+ /// <para>This function is called when the Playable that owns the PlayableBehaviour is created.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ public virtual void OnPlayableCreate(Playable playable) {}
+
+ /// <summary>
+ /// <para>This function is called when the Playable that owns the PlayableBehaviour is destroyed.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ public virtual void OnPlayableDestroy(Playable playable) {}
+
+ /// <summary>
+ /// <para>This function is called when the Playable play state is changed to Playables.PlayState.Playing.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public virtual void OnBehaviourPlay(Playable playable, FrameData info) {}
+
+ /// <summary>
+ /// <para>This function is called when the Playable play state is changed to Playables.PlayState.Paused.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public virtual void OnBehaviourPause(Playable playable, FrameData info) {}
+
+ /// <summary>
+ /// <para>This function is called during the PrepareFrame phase of the PlayableGraph.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public virtual void PrepareFrame(Playable playable, FrameData info) {}
+
+ /// <summary>
+ /// <para>This function is called during the ProcessFrame phase of the PlayableGraph.</para>
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ /// <param name="playerData">The user data of the ScriptPlayableOutput that initiated the process pass.</param>
+ public virtual void ProcessFrame(Playable playable, FrameData info, object playerData) {}
+
+ /// <summary>
+ /// Implement this method to have your asset inject playables into the given graph.
+ /// </summary>
+ /// <param name="graph">The graph to inject playables into.</param>
+ /// <param name="owner">The game object which initiated the build.</param>
+ /// <returns>The playable injected into the graph, or the root playable if multiple playables are injected.</returns>
+ public virtual Playable CreatePlayable(PlayableGraph graph, GameObject owner)
+ {
+ return ScriptPlayable<BasicPlayableBehaviour>.Create(graph, this);
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs.meta
new file mode 100644
index 0000000..414366e
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/BasicScriptPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: fe03a7b0ba57a4d488b6c327ae16c335
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs
new file mode 100644
index 0000000..e619617
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs
@@ -0,0 +1,206 @@
+using System;
+using UnityEngine;
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Playable Behaviour used to control a PlayableDirector.
+ /// </summary>
+ /// <remarks>
+ /// This playable is used to control other PlayableDirector components from a Timeline sequence.
+ /// </remarks>
+ public class DirectorControlPlayable : PlayableBehaviour
+ {
+ /// <summary>
+ /// The PlayableDirector being controlled by this PlayableBehaviour
+ /// </summary>
+ public PlayableDirector director;
+
+ private bool m_SyncTime = false;
+
+ private double m_AssetDuration = double.MaxValue;
+
+ /// <summary>
+ /// Creates a Playable with a DirectorControlPlayable attached
+ /// </summary>
+ /// <param name="graph">The graph to inject the playable into</param>
+ /// <param name="director">The director to control</param>
+ /// <returns>Returns a Playable with a DirectorControlPlayable attached</returns>
+ public static ScriptPlayable<DirectorControlPlayable> Create(PlayableGraph graph, PlayableDirector director)
+ {
+ if (director == null)
+ return ScriptPlayable<DirectorControlPlayable>.Null;
+
+ var handle = ScriptPlayable<DirectorControlPlayable>.Create(graph);
+ handle.GetBehaviour().director = director;
+
+#if UNITY_EDITOR
+ if (!Application.isPlaying && UnityEditor.PrefabUtility.IsPartOfPrefabInstance(director))
+ UnityEditor.PrefabUtility.prefabInstanceUpdated += handle.GetBehaviour().OnPrefabUpdated;
+#endif
+
+ return handle;
+ }
+
+ public override void OnPlayableDestroy(Playable playable)
+ {
+#if UNITY_EDITOR
+ if (!Application.isPlaying)
+ UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabUpdated;
+#endif
+ if (director != null && director.playableAsset != null)
+ director.Stop();
+ }
+
+ /// <summary>
+ /// This function is called during the PrepareFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void PrepareFrame(Playable playable, FrameData info)
+ {
+ if (director == null || !director.isActiveAndEnabled || director.playableAsset == null)
+ return;
+
+ // resync the time on an evaluate or a time jump (caused by loops, or some setTime calls)
+ m_SyncTime |= (info.evaluationType == FrameData.EvaluationType.Evaluate) ||
+ DetectDiscontinuity(playable, info);
+
+ SyncSpeed(info.effectiveSpeed);
+ SyncPlayState(playable.GetGraph(), playable.GetTime());
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPlay(Playable playable, FrameData info)
+ {
+ m_SyncTime = true;
+
+ if (director != null && director.playableAsset != null)
+ m_AssetDuration = director.playableAsset.duration;
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to PlayState.Paused.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ if (director != null && director.playableAsset != null)
+ {
+ if (info.effectivePlayState == PlayState.Playing) // graph was paused
+ director.Pause();
+ else
+ director.Stop();
+ }
+ }
+
+ /// <summary>
+ /// This function is called during the ProcessFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ /// <param name="playerData">unused</param>
+ public override void ProcessFrame(Playable playable, FrameData info, object playerData)
+ {
+ if (director == null || !director.isActiveAndEnabled || director.playableAsset == null)
+ return;
+
+ if (m_SyncTime || DetectOutOfSync(playable))
+ {
+ UpdateTime(playable);
+ director.Evaluate();
+ }
+
+ m_SyncTime = false;
+ }
+
+#if UNITY_EDITOR
+ void OnPrefabUpdated(GameObject go)
+ {
+ // When the prefab asset is updated, we rebuild the graph to reflect the changes in editor
+ if (UnityEditor.PrefabUtility.GetRootGameObject(director) == go)
+ director.RebuildGraph();
+ }
+
+#endif
+
+ void SyncSpeed(double speed)
+ {
+ if (director.playableGraph.IsValid())
+ {
+ int roots = director.playableGraph.GetRootPlayableCount();
+ for (int i = 0; i < roots; i++)
+ {
+ var rootPlayable = director.playableGraph.GetRootPlayable(i);
+ if (rootPlayable.IsValid())
+ {
+ rootPlayable.SetSpeed(speed);
+ }
+ }
+ }
+ }
+
+ void SyncPlayState(PlayableGraph graph, double playableTime)
+ {
+ bool expectedFinished = (playableTime >= m_AssetDuration) && director.extrapolationMode == DirectorWrapMode.None;
+ if (graph.IsPlaying() && !expectedFinished)
+ director.Play();
+ else
+ director.Pause();
+ }
+
+ bool DetectDiscontinuity(Playable playable, FrameData info)
+ {
+ return Math.Abs(playable.GetTime() - playable.GetPreviousTime() - info.m_DeltaTime * info.m_EffectiveSpeed) > DiscreteTime.tickValue;
+ }
+
+ bool DetectOutOfSync(Playable playable)
+ {
+ double expectedTime = playable.GetTime();
+ if (playable.GetTime() >= m_AssetDuration)
+ {
+ if (director.extrapolationMode == DirectorWrapMode.None)
+ return false;
+ else if (director.extrapolationMode == DirectorWrapMode.Hold)
+ expectedTime = m_AssetDuration;
+ else if (m_AssetDuration > float.Epsilon) // loop
+ expectedTime = expectedTime % m_AssetDuration;
+ }
+
+ if (!Mathf.Approximately((float)expectedTime, (float)director.time))
+ {
+#if UNITY_EDITOR
+ double lastDelta = playable.GetTime() - playable.GetPreviousTime();
+ if (UnityEditor.Unsupported.IsDeveloperBuild())
+ Debug.LogWarningFormat("Internal Warning - Control track desync detected on {2} ({0:F10} vs {1:F10} with delta {3:F10}). Time will be resynchronized. Known to happen with nested control tracks", playable.GetTime(), director.time, director.name, lastDelta);
+#endif
+ return true;
+ }
+ return false;
+ }
+
+ // We need to handle loop modes explicitly since we are setting the time directly
+ void UpdateTime(Playable playable)
+ {
+ double duration = Math.Max(0.1, director.playableAsset.duration);
+ switch (director.extrapolationMode)
+ {
+ case DirectorWrapMode.Hold:
+ director.time = Math.Min(duration, Math.Max(0, playable.GetTime()));
+ break;
+ case DirectorWrapMode.Loop:
+ director.time = Math.Max(0, playable.GetTime() % duration);
+ break;
+ case DirectorWrapMode.None:
+ director.time = playable.GetTime();
+ break;
+ }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs.meta
new file mode 100644
index 0000000..5f71a6f
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/DirectorControlPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: be156cc527d606b4aaac403e9843186e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs
new file mode 100644
index 0000000..5d986ae
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs
@@ -0,0 +1,27 @@
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Interface that can be implemented by MonoBehaviours indicating that they receive time-related control calls from a PlayableGraph.
+ /// </summary>
+ /// <remarks>
+ /// Implementing this interface on MonoBehaviours attached to GameObjects under control by control-tracks will cause them to be notified when associated Timeline clips are active.
+ /// </remarks>
+ public interface ITimeControl
+ {
+ /// <summary>
+ /// Called each frame the Timeline clip is active.
+ /// </summary>
+ /// <param name="time">The local time of the associated Timeline clip.</param>
+ void SetTime(double time);
+
+ /// <summary>
+ /// Called when the associated Timeline clip becomes active.
+ /// </summary>
+ void OnControlTimeStart();
+
+ /// <summary>
+ /// Called when the associated Timeline clip becomes deactivated.
+ /// </summary>
+ void OnControlTimeStop();
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs.meta
new file mode 100644
index 0000000..8d4a953
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ITimeControl.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5415c904c4fbc3e498253bc2866b37cd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs
new file mode 100644
index 0000000..a83fc8b
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Use these flags to specify the notification behaviour.
+ /// </summary>
+ /// <see cref="UnityEngine.Playables.INotification"/>
+ [Flags]
+ [Serializable]
+ public enum NotificationFlags : short
+ {
+ /// <summary>
+ /// Use this flag to send the notification in Edit Mode.
+ /// </summary>
+ /// <remarks>
+ /// Sent on discontinuous jumps in time.
+ /// </remarks>
+ TriggerInEditMode = 1 << 0,
+
+ /// <summary>
+ /// Use this flag to send the notification if playback starts after the notification time.
+ /// </summary>
+ Retroactive = 1 << 1,
+
+ /// <summary>
+ /// Use this flag to send the notification only once when looping.
+ /// </summary>
+ TriggerOnce = 1 << 2,
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs.meta
new file mode 100644
index 0000000..4eae696
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/NotificationFlags.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 983c76d87fb6f4f4597a526a4b2b5fd7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs
new file mode 100644
index 0000000..a513d7c
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs
@@ -0,0 +1,177 @@
+using System;
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Playable that synchronizes a particle system simulation.
+ /// </summary>
+ public class ParticleControlPlayable : PlayableBehaviour
+ {
+ const float kUnsetTime = -1;
+ float m_LastTime = kUnsetTime;
+ uint m_RandomSeed = 1;
+
+ // particleSystem.time can not be relied on for an accurate time. It does not advance until a delta threshold is reached(fixedUpdate) and until the start delay has elapsed.
+ float m_SystemTime;
+
+ /// <summary>
+ /// Creates a Playable with a ParticleControlPlayable behaviour attached
+ /// </summary>
+ /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
+ /// <param name="component">The particle systtem to control</param>
+ /// <param name="randomSeed">A random seed to use for particle simulation</param>
+ /// <returns>Returns the created Playable.</returns>
+ public static ScriptPlayable<ParticleControlPlayable> Create(PlayableGraph graph, ParticleSystem component, uint randomSeed)
+ {
+ if (component == null)
+ return ScriptPlayable<ParticleControlPlayable>.Null;
+
+ var handle = ScriptPlayable<ParticleControlPlayable>.Create(graph);
+ handle.GetBehaviour().Initialize(component, randomSeed);
+ return handle;
+ }
+
+ /// <summary>
+ /// The particle system to control
+ /// </summary>
+ public ParticleSystem particleSystem { get; private set; }
+
+ /// <summary>
+ /// Initializes the behaviour with a particle system and random seed.
+ /// </summary>
+ /// <param name="ps"></param>
+ /// <param name="randomSeed"></param>
+ public void Initialize(ParticleSystem ps, uint randomSeed)
+ {
+ m_RandomSeed = Math.Max(1, randomSeed);
+ particleSystem = ps;
+ m_SystemTime = 0;
+ SetRandomSeed();
+
+ #if UNITY_EDITOR
+ if (!Application.isPlaying && UnityEditor.PrefabUtility.IsPartOfPrefabInstance(ps))
+ UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabUpdated;
+ #endif
+ }
+
+ #if UNITY_EDITOR
+ /// <summary>
+ /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ public override void OnPlayableDestroy(Playable playable)
+ {
+ if (!Application.isPlaying)
+ UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabUpdated;
+ }
+
+ void OnPrefabUpdated(GameObject go)
+ {
+ // When the instance is updated from, this will cause the next evaluate to resimulate.
+ if (UnityEditor.PrefabUtility.GetRootGameObject(particleSystem) == go)
+ m_LastTime = kUnsetTime;
+ }
+
+ #endif
+
+ void SetRandomSeed()
+ {
+ particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
+ var systems = particleSystem.gameObject.GetComponentsInChildren<ParticleSystem>();
+ uint seed = m_RandomSeed;
+ foreach (var ps in systems)
+ {
+ // don't overwrite user set random seeds
+ if (ps.useAutoRandomSeed)
+ {
+ ps.useAutoRandomSeed = false;
+ ps.randomSeed = seed;
+ seed++;
+ }
+ }
+ }
+
+ /// <summary>
+ /// This function is called during the PrepareFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="data">A FrameData structure that contains information about the current frame context.</param>
+ public override void PrepareFrame(Playable playable, FrameData data)
+ {
+ if (particleSystem == null || !particleSystem.gameObject.activeInHierarchy)
+ return;
+
+ float localTime = (float)playable.GetTime();
+ bool shouldUpdate = Mathf.Approximately(m_LastTime, kUnsetTime) ||
+ !Mathf.Approximately(m_LastTime, localTime);
+ if (shouldUpdate)
+ {
+ float epsilon = Time.fixedDeltaTime * 0.5f;
+ float simTime = localTime;
+ float expectedDelta = simTime - m_LastTime;
+
+ // The first iteration includes the start delay. Evaluate(particleSystem.randomSeed) is how the particle system generates the random value internally.
+ float startDelay = particleSystem.main.startDelay.Evaluate(particleSystem.randomSeed);
+ float particleSystemDurationLoop0 = particleSystem.main.duration + startDelay;
+
+ // The particle system time does not include the start delay so we need to remove this for our own system time.
+ float expectedSystemTime = simTime > particleSystemDurationLoop0 ? m_SystemTime : m_SystemTime - startDelay;
+
+ // if it's not looping, then the system time won't advance past the end of the duration
+ if (!particleSystem.main.loop)
+ expectedSystemTime = Math.Min(expectedSystemTime, particleSystem.main.duration);
+
+
+ // conditions for restart
+ bool restart = (simTime < m_LastTime) || // time went backwards
+ (simTime < epsilon) || // time is set to 0
+ Mathf.Approximately(m_LastTime, kUnsetTime) || // object disabled
+ (expectedDelta > particleSystem.main.duration) || // large jump (bug workaround)
+ !(Mathf.Abs(expectedSystemTime - particleSystem.time) < Time.maximumParticleDeltaTime); // particle system isn't where we left it
+ if (restart)
+ {
+ // work around for a bug where simulate(simTime, true, true) doesn't work on loops
+ particleSystem.Simulate(0, true, true);
+ particleSystem.Simulate(simTime, true, false);
+ m_SystemTime = simTime;
+ }
+ else
+ {
+ // ps.time will wrap, so we need to account for that in computing delta time
+ float particleSystemDuration = simTime > particleSystemDurationLoop0 ? particleSystem.main.duration : particleSystemDurationLoop0;
+ float fracTime = simTime % particleSystemDuration;
+ float deltaTime = fracTime - m_SystemTime;
+
+ if (deltaTime < -epsilon) // detect wrapping of ps.time
+ deltaTime = fracTime + particleSystemDurationLoop0 - m_SystemTime;
+
+ particleSystem.Simulate(deltaTime, true, false);
+ m_SystemTime += deltaTime;
+ }
+
+ m_LastTime = localTime;
+ }
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPlay(Playable playable, FrameData info)
+ {
+ m_LastTime = kUnsetTime;
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to PlayState.Paused.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ m_LastTime = kUnsetTime;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs.meta
new file mode 100644
index 0000000..33db5b9
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/ParticleControlPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f603edd7163537f44927ad2808147a25
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs
new file mode 100644
index 0000000..f84c9ff
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs
@@ -0,0 +1,158 @@
+using System;
+using UnityEngine.Playables;
+using UnityEngine.SceneManagement;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Playable that controls and instantiates a Prefab.
+ /// </summary>
+ public class PrefabControlPlayable : PlayableBehaviour
+ {
+ GameObject m_Instance;
+
+#if UNITY_EDITOR
+ private bool m_IsActiveCached;
+#endif
+
+ /// <summary>
+ /// Creates a Playable with a PrefabControlPlayable behaviour attached
+ /// </summary>
+ /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
+ /// <param name="prefabGameObject">The prefab to instantiate from</param>
+ /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
+ /// <returns>Returns a Playabe with PrefabControlPlayable behaviour attached.</returns>
+ public static ScriptPlayable<PrefabControlPlayable> Create(PlayableGraph graph, GameObject prefabGameObject, Transform parentTransform)
+ {
+ if (prefabGameObject == null)
+ return ScriptPlayable<PrefabControlPlayable>.Null;
+
+ var handle = ScriptPlayable<PrefabControlPlayable>.Create(graph);
+ handle.GetBehaviour().Initialize(prefabGameObject, parentTransform);
+ return handle;
+ }
+
+ /// <summary>
+ /// The instance of the prefab created by this behaviour
+ /// </summary>
+ public GameObject prefabInstance
+ {
+ get { return m_Instance; }
+ }
+
+ /// <summary>
+ /// Initializes the behaviour with a prefab and parent transform
+ /// </summary>
+ /// <param name="prefabGameObject">The prefab to instantiate from</param>
+ /// <param name="parentTransform">Transform to parent instance to. Can be null.</param>
+ /// <returns>The created instance</returns>
+ public GameObject Initialize(GameObject prefabGameObject, Transform parentTransform)
+ {
+ if (prefabGameObject == null)
+ throw new ArgumentNullException("Prefab cannot be null");
+
+ if (m_Instance != null)
+ {
+ Debug.LogWarningFormat("Prefab Control Playable ({0}) has already been initialized with a Prefab ({1}).", prefabGameObject.name, m_Instance.name);
+ }
+ else
+ {
+ #if UNITY_EDITOR
+ if (!Application.isPlaying)
+ {
+ m_Instance = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefabGameObject, parentTransform);
+ UnityEditor.PrefabUtility.prefabInstanceUpdated += OnPrefabUpdated;
+ }
+ else
+ #endif
+ {
+ m_Instance = Object.Instantiate(prefabGameObject, parentTransform, false);
+ }
+ m_Instance.name = prefabGameObject.name + " [Timeline]";
+ m_Instance.SetActive(false);
+ SetHideFlagsRecursive(m_Instance);
+ }
+ return m_Instance;
+ }
+
+ /// <summary>
+ /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ public override void OnPlayableDestroy(Playable playable)
+ {
+ if (m_Instance)
+ {
+ if (Application.isPlaying)
+ Object.Destroy(m_Instance);
+ else
+ Object.DestroyImmediate(m_Instance);
+ }
+
+#if UNITY_EDITOR
+ UnityEditor.PrefabUtility.prefabInstanceUpdated -= OnPrefabUpdated;
+#endif
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPlay(Playable playable, FrameData info)
+ {
+ if (m_Instance == null)
+ return;
+
+ m_Instance.SetActive(true);
+
+#if UNITY_EDITOR
+ m_IsActiveCached = true;
+#endif
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to PlayState.Paused.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
+ // the effectivePlayState will test if the pause is due to the clip being out of bounds
+ if (m_Instance != null && info.effectivePlayState == PlayState.Paused)
+ {
+ m_Instance.SetActive(false);
+#if UNITY_EDITOR
+ m_IsActiveCached = false;
+#endif
+ }
+ }
+
+#if UNITY_EDITOR
+ void OnPrefabUpdated(GameObject go)
+ {
+ if (go == m_Instance)
+ {
+ SetHideFlagsRecursive(go);
+ go.SetActive(m_IsActiveCached);
+ }
+ }
+
+#endif
+
+ static void SetHideFlagsRecursive(GameObject gameObject)
+ {
+ if (gameObject == null)
+ return;
+
+ gameObject.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
+ if (!Application.isPlaying)
+ gameObject.hideFlags |= HideFlags.HideInHierarchy;
+ foreach (Transform child in gameObject.transform)
+ {
+ SetHideFlagsRecursive(child.gameObject);
+ }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs.meta
new file mode 100644
index 0000000..c148dc2
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/PrefabControlPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 439c018cf4619e94d9a92110ce0aa188
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs
new file mode 100644
index 0000000..68ec80d
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs
@@ -0,0 +1,85 @@
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// A PlayableBehaviour that manages a component that implements the ITimeControl interface
+ /// </summary>
+ public class TimeControlPlayable : PlayableBehaviour
+ {
+ ITimeControl m_timeControl;
+
+ bool m_started;
+
+ /// <summary>
+ /// Creates a Playable with a TimeControlPlayable behaviour attached
+ /// </summary>
+ /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
+ /// <param name="timeControl"></param>
+ /// <returns></returns>
+ public static ScriptPlayable<TimeControlPlayable> Create(PlayableGraph graph, ITimeControl timeControl)
+ {
+ if (timeControl == null)
+ return ScriptPlayable<TimeControlPlayable>.Null;
+
+ var handle = ScriptPlayable<TimeControlPlayable>.Create(graph);
+ handle.GetBehaviour().Initialize(timeControl);
+ return handle;
+ }
+
+ /// <summary>
+ /// Initializes the behaviour
+ /// </summary>
+ /// <param name="timeControl">Component that implements the ITimeControl interface</param>
+ public void Initialize(ITimeControl timeControl)
+ {
+ m_timeControl = timeControl;
+ }
+
+ /// <summary>
+ /// This function is called during the PrepareFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void PrepareFrame(Playable playable, FrameData info)
+ {
+ Debug.Assert(m_started, "PrepareFrame has been called without OnControlTimeStart being called first.");
+ if (m_timeControl != null)
+ m_timeControl.SetTime(playable.GetTime());
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
+ /// </summary>
+ /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPlay(Playable playable, FrameData info)
+ {
+ if (m_timeControl == null)
+ return;
+
+ if (!m_started)
+ {
+ m_timeControl.OnControlTimeStart();
+ m_started = true;
+ }
+ }
+
+ /// <summary>
+ /// This function is called when the Playable play state is changed to PlayState.Paused.
+ /// </summary>
+ /// <param name="playable">The playable this behaviour is attached to.</param>
+ /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ if (m_timeControl == null)
+ return;
+
+ if (m_started)
+ {
+ m_timeControl.OnControlTimeStop();
+ m_started = false;
+ }
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs.meta
new file mode 100644
index 0000000..5ce09ad
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeControlPlayable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1db879070d9a45f4c86cdf5e59616df5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs
new file mode 100644
index 0000000..66a31d1
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine.Playables;
+
+namespace UnityEngine.Timeline
+{
+ /// <summary>
+ /// Use this PlayableBehaviour to send notifications at a given time.
+ /// </summary>
+ /// <seealso cref="UnityEngine.Timeline.NotificationFlags"/>
+ public class TimeNotificationBehaviour : PlayableBehaviour
+ {
+ struct NotificationEntry
+ {
+ public double time;
+ public INotification payload;
+ public bool notificationFired;
+ public NotificationFlags flags;
+
+ public bool triggerInEditor
+ {
+ get { return (flags & NotificationFlags.TriggerInEditMode) != 0; }
+ }
+ public bool prewarm
+ {
+ get { return (flags & NotificationFlags.Retroactive) != 0; }
+ }
+ public bool triggerOnce
+ {
+ get { return (flags & NotificationFlags.TriggerOnce) != 0; }
+ }
+ }
+
+ readonly List<NotificationEntry> m_Notifications = new List<NotificationEntry>();
+ double m_PreviousTime;
+ bool m_NeedSortNotifications;
+
+ Playable m_TimeSource;
+
+ /// <summary>
+ /// Sets an optional Playable that provides duration and Wrap mode information.
+ /// </summary>
+ /// <remarks>
+ /// timeSource is optional. By default, the duration and Wrap mode will come from the current Playable.
+ /// </remarks>
+ public Playable timeSource
+ {
+ set { m_TimeSource = value; }
+ }
+
+ /// <summary>
+ /// Creates and initializes a ScriptPlayable with a TimeNotificationBehaviour.
+ /// </summary>
+ /// <param name="graph">The playable graph.</param>
+ /// <param name="duration">The duration of the playable.</param>
+ /// <param name="loopMode">The loop mode of the playable.</param>
+ /// <returns>A new TimeNotificationBehaviour linked to the PlayableGraph.</returns>
+ public static ScriptPlayable<TimeNotificationBehaviour> Create(PlayableGraph graph, double duration, DirectorWrapMode loopMode)
+ {
+ var notificationsPlayable = ScriptPlayable<TimeNotificationBehaviour>.Create(graph);
+ notificationsPlayable.SetDuration(duration);
+ notificationsPlayable.SetTimeWrapMode(loopMode);
+ notificationsPlayable.SetPropagateSetTime(true);
+ return notificationsPlayable;
+ }
+
+ /// <summary>
+ /// Adds a notification to be sent with flags, at a specific time.
+ /// </summary>
+ /// <param name="time">The time to send the notification.</param>
+ /// <param name="payload">The notification.</param>
+ /// <param name="flags">The notification flags that determine the notification behaviour. This parameter is set to Retroactive by default.</param>
+ /// <seealso cref="UnityEngine.Timeline.NotificationFlags"/>
+ public void AddNotification(double time, INotification payload, NotificationFlags flags = NotificationFlags.Retroactive)
+ {
+ m_Notifications.Add(new NotificationEntry
+ {
+ time = time,
+ payload = payload,
+ flags = flags
+ });
+ m_NeedSortNotifications = true;
+ }
+
+ /// <summary>
+ /// This method is called when the PlayableGraph that owns this PlayableBehaviour starts.
+ /// </summary>
+ /// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
+ public override void OnGraphStart(Playable playable)
+ {
+ SortNotifications();
+ for (var i = 0; i < m_Notifications.Count; i++)
+ {
+ var notification = m_Notifications[i];
+ notification.notificationFired = false;
+ m_Notifications[i] = notification;
+ }
+
+ m_PreviousTime = playable.GetTime();
+ }
+
+ /// <summary>
+ /// This method is called when the Playable play state is changed to PlayState.Paused
+ /// </summary>
+ /// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
+ /// <param name="info">Playable context information such as weight, evaluationType, and so on.</param>
+ public override void OnBehaviourPause(Playable playable, FrameData info)
+ {
+ if (playable.IsDone())
+ {
+ SortNotifications();
+ for (var i = 0; i < m_Notifications.Count; i++)
+ {
+ var e = m_Notifications[i];
+ if (!e.notificationFired)
+ {
+ var duration = playable.GetDuration();
+ var canTrigger = m_PreviousTime <= e.time && e.time <= duration;
+ if (canTrigger)
+ {
+ Trigger_internal(playable, info.output, ref e);
+ m_Notifications[i] = e;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method is called during the PrepareFrame phase of the PlayableGraph.
+ /// </summary>
+ /// <remarks>
+ /// Called once before processing starts.
+ /// </remarks>
+ /// <param name="playable">The reference to the playable associated with this PlayableBehaviour.</param>
+ /// <param name="info">Playable context information such as weight, evaluationType, and so on.</param>
+ public override void PrepareFrame(Playable playable, FrameData info)
+ {
+ // Never trigger on scrub
+ if (info.evaluationType == FrameData.EvaluationType.Evaluate)
+ {
+ return;
+ }
+
+ SyncDurationWithExternalSource(playable);
+ SortNotifications();
+ var currentTime = playable.GetTime();
+
+ // Fire notifications from previousTime till the end
+ if (info.timeLooped)
+ {
+ var duration = playable.GetDuration();
+ TriggerNotificationsInRange(m_PreviousTime, duration, info, playable, true);
+ var dx = playable.GetDuration() - m_PreviousTime;
+ var nFullTimelines = (int)((info.deltaTime * info.effectiveSpeed - dx) / playable.GetDuration());
+ for (var i = 0; i < nFullTimelines; i++)
+ {
+ TriggerNotificationsInRange(0, duration, info, playable, false);
+ }
+ TriggerNotificationsInRange(0, currentTime, info, playable, false);
+ }
+ else
+ {
+ var pt = playable.GetTime();
+ TriggerNotificationsInRange(m_PreviousTime, pt, info,
+ playable, true);
+ }
+
+ for (var i = 0; i < m_Notifications.Count; ++i)
+ {
+ var e = m_Notifications[i];
+ if (e.notificationFired && CanRestoreNotification(e, info, currentTime, m_PreviousTime))
+ {
+ Restore_internal(ref e);
+ m_Notifications[i] = e;
+ }
+ }
+
+ m_PreviousTime = playable.GetTime();
+ }
+
+ void SortNotifications()
+ {
+ if (m_NeedSortNotifications)
+ {
+ m_Notifications.Sort((x, y) => x.time.CompareTo(y.time));
+ m_NeedSortNotifications = false;
+ }
+ }
+
+ static bool CanRestoreNotification(NotificationEntry e, FrameData info, double currentTime, double previousTime)
+ {
+ if (e.triggerOnce)
+ return false;
+ if (info.timeLooped)
+ return true;
+
+ //case 1111595: restore the notification if the time is manually set before it
+ return previousTime > currentTime && currentTime <= e.time;
+ }
+
+ void TriggerNotificationsInRange(double start, double end, FrameData info, Playable playable, bool checkState)
+ {
+ if (start <= end)
+ {
+ var playMode = Application.isPlaying;
+ for (var i = 0; i < m_Notifications.Count; i++)
+ {
+ var e = m_Notifications[i];
+ if (e.notificationFired && (checkState || e.triggerOnce))
+ continue;
+
+ var notificationTime = e.time;
+ if (e.prewarm && notificationTime < end && (e.triggerInEditor || playMode))
+ {
+ Trigger_internal(playable, info.output, ref e);
+ m_Notifications[i] = e;
+ }
+ else
+ {
+ if (notificationTime < start || notificationTime > end)
+ continue;
+
+ if (e.triggerInEditor || playMode)
+ {
+ Trigger_internal(playable, info.output, ref e);
+ m_Notifications[i] = e;
+ }
+ }
+ }
+ }
+ }
+
+ void SyncDurationWithExternalSource(Playable playable)
+ {
+ if (m_TimeSource.IsValid())
+ {
+ playable.SetDuration(m_TimeSource.GetDuration());
+ playable.SetTimeWrapMode(m_TimeSource.GetTimeWrapMode());
+ }
+ }
+
+ static void Trigger_internal(Playable playable, PlayableOutput output, ref NotificationEntry e)
+ {
+ output.PushNotification(playable, e.payload);
+ e.notificationFired = true;
+ }
+
+ static void Restore_internal(ref NotificationEntry e)
+ {
+ e.notificationFired = false;
+ }
+ }
+}
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs.meta
new file mode 100644
index 0000000..593b6c2
--- /dev/null
+++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Playables/TimeNotificationBehaviour.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: afeb55855d7a63b45ba6f8bd97599202
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: