From c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Sun, 19 Apr 2020 17:19:32 -0400 Subject: Inital commit --- .../Animation/AnimationOutputWeightProcessor.cs | 93 ++ .../AnimationOutputWeightProcessor.cs.meta | 11 + .../Runtime/Animation/AnimationPlayableAsset.cs | 326 +++++++ .../Animation/AnimationPlayableAsset.cs.meta | 11 + .../Animation/AnimationPreviewUpdateCallback.cs | 54 ++ .../AnimationPreviewUpdateCallback.cs.meta | 11 + .../Runtime/Animation/AnimationTrack.cs | 971 +++++++++++++++++++++ .../Runtime/Animation/AnimationTrack.cs.meta | 11 + .../Runtime/Animation/ICurvesOwner.cs | 15 + .../Runtime/Animation/ICurvesOwner.cs.meta | 11 + 10 files changed, 1514 insertions(+) create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs.meta create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs create mode 100644 Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs.meta (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation') diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs new file mode 100644 index 0000000..ae190e3 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using UnityEngine.Animations; +using UnityEngine.Playables; + +namespace UnityEngine.Timeline +{ + // Does a post processing of the weights on an animation track to properly normalize + // the mixer weights so that blending does not bring default poses and subtracks, layers and + // layer graphs blend correctly + class AnimationOutputWeightProcessor : ITimelineEvaluateCallback + { + struct WeightInfo + { + public Playable mixer; + public Playable parentMixer; + public int port; + } + + AnimationPlayableOutput m_Output; + AnimationMotionXToDeltaPlayable m_MotionXPlayable; + readonly List m_Mixers = new List(); + + public AnimationOutputWeightProcessor(AnimationPlayableOutput output) + { + m_Output = output; + output.SetWeight(0); + FindMixers(); + } + + void FindMixers() + { + var playable = m_Output.GetSourcePlayable(); + var outputPort = m_Output.GetSourceOutputPort(); + + m_Mixers.Clear(); + // only write the final output in playmode. it should always be 1 in editor because we blend to the defaults + FindMixers(playable, outputPort, playable.GetInput(outputPort)); + } + + // Recursively accumulates mixers. + void FindMixers(Playable parent, int port, Playable node) + { + if (!node.IsValid()) + return; + + var type = node.GetPlayableType(); + if (type == typeof(AnimationMixerPlayable) || type == typeof(AnimationLayerMixerPlayable)) + { + // use post fix traversal so children come before parents + int subCount = node.GetInputCount(); + for (int j = 0; j < subCount; j++) + { + FindMixers(node, j, node.GetInput(j)); + } + + // if we encounter a layer mixer, we assume there is nesting occuring + // and we modulate the weight instead of overwriting it. + var weightInfo = new WeightInfo + { + parentMixer = parent, + mixer = node, + port = port, + }; + m_Mixers.Add(weightInfo); + } + else + { + var count = node.GetInputCount(); + for (var i = 0; i < count; i++) + { + FindMixers(parent, port, node.GetInput(i)); + } + } + } + + public void Evaluate() + { + float weight = 1; + m_Output.SetWeight(1); + for (int i = 0; i < m_Mixers.Count; i++) + { + var mixInfo = m_Mixers[i]; + weight = WeightUtility.NormalizeMixer(mixInfo.mixer); + mixInfo.parentMixer.SetInputWeight(mixInfo.port, weight); + } + + // only write the final weight in player/playmode. In editor, we are blending to the appropriate defaults + // the last mixer in the list is the final blend, since the list is composed post-order. + if (Application.isPlaying) + m_Output.SetWeight(weight); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs.meta new file mode 100644 index 0000000..c487e39 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationOutputWeightProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a429b38ee9d48c7408c8870baf406034 +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/Animation/AnimationPlayableAsset.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs new file mode 100644 index 0000000..68355c0 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs @@ -0,0 +1,326 @@ +using System.Collections.Generic; +using UnityEngine.Animations; +using UnityEngine.Playables; + +namespace UnityEngine.Timeline +{ + /// + /// A Playable Asset that represents a single AnimationClip clip. + /// + [System.Serializable, NotKeyable] + public partial class AnimationPlayableAsset : PlayableAsset, ITimelineClipAsset, IPropertyPreview + { + /// + /// Whether the source AnimationClip loops during playback. + /// + public enum LoopMode + { + /// + /// Use the loop time setting from the source AnimationClip. + /// + [Tooltip("Use the loop time setting from the source AnimationClip.")] + UseSourceAsset = 0, + + /// + /// The source AnimationClip loops during playback. + /// + [Tooltip("The source AnimationClip loops during playback.")] + On = 1, + + /// + /// The source AnimationClip does not loop during playback. + /// + [Tooltip("The source AnimationClip does not loop during playback.")] + Off = 2 + } + + + [SerializeField] private AnimationClip m_Clip; + [SerializeField] private Vector3 m_Position = Vector3.zero; + [SerializeField] private Vector3 m_EulerAngles = Vector3.zero; + [SerializeField] private bool m_UseTrackMatchFields = true; + [SerializeField] private MatchTargetFields m_MatchTargetFields = MatchTargetFieldConstants.All; + [SerializeField] private bool m_RemoveStartOffset = true; // set by animation track prior to compilation + [SerializeField] private bool m_ApplyFootIK = true; + [SerializeField] private LoopMode m_Loop = LoopMode.UseSourceAsset; + + +#if UNITY_EDITOR + private AnimationOffsetPlayable m_AnimationOffsetPlayable; +#endif + + /// + /// The translational offset of the clip + /// + public Vector3 position + { + get + { + return m_Position; + } + set + { + m_Position = value; +#if UNITY_EDITOR + if (m_AnimationOffsetPlayable.IsValid()) + m_AnimationOffsetPlayable.SetPosition(position); +#endif + } + } + + /// + /// The rotational offset of the clip, expressed as a Quaternion + /// + public Quaternion rotation + { + get + { + return Quaternion.Euler(m_EulerAngles); + } + + set + { + m_EulerAngles = value.eulerAngles; +#if UNITY_EDITOR + if (m_AnimationOffsetPlayable.IsValid()) + m_AnimationOffsetPlayable.SetRotation(value); +#endif + } + } + + /// + /// The rotational offset of the clip, expressed in Euler angles + /// + public Vector3 eulerAngles + { + get { return m_EulerAngles; } + set + { + m_EulerAngles = value; +#if UNITY_EDITOR + if (m_AnimationOffsetPlayable.IsValid()) + m_AnimationOffsetPlayable.SetRotation(rotation); +#endif + } + } + + /// + /// Specifies whether to use offset matching options as defined by the track. + /// + public bool useTrackMatchFields + { + get { return m_UseTrackMatchFields; } + set { m_UseTrackMatchFields = value; } + } + + /// + /// Specifies which fields should be matched when aligning offsets. + /// + public MatchTargetFields matchTargetFields + { + get { return m_MatchTargetFields; } + set { m_MatchTargetFields = value; } + } + + /// + /// Whether to make the animation clip play relative to its first keyframe. + /// + /// + /// This option only applies to animation clips that animate Transform components. + /// + public bool removeStartOffset + { + get { return m_RemoveStartOffset; } + set { m_RemoveStartOffset = value; } + } + + + /// + /// Enable to apply foot IK to the AnimationClip when the target is humanoid. + /// + public bool applyFootIK + { + get { return m_ApplyFootIK; } + set { m_ApplyFootIK = value; } + } + + /// + /// Whether the source AnimationClip loops during playback + /// + public LoopMode loop + { + get { return m_Loop; } + set { m_Loop = value; } + } + + + internal bool hasRootTransforms + { + get { return m_Clip != null && HasRootTransforms(m_Clip); } + } + + // used for legacy 'scene' mode. + internal AppliedOffsetMode appliedOffsetMode { get; set; } + + + /// + /// The source animation clip + /// + public AnimationClip clip + { + get { return m_Clip; } + set + { + if (value != null) + name = "AnimationPlayableAsset of " + value.name; + m_Clip = value; + } + } + + /// + /// Returns the duration required to play the animation clip exactly once + /// + public override double duration + { + get + { + double length = TimeUtility.GetAnimationClipLength(clip); + if (length < float.Epsilon) + return base.duration; + return length; + } + } + + /// + /// Returns a description of the PlayableOutputs that may be created for this asset. + /// + public override IEnumerable outputs + { + get { yield return AnimationPlayableBinding.Create(name, this); } + } + + /// + /// Creates the root of a Playable subgraph to play the animation clip. + /// + /// PlayableGraph that will own the playable + /// The gameobject that triggered the graph build + /// The root playable of the subgraph + public override Playable CreatePlayable(PlayableGraph graph, GameObject go) + { + Playable root = CreatePlayable(graph, m_Clip, position, eulerAngles, removeStartOffset, appliedOffsetMode, applyFootIK, m_Loop); + +#if UNITY_EDITOR + m_AnimationOffsetPlayable = AnimationOffsetPlayable.Null; + if (root.IsValid() && root.IsPlayableOfType()) + { + m_AnimationOffsetPlayable = (AnimationOffsetPlayable)root; + } + + LiveLink(); +#endif + + return root; + } + + internal static Playable CreatePlayable(PlayableGraph graph, AnimationClip clip, Vector3 positionOffset, Vector3 eulerOffset, bool removeStartOffset, AppliedOffsetMode mode, bool applyFootIK, LoopMode loop) + { + if (clip == null || clip.legacy) + return Playable.Null; + + + var clipPlayable = AnimationClipPlayable.Create(graph, clip); + clipPlayable.SetRemoveStartOffset(removeStartOffset); + clipPlayable.SetApplyFootIK(applyFootIK); + clipPlayable.SetOverrideLoopTime(loop != LoopMode.UseSourceAsset); + clipPlayable.SetLoopTime(loop == LoopMode.On); + + Playable root = clipPlayable; + + if (ShouldApplyScaleRemove(mode)) + { + var removeScale = AnimationRemoveScalePlayable.Create(graph, 1); + graph.Connect(root, 0, removeScale, 0); + removeScale.SetInputWeight(0, 1.0f); + root = removeScale; + } + + if (ShouldApplyOffset(mode, clip)) + { + var offsetPlayable = AnimationOffsetPlayable.Create(graph, positionOffset, Quaternion.Euler(eulerOffset), 1); + graph.Connect(root, 0, offsetPlayable, 0); + offsetPlayable.SetInputWeight(0, 1.0F); + root = offsetPlayable; + } + + return root; + } + + private static bool ShouldApplyOffset(AppliedOffsetMode mode, AnimationClip clip) + { + if (mode == AppliedOffsetMode.NoRootTransform || mode == AppliedOffsetMode.SceneOffsetLegacy) + return false; + + return HasRootTransforms(clip); + } + + private static bool ShouldApplyScaleRemove(AppliedOffsetMode mode) + { + return mode == AppliedOffsetMode.SceneOffsetLegacyEditor || mode == AppliedOffsetMode.SceneOffsetLegacy || mode == AppliedOffsetMode.TransformOffsetLegacy; + } + +#if UNITY_EDITOR + public void LiveLink() + { + if (m_AnimationOffsetPlayable.IsValid()) + { + m_AnimationOffsetPlayable.SetPosition(position); + m_AnimationOffsetPlayable.SetRotation(rotation); + } + } + +#endif + + /// + /// Returns the capabilities of TimelineClips that contain a AnimationPlayableAsset + /// + public ClipCaps clipCaps + { + get + { + var caps = ClipCaps.All; + if (m_Clip == null || (m_Loop == LoopMode.Off) || (m_Loop == LoopMode.UseSourceAsset && !m_Clip.isLooping)) + caps &= ~ClipCaps.Looping; + + // empty clips don't support clip in. This allows trim operations to simply become + // move operations + if (m_Clip == null || m_Clip.empty) + caps &= ~ClipCaps.ClipIn; + + return caps; + } + } + + /// + /// Resets the offsets to default values + /// + public void ResetOffsets() + { + position = Vector3.zero; + eulerAngles = Vector3.zero; + } + + /// + public void GatherProperties(PlayableDirector director, IPropertyCollector driver) + { + driver.AddFromClip(m_Clip); + } + + internal static bool HasRootTransforms(AnimationClip clip) + { + if (clip == null || clip.empty) + return false; + + return clip.hasRootMotion || clip.hasGenericRootTransform || clip.hasMotionCurves || clip.hasRootCurves; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs.meta new file mode 100644 index 0000000..698bcd5 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPlayableAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 030f85c3f73729f4f976f66ffb23b875 +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/Animation/AnimationPreviewUpdateCallback.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs new file mode 100644 index 0000000..560f900 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using UnityEngine.Animations; +using UnityEngine.Experimental.Animations; +using UnityEngine.Playables; + +namespace UnityEngine.Timeline +{ + class AnimationPreviewUpdateCallback : ITimelineEvaluateCallback + { + AnimationPlayableOutput m_Output; + PlayableGraph m_Graph; + List m_PreviewComponents; + + public AnimationPreviewUpdateCallback(AnimationPlayableOutput output) + { + m_Output = output; + + Playable playable = m_Output.GetSourcePlayable(); + if (playable.IsValid()) + { + m_Graph = playable.GetGraph(); + } + } + + public void Evaluate() + { + if (!m_Graph.IsValid()) + return; + + if (m_PreviewComponents == null) + FetchPreviewComponents(); + + foreach (var component in m_PreviewComponents) + { + if (component != null) + { + component.UpdatePreviewGraph(m_Graph); + } + } + } + + private void FetchPreviewComponents() + { + m_PreviewComponents = new List(); + + var animator = m_Output.GetTarget(); + if (animator == null) + return; + + var gameObject = animator.gameObject; + m_PreviewComponents.AddRange(gameObject.GetComponents()); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs.meta new file mode 100644 index 0000000..9d6167b --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationPreviewUpdateCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 755e3e942f7784d458bddba421c0bb72 +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/Animation/AnimationTrack.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs new file mode 100644 index 0000000..21e811d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs @@ -0,0 +1,971 @@ +using System; +using System.Collections.Generic; +using UnityEngine.Animations; +using UnityEngine.Experimental.Animations; +using UnityEngine.Playables; +using UnityEngine.Serialization; + +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace UnityEngine.Timeline +{ + /// + /// Flags specifying which offset fields to match + /// + [Flags] + public enum MatchTargetFields + { + /// + /// Translation X value + /// + PositionX = 1 << 0, + /// + /// Translation Y value + /// + PositionY = 1 << 1, + /// + /// Translation Z value + /// + PositionZ = 1 << 2, + /// + /// Rotation Euler Angle X value + /// + RotationX = 1 << 3, + /// + /// Rotation Euler Angle Y value + /// + RotationY = 1 << 4, + /// + /// Rotation Euler Angle Z value + /// + RotationZ = 1 << 5 + } + + /// + /// Describes what is used to set the starting position and orientation of each Animation Track. + /// + /// + /// By default, each Animation Track uses ApplyTransformOffsets to start from a set position and orientation. + /// To offset each Animation Track based on the current position and orientation in the scene, use ApplySceneOffsets. + /// + public enum TrackOffset + { + /// + /// Use this setting to offset each Animation Track based on a set position and orientation. + /// + ApplyTransformOffsets, + /// + /// Use this setting to offset each Animation Track based on the current position and orientation in the scene. + /// + ApplySceneOffsets, + /// + /// Use this setting to offset root transforms based on the state of the animator. + /// + /// + /// Only use this setting to support legacy Animation Tracks. This mode may be deprecated in a future release. + /// + /// In Auto mode, when the animator bound to the animation track contains an AnimatorController, it offsets all animations similar to ApplySceneOffsets. + /// If no controller is assigned, then all offsets are set to start from a fixed position and orientation, similar to ApplyTransformOffsets. + /// In Auto mode, in most cases, root transforms are not affected by local scale or Animator.humanScale, unless the animator has an AnimatorController and Animator.applyRootMotion is set to true. + /// + Auto + } + + + // offset mode + enum AppliedOffsetMode + { + NoRootTransform, + TransformOffset, + SceneOffset, + TransformOffsetLegacy, + SceneOffsetLegacy, + SceneOffsetEditor, // scene offset mode in editor + SceneOffsetLegacyEditor, + } + + + // separate from the enum to hide them from UI elements + static class MatchTargetFieldConstants + { + public static MatchTargetFields All = MatchTargetFields.PositionX | MatchTargetFields.PositionY | + MatchTargetFields.PositionZ | MatchTargetFields.RotationX | + MatchTargetFields.RotationY | MatchTargetFields.RotationZ; + + public static MatchTargetFields None = 0; + + public static MatchTargetFields Position = MatchTargetFields.PositionX | MatchTargetFields.PositionY | + MatchTargetFields.PositionZ; + + public static MatchTargetFields Rotation = MatchTargetFields.RotationX | MatchTargetFields.RotationY | + MatchTargetFields.RotationZ; + + public static bool HasAny(this MatchTargetFields me, MatchTargetFields fields) + { + return (me & fields) != None; + } + + public static MatchTargetFields Toggle(this MatchTargetFields me, MatchTargetFields flag) + { + return me ^ flag; + } + } + + + /// + /// A Timeline track used for playing back animations on an Animator. + /// + [Serializable] + [TrackClipType(typeof(AnimationPlayableAsset), false)] + [TrackBindingType(typeof(Animator))] + [ExcludeFromPreset] + public partial class AnimationTrack : TrackAsset, ILayerable + { + const string k_DefaultInfiniteClipName = "Recorded"; + const string k_DefaultRecordableClipName = "Recorded"; + + [SerializeField, FormerlySerializedAs("m_OpenClipPreExtrapolation")] + TimelineClip.ClipExtrapolation m_InfiniteClipPreExtrapolation = TimelineClip.ClipExtrapolation.None; + + [SerializeField, FormerlySerializedAs("m_OpenClipPostExtrapolation")] + TimelineClip.ClipExtrapolation m_InfiniteClipPostExtrapolation = TimelineClip.ClipExtrapolation.None; + + [SerializeField, FormerlySerializedAs("m_OpenClipOffsetPosition")] + Vector3 m_InfiniteClipOffsetPosition = Vector3.zero; + + [SerializeField, FormerlySerializedAs("m_OpenClipOffsetEulerAngles")] + Vector3 m_InfiniteClipOffsetEulerAngles = Vector3.zero; + + [SerializeField, FormerlySerializedAs("m_OpenClipTimeOffset")] + double m_InfiniteClipTimeOffset; + + [SerializeField, FormerlySerializedAs("m_OpenClipRemoveOffset")] + bool m_InfiniteClipRemoveOffset; // cached value for remove offset + + [SerializeField] + bool m_InfiniteClipApplyFootIK = true; + + [SerializeField, HideInInspector] + AnimationPlayableAsset.LoopMode mInfiniteClipLoop = AnimationPlayableAsset.LoopMode.UseSourceAsset; + + [SerializeField] + MatchTargetFields m_MatchTargetFields = MatchTargetFieldConstants.All; + [SerializeField] + Vector3 m_Position = Vector3.zero; + [SerializeField] + Vector3 m_EulerAngles = Vector3.zero; + + + [SerializeField] AvatarMask m_AvatarMask; + [SerializeField] bool m_ApplyAvatarMask = true; + + [SerializeField] TrackOffset m_TrackOffset = TrackOffset.ApplyTransformOffsets; + + [SerializeField, HideInInspector] AnimationClip m_InfiniteClip; + + +#if UNITY_EDITOR + private AnimationClip m_DefaultPoseClip; + private AnimationClip m_CachedPropertiesClip; + + AnimationOffsetPlayable m_ClipOffset; + + private Vector3 m_SceneOffsetPosition = Vector3.zero; + private Vector3 m_SceneOffsetRotation = Vector3.zero; + + private bool m_HasPreviewComponents = false; +#endif + + /// + /// The translation offset of the entire track. + /// + public Vector3 position + { + get { return m_Position; } + set { m_Position = value; } + } + + /// + /// The rotation offset of the entire track, expressed as a quaternion. + /// + public Quaternion rotation + { + get { return Quaternion.Euler(m_EulerAngles); } + set { m_EulerAngles = value.eulerAngles; } + } + + /// + /// The euler angle representation of the rotation offset of the entire track. + /// + public Vector3 eulerAngles + { + get { return m_EulerAngles; } + set { m_EulerAngles = value; } + } + + /// + /// Specifies whether to apply track offsets to all clips on the track. + /// + /// + /// This can be used to offset all clips on a track, in addition to the clips individual offsets. + /// + [Obsolete("applyOffset is deprecated. Use trackOffset instead", true)] + public bool applyOffsets + { + get { return false; } + set {} + } + + /// + /// Specifies what is used to set the starting position and orientation of an Animation Track. + /// + /// + /// Track Offset is only applied when the Animation Track contains animation that modifies the root Transform. + /// + public TrackOffset trackOffset + { + get { return m_TrackOffset; } + set { m_TrackOffset = value; } + } + + /// + /// Specifies which fields to match when aligning offsets of clips. + /// + public MatchTargetFields matchTargetFields + { + get { return m_MatchTargetFields; } + set { m_MatchTargetFields = value & MatchTargetFieldConstants.All; } + } + + /// + /// An AnimationClip storing the data for an infinite track. + /// + /// + /// The value of this property is null when the AnimationTrack is in Clip Mode. + /// + public AnimationClip infiniteClip + { + get { return m_InfiniteClip; } + internal set { m_InfiniteClip = value; } + } + + // saved value for converting to/from infinite mode + internal bool infiniteClipRemoveOffset + { + get { return m_InfiniteClipRemoveOffset; } + set { m_InfiniteClipRemoveOffset = value; } + } + + /// + /// Specifies the AvatarMask to be applied to all clips on the track. + /// + /// + /// Applying an AvatarMask to an animation track will allow discarding portions of the animation being applied on the track. + /// + public AvatarMask avatarMask + { + get { return m_AvatarMask; } + set { m_AvatarMask = value; } + } + + /// + /// Specifies whether to apply the AvatarMask to the track. + /// + public bool applyAvatarMask + { + get { return m_ApplyAvatarMask; } + set { m_ApplyAvatarMask = value; } + } + + // is this track compilable + + internal override bool CanCompileClips() + { + return !muted && (m_Clips.Count > 0 || (m_InfiniteClip != null && !m_InfiniteClip.empty)); + } + + /// + public override IEnumerable outputs + { + get { yield return AnimationPlayableBinding.Create(name, this); } + } + + + /// + /// Specifies whether the Animation Track has clips, or is in infinite mode. + /// + public bool inClipMode + { + get { return clips != null && clips.Length != 0; } + } + + /// + /// The translation offset of a track in infinite mode. + /// + public Vector3 infiniteClipOffsetPosition + { + get { return m_InfiniteClipOffsetPosition; } + set { m_InfiniteClipOffsetPosition = value; } + } + + /// + /// The rotation offset of a track in infinite mode. + /// + public Quaternion infiniteClipOffsetRotation + { + get { return Quaternion.Euler(m_InfiniteClipOffsetEulerAngles); } + set { m_InfiniteClipOffsetEulerAngles = value.eulerAngles; } + } + + /// + /// The euler angle representation of the rotation offset of the track when in infinite mode. + /// + public Vector3 infiniteClipOffsetEulerAngles + { + get { return m_InfiniteClipOffsetEulerAngles; } + set { m_InfiniteClipOffsetEulerAngles = value; } + } + + internal bool infiniteClipApplyFootIK + { + get { return m_InfiniteClipApplyFootIK; } + set { m_InfiniteClipApplyFootIK = value; } + } + + internal double infiniteClipTimeOffset + { + get { return m_InfiniteClipTimeOffset; } + set { m_InfiniteClipTimeOffset = value; } + } + + /// + /// The saved state of pre-extrapolation for clips converted to infinite mode. + /// + public TimelineClip.ClipExtrapolation infiniteClipPreExtrapolation + { + get { return m_InfiniteClipPreExtrapolation; } + set { m_InfiniteClipPreExtrapolation = value; } + } + + /// + /// The saved state of post-extrapolation for clips when converted to infinite mode. + /// + public TimelineClip.ClipExtrapolation infiniteClipPostExtrapolation + { + get { return m_InfiniteClipPostExtrapolation; } + set { m_InfiniteClipPostExtrapolation = value; } + } + + /// + /// The saved state of animation clip loop state when converted to infinite mode + /// + internal AnimationPlayableAsset.LoopMode infiniteClipLoop + { + get { return mInfiniteClipLoop; } + set { mInfiniteClipLoop = value; } + } + + [ContextMenu("Reset Offsets")] + void ResetOffsets() + { + m_Position = Vector3.zero; + m_EulerAngles = Vector3.zero; + UpdateClipOffsets(); + } + + /// + /// Creates a TimelineClip on this track that uses an AnimationClip. + /// + /// Source animation clip of the resulting TimelineClip. + /// A new TimelineClip which has an AnimationPlayableAsset asset attached. + public TimelineClip CreateClip(AnimationClip clip) + { + if (clip == null) + return null; + + var newClip = CreateClip(); + AssignAnimationClip(newClip, clip); + return newClip; + } + + /// + /// Creates an AnimationClip that stores the data for an infinite track. + /// + /// + /// If an infiniteClip already exists, this method produces no result, even if you provide a different value + /// for infiniteClipName. + /// + /// + /// This method can't create an infinite clip for an AnimationTrack that contains one or more Timeline clips. + /// Use AnimationTrack.inClipMode to determine whether it is possible to create an infinite clip on an AnimationTrack. + /// + /// + /// When used from the editor, this method attempts to save the created infinite clip to the TimelineAsset. + /// The TimelineAsset must already exist in the AssetDatabase to save the infinite clip. If the TimelineAsset + /// does not exist, the infinite clip is still created but it is not saved. + /// + /// + /// The name of the AnimationClip to create. + /// This method does not ensure unique names. If you want a unique clip name, you must provide one. + /// See ObjectNames.GetUniqueName for information on a method that creates unique names. + /// + public void CreateInfiniteClip(string infiniteClipName) + { + if (inClipMode) + { + Debug.LogWarning("CreateInfiniteClip cannot create an infinite clip for an AnimationTrack that contains one or more Timeline Clips."); + return; + } + + if (m_InfiniteClip != null) + return; + + m_InfiniteClip = TimelineCreateUtilities.CreateAnimationClipForTrack(string.IsNullOrEmpty(infiniteClipName) ? k_DefaultInfiniteClipName : infiniteClipName, this, false); + } + + /// + /// Creates a TimelineClip, AnimationPlayableAsset and an AnimationClip. Use this clip to record in a timeline. + /// + /// + /// When used from the editor, this method attempts to save the created recordable clip to the TimelineAsset. + /// The TimelineAsset must already exist in the AssetDatabase to save the recordable clip. If the TimelineAsset + /// does not exist, the recordable clip is still created but it is not saved. + /// + /// + /// The name of the AnimationClip to create. + /// This method does not ensure unique names. If you want a unique clip name, you must provide one. + /// See ObjectNames.GetUniqueName for information on a method that creates unique names. + /// + /// + /// Returns a new TimelineClip with an AnimationPlayableAsset asset attached. + /// + public TimelineClip CreateRecordableClip(string animClipName) + { + var clip = TimelineCreateUtilities.CreateAnimationClipForTrack(string.IsNullOrEmpty(animClipName) ? k_DefaultRecordableClipName : animClipName, this, false); + + var timelineClip = CreateClip(clip); + timelineClip.displayName = animClipName; + timelineClip.recordable = true; + timelineClip.start = 0; + timelineClip.duration = 1; + + var apa = timelineClip.asset as AnimationPlayableAsset; + if (apa != null) + apa.removeStartOffset = false; + + return timelineClip; + } + +#if UNITY_EDITOR + internal Vector3 sceneOffsetPosition + { + get { return m_SceneOffsetPosition; } + set { m_SceneOffsetPosition = value; } + } + + internal Vector3 sceneOffsetRotation + { + get { return m_SceneOffsetRotation; } + set { m_SceneOffsetRotation = value; } + } + + internal bool hasPreviewComponents + { + get + { + if (m_HasPreviewComponents) + return true; + + var parentTrack = parent as AnimationTrack; + if (parentTrack != null) + { + return parentTrack.hasPreviewComponents; + } + + return false; + } + } +#endif + + /// + /// Used to initialize default values on a newly created clip + /// + /// The clip added to the track + protected override void OnCreateClip(TimelineClip clip) + { + var extrapolation = TimelineClip.ClipExtrapolation.None; + if (!isSubTrack) + extrapolation = TimelineClip.ClipExtrapolation.Hold; + clip.preExtrapolationMode = extrapolation; + clip.postExtrapolationMode = extrapolation; + } + + protected internal override int CalculateItemsHash() + { + return GetAnimationClipHash(m_InfiniteClip).CombineHash(base.CalculateItemsHash()); + } + + internal void UpdateClipOffsets() + { +#if UNITY_EDITOR + if (m_ClipOffset.IsValid()) + { + m_ClipOffset.SetPosition(position); + m_ClipOffset.SetRotation(rotation); + } +#endif + } + + Playable CompileTrackPlayable(PlayableGraph graph, TrackAsset track, GameObject go, IntervalTree tree, AppliedOffsetMode mode) + { + var mixer = AnimationMixerPlayable.Create(graph, track.clips.Length); + for (int i = 0; i < track.clips.Length; i++) + { + var c = track.clips[i]; + var asset = c.asset as PlayableAsset; + if (asset == null) + continue; + + var animationAsset = asset as AnimationPlayableAsset; + if (animationAsset != null) + animationAsset.appliedOffsetMode = mode; + + var source = asset.CreatePlayable(graph, go); + if (source.IsValid()) + { + var clip = new RuntimeClip(c, source, mixer); + tree.Add(clip); + graph.Connect(source, 0, mixer, i); + mixer.SetInputWeight(i, 0.0f); + } + } + + return ApplyTrackOffset(graph, mixer, go, mode); + } + + Playable ILayerable.CreateLayerMixer(PlayableGraph graph, GameObject go, int inputCount) + { + return Playable.Null; + } + + internal override Playable OnCreateClipPlayableGraph(PlayableGraph graph, GameObject go, IntervalTree tree) + { + if (isSubTrack) + throw new InvalidOperationException("Nested animation tracks should never be asked to create a graph directly"); + + List flattenTracks = new List(); + if (CanCompileClips()) + flattenTracks.Add(this); + + + bool animatesRootTransform = AnimatesRootTransform(); + foreach (var subTrack in GetChildTracks()) + { + var child = subTrack as AnimationTrack; + if (child != null && child.CanCompileClips()) + { + animatesRootTransform |= child.AnimatesRootTransform(); + flattenTracks.Add(child); + } + } + + // figure out which mode to apply + AppliedOffsetMode mode = GetOffsetMode(go, animatesRootTransform); + var layerMixer = CreateGroupMixer(graph, go, flattenTracks.Count); + for (int c = 0; c < flattenTracks.Count; c++) + { + var compiledTrackPlayable = flattenTracks[c].inClipMode ? + CompileTrackPlayable(graph, flattenTracks[c], go, tree, mode) : + flattenTracks[c].CreateInfiniteTrackPlayable(graph, go, tree, mode); + graph.Connect(compiledTrackPlayable, 0, layerMixer, c); + layerMixer.SetInputWeight(c, flattenTracks[c].inClipMode ? 0 : 1); + if (flattenTracks[c].applyAvatarMask && flattenTracks[c].avatarMask != null) + { + layerMixer.SetLayerMaskFromAvatarMask((uint)c, flattenTracks[c].avatarMask); + } + } + + bool requiresMotionXPlayable = RequiresMotionXPlayable(mode, go); + + Playable mixer = layerMixer; + mixer = CreateDefaultBlend(graph, go, mixer, requiresMotionXPlayable); + + // motionX playable not required in scene offset mode, or root transform mode + if (requiresMotionXPlayable) + { + // If we are animating a root transform, add the motionX to delta playable as the root node + var motionXToDelta = AnimationMotionXToDeltaPlayable.Create(graph); + graph.Connect(mixer, 0, motionXToDelta, 0); + motionXToDelta.SetInputWeight(0, 1.0f); + motionXToDelta.SetAbsoluteMotion(UsesAbsoluteMotion(mode)); + mixer = (Playable)motionXToDelta; + } + + +#if UNITY_EDITOR + if (!Application.isPlaying) + { + var animator = GetBinding(go != null ? go.GetComponent() : null); + if (animator != null) + { + GameObject targetGO = animator.gameObject; + IAnimationWindowPreview[] previewComponents = targetGO.GetComponents(); + + m_HasPreviewComponents = previewComponents.Length > 0; + if (m_HasPreviewComponents) + { + foreach (var component in previewComponents) + { + mixer = component.BuildPreviewGraph(graph, mixer); + } + } + } + } +#endif + + return mixer; + } + + // Creates a layer mixer containing default blends + // the base layer is a default clip of all driven properties + // the next layer is optionally the desired default pose (in the case of humanoid, the tpose + private Playable CreateDefaultBlend(PlayableGraph graph, GameObject go, Playable mixer, bool requireOffset) + { +#if UNITY_EDITOR + if (Application.isPlaying) + return mixer; + + int inputs = 1 + ((m_CachedPropertiesClip != null) ? 1 : 0) + ((m_DefaultPoseClip != null) ? 1 : 0); + if (inputs == 1) + return mixer; + + var defaultPoseMixer = AnimationLayerMixerPlayable.Create(graph, inputs); + + int mixerInput = 0; + if (m_CachedPropertiesClip) + { + var cachedPropertiesClip = AnimationClipPlayable.Create(graph, m_CachedPropertiesClip); + cachedPropertiesClip.SetApplyFootIK(false); + var defaults = (Playable) cachedPropertiesClip; + if (requireOffset) + defaults = AttachOffsetPlayable(graph, defaults, m_SceneOffsetPosition, Quaternion.Euler(m_SceneOffsetRotation)); + graph.Connect(defaults, 0, defaultPoseMixer, mixerInput); + defaultPoseMixer.SetInputWeight(mixerInput, 1.0f); + mixerInput++; + } + + if (m_DefaultPoseClip) + { + var defaultPose = AnimationClipPlayable.Create(graph, m_DefaultPoseClip); + defaultPose.SetApplyFootIK(false); + var blendDefault = (Playable) defaultPose; + if (requireOffset) + blendDefault = AttachOffsetPlayable(graph, blendDefault, m_SceneOffsetPosition, Quaternion.Euler(m_SceneOffsetRotation)); + + graph.Connect(blendDefault, 0, defaultPoseMixer, mixerInput); + defaultPoseMixer.SetInputWeight(mixerInput, 1.0f); + mixerInput++; + } + + + graph.Connect(mixer, 0, defaultPoseMixer, mixerInput); + defaultPoseMixer.SetInputWeight(mixerInput, 1.0f); + + return defaultPoseMixer; +#else + return mixer; +#endif + } + + private Playable AttachOffsetPlayable(PlayableGraph graph, Playable playable, Vector3 pos, Quaternion rot) + { + var offsetPlayable = AnimationOffsetPlayable.Create(graph, pos, rot, 1); + offsetPlayable.SetInputWeight(0, 1.0f); + graph.Connect(playable, 0, offsetPlayable, 0); + return offsetPlayable; + } + +#if UNITY_EDITOR + private static string k_DefaultHumanoidClipPath = "Packages/com.unity.timeline/Editor/StyleSheets/res/HumanoidDefault.anim"; + private static AnimationClip s_DefaultHumanoidClip = null; + + AnimationClip GetDefaultHumanoidClip() + { + if (s_DefaultHumanoidClip == null) + { + s_DefaultHumanoidClip = EditorGUIUtility.LoadRequired(k_DefaultHumanoidClipPath) as AnimationClip; + if (s_DefaultHumanoidClip == null) + Debug.LogError("Could not load default humanoid animation clip for Timeline"); + } + + return s_DefaultHumanoidClip; + } + +#endif + + bool RequiresMotionXPlayable(AppliedOffsetMode mode, GameObject gameObject) + { + if (mode == AppliedOffsetMode.NoRootTransform) + return false; + if (mode == AppliedOffsetMode.SceneOffsetLegacy) + { + var animator = GetBinding(gameObject != null ? gameObject.GetComponent() : null); + return animator != null && animator.hasRootMotion; + } + return true; + } + + static bool UsesAbsoluteMotion(AppliedOffsetMode mode) + { +#if UNITY_EDITOR + // in editor, previewing is always done in absolute motion + if (!Application.isPlaying) + return true; +#endif + return mode != AppliedOffsetMode.SceneOffset && + mode != AppliedOffsetMode.SceneOffsetLegacy; + } + + bool HasController(GameObject gameObject) + { + var animator = GetBinding(gameObject != null ? gameObject.GetComponent() : null); + + return animator != null && animator.runtimeAnimatorController != null; + } + + internal Animator GetBinding(PlayableDirector director) + { + if (director == null) + return null; + + UnityEngine.Object key = this; + if (isSubTrack) + key = parent; + + UnityEngine.Object binding = null; + if (director != null) + binding = director.GetGenericBinding(key); + + Animator animator = null; + if (binding != null) // the binding can be an animator or game object + { + animator = binding as Animator; + var gameObject = binding as GameObject; + if (animator == null && gameObject != null) + animator = gameObject.GetComponent(); + } + + return animator; + } + + static AnimationLayerMixerPlayable CreateGroupMixer(PlayableGraph graph, GameObject go, int inputCount) + { + return AnimationLayerMixerPlayable.Create(graph, inputCount); + } + + Playable CreateInfiniteTrackPlayable(PlayableGraph graph, GameObject go, IntervalTree tree, AppliedOffsetMode mode) + { + if (m_InfiniteClip == null) + return Playable.Null; + + var mixer = AnimationMixerPlayable.Create(graph, 1); + + // In infinite mode, we always force the loop mode of the clip off because the clip keys are offset in infinite mode + // which causes loop to behave different. + // The inline curve editor never shows loops in infinite mode. + var playable = AnimationPlayableAsset.CreatePlayable(graph, m_InfiniteClip, m_InfiniteClipOffsetPosition, m_InfiniteClipOffsetEulerAngles, false, mode, infiniteClipApplyFootIK, AnimationPlayableAsset.LoopMode.Off); + if (playable.IsValid()) + { + tree.Add(new InfiniteRuntimeClip(playable)); + graph.Connect(playable, 0, mixer, 0); + mixer.SetInputWeight(0, 1.0f); + } + + return ApplyTrackOffset(graph, mixer, go, mode); + } + + Playable ApplyTrackOffset(PlayableGraph graph, Playable root, GameObject go, AppliedOffsetMode mode) + { +#if UNITY_EDITOR + m_ClipOffset = AnimationOffsetPlayable.Null; +#endif + + // offsets don't apply in scene offset, or if there is no root transform (globally or on this track) + if (mode == AppliedOffsetMode.SceneOffsetLegacy || + mode == AppliedOffsetMode.SceneOffset || + mode == AppliedOffsetMode.NoRootTransform || + !AnimatesRootTransform() + ) + return root; + + + var pos = position; + var rot = rotation; + +#if UNITY_EDITOR + // in the editor use the preview position to playback from if available + if (mode == AppliedOffsetMode.SceneOffsetEditor) + { + pos = m_SceneOffsetPosition; + rot = Quaternion.Euler(m_SceneOffsetRotation); + } +#endif + + var offsetPlayable = AnimationOffsetPlayable.Create(graph, pos, rot, 1); +#if UNITY_EDITOR + m_ClipOffset = offsetPlayable; +#endif + graph.Connect(root, 0, offsetPlayable, 0); + offsetPlayable.SetInputWeight(0, 1); + + return offsetPlayable; + } + + // the evaluation time is large so that the properties always get evaluated + internal override void GetEvaluationTime(out double outStart, out double outDuration) + { + if (inClipMode) + { + base.GetEvaluationTime(out outStart, out outDuration); + } + else + { + outStart = 0; + outDuration = TimelineClip.kMaxTimeValue; + } + } + + internal override void GetSequenceTime(out double outStart, out double outDuration) + { + if (inClipMode) + { + base.GetSequenceTime(out outStart, out outDuration); + } + else + { + outStart = 0; + outDuration = Math.Max(GetNotificationDuration(), TimeUtility.GetAnimationClipLength(m_InfiniteClip)); + } + } + + void AssignAnimationClip(TimelineClip clip, AnimationClip animClip) + { + if (clip == null || animClip == null) + return; + + if (animClip.legacy) + throw new InvalidOperationException("Legacy Animation Clips are not supported"); + + AnimationPlayableAsset asset = clip.asset as AnimationPlayableAsset; + if (asset != null) + { + asset.clip = animClip; + asset.name = animClip.name; + var duration = asset.duration; + if (!double.IsInfinity(duration) && duration >= TimelineClip.kMinDuration && duration < TimelineClip.kMaxTimeValue) + clip.duration = duration; + } + clip.displayName = animClip.name; + } + + /// + /// Called by the Timeline Editor to gather properties requiring preview. + /// + /// The PlayableDirector invoking the preview + /// PropertyCollector used to gather previewable properties + public override void GatherProperties(PlayableDirector director, IPropertyCollector driver) + { +#if UNITY_EDITOR + m_SceneOffsetPosition = Vector3.zero; + m_SceneOffsetRotation = Vector3.zero; + + var animator = GetBinding(director); + if (animator == null) + return; + + var animClips = new List(this.clips.Length + 2); + GetAnimationClips(animClips); + + var hasHumanMotion = animClips.Exists(clip => clip.humanMotion); + + m_SceneOffsetPosition = animator.transform.localPosition; + m_SceneOffsetRotation = animator.transform.localEulerAngles; + + // Create default pose clip from collected properties + if (hasHumanMotion) + animClips.Add(GetDefaultHumanoidClip()); + + var bindings = AnimationPreviewUtilities.GetBindings(animator.gameObject, animClips); + + m_CachedPropertiesClip = AnimationPreviewUtilities.CreateDefaultClip(animator.gameObject, bindings); + AnimationPreviewUtilities.PreviewFromCurves(animator.gameObject, bindings); // faster to preview from curves then an animation clip + m_DefaultPoseClip = hasHumanMotion ? GetDefaultHumanoidClip() : null; +#endif + } + + /// + /// Gather all the animation clips for this track + /// + /// + private void GetAnimationClips(List animClips) + { + foreach (var c in clips) + { + var a = c.asset as AnimationPlayableAsset; + if (a != null && a.clip != null) + animClips.Add(a.clip); + } + + if (m_InfiniteClip != null) + animClips.Add(m_InfiniteClip); + + foreach (var childTrack in GetChildTracks()) + { + var animChildTrack = childTrack as AnimationTrack; + if (animChildTrack != null) + animChildTrack.GetAnimationClips(animClips); + } + } + + // calculate which offset mode to apply + AppliedOffsetMode GetOffsetMode(GameObject go, bool animatesRootTransform) + { + if (!animatesRootTransform) + return AppliedOffsetMode.NoRootTransform; + + if (m_TrackOffset == TrackOffset.ApplyTransformOffsets) + return AppliedOffsetMode.TransformOffset; + + if (m_TrackOffset == TrackOffset.ApplySceneOffsets) + return (Application.isPlaying) ? AppliedOffsetMode.SceneOffset : AppliedOffsetMode.SceneOffsetEditor; + + if (HasController(go)) + { + if (!Application.isPlaying) + return AppliedOffsetMode.SceneOffsetLegacyEditor; + return AppliedOffsetMode.SceneOffsetLegacy; + } + + return AppliedOffsetMode.TransformOffsetLegacy; + } + + internal bool AnimatesRootTransform() + { + // infinite mode + if (AnimationPlayableAsset.HasRootTransforms(m_InfiniteClip)) + return true; + + // clip mode + foreach (var c in GetClips()) + { + var apa = c.asset as AnimationPlayableAsset; + if (apa != null && apa.hasRootTransforms) + return true; + } + + return false; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs.meta new file mode 100644 index 0000000..9ba4e15 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/AnimationTrack.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d21dcc2386d650c4597f3633c75a1f98 +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/Animation/ICurvesOwner.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs new file mode 100644 index 0000000..8d61f57 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs @@ -0,0 +1,15 @@ +namespace UnityEngine.Timeline +{ + interface ICurvesOwner + { + AnimationClip curves { get; } + bool hasCurves { get; } + double duration { get; } + void CreateCurves(string curvesClipName); + + string defaultCurvesName { get; } + Object asset { get; } + Object assetOwner { get; } + TrackAsset targetTrack { get; } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs.meta new file mode 100644 index 0000000..d5d95df --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Runtime/Animation/ICurvesOwner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89b31ff5ca0a5eb4797ac65d43949807 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: -- cgit v1.2.3