/// Finds the closest selectable point on the curve. /// - Key frames /// - if a key frame is selected, searches the tangents CurveSelection FindClosest(AnimationCurve curve, Vector2 mousePos, out float outDist) { float distance = Mathf.Infinity; CurveSelection closest = new CurveSelection(); // Find closest key point for (int i = 0; i < curve.length; i++) { Vector2 pos = new Vector2(curve[i].time, curve[i].value); float curDist = Vector2.Distance(pos, mousePos); if (curDist < distance) { closest.index = i; closest.type = SelectionType.Key; distance = curDist; } } // Find if selected key is close CurveSelection activeKey = m_DragKey != null ? m_DragKey : m_SelectedKey; if (activeKey != null) { // Go through tangents and key for (int i = 0; i < (int)SelectionType.Count; i++) { Vector2 pos = GetPosition(curve, new CurveSelection(activeKey.index, (SelectionType)i)); float curDist = Vector2.Distance(pos, mousePos); if (curDist < distance) { closest.index = activeKey.index; closest.type = (SelectionType)i; distance = curDist; } } } outDist = distance; if (closest.index != -1) { return(closest); } else { return(null); } }
public static CurveSelection AnimationWindowKeyframeToCurveSelection(AnimationWindowKeyframe keyframe, CurveEditor curveEditor) { int hashCode = keyframe.curve.GetHashCode(); CurveWrapper[] animationCurves = curveEditor.animationCurves; CurveSelection result; for (int i = 0; i < animationCurves.Length; i++) { CurveWrapper curveWrapper = animationCurves[i]; if (curveWrapper.id == hashCode && keyframe.GetIndex() >= 0) { result = new CurveSelection(curveWrapper.id, keyframe.GetIndex()); return(result); } } result = null; return(result); }
Vector2 GetPosition(AnimationCurve curve, CurveSelection selection) { Keyframe key = curve[selection.index]; Vector2 position = new Vector2(key.time, key.value); if (selection.type == SelectionType.InTangent) { if (key.inTangent == Mathf.Infinity) { return(position + Vector2.Scale(new Vector2(0.0F, -1.0F), GetTangentScale())); } else { Vector2 dir = new Vector2(1.0F, key.inTangent); dir /= dir.magnitude; return(position - Vector2.Scale(dir, GetTangentScale())); } } else if (selection.type == SelectionType.OutTangent) { if (key.outTangent == Mathf.Infinity) { return(position + Vector2.Scale(new Vector2(0.0F, 1.0F), GetTangentScale())); } else { Vector2 dir = new Vector2(1.0F, key.outTangent); dir /= dir.magnitude; return(position + Vector2.Scale(dir, GetTangentScale())); } } else { return(position); } }
public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List <AnimationWindowCurve> allCurves) { using (List <AnimationWindowCurve> .Enumerator enumerator = allCurves.GetEnumerator()) { while (enumerator.MoveNext()) { AnimationWindowCurve current = enumerator.Current; if (current.binding == curveSelection.curveWrapper.binding && current.m_Keyframes.Count > curveSelection.key) { return(current.m_Keyframes[curveSelection.key]); } } } return((AnimationWindowKeyframe)null); }
public bool OnGUI(Rect rect) { bool modified = false; GUILayout.BeginArea(rect); Color oldColor = GUI.color; // Check selection indices out of bounds if (m_DragKey != null && (m_DragKey.index < 0 || m_DragKey.index >= animationCurve.length)) { m_DragKey = null; } if (m_SelectedKey != null && (m_SelectedKey.index < 0 || m_SelectedKey.index >= animationCurve.length)) { m_SelectedKey = null; } modified = DisplayActionsGui(rect); bool mouseEvent = Event.current.type == EventType.mouseDown || Event.current.type == EventType.mouseDrag | Event.current.type == EventType.mouseUp; if (Event.current.type == EventType.repaint) { DrawGrid(rect); DrawCurve(animationCurve); } else if (Event.current.type == EventType.mouseDown && Event.current.clickCount == 2) { Keyframe key = new Keyframe(transformedMousePosition.x, transformedMousePosition.y); SetKeyTangentMode(ref key, 0, TangentMode.Smooth); SetKeyTangentMode(ref key, 1, TangentMode.Smooth); int index = animationCurve.AddKey(key); UpdateTangentsFromModeSurrounding(animationCurve, index); m_DragKey = new CurveSelection(index, SelectionType.Key); modified = true; Event.current.Use(); } else if ((Event.current.type == EventType.scrollWheel) || (mouseEvent && Event.current.command)) { m_Scale *= (1 - Event.current.delta.y * 0.01F); m_Scale.x = Mathf.Clamp(m_Scale.x, 0.02F, 10000.0F); m_Scale.y = -m_Scale.x; Event.current.Use(); } else if (mouseEvent && Event.current.alt) { m_Translation += Event.current.delta; Event.current.Use(); } else if (Event.current.type == EventType.mouseDown) { float dist; CurveSelection closest = FindClosest(animationCurve, transformedMousePosition, out dist); if (dist < 20 / m_Scale.magnitude) { m_SelectedKey = m_DragKey = closest; Vector2 keyPos = GetPosition(animationCurve, m_DragKey); m_MouseDownOffset = keyPos - transformedMousePosition; } else { m_DragKey = null; } Event.current.Use(); } else if (Event.current.type == EventType.mouseUp) { m_SelectedKey = m_DragKey; m_DragKey = null; Event.current.Use(); } else if (Event.current.type == EventType.mouseDrag && m_DragKey != null) { Keyframe key = animationCurve[m_DragKey.index]; Vector2 newPosition = transformedMousePosition + m_MouseDownOffset; if (m_DragKey.type == SelectionType.Key) { key.time = newPosition.x; key.value = newPosition.y; } else if (m_DragKey.type == SelectionType.InTangent) { Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value); if (tangentDirection.x < -0.0001F) { key.inTangent = tangentDirection.y / tangentDirection.x; } else { key.inTangent = Mathf.Infinity; } SetKeyTangentMode(ref key, 0, TangentMode.Editable); if (!GetKeyBroken(key)) { key.outTangent = key.inTangent; SetKeyTangentMode(ref key, 1, TangentMode.Editable); } } else if (m_DragKey.type == SelectionType.OutTangent) { Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value); if (tangentDirection.x > 0.0001F) { key.outTangent = tangentDirection.y / tangentDirection.x; } else { key.outTangent = Mathf.Infinity; } SetKeyTangentMode(ref key, 1, TangentMode.Editable); if (!GetKeyBroken(key)) { key.inTangent = key.outTangent; SetKeyTangentMode(ref key, 0, TangentMode.Editable); } } m_DragKey.index = animationCurve.MoveKey(m_DragKey.index, key); UpdateTangentsFromModeSurrounding(animationCurve, m_DragKey.index); modified = true; Event.current.Use(); } else if ((Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Backspace) || (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == "Delete")) { if (m_SelectedKey != null) { animationCurve.RemoveKey(m_SelectedKey.index); m_SelectedKey.index--; modified = true; Event.current.Use(); } } else if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == "FrameSelected") { FrameSelected(rect); Event.current.Use(); } GUILayout.EndArea(); GUI.color = oldColor; return(modified); }
void DrawCurve(AnimationCurve curve) { float normalStepSize = 0.05F; float initialstepSize = 0.00001F; if (curve.length == 0) { return; } // Draw curve Vector3 lhs, rhs; Handles.color = m_CurveColor; float lastPosition = curve[0].value; float lastTime = curve[0].time; for (int i = 0; i < curve.length - 1; i++) { float stepSize = initialstepSize; lastTime = curve[i].time; lastPosition = curve.Evaluate(curve[i].time); for (float f = 0.0F; f < 1.0F - stepSize * 0.5F; f += stepSize) { float newTime = Mathf.Lerp(curve[i].time, curve[i + 1].time, f); newTime = Mathf.Min(curve[i + 1].time, newTime); newTime = Mathf.Max(curve[i].time, newTime); float newPosition = curve.Evaluate(newTime); lhs = new Vector3(lastTime, lastPosition, 0); rhs = new Vector3(newTime, newPosition, 0); Handles.DrawLine(transform.MultiplyPoint(lhs), transform.MultiplyPoint(rhs)); lastTime = newTime; lastPosition = newPosition; if (f != 0.0F) { stepSize = normalStepSize; } } float newTime2 = curve[i + 1].time - 0.00001F; lhs = new Vector3(lastTime, lastPosition, 0); rhs = new Vector3(newTime2, curve.Evaluate(newTime2), 0); Handles.DrawLine(transform.MultiplyPoint(lhs), transform.MultiplyPoint(rhs)); } // Draw all keys (except selected) CurveSelection activeKey = m_DragKey != null ? m_DragKey : m_SelectedKey; GUI.color = m_KeyColor; for (int i = 0; i < curve.length; i++) { if (activeKey != null && i == activeKey.index) { continue; } DrawPoint(curve[i].time, curve[i].value); } // Draw Selected if (activeKey != null) { Vector2 keyPoint = GetPosition(curve, new CurveSelection(activeKey.index, SelectionType.Key)); Vector2 leftTangent = GetPosition(curve, new CurveSelection(activeKey.index, SelectionType.InTangent)); Vector2 rightTangent = GetPosition(curve, new CurveSelection(activeKey.index, SelectionType.OutTangent)); GUI.color = activeKey.type == SelectionType.Key ? m_SelectedKeyColor : m_KeyColor; DrawPoint(keyPoint.x, keyPoint.y); GUI.color = activeKey.type == SelectionType.InTangent ? m_SelectedKeyColor : m_KeyColor; DrawPoint(leftTangent.x, leftTangent.y); GUI.color = activeKey.type == SelectionType.OutTangent ? m_SelectedKeyColor : m_KeyColor; DrawPoint(rightTangent.x, rightTangent.y); // Draw Handles Handles.color = m_TangentColor; DrawLine(leftTangent, keyPoint); DrawLine(keyPoint, rightTangent); } }
public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List <AnimationWindowCurve> allCurves) { foreach (AnimationWindowCurve current in allCurves) { int curveID = current.GetCurveID(); if (curveID == curveSelection.curveID && current.m_Keyframes.Count > curveSelection.key) { return(current.m_Keyframes[curveSelection.key]); } } return(null); }
public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List <AnimationWindowCurve> allCurves) { AnimationWindowKeyframe result; foreach (AnimationWindowCurve current in allCurves) { int hashCode = current.GetHashCode(); if (hashCode == curveSelection.curveID && current.m_Keyframes.Count > curveSelection.key) { result = current.m_Keyframes[curveSelection.key]; return(result); } } result = null; return(result); }
public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List <AnimationWindowCurve> allCurves) { foreach (AnimationWindowCurve curve in allCurves) { if ((curve.binding == curveSelection.curveWrapper.binding) && (curve.m_Keyframes.Count > curveSelection.key)) { return(curve.m_Keyframes[curveSelection.key]); } } return(null); }