Пример #1
0
        public void EventLineGUI(Rect rect, AnimationWindowState state)
        {
            //  We only display and manipulate animation events from the main
            //  game object in selection.  If we ever want to update to handle
            //  a multiple selection, a single timeline might not be sufficient...
            AnimationClip clip     = state.activeAnimationClip;
            GameObject    animated = state.activeRootGameObject;

            GUI.BeginGroup(rect);
            Color backupCol = GUI.color;

            Rect eventLineRect = new Rect(0, 0, rect.width, rect.height);

            float mousePosTime = Mathf.Max(Mathf.RoundToInt(state.PixelToTime(Event.current.mousePosition.x, rect) * state.frameRate) / state.frameRate, 0.0f);

            // Draw events
            if (clip != null)
            {
                AnimationEvent[] events      = AnimationUtility.GetAnimationEvents(clip);
                Texture          eventMarker = EditorGUIUtility.IconContent("Animation.EventMarker").image;

                // Calculate rects
                Rect[] hitRects   = new Rect[events.Length];
                Rect[] drawRects  = new Rect[events.Length];
                int    shared     = 1;
                int    sharedLeft = 0;
                for (int i = 0; i < events.Length; i++)
                {
                    AnimationEvent evt = events[i];

                    if (sharedLeft == 0)
                    {
                        shared = 1;
                        while (i + shared < events.Length && events[i + shared].time == evt.time)
                        {
                            shared++;
                        }
                        sharedLeft = shared;
                    }
                    sharedLeft--;

                    // Important to take floor of positions of GUI stuff to get pixel correct alignment of
                    // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time.
                    float keypos       = Mathf.Floor(state.FrameToPixel(evt.time * clip.frameRate, rect));
                    int   sharedOffset = 0;
                    if (shared > 1)
                    {
                        float spread = Mathf.Min((shared - 1) * (eventMarker.width - 1), (int)(state.FrameDeltaToPixel(rect) - eventMarker.width * 2));
                        sharedOffset = Mathf.FloorToInt(Mathf.Max(0, spread - (eventMarker.width - 1) * (sharedLeft)));
                    }

                    Rect r = new Rect(
                        keypos + sharedOffset - eventMarker.width / 2,
                        (rect.height - 10) * (float)(sharedLeft - shared + 1) / Mathf.Max(1, shared - 1),
                        eventMarker.width,
                        eventMarker.height);

                    hitRects[i]  = r;
                    drawRects[i] = r;
                }

                // Store tooptip info
                if (m_DirtyTooltip)
                {
                    if (m_HoverEvent >= 0 && m_HoverEvent < hitRects.Length)
                    {
                        m_InstantTooltipText  = AnimationWindowEventInspector.FormatEvent(animated, events[m_HoverEvent]);
                        m_InstantTooltipPoint = new Vector2(hitRects[m_HoverEvent].xMin + (int)(hitRects[m_HoverEvent].width / 2) + rect.x - 30, rect.yMax);
                    }
                    m_DirtyTooltip = false;
                }

                bool[] selectedEvents = new bool[events.Length];

                Object[] selectedObjects = Selection.objects;
                foreach (Object selectedObject in selectedObjects)
                {
                    AnimationWindowEvent awe = selectedObject as AnimationWindowEvent;
                    if (awe != null)
                    {
                        if (awe.eventIndex >= 0 && awe.eventIndex < selectedEvents.Length)
                        {
                            selectedEvents[awe.eventIndex] = true;
                        }
                    }
                }

                Vector2 offset = Vector2.zero;
                int     clickedIndex;
                float   startSelection, endSelection;

                // TODO: GUIStyle.none has hopping margins that need to be fixed
                HighLevelEvent hEvent = EditorGUIExt.MultiSelection(
                    rect,
                    drawRects,
                    new GUIContent(eventMarker),
                    hitRects,
                    ref selectedEvents,
                    null,
                    out clickedIndex,
                    out offset,
                    out startSelection,
                    out endSelection,
                    GUIStyle.none
                    );

                if (hEvent != HighLevelEvent.None)
                {
                    switch (hEvent)
                    {
                    case HighLevelEvent.BeginDrag:
                        m_EventsAtMouseDown = events;
                        m_EventTimes        = new float[events.Length];
                        for (int i = 0; i < events.Length; i++)
                        {
                            m_EventTimes[i] = events[i].time;
                        }
                        break;

                    case HighLevelEvent.SelectionChanged:
                        state.ClearKeySelections();
                        EditEvents(animated, clip, selectedEvents);
                        break;

                    case HighLevelEvent.Delete:
                        DeleteEvents(clip, selectedEvents);
                        break;

                    case HighLevelEvent.DoubleClick:

                        if (clickedIndex != -1)
                        {
                            EditEvents(animated, clip, selectedEvents);
                        }
                        else
                        {
                            EventLineContextMenuAdd(new EventLineContextMenuObject(animated, clip, mousePosTime, -1, selectedEvents));
                        }
                        break;

                    case HighLevelEvent.Drag:
                        for (int i = events.Length - 1; i >= 0; i--)
                        {
                            if (selectedEvents[i])
                            {
                                AnimationEvent evt = m_EventsAtMouseDown[i];
                                evt.time = m_EventTimes[i] + offset.x * state.PixelDeltaToTime(rect);
                                evt.time = Mathf.Max(0.0F, evt.time);
                                evt.time = Mathf.RoundToInt(evt.time * clip.frameRate) / clip.frameRate;
                            }
                        }
                        int[] order = new int[selectedEvents.Length];
                        for (int i = 0; i < order.Length; i++)
                        {
                            order[i] = i;
                        }
                        System.Array.Sort(m_EventsAtMouseDown, order, new EventComparer());
                        bool[]  selectedOld = (bool[])selectedEvents.Clone();
                        float[] timesOld    = (float[])m_EventTimes.Clone();
                        for (int i = 0; i < order.Length; i++)
                        {
                            selectedEvents[i] = selectedOld[order[i]];
                            m_EventTimes[i]   = timesOld[order[i]];
                        }

                        // Update selection to reflect new order.
                        EditEvents(animated, clip, selectedEvents);

                        Undo.RegisterCompleteObjectUndo(clip, "Move Event");
                        AnimationUtility.SetAnimationEvents(clip, m_EventsAtMouseDown);
                        m_DirtyTooltip = true;
                        break;

                    case HighLevelEvent.ContextClick:
                        GenericMenu menu                = new GenericMenu();
                        var         contextData         = new EventLineContextMenuObject(animated, clip, events[clickedIndex].time, clickedIndex, selectedEvents);
                        int         selectedEventsCount = selectedEvents.Count(selected => selected);

                        menu.AddItem(
                            EditorGUIUtility.TrTextContent("Add Animation Event"),
                            false,
                            EventLineContextMenuAdd,
                            contextData);
                        menu.AddItem(
                            new GUIContent(selectedEventsCount > 1 ? "Delete Animation Events" : "Delete Animation Event"),
                            false,
                            EventLineContextMenuDelete,
                            contextData);
                        menu.ShowAsContext();

                        // Mouse may move while context menu is open - make sure instant tooltip is handled
                        m_InstantTooltipText = null;
                        m_DirtyTooltip       = true;
                        state.Repaint();
                        break;
                    }
                }

                CheckRectsOnMouseMove(rect, events, hitRects);

                // Create context menu on context click
                if (Event.current.type == EventType.ContextClick && eventLineRect.Contains(Event.current.mousePosition))
                {
                    Event.current.Use();
                    // Create menu
                    GenericMenu menu                = new GenericMenu();
                    var         contextData         = new EventLineContextMenuObject(animated, clip, mousePosTime, -1, selectedEvents);
                    int         selectedEventsCount = selectedEvents.Count(selected => selected);

                    menu.AddItem(
                        EditorGUIUtility.TrTextContent("Add Animation Event"),
                        false,
                        EventLineContextMenuAdd,
                        contextData);

                    if (selectedEventsCount > 0)
                    {
                        menu.AddItem(
                            new GUIContent(selectedEventsCount > 1 ? "Delete Animation Events" : "Delete Animation Event"),
                            false,
                            EventLineContextMenuDelete,
                            contextData);
                    }

                    menu.ShowAsContext();
                }
            }

            GUI.color = backupCol;
            GUI.EndGroup();
        }
        void SliderGUI()
        {
            if (!m_HSlider && !m_VSlider)
            {
                return;
            }

            using (new EditorGUI.DisabledScope(!enableMouseInput))
            {
                Bounds editorBounds = drawingBounds;
                Rect   area = shownAreaInsideMargins;
                float  min, max;
                float  inset      = styles.sliderWidth - styles.visualSliderWidth;
                float  otherInset = (vSlider && hSlider) ? inset : 0;

                Vector2 scaleDelta = m_Scale;
                // Horizontal range slider
                if (m_HSlider)
                {
                    Rect  hRangeSliderRect = new Rect(drawRect.x + 1, drawRect.yMax - inset, drawRect.width - otherInset, styles.sliderWidth);
                    float shownXRange      = area.width;
                    float shownXMin        = area.xMin;
                    if (allowSliderZoomHorizontal)
                    {
                        EditorGUIExt.MinMaxScroller(hRangeSliderRect, horizontalScrollbarID,
                                                    ref shownXMin, ref shownXRange,
                                                    editorBounds.min.x, editorBounds.max.x,
                                                    Mathf.NegativeInfinity, Mathf.Infinity,
                                                    styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb,
                                                    styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true);
                    }
                    else
                    {
                        shownXMin = GUI.Scroller(hRangeSliderRect,
                                                 shownXMin, shownXRange, editorBounds.min.x, editorBounds.max.x,
                                                 styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb,
                                                 styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true);
                    }
                    min = shownXMin;
                    max = shownXMin + shownXRange;
                    float rectWidthWithinMargins = GetWidthInsideMargins(rect.width, true);
                    if (min > area.xMin)
                    {
                        min = Mathf.Min(min, max - rectWidthWithinMargins / m_HScaleMax);
                    }
                    if (max < area.xMax)
                    {
                        max = Mathf.Max(max, min + rectWidthWithinMargins / m_HScaleMax);
                    }
                    SetShownHRangeInsideMargins(min, max);
                }

                // Vertical range slider
                // Reverse y values since y increses upwards for the draw area but downwards for the slider
                if (m_VSlider)
                {
                    if (m_UpDirection == YDirection.Positive)
                    {
                        Rect  vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset);
                        float shownYRange      = area.height;
                        float shownYMin        = -area.yMax;
                        if (allowSliderZoomVertical)
                        {
                            EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID,
                                                        ref shownYMin, ref shownYRange,
                                                        -editorBounds.max.y, -editorBounds.min.y,
                                                        Mathf.NegativeInfinity, Mathf.Infinity,
                                                        styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,
                                                        styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);
                        }
                        else
                        {
                            shownYMin = GUI.Scroller(vRangeSliderRect,
                                                     shownYMin, shownYRange, -editorBounds.max.y, -editorBounds.min.y,
                                                     styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,
                                                     styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);
                        }
                        min = -(shownYMin + shownYRange);
                        max = -shownYMin;
                        float rectHeightWithinMargins = GetHeightInsideMargins(rect.height, true);
                        if (min > area.yMin)
                        {
                            min = Mathf.Min(min, max - rectHeightWithinMargins / m_VScaleMax);
                        }
                        if (max < area.yMax)
                        {
                            max = Mathf.Max(max, min + rectHeightWithinMargins / m_VScaleMax);
                        }
                        SetShownVRangeInsideMargins(min, max);
                    }
                    else
                    {
                        Rect  vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset);
                        float shownYRange      = area.height;
                        float shownYMin        = area.yMin;
                        if (allowSliderZoomVertical)
                        {
                            EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID,
                                                        ref shownYMin, ref shownYRange,
                                                        editorBounds.min.y, editorBounds.max.y,
                                                        Mathf.NegativeInfinity, Mathf.Infinity,
                                                        styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,
                                                        styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);
                        }
                        else
                        {
                            shownYMin = GUI.Scroller(vRangeSliderRect,
                                                     shownYMin, shownYRange, editorBounds.min.y, editorBounds.max.y,
                                                     styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb,
                                                     styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false);
                        }
                        min = shownYMin;
                        max = shownYMin + shownYRange;
                        float rectHeightWithinMargins = GetHeightInsideMargins(rect.height, true);
                        if (min > area.yMin)
                        {
                            min = Mathf.Min(min, max - rectHeightWithinMargins / m_VScaleMax);
                        }
                        if (max < area.yMax)
                        {
                            max = Mathf.Max(max, min + rectHeightWithinMargins / m_VScaleMax);
                        }
                        SetShownVRangeInsideMargins(min, max);
                    }
                }

                if (uniformScale)
                {
                    float aspect = drawRect.width / drawRect.height;
                    scaleDelta -= m_Scale;
                    var delta = new Vector2(-scaleDelta.y * aspect, -scaleDelta.x / aspect);

                    m_Scale         -= delta;
                    m_Translation.x -= scaleDelta.y / 2;
                    m_Translation.y -= scaleDelta.x / 2;
                    EnforceScaleAndRange();
                }
            }
        }