internal static AnimationClipSettings GetAnimationClipSettings([NotNull] AnimationClip clip) { if (!k_ClipSettingsCache.ContainsKey(clip)) { k_ClipSettingsCache.Add(clip, clip.legacy ? null : TinyAnimationEditorBridge.GetAnimationClipSettings(clip)); } return(k_ClipSettingsCache[clip]); }
void OnEnable() { m_TinyAnimationAuthoring = (TinyAnimationAuthoring)target; m_Animator = m_TinyAnimationAuthoring.GetComponent <Animator>(); m_CurrentController = TinyAnimationEditorBridge.GetEffectiveAnimatorController(m_Animator); // Ensures an update during first pass m_TargetDirtyCount = -1; m_AnimatorDirtyCount = -1; m_AnimationClipsProp = serializedObject.FindProperty(nameof(TinyAnimationAuthoring.animationClips)); m_PlayAutomaticallyProp = serializedObject.FindProperty(nameof(TinyAnimationAuthoring.playAutomatically)); m_PatchScaleProp = serializedObject.FindProperty(nameof(TinyAnimationAuthoring.patchMissingScaleIfNeeded)); m_AdditionalAnimatorClipsProp = serializedObject.FindProperty(nameof(TinyAnimationAuthoring.additionalAnimatorClips)); }
void OnDisable() { if (m_CurrentController != null) { TinyAnimationEditorBridge.UnregisterDirtyCallbackFromAnimatorController(m_CurrentController, OnControllerDirty); m_CurrentController = null; } m_TinyAnimationAuthoring = null; m_Animator = null; m_AnimationClipsProp = null; m_PlayAutomaticallyProp = null; m_PatchScaleProp = null; m_AdditionalAnimatorClipsProp = null; }
public override void OnInspectorGUI() { serializedObject.UpdateIfRequiredOrScript(); EditorGUILayout.PropertyField(m_AnimationClipsProp, true, null); EditorGUILayout.PropertyField(m_PlayAutomaticallyProp, false, null); EditorGUILayout.PropertyField(m_PatchScaleProp, false, null); serializedObject.ApplyModifiedProperties(); var newTargetDirtyCount = EditorUtility.GetDirtyCount(m_TinyAnimationAuthoring); var newAnimatorDirtyCount = EditorUtility.GetDirtyCount(m_Animator); var targetIsDirty = m_TargetDirtyCount != newTargetDirtyCount; var animatorComponentIsDirty = m_AnimatorDirtyCount != newAnimatorDirtyCount; var animatorControllerAssetIsDirty = m_AnimatorControllerIsDirty; if (targetIsDirty) { m_TargetDirtyCount = newTargetDirtyCount; } if (animatorComponentIsDirty) { m_AnimatorDirtyCount = newAnimatorDirtyCount; if (m_CurrentController != null) { TinyAnimationEditorBridge.UnregisterDirtyCallbackFromAnimatorController(m_CurrentController, OnControllerDirty); } m_CurrentController = TinyAnimationEditorBridge.GetEffectiveAnimatorController(m_Animator); if (m_CurrentController != null) { TinyAnimationEditorBridge.RegisterDirtyCallbackForAnimatorController(m_CurrentController, OnControllerDirty); } } if (animatorControllerAssetIsDirty) { m_AnimatorControllerIsDirty = false; } if (targetIsDirty || animatorComponentIsDirty || animatorControllerAssetIsDirty) { m_TinyAnimationAuthoring.UpdateAdditionalAnimatorClips(); } if (m_TinyAnimationAuthoring.additionalAnimatorClips.Count == 0) { return; } if (targetIsDirty) { UpdateNonNullUserClipsCount(); } EditorGUILayout.Space(); EditorGUILayout.HelpBox($"The following clips will be converted (in that order, starting at index {m_NonNullUserClipsCount.ToString(CultureInfo.InvariantCulture)}) from the Animator.\n" + "Note that the Animator's state machine will not get converted; only the clips.", MessageType.Info, true); using (new EditorGUI.DisabledScope(true)) { EditorGUILayout.PropertyField(m_AdditionalAnimatorClipsProp, true, null); } }
static BlobAssetReference <CurvesInfo> ConvertFloatCurves([NotNull] AnimationClip clip) { var bindings = AnimationUtility .GetCurveBindings(clip) .OrderBy(b => b.path) // Ensures we are processing one target at a time .ThenBy(b => b.propertyName) // Ensures we are processing vector properties together .ToArray(); var numBindings = bindings.Length; var blobAssetRef = BlobAssetReference <CurvesInfo> .Null; if (numBindings == 0) { return(blobAssetRef); } var targetPaths = new List <FixedString512>(numBindings); var animationBindingsConvertedNames = new List <FixedString512>(numBindings); var keyframeCurves = new List <KeyframeCurve>(numBindings); var scaleRequired = false; var numKeys = 0; var numBindingsAfterConversion = numBindings; for (var i = 0; i < numBindings; i++) { var binding = bindings[i]; var rotationMode = TinyAnimationEditorBridge.GetRotationMode(binding); // Handle non quaternion rotation. if (rotationMode != TinyAnimationEditorBridge.RotationMode.Undefined && rotationMode != TinyAnimationEditorBridge.RotationMode.RawQuaternions) { // TODO: Handle other modes when/if they show up if (rotationMode == TinyAnimationEditorBridge.RotationMode.RawEuler) { var currentPath = binding.path; var xBinding = default(EditorCurveBinding); var yBinding = default(EditorCurveBinding); var zBinding = default(EditorCurveBinding); var rotationBindingOffset = 0; while (rotationBindingOffset < 3 && i + rotationBindingOffset < numBindings) { var nextBinding = bindings[i + rotationBindingOffset]; if (!string.Equals(currentPath, nextBinding.path, StringComparison.Ordinal) || TinyAnimationEditorBridge.GetRotationMode(nextBinding) != TinyAnimationEditorBridge.RotationMode.RawEuler) { // Binding is either for a different target or not a rotation: skip! break; } if (nextBinding.propertyName.EndsWith(".x", StringComparison.Ordinal)) { xBinding = nextBinding; } else if (nextBinding.propertyName.EndsWith(".y", StringComparison.Ordinal)) { yBinding = nextBinding; } else { zBinding = nextBinding; } rotationBindingOffset++; } var xCurveOriginal = xBinding != default ? AnimationUtility.GetEditorCurve(clip, xBinding) : new AnimationCurve(new UnityEngine.Keyframe(0.0f, 0.0f), new UnityEngine.Keyframe(clip.length, 0.0f)); var yCurveOriginal = yBinding != default ? AnimationUtility.GetEditorCurve(clip, yBinding) : new AnimationCurve(new UnityEngine.Keyframe(0.0f, 0.0f), new UnityEngine.Keyframe(clip.length, 0.0f)); var zCurveOriginal = zBinding != default ? AnimationUtility.GetEditorCurve(clip, zBinding) : new AnimationCurve(new UnityEngine.Keyframe(0.0f, 0.0f), new UnityEngine.Keyframe(clip.length, 0.0f)); var xCurveNew = new AnimationCurve(); var yCurveNew = new AnimationCurve(); var zCurveNew = new AnimationCurve(); var wCurveNew = new AnimationCurve(); // We *need* to resample at the framerate when converting from Euler to Quaternion var step = clip.length / clip.frameRate; var time = 0.0f; do { EvaluateAndConvert(time); time += step; }while (time <= clip.length - step); // Setting the last frame explicitly to avoid precision errors EvaluateAndConvert(clip.length); void EvaluateAndConvert(float t) { var euler = new float3(xCurveOriginal.Evaluate(t), yCurveOriginal.Evaluate(t), zCurveOriginal.Evaluate(t)); var quat = quaternion.Euler(math.radians(euler)); xCurveNew.AddKey(new UnityEngine.Keyframe(t, quat.value.x, Mathf.Infinity, Mathf.Infinity)); yCurveNew.AddKey(new UnityEngine.Keyframe(t, quat.value.y, Mathf.Infinity, Mathf.Infinity)); zCurveNew.AddKey(new UnityEngine.Keyframe(t, quat.value.z, Mathf.Infinity, Mathf.Infinity)); wCurveNew.AddKey(new UnityEngine.Keyframe(t, quat.value.w, Mathf.Infinity, Mathf.Infinity)); } var resampledKeysCount = xCurveNew.length; var xPropName = GetConvertedName(binding.type, TinyAnimationEditorBridge.CreateRawQuaternionsBindingName("x")); var yPropName = GetConvertedName(binding.type, TinyAnimationEditorBridge.CreateRawQuaternionsBindingName("y")); var zPropName = GetConvertedName(binding.type, TinyAnimationEditorBridge.CreateRawQuaternionsBindingName("z")); var wPropName = GetConvertedName(binding.type, TinyAnimationEditorBridge.CreateRawQuaternionsBindingName("w")); animationBindingsConvertedNames.Add(new FixedString512(xPropName)); animationBindingsConvertedNames.Add(new FixedString512(yPropName)); animationBindingsConvertedNames.Add(new FixedString512(zPropName)); animationBindingsConvertedNames.Add(new FixedString512(wPropName)); keyframeCurves.Add(xCurveNew.ToKeyframeCurve()); keyframeCurves.Add(yCurveNew.ToKeyframeCurve()); keyframeCurves.Add(zCurveNew.ToKeyframeCurve()); keyframeCurves.Add(wCurveNew.ToKeyframeCurve()); numKeys += resampledKeysCount * 4; var targetPath = string.IsNullOrEmpty(binding.path) ? string.Empty : binding.path; targetPaths.Add(targetPath); targetPaths.Add(targetPath); targetPaths.Add(targetPath); targetPaths.Add(targetPath); // How many new bindings were added by this conversion? // e.g.: // Euler bindings to [x,y,z] converts to quaternion bindings [x,y,z,w], so we added 1 new binding // Euler bindings to [y] converts to quaternion bindings [x,y,z,w], so we added 3 new binding numBindingsAfterConversion += 4 - rotationBindingOffset; // Skip already processed bindings i += rotationBindingOffset - 1; } else { throw new InvalidOperationException($"Rotation mode: {rotationMode} is not supported."); } } else { // Note: Empty string maps to self in Transform.Find() targetPaths.Add(string.IsNullOrEmpty(binding.path) ? string.Empty : binding.path); var bindingPropertyName = binding.propertyName; var convertedName = GetConvertedName(binding.type, bindingPropertyName); animationBindingsConvertedNames.Add(new FixedString512(convertedName)); var animationCurve = AnimationUtility.GetEditorCurve(clip, binding); var curve = animationCurve.ToKeyframeCurve(); keyframeCurves.Add(curve); numKeys += curve.Length; if (!scaleRequired && binding.type == typeof(Transform) && bindingPropertyName.StartsWith("m_LocalScale.", StringComparison.Ordinal)) { scaleRequired = true; } } } using (var blobBuilder = new BlobBuilder(Allocator.Temp)) { ref var builderRoot = ref blobBuilder.ConstructRoot <CurvesInfo>(); var keyframesBuilder = blobBuilder.Allocate(ref builderRoot.Keyframes, numKeys); var curveOffsetsBuilder = blobBuilder.Allocate(ref builderRoot.CurveOffsets, numBindingsAfterConversion); var bindingNamesBuilder = blobBuilder.Allocate(ref builderRoot.BindingNames, numBindingsAfterConversion); var targetPathsBuilder = blobBuilder.Allocate(ref builderRoot.TargetGameObjectPaths, numBindingsAfterConversion); // We don't care about that field in this case blobBuilder.Allocate(ref builderRoot.AnimatedAssetGroupings, 0); for (int bindingIndex = 0, keyIndex = 0, curveOffset = 0; bindingIndex < numBindingsAfterConversion; ++bindingIndex) { var keyframeCurve = keyframeCurves[bindingIndex]; for (var i = 0; i < keyframeCurve.Length; ++i) { keyframesBuilder[keyIndex++] = keyframeCurve[i]; } curveOffsetsBuilder[bindingIndex] = curveOffset; curveOffset += keyframeCurve.Length; bindingNamesBuilder[bindingIndex] = animationBindingsConvertedNames[bindingIndex]; targetPathsBuilder[bindingIndex] = targetPaths[bindingIndex]; } builderRoot.ConversionActions = scaleRequired ? RequiredConversionActions.PatchScale : RequiredConversionActions.None; blobAssetRef = blobBuilder.CreateBlobAssetReference <CurvesInfo>(Allocator.Persistent); }