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