176 lines
5.1 KiB
C#
176 lines
5.1 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.Timeline
|
|
{
|
|
abstract class RectangleTool
|
|
{
|
|
readonly struct TimelinePoint
|
|
{
|
|
readonly double m_Time;
|
|
readonly float m_YPos;
|
|
readonly float m_YScrollPos;
|
|
|
|
readonly WindowState m_State;
|
|
readonly TimelineTreeViewGUI m_TreeViewGUI;
|
|
|
|
public TimelinePoint(WindowState state, Vector2 mousePosition)
|
|
{
|
|
m_State = state;
|
|
m_TreeViewGUI = state.GetWindow().treeView;
|
|
|
|
m_Time = m_State.PixelToTime(mousePosition.x);
|
|
m_YPos = mousePosition.y;
|
|
m_YScrollPos = m_TreeViewGUI.scrollPosition.y;
|
|
}
|
|
|
|
public Vector2 ToPixel()
|
|
{
|
|
return new Vector2(m_State.TimeToPixel(m_Time), m_YPos - (m_TreeViewGUI.scrollPosition.y - m_YScrollPos));
|
|
}
|
|
}
|
|
|
|
const float k_HeaderSplitterOverlap = WindowConstants.headerSplitterWidth / 2;
|
|
|
|
TimeAreaAutoPanner m_TimeAreaAutoPanner;
|
|
|
|
TimelinePoint m_StartPoint;
|
|
Vector2 m_EndPixel = Vector2.zero;
|
|
|
|
Rect m_ActiveRect;
|
|
|
|
protected abstract bool enableAutoPan { get; }
|
|
protected abstract bool CanStartRectangle(Event evt);
|
|
protected abstract bool OnFinish(Event evt, WindowState state, Rect rect);
|
|
|
|
int m_Id;
|
|
|
|
public void OnGUI(WindowState state, EventType rawType, Vector2 mousePosition)
|
|
{
|
|
if (m_Id == 0)
|
|
m_Id = GUIUtility.GetPermanentControlID();
|
|
|
|
if (state == null || state.GetWindow().treeView == null)
|
|
return;
|
|
|
|
var evt = Event.current;
|
|
|
|
if (rawType == EventType.MouseDown || evt.type == EventType.MouseDown)
|
|
{
|
|
if (state.IsCurrentEditingASequencerTextField())
|
|
return;
|
|
|
|
m_ActiveRect = TimelineWindow.instance.sequenceContentRect;
|
|
|
|
//remove the track header splitter overlap
|
|
m_ActiveRect.x += k_HeaderSplitterOverlap;
|
|
m_ActiveRect.width -= k_HeaderSplitterOverlap;
|
|
|
|
if (!m_ActiveRect.Contains(mousePosition))
|
|
return;
|
|
|
|
if (!CanStartRectangle(evt))
|
|
return;
|
|
|
|
if (enableAutoPan)
|
|
m_TimeAreaAutoPanner = new TimeAreaAutoPanner(state);
|
|
|
|
m_StartPoint = new TimelinePoint(state, mousePosition);
|
|
m_EndPixel = mousePosition;
|
|
|
|
GUIUtility.hotControl = m_Id; //HACK: Because the treeView eats all the events, steal the hotControl if necessary...
|
|
evt.Use();
|
|
|
|
return;
|
|
}
|
|
|
|
switch (evt.GetTypeForControl(m_Id))
|
|
{
|
|
case EventType.KeyDown:
|
|
{
|
|
if (GUIUtility.hotControl == m_Id)
|
|
{
|
|
if (evt.keyCode == KeyCode.Escape)
|
|
{
|
|
m_TimeAreaAutoPanner = null;
|
|
|
|
GUIUtility.hotControl = 0;
|
|
evt.Use();
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
case EventType.MouseDrag:
|
|
{
|
|
if (GUIUtility.hotControl != m_Id)
|
|
return;
|
|
|
|
m_EndPixel = mousePosition;
|
|
evt.Use();
|
|
|
|
return;
|
|
}
|
|
|
|
case EventType.MouseUp:
|
|
{
|
|
if (GUIUtility.hotControl != m_Id)
|
|
return;
|
|
|
|
m_TimeAreaAutoPanner = null;
|
|
|
|
var rect = CurrentRectangle();
|
|
|
|
if (IsValidRect(rect))
|
|
OnFinish(evt, state, rect);
|
|
|
|
GUIUtility.hotControl = 0;
|
|
evt.Use();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (GUIUtility.hotControl == m_Id)
|
|
{
|
|
if (evt.type == EventType.Repaint)
|
|
{
|
|
var r = CurrentRectangle();
|
|
|
|
if (IsValidRect(r))
|
|
{
|
|
using (new GUIViewportScope(m_ActiveRect))
|
|
{
|
|
DrawRectangle(r);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_TimeAreaAutoPanner != null)
|
|
m_TimeAreaAutoPanner.OnGUI(evt);
|
|
}
|
|
}
|
|
|
|
static void DrawRectangle(Rect rect)
|
|
{
|
|
EditorStyles.selectionRect.Draw(rect, GUIContent.none, false, false, false, false);
|
|
}
|
|
|
|
static bool IsValidRect(Rect rect)
|
|
{
|
|
return rect.width >= 1.0f && rect.height >= 1.0f;
|
|
}
|
|
|
|
Rect CurrentRectangle()
|
|
{
|
|
var startPixel = m_StartPoint.ToPixel();
|
|
return Rect.MinMaxRect(
|
|
Math.Min(startPixel.x, m_EndPixel.x),
|
|
Math.Min(startPixel.y, m_EndPixel.y),
|
|
Math.Max(startPixel.x, m_EndPixel.x),
|
|
Math.Max(startPixel.y, m_EndPixel.y));
|
|
}
|
|
}
|
|
}
|