Example #1
0
        /// <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;
        }