RectangleTool.cs
4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
using System;
using UnityEngine;
namespace UnityEditor.Timeline
{
abstract class RectangleTool
{
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));
}
}
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, Vector2 mousePosition, WindowState state);
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;
if (!m_ActiveRect.Contains(mousePosition))
return;
if (!CanStartRectangle(evt, mousePosition, state))
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);
}
}
protected virtual 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));
}
}
}