Initial Commit
This commit is contained in:
parent
53eb92e9af
commit
270ab7d11f
15341 changed files with 700234 additions and 0 deletions
|
@ -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<WeightInfo> m_Mixers = new List<WeightInfo>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a429b38ee9d48c7408c8870baf406034
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,325 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
namespace UnityEngine.Timeline
|
||||
{
|
||||
/// <summary>
|
||||
/// A Playable Asset that represents a single AnimationClip clip.
|
||||
/// </summary>
|
||||
[System.Serializable, NotKeyable]
|
||||
public partial class AnimationPlayableAsset : PlayableAsset, ITimelineClipAsset, IPropertyPreview
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the source AnimationClip loops during playback.
|
||||
/// </summary>
|
||||
public enum LoopMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Use the loop time setting from the source AnimationClip.
|
||||
/// </summary>
|
||||
[Tooltip("Use the loop time setting from the source AnimationClip.")]
|
||||
UseSourceAsset = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The source AnimationClip loops during playback.
|
||||
/// </summary>
|
||||
[Tooltip("The source AnimationClip loops during playback.")]
|
||||
On = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The source AnimationClip does not loop during playback.
|
||||
/// </summary>
|
||||
[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
|
||||
|
||||
/// <summary>
|
||||
/// The translational offset of the clip
|
||||
/// </summary>
|
||||
public Vector3 position
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_Position = value;
|
||||
#if UNITY_EDITOR
|
||||
if (m_AnimationOffsetPlayable.IsValid())
|
||||
m_AnimationOffsetPlayable.SetPosition(position);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The rotational offset of the clip, expressed as a Quaternion
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The rotational offset of the clip, expressed in Euler angles
|
||||
/// </summary>
|
||||
public Vector3 eulerAngles
|
||||
{
|
||||
get { return m_EulerAngles; }
|
||||
set
|
||||
{
|
||||
m_EulerAngles = value;
|
||||
#if UNITY_EDITOR
|
||||
if (m_AnimationOffsetPlayable.IsValid())
|
||||
m_AnimationOffsetPlayable.SetRotation(rotation);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to use offset matching options as defined by the track.
|
||||
/// </summary>
|
||||
public bool useTrackMatchFields
|
||||
{
|
||||
get { return m_UseTrackMatchFields; }
|
||||
set { m_UseTrackMatchFields = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies which fields should be matched when aligning offsets.
|
||||
/// </summary>
|
||||
public MatchTargetFields matchTargetFields
|
||||
{
|
||||
get { return m_MatchTargetFields; }
|
||||
set { m_MatchTargetFields = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether to make the animation clip play relative to its first keyframe.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This option only applies to animation clips that animate Transform components.
|
||||
/// </remarks>
|
||||
public bool removeStartOffset
|
||||
{
|
||||
get { return m_RemoveStartOffset; }
|
||||
set { m_RemoveStartOffset = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enable to apply foot IK to the AnimationClip when the target is humanoid.
|
||||
/// </summary>
|
||||
public bool applyFootIK
|
||||
{
|
||||
get { return m_ApplyFootIK; }
|
||||
set { m_ApplyFootIK = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the source AnimationClip loops during playback
|
||||
/// </summary>
|
||||
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; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The source animation clip
|
||||
/// </summary>
|
||||
public AnimationClip clip
|
||||
{
|
||||
get { return m_Clip; }
|
||||
set
|
||||
{
|
||||
if (value != null)
|
||||
name = "AnimationPlayableAsset of " + value.name;
|
||||
m_Clip = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the duration required to play the animation clip exactly once
|
||||
/// </summary>
|
||||
public override double duration
|
||||
{
|
||||
get
|
||||
{
|
||||
double length = TimeUtility.GetAnimationClipLength(clip);
|
||||
if (length < float.Epsilon)
|
||||
return base.duration;
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a description of the PlayableOutputs that may be created for this asset.
|
||||
/// </summary>
|
||||
public override IEnumerable<PlayableBinding> outputs
|
||||
{
|
||||
get { yield return AnimationPlayableBinding.Create(name, this); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the root of a Playable subgraph to play the animation clip.
|
||||
/// </summary>
|
||||
/// <param name="graph">PlayableGraph that will own the playable</param>
|
||||
/// <param name="go">The gameobject that triggered the graph build</param>
|
||||
/// <returns>The root playable of the subgraph</returns>
|
||||
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<AnimationOffsetPlayable>())
|
||||
{
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Returns the capabilities of TimelineClips that contain a AnimationPlayableAsset
|
||||
/// </summary>
|
||||
public ClipCaps clipCaps
|
||||
{
|
||||
get
|
||||
{
|
||||
var caps = ClipCaps.Extrapolation | ClipCaps.SpeedMultiplier | ClipCaps.Blending;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the offsets to default values
|
||||
/// </summary>
|
||||
public void ResetOffsets()
|
||||
{
|
||||
position = Vector3.zero;
|
||||
eulerAngles = Vector3.zero;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 030f85c3f73729f4f976f66ffb23b875
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,57 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine.Animations;
|
||||
#if !UNITY_2020_1_OR_NEWER
|
||||
using UnityEngine.Experimental.Animations;
|
||||
#endif
|
||||
|
||||
using UnityEngine.Playables;
|
||||
|
||||
namespace UnityEngine.Timeline
|
||||
{
|
||||
class AnimationPreviewUpdateCallback : ITimelineEvaluateCallback
|
||||
{
|
||||
AnimationPlayableOutput m_Output;
|
||||
PlayableGraph m_Graph;
|
||||
List<IAnimationWindowPreview> 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<IAnimationWindowPreview>();
|
||||
|
||||
var animator = m_Output.GetTarget();
|
||||
if (animator == null)
|
||||
return;
|
||||
|
||||
var gameObject = animator.gameObject;
|
||||
m_PreviewComponents.AddRange(gameObject.GetComponents<IAnimationWindowPreview>());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 755e3e942f7784d458bddba421c0bb72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d21dcc2386d650c4597f3633c75a1f98
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 89b31ff5ca0a5eb4797ac65d43949807
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue