/// <summary> /// Attempts to find a curve under the provided coordinates. /// </summary> /// <param name="pixelCoords">Coordinates relative to this GUI element in pixels.</param> /// <returns>Index of the curve, or -1 if none found.</returns> public int FindCurve(Vector2I pixelCoords) { PixelToCurveSpace(pixelCoords, out var curveCoords, true); float time = curveCoords.x; float nearestDistance = float.MaxValue; int curveIdx = -1; for (int i = 0; i < curveInfos.Length; i++) { EdAnimationCurve curve = curveInfos[i].curve; float value = curve.Evaluate(time, false); Vector2I curPixelPos = CurveToPixelSpace(new Vector2(time, value)); float distanceToKey = Vector2I.Distance(pixelCoords, curPixelPos); if (distanceToKey < nearestDistance) { nearestDistance = distanceToKey; curveIdx = i; } } // We're not near any curve if (nearestDistance > 5.0f) { return(-1); } return(curveIdx); }
/// <summary> /// Draws the curve using the provided color. /// </summary> /// <param name="curve">Curve to draw within the currently set range. </param> /// <param name="color">Color to draw the curve with.</param> private void DrawCurve(EdAnimationCurve curve, Color color) { float range = GetRange(true); float lengthPerPixel = range / drawableWidth; KeyFrame[] keyframes = curve.KeyFrames; if (keyframes.Length <= 0) { return; } // Draw start line { float curveStart = keyframes[0].time; float curveValue = curve.Evaluate(curveStart, false); Vector2I end = CurveToPixelSpace(new Vector2(curveStart, curveValue)); Vector2I start = new Vector2I(-GUIGraphTime.PADDING, end.y); if (start.x < end.x) { canvas.DrawLine(start, end, COLOR_MID_GRAY); } } List <Vector2I> linePoints = new List <Vector2I>(); // Draw in between keyframes float startVisibleTime = rangeOffset; float endVisibleTime = startVisibleTime + range; for (int i = 0; i < keyframes.Length - 1; i++) { float start = keyframes[i].time; float end = keyframes[i + 1].time; if (end < startVisibleTime || start > endVisibleTime) { continue; } bool isStep = keyframes[i].outTangent == float.PositiveInfinity || keyframes[i + 1].inTangent == float.PositiveInfinity; // If step tangent, draw the required lines without sampling, as the sampling will miss the step if (isStep) { float startValue = curve.Evaluate(start, false); float endValue = curve.Evaluate(end, false); linePoints.Add(CurveToPixelSpace(new Vector2(start, startValue))); linePoints.Add(CurveToPixelSpace(new Vector2(end, startValue))); linePoints.Add(CurveToPixelSpace(new Vector2(end, endValue))); } else // Draw normally { float splitIncrement = LINE_SPLIT_WIDTH * lengthPerPixel; float startValue = keyframes[i].value; float endValue = keyframes[i + 1].value; Vector2I startPixel = new Vector2I(); startPixel.x = (int)(start / lengthPerPixel); startPixel.y = (int)(startValue / lengthPerPixel); Vector2I endPixel = new Vector2I(); endPixel.x = (int)(end / lengthPerPixel); endPixel.y = (int)(endValue / lengthPerPixel); int distance = Vector2I.Distance(startPixel, endPixel); int numSplits; if (distance > 0) { float fNumSplits = distance / splitIncrement; numSplits = MathEx.CeilToInt(fNumSplits); splitIncrement = distance / (float)numSplits; } else { numSplits = 1; splitIncrement = 0.0f; } for (int j = 0; j < numSplits; j++) { float t = Math.Min(start + j * splitIncrement, end); float value = curve.Evaluate(t, false); linePoints.Add(CurveToPixelSpace(new Vector2(t, value))); } } } canvas.DrawPolyLine(linePoints.ToArray(), color); // Draw end line { float curveEnd = keyframes[keyframes.Length - 1].time; float curveValue = curve.Evaluate(curveEnd, false); Vector2I start = CurveToPixelSpace(new Vector2(curveEnd, curveValue)); Vector2I end = new Vector2I(width, start.y); if (start.x < end.x) { canvas.DrawLine(start, end, COLOR_MID_GRAY); } } }
/// <summary> /// Draws the curve using the provided color. /// </summary> /// <param name="curve">Curve to draw within the currently set range. </param> /// <param name="color">Color to draw the curve with.</param> private void DrawCurve(EdAnimationCurve curve, Color color) { float range = GetRange(); float lengthPerPixel = range / drawableWidth; KeyFrame[] keyframes = curve.KeyFrames; if (keyframes.Length <= 0) { return; } // Draw start line { float curveStart = MathEx.Clamp(keyframes[0].time, 0.0f, range); float curveValue = curve.Evaluate(0.0f, false); Vector2I start = CurveToPixelSpace(new Vector2(0.0f, curveValue)); start.x -= GUIGraphTime.PADDING; Vector2I end = CurveToPixelSpace(new Vector2(curveStart, curveValue)); canvas.DrawLine(start, end, COLOR_MID_GRAY); } List <Vector2I> linePoints = new List <Vector2I>(); // Draw in between keyframes for (int i = 0; i < keyframes.Length - 1; i++) { float start = MathEx.Clamp(keyframes[i].time, 0.0f, range); float end = MathEx.Clamp(keyframes[i + 1].time, 0.0f, range); bool isStep = keyframes[i].outTangent == float.PositiveInfinity || keyframes[i + 1].inTangent == float.PositiveInfinity; // If step tangent, draw the required lines without sampling, as the sampling will miss the step if (isStep) { float startValue = curve.Evaluate(start, false); float endValue = curve.Evaluate(end, false); linePoints.Add(CurveToPixelSpace(new Vector2(start, startValue))); linePoints.Add(CurveToPixelSpace(new Vector2(end, startValue))); linePoints.Add(CurveToPixelSpace(new Vector2(end, endValue))); } else // Draw normally { float timeIncrement = LINE_SPLIT_WIDTH * lengthPerPixel; int startPixel = (int)(start / lengthPerPixel); int endPixel = (int)(end / lengthPerPixel); int numSplits; if (startPixel != endPixel) { float fNumSplits = (end - start) / timeIncrement; numSplits = MathEx.FloorToInt(fNumSplits); float remainder = fNumSplits - numSplits; float lengthRounded = (end - start) * (numSplits / fNumSplits); timeIncrement = lengthRounded / numSplits; numSplits += MathEx.CeilToInt(remainder) + 1; } else { numSplits = 1; timeIncrement = 0.0f; } for (int j = 0; j < numSplits; j++) { float t = Math.Min(start + j * timeIncrement, end); float value = curve.Evaluate(t, false); linePoints.Add(CurveToPixelSpace(new Vector2(t, value))); } } } canvas.DrawPolyLine(linePoints.ToArray(), color); // Draw end line { float curveEnd = MathEx.Clamp(keyframes[keyframes.Length - 1].time, 0.0f, range); float curveValue = curve.Evaluate(range, false); Vector2I start = CurveToPixelSpace(new Vector2(curveEnd, curveValue)); Vector2I end = new Vector2I(width, start.y); canvas.DrawLine(start, end, COLOR_MID_GRAY); } }