Example #1
0
        // NB: if draw is true, it'll draw stuff only, otherwise it'll handle events only.
        void LayoutEvent(Rect rect, AnimEvent animEvent, AnimEventLayoutData layoutData, bool draw)
        {
            // check if it's visible on timeline
            if (layoutData.start > rect.xMax || layoutData.end < rect.xMin)
            {
                return;
            }

            float heightOffset = (layoutData.heightOffset * TIMELINE_EVENT_HEIGHT);
            Rect  eventRect    = new Rect(layoutData.start, heightOffset, 0, TIMELINE_EVENT_HEIGHT);
            Rect  labelRect    = new Rect(layoutData.start + 2, heightOffset, layoutData.textWidth, TIMELINE_EVENT_HEIGHT - 2);

            if (draw)
            {
                LayoutEventVisuals(animEvent, layoutData.selected, eventRect, layoutData.text, labelRect);
            }
            else
            {
                LayoutEventGuiEvents(rect, animEvent, layoutData.selected, eventRect, layoutData.text, labelRect);
            }
        }
Example #2
0
        void LayoutEvents(Rect rect)
        {
            Event e = Event.current;

            if (e.type == EventType.mouseDown && e.button == 0 && rect.Contains(e.mousePosition) && m_playing == false)
            {
                // Move timeline
                m_animTime = SnapTimeToFrameRate(GuiPosToAnimTime(rect, e.mousePosition.x));
            }
            if (e.type == EventType.MouseDown && e.button == 0 && e.clickCount == 2 && rect.Contains(e.mousePosition))
            {
                // Double click for new event at that time

                // New event
                InsertEvent(GuiPosToAnimTime(rect, e.mousePosition.x), true);
                e.Use();
            }

            GUI.BeginGroup(rect);

            if (m_events.Count == 0)
            {
                GUI.Label(new Rect(0, 0, rect.width, rect.height), "Double click to insert event", EditorStyles.centeredGreyMiniLabel);
            }

            // Layout events. This is done in 4 stages so that selected items are drawn on top of (after) non-selected ones, but have their gui events handled first.

            // Calc some metadata about each event (start/end position on timeline, etc). This is stored in a temporary array, parallel to events
            AnimEventLayoutData[] eventTimelineData = new AnimEventLayoutData[m_events.Count];

            // First loop over and calculate start/end positions of events
            for (int i = 0; i < m_events.Count; ++i)
            {
                AnimEvent           animEvent = m_events[i];
                AnimEventLayoutData eventData = new AnimEventLayoutData();
                eventTimelineData[i] = eventData;

                eventData.start     = AnimTimeToGuiPos(rect, SnapTimeToFrameRate(animEvent.m_time));
                eventData.text      = animEvent.m_functionName;   //.Replace(ANIM_EVENT_PREFIX,null);
                eventData.textWidth = Styles.TIMELINE_EVENT_TEXT.CalcSize(new GUIContent(eventData.text)).x;
                eventData.end       = eventData.start + eventData.textWidth + 4;
                eventData.selected  = m_selectedEvents.Contains(m_events[i]);
            }

            int maxEventOffset = 0;

            // Now loop over events and calculate the vertical offset of events so that they don't overlap
            for (int i = 0; i < m_events.Count; ++i)
            {
                // Store the offset of everything we're overlapping with in a mask, so we can get the first available offset.
                int usedOffsetsMask      = 0;
                AnimEventLayoutData data = eventTimelineData[i];
                for (int j = i - 1; j >= 0; --j)
                {
                    // check for overlap of items before this one. A
                    AnimEventLayoutData other = eventTimelineData[j];
                    if ((data.start > other.end || data.end < other.start) == false)
                    {
                        // overlaps!
                        usedOffsetsMask |= 1 << (other.heightOffset);
                    }
                }

                // Loop through mask to find first available offset.
                while (data.heightOffset < 32 && (usedOffsetsMask & (1 << data.heightOffset)) != 0)
                {
                    data.heightOffset++;
                }

                if (data.heightOffset > maxEventOffset)
                {
                    maxEventOffset = data.heightOffset;
                }
            }

            // Draw vertical lines where there's an event
            for (int i = 0; i < m_events.Count; ++i)
            {
                DrawRect(new Rect(eventTimelineData[i].start, 0, 1, rect.height), Color.grey);
            }

            // First draw events
            for (int i = 0; i < m_events.Count; ++i)
            {
                LayoutEvent(rect, m_events[i], eventTimelineData[i], true);
            }

            // Then handle gui events in reverse order
            for (int i = m_events.Count - 1; i >= 0; --i)
            {
                LayoutEvent(rect, m_events[i], eventTimelineData[i], false);
            }

            GUI.EndGroup();


            // Draw selection rect
            if (m_dragState == eDragState.SelectEvent && Mathf.Abs(m_selectionMouseStart - e.mousePosition.x) > 1.0f)
            {
                // Draw selection rect
                Rect selectionRect = new Rect(rect)
                {
                    xMin = Mathf.Min(m_selectionMouseStart, e.mousePosition.x), xMax = Mathf.Max(m_selectionMouseStart, e.mousePosition.x)
                };
                DrawRect(selectionRect, COLOR_UNITY_BLUE.WithAlpha(0.1f), COLOR_UNITY_BLUE.WithAlpha(0.6f));
            }

            // Check for unhandled mouse left click. It should deselect any selected events
            if (e.type == EventType.MouseDown && e.button == 0)
            {
                if (rect.Contains(e.mousePosition))
                {
                    ClearSelection();
                    e.Use();
                }
            }

            // Check for unhanlded drag, it should start a select
            if (m_dragState == eDragState.None && e.type == EventType.MouseDrag && e.button == 0)
            {
                if (rect.Contains(e.mousePosition))
                {
                    m_dragState = eDragState.SelectEvent;
                    e.Use();
                }
            }

            if (m_dragState == eDragState.MoveEvent)
            {
                // While moving frame, show the move cursor
                EditorGUIUtility.AddCursorRect(rect, MouseCursor.MoveArrow);
                if (e.type == EventType.MouseDrag)
                {
                    MoveSelectedEvents(e.delta.x);

                    // move the frame
                    e.Use();
                }
                if (e.rawType == EventType.MouseUp && e.button == 0)
                {
                    // Apply the move change
                    ApplyChanges();
                    m_dragState = eDragState.None;
                    e.Use();
                }
            }

            float newTimelineHeight = Mathf.Max((maxEventOffset + 1), 1.5f) * TIMELINE_EVENT_HEIGHT;

            if (newTimelineHeight != m_timelineEventBarHeight)
            {
                m_timelineEventBarHeight = newTimelineHeight;
                Repaint();
            }
        }