using System; using UnityEngine; using UnityEngine.Timeline; namespace UnityEditor.Timeline { static class CurvesOwnerInspectorHelper { // Because what is animated is not the asset, but the instanced playable, // we apply the animation clip here to preview what is being shown // This could be improved doing something more inline with animation mode, // and reverting values that aren't be recorded later to avoid dirtying the asset public static void PreparePlayableAsset(ICurvesOwnerInspectorWrapper wrapper) { if (wrapper.serializedPlayableAsset == null) return; var curvesOwner = wrapper.curvesOwner; if (curvesOwner == null || curvesOwner.curves == null) return; var timelineWindow = TimelineWindow.instance; if (timelineWindow == null || timelineWindow.state == null) return; // requires preview mode. reset the eval time so previous value is correct value is displayed while toggling if (!timelineWindow.state.previewMode) { wrapper.lastEvalTime = -1; return; } var time = wrapper.ToLocalTime(timelineWindow.state.editSequence.time); // detect if the time has changed, or if the curves have changed if (Math.Abs(wrapper.lastEvalTime - time) < TimeUtility.kTimeEpsilon) { int curveVersion = AnimationClipCurveCache.Instance.GetCurveInfo(curvesOwner.curves).version; if (curveVersion == wrapper.lastCurveVersion) return; wrapper.lastCurveVersion = curveVersion; } wrapper.lastEvalTime = time; var clipInfo = AnimationClipCurveCache.Instance.GetCurveInfo(curvesOwner.curves); int count = clipInfo.bindings.Length; if (count == 0) return; wrapper.serializedPlayableAsset.Update(); var prop = wrapper.serializedPlayableAsset.GetIterator(); while (prop.NextVisible(true)) { if (curvesOwner.IsParameterAnimated(prop.propertyPath)) { var curve = curvesOwner.GetAnimatedParameter(prop.propertyPath); switch (prop.propertyType) { case SerializedPropertyType.Boolean: prop.boolValue = curve.Evaluate((float)time) > 0; break; case SerializedPropertyType.Float: prop.floatValue = curve.Evaluate((float)time); break; case SerializedPropertyType.Integer: prop.intValue = Mathf.FloorToInt(curve.Evaluate((float)time)); break; case SerializedPropertyType.Color: SetAnimatedValue(curvesOwner, prop, "r", time); SetAnimatedValue(curvesOwner, prop, "g", time); SetAnimatedValue(curvesOwner, prop, "b", time); SetAnimatedValue(curvesOwner, prop, "a", time); break; case SerializedPropertyType.Quaternion: case SerializedPropertyType.Vector4: SetAnimatedValue(curvesOwner, prop, "w", time); goto case SerializedPropertyType.Vector3; case SerializedPropertyType.Vector3: SetAnimatedValue(curvesOwner, prop, "z", time); goto case SerializedPropertyType.Vector2; case SerializedPropertyType.Vector2: SetAnimatedValue(curvesOwner, prop, "x", time); SetAnimatedValue(curvesOwner, prop, "y", time); break; } } } wrapper.serializedPlayableAsset.ApplyModifiedPropertiesWithoutUndo(); } static void SetAnimatedValue(ICurvesOwner clip, SerializedProperty property, string path, double localTime) { var prop = property.FindPropertyRelative(path); if (prop != null) { var curve = clip.GetAnimatedParameter(prop.propertyPath); if (curve != null) prop.floatValue = curve.Evaluate((float)localTime); } } } }