public void ProcessCandidates()
        {
            BeginKeyModification();

            EditorCurveBinding[] bindings            = AnimationUtility.GetCurveBindings(m_CandidateClip);
            EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(m_CandidateClip);

            List <AnimationWindowCurve> curves = new List <AnimationWindowCurve>();

            for (int i = 0; i < state.allCurves.Count; ++i)
            {
                AnimationWindowCurve curve           = state.allCurves[i];
                EditorCurveBinding   remappedBinding = UnityEditor.PlayEm.RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(curve.binding, m_CandidateClip);
                if (Array.Exists(bindings, binding => remappedBinding.Equals(binding)) || Array.Exists(objectCurveBindings, binding => remappedBinding.Equals(binding)))
                {
                    curves.Add(curve);
                }
            }

            AnimationWindowUtility.AddKeyframes(state, curves, time);

            EndKeyModification();

            ClearCandidates();
        }
        public void GoToNextKeyframe(PropertyModification[] modifications)
        {
            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);
            if (bindings.Length == 0)
            {
                return;
            }

            List <AnimationWindowCurve> curves = new List <AnimationWindowCurve>();

            for (int i = 0; i < state.allCurves.Count; ++i)
            {
                AnimationWindowCurve curve = state.allCurves[i];
                if (Array.Exists(bindings, binding => curve.binding.Equals(binding)))
                {
                    curves.Add(curve);
                }
            }

            float newTime = AnimationWindowUtility.GetNextKeyframeTime(curves.ToArray(), time.time, state.clipFrameRate);

            SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToClipFrame));

            state.Repaint();
        }
        private List <AnimationWindowKeyframe> GetKeys(PropertyModification[] modifications)
        {
            var keys = new List <AnimationWindowKeyframe>();

            EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip);
            if (bindings.Length == 0)
            {
                return(keys);
            }

            for (int i = 0; i < state.allCurves.Count; ++i)
            {
                AnimationWindowCurve curve = state.allCurves[i];
                if (Array.Exists(bindings, binding => curve.binding.Equals(binding)))
                {
                    int keyIndex = curve.GetKeyframeIndex(state.time);
                    if (keyIndex >= 0)
                    {
                        keys.Add(curve.m_Keyframes[keyIndex]);
                    }
                }
            }

            return(keys);
        }
        private void FillPropertyGroup(ref EditorCurveBinding?[] propertyGroup, EditorCurveBinding lastBinding, string propertyGroupName, ref List <AnimationWindowCurve> curvesCache)
        {
            var newBinding = lastBinding;

            newBinding.isPhantom = true;
            if (!propertyGroup[0].HasValue)
            {
                newBinding.propertyName = propertyGroupName + ".x";
                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding));
                curve.selectionBinding = this;
                curvesCache.Add(curve);
            }

            if (!propertyGroup[1].HasValue)
            {
                newBinding.propertyName = propertyGroupName + ".y";
                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding));
                curve.selectionBinding = this;
                curvesCache.Add(curve);
            }

            if (!propertyGroup[2].HasValue)
            {
                newBinding.propertyName = propertyGroupName + ".z";
                AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding));
                curve.selectionBinding = this;
                curvesCache.Add(curve);
            }
        }
예제 #5
0
        static void AddRotationKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, Vector3 previousEulerAngles, Vector3 currentEulerAngles)
        {
            AnimationClip clip = state.activeAnimationClip;

            if ((clip.hideFlags & HideFlags.NotEditable) != 0)
            {
                return;
            }

            EditorCurveBinding[] additionalBindings = RotationCurveInterpolation.RemapAnimationBindingForRotationAddKey(binding, clip);

            // Add key at current frame
            for (int i = 0; i < 3; i++)
            {
                AnimationWindowCurve curve = new AnimationWindowCurve(clip, additionalBindings[i], type);

                if (state.addZeroFrame)
                {
                    // Is it a new curve?
                    if (curve.length == 0)
                    {
                        if (state.currentFrame != 0)
                        {
                            AnimationWindowUtility.AddKeyframeToCurve(curve, previousEulerAngles[i], type, AnimationKeyTime.Frame(0, clip.frameRate));
                        }
                    }
                }

                AnimationWindowUtility.AddKeyframeToCurve(curve, currentEulerAngles[i], type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));
                state.SaveCurve(curve);
            }
        }
예제 #6
0
        static void AddKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, object previousValue, object currentValue)
        {
            GameObject    root = state.activeRootGameObject;
            AnimationClip clip = state.activeAnimationClip;

            if ((clip.hideFlags & HideFlags.NotEditable) != 0)
            {
                return;
            }

            AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, type);

            // Add previous value at first frame on empty curves.
            if (state.addZeroFrame)
            {
                // Is it a new curve?
                if (curve.length == 0)
                {
                    if (state.currentFrame != 0)
                    {
                        AnimationWindowUtility.AddKeyframeToCurve(curve, previousValue, type, AnimationKeyTime.Frame(0, clip.frameRate));
                    }
                }
            }

            // Add key at current frame.
            AnimationWindowUtility.AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));

            state.SaveCurve(curve);
        }
예제 #7
0
 // Retrieve current value.  If bindings are available and value is animated, use bindings to get value.
 // Otherwise, evaluate AnimationWindowCurve at current time.
 public static object GetCurrentValue(AnimationWindowState state, AnimationWindowCurve curve)
 {
     if (state.previewing && curve.rootGameObject != null)
     {
         return(AnimationWindowUtility.GetCurrentValue(curve.rootGameObject, curve.binding));
     }
     else
     {
         return(curve.Evaluate(state.currentTime));
     }
 }
 public AnimationWindowKeyframe(AnimationWindowCurve curve, Keyframe key)
 {
     this.time           = key.time;
     this.value          = key.value;
     this.curve          = curve;
     this.m_InTangent    = key.inTangent;
     this.m_OutTangent   = key.outTangent;
     this.m_InWeight     = key.inWeight;
     this.m_OutWeight    = key.outWeight;
     this.m_WeightedMode = key.weightedMode;
     this.m_TangentMode  = key.tangentModeInternal;
     this.m_curve        = curve;
 }
예제 #9
0
        static void ProcessRootMotionModification(IAnimationRecordingState state, Animator animator, UndoPropertyModification modification, string name, float value, float scale)
        {
            AnimationClip clip = state.activeAnimationClip;

            if ((clip.hideFlags & HideFlags.NotEditable) != 0)
            {
                return;
            }

            float prevValue = value;

            object oValue;

            if (ValueFromPropertyModification(modification.currentValue, new EditorCurveBinding(), out oValue))
            {
                value = (float)oValue;
            }

            if (ValueFromPropertyModification(modification.previousValue, new EditorCurveBinding(), out oValue))
            {
                prevValue = (float)oValue;
            }

            value     = Mathf.Abs(scale) > Mathf.Epsilon ? value / scale : value;
            prevValue = Mathf.Abs(scale) > Mathf.Epsilon ? prevValue / scale : prevValue;

            var binding = new EditorCurveBinding();

            binding.propertyName = name;
            binding.path         = "";
            binding.type         = typeof(Animator);

            var prop = new PropertyModification();

            prop.target       = animator;
            prop.propertyPath = binding.propertyName;
            prop.value        = value.ToString(CultureInfo.InvariantCulture.NumberFormat);

            state.AddPropertyModification(binding, prop, modification.keepPrefabOverride);

            AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, typeof(float));

            if (state.addZeroFrame && state.currentFrame != 0 && curve.length == 0)
            {
                AnimationWindowUtility.AddKeyframeToCurve(curve, prevValue, typeof(float), AnimationKeyTime.Frame(0, clip.frameRate));
            }

            AnimationWindowUtility.AddKeyframeToCurve(curve, value, typeof(float), AnimationKeyTime.Frame(state.currentFrame, clip.frameRate));

            state.SaveCurve(curve);
        }
예제 #10
0
        private AnimationWindowHierarchyPropertyNode AddPropertyToHierarchy(AnimationWindowCurve curve, AnimationWindowHierarchyNode parentNode)
        {
            AnimationWindowHierarchyPropertyNode node = new AnimationWindowHierarchyPropertyNode(curve.type, 0, curve.propertyName, curve.path, parentNode, curve.binding, curve.isPPtrCurve);

            if (parentNode.icon != null)
            {
                node.icon = parentNode.icon;
            }
            else
            {
                node.icon = GetIcon(curve.binding);
            }

            node.indent = curve.depth;
            node.curves = new[] { curve };
            return(node);
        }
예제 #11
0
        public List <AnimationWindowHierarchyNode> CreateTreeFromCurves()
        {
            List <AnimationWindowHierarchyNode> nodes = new List <AnimationWindowHierarchyNode>();
            List <AnimationWindowCurve>         singlePropertyCurves = new List <AnimationWindowCurve>();

            AnimationWindowCurve[]       curves     = state.allCurves.ToArray();
            AnimationWindowHierarchyNode parentNode = (AnimationWindowHierarchyNode)m_RootItem;

            for (int i = 0; i < curves.Length; i++)
            {
                AnimationWindowCurve curve = curves[i];

                if (!state.ShouldShowCurve(curve))
                {
                    continue;
                }

                AnimationWindowCurve nextCurve = i < curves.Length - 1 ? curves[i + 1] : null;

                singlePropertyCurves.Add(curve);

                bool areSameGroup       = nextCurve != null && AnimationWindowUtility.GetPropertyGroupName(nextCurve.propertyName) == AnimationWindowUtility.GetPropertyGroupName(curve.propertyName);
                bool areSamePathAndType = nextCurve != null && curve.path.Equals(nextCurve.path) && curve.type == nextCurve.type;

                // We expect curveBindings to come sorted by propertyname
                // So we compare curve vs nextCurve. If its different path or different group (think "scale.xyz" as group), then we know this is the last element of such group.
                if (i == curves.Length - 1 || !areSameGroup || !areSamePathAndType)
                {
                    if (singlePropertyCurves.Count > 1)
                    {
                        nodes.Add(AddPropertyGroupToHierarchy(singlePropertyCurves.ToArray(), parentNode));
                    }
                    else
                    {
                        nodes.Add(AddPropertyToHierarchy(singlePropertyCurves[0], parentNode));
                    }
                    singlePropertyCurves.Clear();
                }
            }

            return(nodes);
        }
        private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row)
        {
            bool curvesChanged = false;

            if (node is AnimationWindowHierarchyPropertyNode)
            {
                AnimationWindowCurve[] curves = node.curves;
                if (curves == null || curves.Length == 0)
                {
                    return;
                }

                // We do valuefields for dopelines that only have single curve
                AnimationWindowCurve curve = curves[0];
                object objectValue         = CurveBindingUtility.GetCurrentValue(state, curve);

                if (objectValue is float)
                {
                    float value = (float)objectValue;

                    Rect valueFieldDragRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide - k_ValueFieldDragWidth, rect.y, k_ValueFieldDragWidth, rect.height);
                    Rect valueFieldRect     = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide, rect.y, k_ValueFieldWidth, rect.height);

                    if (Event.current.type == EventType.MouseMove && valueFieldRect.Contains(Event.current.mousePosition))
                    {
                        s_WasInsideValueRectFrame = Time.frameCount;
                    }

                    EditorGUI.BeginChangeCheck();

                    if (curve.valueType == typeof(bool))
                    {
                        value = GUI.Toggle(valueFieldRect, m_HierarchyItemValueControlIDs[row], value != 0, GUIContent.none, EditorStyles.toggle) ? 1 : 0;
                    }
                    else
                    {
                        int  id = m_HierarchyItemValueControlIDs[row];
                        bool enterInTextField = (EditorGUIUtility.keyboardControl == id &&
                                                 EditorGUIUtility.editingTextField &&
                                                 Event.current.type == EventType.KeyDown &&
                                                 (Event.current.character == '\n' || (int)Event.current.character == 3));

                        //  Force back keyboard focus to float field editor when editing it.
                        //  TreeView forces keyboard focus on itself at mouse down and we lose focus here.
                        if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition))
                        {
                            GUIUtility.keyboardControl = id;
                        }

                        value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor,
                                                       valueFieldRect,
                                                       valueFieldDragRect,
                                                       id,
                                                       value,
                                                       "g5",
                                                       m_AnimationSelectionTextField,
                                                       true);
                        if (enterInTextField)
                        {
                            GUI.changed = true;
                            Event.current.Use();
                        }
                    }

                    if (float.IsInfinity(value) || float.IsNaN(value))
                    {
                        value = 0;
                    }

                    if (EditorGUI.EndChangeCheck())
                    {
                        string undoLabel = "Edit Key";

                        AnimationKeyTime newAnimationKeyTime = AnimationKeyTime.Time(state.currentTime, curve.clip.frameRate);

                        AnimationWindowKeyframe existingKeyframe = null;
                        foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes)
                        {
                            if (Mathf.Approximately(keyframe.time, state.currentTime))
                            {
                                existingKeyframe = keyframe;
                            }
                        }

                        if (existingKeyframe == null)
                        {
                            AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, newAnimationKeyTime);
                        }
                        else
                        {
                            existingKeyframe.value = value;
                        }

                        state.SaveCurve(curve.clip, curve, undoLabel);
                        curvesChanged = true;
                    }
                }
            }

            if (curvesChanged)
            {
                state.ResampleAnimation();
            }
        }
 public void SaveCurve(AnimationWindowCurve curve)
 {
     Undo.RegisterCompleteObjectUndo(curve.clip, "Edit Candidate Curve");
     AnimationWindowUtility.SaveCurve(curve.clip, curve);
 }
 public void SaveCurve(AnimationWindowCurve curve)
 {
     m_State.SaveCurve(curve.clip, curve);
 }
 public AnimationWindowKeyframe(AnimationWindowCurve curve, ObjectReferenceKeyframe key)
 {
     this.time  = key.time;
     this.value = key.value;
     this.curve = curve;
 }