/// <summary>Initializes the struct with default values.</summary> public static TangentRef Default() { TangentRef value = new TangentRef(); value.keyframeRef = new KeyframeRef(); value.type = TangentType.In; return(value); }
private static extern bool Internal_findTangent(IntPtr thisPtr, ref Vector2I pixelCoords, out TangentRef tangent);
/// <summary>Attempts to find a a tangent handle under the provided coordinates.</summary> /// <param name="pixelCoords">Coordinates relative to this GUI element in pixels.</param> /// <param name="tangent"> /// Output object containing keyframe information and tangent type. Only valid if method returns true. /// </param> /// <returns>True if there is a tangent handle under the coordinates, false otherwise.</returns> public bool FindTangent(Vector2I pixelCoords, out TangentRef tangent) { return(Internal_findTangent(mCachedPtr, ref pixelCoords, out tangent)); }
/// <summary> /// Handles input. Should be called by the owning window whenever a pointer is pressed. /// </summary> /// <param name="ev">Object containing pointer press event information.</param> internal void OnPointerPressed(PointerEvent ev) { if (ev.IsUsed) return; Vector2I windowPos = window.ScreenToWindowPos(ev.ScreenPos); Rect2I elementBounds = GUIUtility.CalculateBounds(gui, window.GUI); Vector2I pointerPos = windowPos - new Vector2I(elementBounds.x, elementBounds.y); bool isOverEditor = pointerPos.x >= 0 && pointerPos.x < width && pointerPos.y >= 0 && pointerPos.y < height; if (!isOverEditor) return; else OnClicked?.Invoke(); Rect2I drawingBounds = drawingPanel.Bounds; Vector2I drawingPos = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y); Rect2I eventBounds = eventsPanel.Bounds; Vector2I eventPos = pointerPos - new Vector2I(eventBounds.x, eventBounds.y); if (ev.Button == PointerButton.Left) { Vector2 curveCoord; if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord, true)) { KeyframeRef keyframeRef; if (!guiCurveDrawing.FindKeyFrame(drawingPos, out keyframeRef)) { TangentRef tangentRef; if (guiCurveDrawing.FindTangent(drawingPos, out tangentRef)) { isMousePressedOverTangent = true; dragStart = drawingPos; draggedTangent = tangentRef; } else ClearSelection(); } else { if (!IsSelected(keyframeRef)) { if (!Input.IsButtonHeld(ButtonCode.LeftShift) && !Input.IsButtonHeld(ButtonCode.RightShift)) ClearSelection(); SelectKeyframe(keyframeRef); } isMousePressedOverKey = true; dragStart = drawingPos; } guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } else { int frameIdx = guiTimeline.GetFrame(pointerPos); if (frameIdx != -1) SetMarkedFrame(frameIdx); else { int eventIdx; if (guiEvents.FindEvent(eventPos, out eventIdx)) { if (!Input.IsButtonHeld(ButtonCode.LeftShift) && !Input.IsButtonHeld(ButtonCode.RightShift)) ClearSelection(); events[eventIdx].selected = true; UpdateEventsGUI(); } else { ClearSelection(); guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } } OnFrameSelected?.Invoke(frameIdx); } isPointerHeld = true; } else if (ev.Button == PointerButton.Right) { Vector2 curveCoord; if (guiCurveDrawing.PixelToCurveSpace(drawingPos, out curveCoord, true)) { contextClickPosition = drawingPos; KeyframeRef keyframeRef; if (!guiCurveDrawing.FindKeyFrame(drawingPos, out keyframeRef)) { ClearSelection(); blankContextMenu.Open(pointerPos, gui); guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } else { // If clicked outside of current selection, just select the one keyframe if (!IsSelected(keyframeRef)) { ClearSelection(); SelectKeyframe(keyframeRef); guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } keyframeContextMenu.Open(pointerPos, gui); } } else if (guiEvents.GetFrame(eventPos) != -1) // Clicked over events bar { contextClickPosition = eventPos; int eventIdx; if (!guiEvents.FindEvent(eventPos, out eventIdx)) { ClearSelection(); blankEventContextMenu.Open(pointerPos, gui); guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } else { // If clicked outside of current selection, just select the one event if (!events[eventIdx].selected) { ClearSelection(); events[eventIdx].selected = true; guiCurveDrawing.Rebuild(); UpdateEventsGUI(); } eventContextMenu.Open(pointerPos, gui); } } } }
/// <summary> /// Attempts to find a a tangent handle under the provided coordinates. /// </summary> /// <param name="pixelCoords">Coordinates relative to this GUI element in pixels.</param> /// <param name="tangent">Output object containing keyframe information and tangent type. Only valid if method /// returns true.</param> /// <returns>True if there is a tangent handle under the coordinates, false otherwise.</returns> public bool FindTangent(Vector2I pixelCoords, out TangentRef tangent) { tangent = new TangentRef(); float nearestDistance = float.MaxValue; for (int i = 0; i < curveInfos.Length; i++) { EdAnimationCurve curve = curveInfos[i].curve; KeyFrame[] keyframes = curve.KeyFrames; for (int j = 0; j < keyframes.Length; j++) { if (!IsSelected(i, j)) continue; TangentMode tangentMode = curve.TangentModes[j]; if (IsTangentDisplayed(tangentMode, TangentType.In)) { Vector2I tangentCoords = GetTangentPosition(keyframes[j], TangentType.In); float distanceToHandle = Vector2I.Distance(pixelCoords, tangentCoords); if (distanceToHandle < nearestDistance) { nearestDistance = distanceToHandle; tangent.keyframeRef.keyIdx = j; tangent.keyframeRef.curveIdx = i; tangent.type = TangentType.In; } ; } if (IsTangentDisplayed(tangentMode, TangentType.Out)) { Vector2I tangentCoords = GetTangentPosition(keyframes[j], TangentType.Out); float distanceToHandle = Vector2I.Distance(pixelCoords, tangentCoords); if (distanceToHandle < nearestDistance) { nearestDistance = distanceToHandle; tangent.keyframeRef.keyIdx = j; tangent.keyframeRef.curveIdx = i; tangent.type = TangentType.Out; } } } } // We're not near any keyframe if (nearestDistance > 5.0f) return false; return true; }