1
+ using System . Collections . Generic ;
2
+ using Unity . UIWidgets . foundation ;
3
+ using Unity . UIWidgets . scheduler ;
4
+ using UnityEditor ;
5
+
6
+ namespace Unity . UIWidgets . gestures {
7
+ #if UNITY_EDITOR
8
+ public partial class MouseTracker {
9
+ bool _enableDragFromEditorRelease = false ;
10
+
11
+ void _handleDragFromEditorEvent ( PointerEvent evt , int deviceId ) {
12
+ if ( ! this . inEditorWindow ) {
13
+ return ;
14
+ }
15
+
16
+ if ( evt is PointerDragFromEditorReleaseEvent ) {
17
+ this . _enableDragFromEditorRelease = false ;
18
+ this . _scheduleDragFromEditorReleaseCheck ( ) ;
19
+ this . _lastMouseEvent . Remove ( deviceId ) ;
20
+ }
21
+ else if ( evt is PointerDragFromEditorEnterEvent ||
22
+ evt is PointerDragFromEditorHoverEvent ||
23
+ evt is PointerDragFromEditorExitEvent ) {
24
+ if ( ! this . _lastMouseEvent . ContainsKey ( deviceId ) ||
25
+ this . _lastMouseEvent [ deviceId ] . position != evt . position ) {
26
+ this . _scheduleDragFromEditorMousePositionCheck ( ) ;
27
+ }
28
+
29
+ this . _lastMouseEvent [ deviceId ] = evt ;
30
+ }
31
+ }
32
+
33
+ void detachDragFromEditorAnnotation ( MouseTrackerAnnotation annotation , int deviceId ) {
34
+ if ( ! this . inEditorWindow ) {
35
+ return ;
36
+ }
37
+
38
+ if ( annotation . onDragFromEditorExit != null ) {
39
+ annotation . onDragFromEditorExit (
40
+ PointerDragFromEditorExitEvent . fromDragFromEditorEvent ( this . _lastMouseEvent [ deviceId ] ) ) ;
41
+ }
42
+ }
43
+
44
+ void _scheduleDragFromEditorReleaseCheck ( ) {
45
+ DragAndDrop . AcceptDrag ( ) ;
46
+
47
+ var lastMouseEvent = new List < PointerEvent > ( ) ;
48
+ foreach ( int deviceId in this . _lastMouseEvent . Keys ) {
49
+ var _deviceId = deviceId ;
50
+ lastMouseEvent . Add ( this . _lastMouseEvent [ _deviceId ] ) ;
51
+ SchedulerBinding . instance . addPostFrameCallback ( _ => {
52
+ foreach ( var lastEvent in lastMouseEvent ) {
53
+ MouseTrackerAnnotation hit = this . annotationFinder ( lastEvent . position ) ;
54
+
55
+ if ( hit == null ) {
56
+ foreach ( _TrackedAnnotation trackedAnnotation in this . _trackedAnnotations . Values ) {
57
+ if ( trackedAnnotation . activeDevices . Contains ( _deviceId ) ) {
58
+ trackedAnnotation . activeDevices . Remove ( _deviceId ) ;
59
+ }
60
+ }
61
+
62
+ return ;
63
+ }
64
+
65
+ _TrackedAnnotation hitAnnotation = this . _findAnnotation ( hit ) ;
66
+
67
+ // release
68
+ if ( hitAnnotation . activeDevices . Contains ( _deviceId ) ) {
69
+ if ( hitAnnotation . annotation ? . onDragFromEditorRelease != null ) {
70
+ hitAnnotation . annotation . onDragFromEditorRelease (
71
+ PointerDragFromEditorReleaseEvent
72
+ . fromDragFromEditorEvent (
73
+ lastEvent , DragAndDrop . objectReferences ) ) ;
74
+ }
75
+
76
+ hitAnnotation . activeDevices . Remove ( _deviceId ) ;
77
+ }
78
+ }
79
+ } ) ;
80
+ }
81
+
82
+ SchedulerBinding . instance . scheduleFrame ( ) ;
83
+ }
84
+
85
+ /// <summary>
86
+ /// Due to the [DragAndDrop] property, DragAndDrop.visualMode must be set to Copy
87
+ /// after which editor window can trigger DragPerform event.
88
+ /// And because visualMode will be set to None when every frame finished in IMGUI,
89
+ /// here we start a scheduler to update VisualMode in every post frame.
90
+ /// When [_enableDragFromEditorRelease] set to false, it will stop, vice versa.
91
+ /// </summary>
92
+ void _enableDragFromEditorReleaseVisualModeLoop ( ) {
93
+ if ( this . _enableDragFromEditorRelease ) {
94
+ DragAndDrop . visualMode = DragAndDropVisualMode . Copy ;
95
+ SchedulerBinding . instance . addPostFrameCallback ( _ => {
96
+ this . _enableDragFromEditorReleaseVisualModeLoop ( ) ;
97
+ } ) ;
98
+ SchedulerBinding . instance . scheduleFrame ( ) ;
99
+ }
100
+ }
101
+
102
+ void _scheduleDragFromEditorMousePositionCheck ( ) {
103
+ if ( ! this . inEditorWindow ) {
104
+ return ;
105
+ }
106
+
107
+ SchedulerBinding . instance . addPostFrameCallback ( _ => { this . collectDragFromEditorMousePositions ( ) ; } ) ;
108
+ SchedulerBinding . instance . scheduleFrame ( ) ;
109
+ }
110
+
111
+ public void collectDragFromEditorMousePositions ( ) {
112
+ void exitAnnotation ( _TrackedAnnotation trackedAnnotation , int deviceId ) {
113
+ if ( trackedAnnotation . activeDevices . Contains ( deviceId ) ) {
114
+ this . _enableDragFromEditorRelease = false ;
115
+ if ( trackedAnnotation . annotation ? . onDragFromEditorExit != null ) {
116
+ trackedAnnotation . annotation . onDragFromEditorExit (
117
+ PointerDragFromEditorExitEvent . fromDragFromEditorEvent (
118
+ this . _lastMouseEvent [ deviceId ] ) ) ;
119
+ }
120
+
121
+ trackedAnnotation . activeDevices . Remove ( deviceId ) ;
122
+ }
123
+ }
124
+
125
+ void exitAllDevices ( _TrackedAnnotation trackedAnnotation ) {
126
+ if ( trackedAnnotation . activeDevices . isNotEmpty ( ) ) {
127
+ HashSet < int > deviceIds = new HashSet < int > ( trackedAnnotation . activeDevices ) ;
128
+ foreach ( int deviceId in deviceIds ) {
129
+ exitAnnotation ( trackedAnnotation , deviceId ) ;
130
+ }
131
+ }
132
+ }
133
+
134
+ if ( ! this . mouseIsConnected ) {
135
+ foreach ( var annotation in this . _trackedAnnotations . Values ) {
136
+ exitAllDevices ( annotation ) ;
137
+ }
138
+
139
+ return ;
140
+ }
141
+
142
+ foreach ( int deviceId in this . _lastMouseEvent . Keys ) {
143
+ PointerEvent lastEvent = this . _lastMouseEvent [ deviceId ] ;
144
+ MouseTrackerAnnotation hit = this . annotationFinder ( lastEvent . position ) ;
145
+
146
+ if ( hit == null ) {
147
+ foreach ( _TrackedAnnotation trackedAnnotation in this . _trackedAnnotations . Values ) {
148
+ exitAnnotation ( trackedAnnotation , deviceId ) ;
149
+ }
150
+
151
+ return ;
152
+ }
153
+
154
+ _TrackedAnnotation hitAnnotation = this . _findAnnotation ( hit ) ;
155
+
156
+ // While acrossing two areas, set the flag to true to prevent setting the Pointer Copy VisualMode to None
157
+ bool enterFlag = false ;
158
+
159
+ // enter
160
+ if ( ! hitAnnotation . activeDevices . Contains ( deviceId ) ) {
161
+ hitAnnotation . activeDevices . Add ( deviceId ) ;
162
+ enterFlag = true ;
163
+ // Both onRelease or onEnter event will enable Copy VisualMode
164
+ if ( hitAnnotation . annotation ? . onDragFromEditorRelease != null ||
165
+ hitAnnotation . annotation ? . onDragFromEditorEnter != null ) {
166
+ if ( ! this . _enableDragFromEditorRelease ) {
167
+ this . _enableDragFromEditorRelease = true ;
168
+ this . _enableDragFromEditorReleaseVisualModeLoop ( ) ;
169
+ }
170
+
171
+ if ( hitAnnotation . annotation ? . onDragFromEditorEnter != null ) {
172
+ hitAnnotation . annotation . onDragFromEditorEnter (
173
+ PointerDragFromEditorEnterEvent
174
+ . fromDragFromEditorEvent ( lastEvent ) ) ;
175
+ }
176
+ }
177
+ }
178
+
179
+ // hover
180
+ if ( hitAnnotation . annotation ? . onDragFromEditorHover != null ) {
181
+ hitAnnotation . annotation . onDragFromEditorHover (
182
+ PointerDragFromEditorHoverEvent . fromDragFromEditorEvent ( lastEvent ) ) ;
183
+ }
184
+
185
+ // leave
186
+ foreach ( _TrackedAnnotation trackedAnnotation in this . _trackedAnnotations . Values ) {
187
+ if ( hitAnnotation == trackedAnnotation ) {
188
+ continue ;
189
+ }
190
+
191
+ if ( trackedAnnotation . activeDevices . Contains ( deviceId ) ) {
192
+ if ( ! enterFlag ) {
193
+ this . _enableDragFromEditorRelease = false ;
194
+ }
195
+
196
+ if ( trackedAnnotation . annotation ? . onDragFromEditorExit != null ) {
197
+ trackedAnnotation . annotation . onDragFromEditorExit (
198
+ PointerDragFromEditorExitEvent
199
+ . fromDragFromEditorEvent ( lastEvent ) ) ;
200
+ }
201
+
202
+ trackedAnnotation . activeDevices . Remove ( deviceId ) ;
203
+ }
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ #endif
210
+ }
0 commit comments