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