@@ -14,6 +14,33 @@ namespace TouchScript.InputSources.InputHandlers
1414 /// </summary>
1515 public class MouseHandler : IInputSource , IDisposable
1616 {
17+ #region Consts
18+
19+ private enum State
20+ {
21+ /// <summary>
22+ /// Only mouse pointer is active
23+ /// </summary>
24+ Mouse ,
25+
26+ /// <summary>
27+ /// ALT is pressed but mouse isn't
28+ /// </summary>
29+ WaitingForFake ,
30+
31+ /// <summary>
32+ /// Mouse and fake pointers are moving together after ALT+PRESS
33+ /// </summary>
34+ MouseAndFake ,
35+
36+ /// <summary>
37+ /// After ALT+RELEASE fake pointer is stationary while mouse can move freely
38+ /// </summary>
39+ StationaryFake
40+ }
41+
42+ #endregion
43+
1744 #region Public properties
1845
1946 /// <inheritdoc />
@@ -48,10 +75,10 @@ public bool EmulateSecondMousePointer
4875 private PointerDelegate removePointer ;
4976 private PointerDelegate cancelPointer ;
5077
78+ private State state ;
5179 private ObjectPool < MousePointer > mousePool ;
5280 private MousePointer mousePointer , fakeMousePointer ;
5381 private Vector3 mousePointPos = Vector3 . zero ;
54- private DelayedFakePointer addFakePointer ;
5582
5683 #endregion
5784
@@ -75,85 +102,97 @@ public MouseHandler(PointerDelegate addPointer, PointerDelegate updatePointer, P
75102
76103 mousePool = new ObjectPool < MousePointer > ( 4 , ( ) => new MousePointer ( this ) , null , ( t ) => t . INTERNAL_Reset ( ) ) ;
77104
78- addFakePointer . ShouldAdd = false ;
79105 mousePointPos = Input . mousePosition ;
80- mousePointer = internalAddPointer ( mousePointPos ) ;
106+ mousePointer = internalAddPointer ( remapCoordinates ( mousePointPos ) ) ;
107+
108+ stateMouse ( ) ;
81109 }
82110
83111 #region Public methods
84112
85113 /// <inheritdoc />
86114 public void UpdateInput ( )
87115 {
88- if ( addFakePointer . ShouldAdd )
89- {
90- addFakePointer . ShouldAdd = false ;
91- fakeMousePointer = internalAddPointer ( addFakePointer . Position , addFakePointer . Buttons , addFakePointer . Flags ) ;
92- pressPointer ( fakeMousePointer ) ;
93- }
94-
95- if ( fakeMousePointer != null
96- && ! ( Input . GetKey ( KeyCode . LeftAlt ) || Input . GetKey ( KeyCode . RightAlt ) ) )
97- {
98- releasePointer ( fakeMousePointer ) ;
99- removePointer ( fakeMousePointer ) ;
100- fakeMousePointer = null ;
101- }
102-
103- var pos = Input . mousePosition ;
104- if ( mousePointPos != pos )
105- {
106- mousePointPos = pos ;
107- mousePointer . Position = remapCoordinates ( new Vector2 ( pos . x , pos . y ) ) ;
108- updatePointer ( mousePointer ) ;
109- }
110-
111- var scroll = Input . mouseScrollDelta ;
112- mousePointer . ScrollDelta = scroll ;
113- if ( ! Mathf . Approximately ( scroll . sqrMagnitude , 0.0f ) )
114- {
115- updatePointer ( mousePointer ) ;
116- }
117-
118- var buttons = mousePointer . Buttons ;
119- var newButtons = getMouseButtons ( ) ;
120-
121- if ( buttons == newButtons ) return ; // nothing new happened
122-
123- // pressed something
124- if ( buttons == Pointer . PointerButtonState . Nothing )
125- {
126- // pressed and released this frame
127- if ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 )
128- {
129- // Add pressed buttons for processing
130- mousePointer . Buttons = newButtons | ( Pointer . PointerButtonState ) ( ( uint ) ( newButtons & Pointer . PointerButtonState . AnyButtonDown ) >> 1 ) ;
131- pressPointer ( mousePointer ) ;
132- internalReleaseMousePointer ( newButtons ) ;
133- }
134- // pressed this frame
135- else
136- {
137- mousePointer . Buttons = newButtons ;
138- pressPointer ( mousePointer ) ;
139- }
140- }
141- // released or button state changed
142- else
116+ var buttons = state == State . MouseAndFake ? fakeMousePointer . Buttons : mousePointer . Buttons ;
117+ var newButtons = getMouseButtons ( ) ;
118+ var pos = Input . mousePosition ;
119+ Vector2 remappedPos = new Vector2 ( 0 , 0 ) ;
120+
121+ if ( mousePointPos != pos )
122+ {
123+ remappedPos = remapCoordinates ( new Vector2 ( pos . x , pos . y ) ) ;
124+ mousePointer . Position = remappedPos ;
125+ updatePointer ( mousePointer ) ;
126+ }
127+
128+ var scroll = Input . mouseScrollDelta ;
129+ if ( ! Mathf . Approximately ( scroll . sqrMagnitude , 0.0f ) )
130+ {
131+ mousePointer . ScrollDelta = scroll ;
132+ updatePointer ( mousePointer ) ;
133+ }
134+
135+ if ( emulateSecondMousePointer )
143136 {
144- // released this frame
145- if ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 )
146- {
147- mousePointer . Buttons = newButtons ;
148- internalReleaseMousePointer ( newButtons ) ;
149- }
150- // button state changed this frame
151- else
152- {
153- mousePointer . Buttons = newButtons ;
154- updatePointer ( mousePointer ) ;
155- }
156- }
137+ switch ( state )
138+ {
139+ case State . Mouse :
140+ if ( Input . GetKeyDown ( KeyCode . LeftAlt ) && ! Input . GetKeyUp ( KeyCode . LeftAlt )
141+ && ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 ) )
142+ {
143+ stateWaitingForFake ( ) ;
144+ } else {
145+ if ( buttons != newButtons ) updateButtons ( buttons , newButtons ) ;
146+ }
147+ break ;
148+ case State . WaitingForFake :
149+ if ( Input . GetKey ( KeyCode . LeftAlt ) )
150+ {
151+ if ( ( newButtons & Pointer . PointerButtonState . AnyButtonDown ) != 0 )
152+ {
153+ // A button is down while holding Alt
154+ fakeMousePointer = internalAddPointer ( pos , newButtons , mousePointer . Flags | Pointer . FLAG_ARTIFICIAL ) ;
155+ pressPointer ( fakeMousePointer ) ;
156+ stateMouseAndFake ( ) ;
157+ }
158+ } else {
159+ stateMouse ( ) ;
160+ }
161+ break ;
162+ case State . MouseAndFake :
163+ if ( fakeTouchReleased ( ) )
164+ {
165+ stateMouse ( ) ;
166+ } else {
167+ if ( mousePointPos != pos )
168+ {
169+ fakeMousePointer . Position = remappedPos ;
170+ updatePointer ( fakeMousePointer ) ;
171+ }
172+ if ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 )
173+ {
174+ // All buttons are released, Alt is still holding
175+ stateStationaryFake ( ) ;
176+ } else if ( buttons != newButtons )
177+ {
178+ fakeMousePointer . Buttons = newButtons ;
179+ updatePointer ( fakeMousePointer ) ;
180+ }
181+ }
182+ break ;
183+ case State . StationaryFake :
184+ if ( buttons != newButtons ) updateButtons ( buttons , newButtons ) ;
185+ if ( fakeTouchReleased ( ) )
186+ {
187+ stateMouse ( ) ;
188+ }
189+ break ;
190+ }
191+ } else {
192+ if ( buttons != newButtons ) updateButtons ( buttons , newButtons ) ;
193+ }
194+
195+ mousePointPos = pos ;
157196 }
158197
159198 /// <inheritdoc />
@@ -163,7 +202,7 @@ public bool CancelPointer(Pointer pointer, bool shouldReturn)
163202 {
164203 cancelPointer ( mousePointer ) ;
165204 if ( shouldReturn ) mousePointer = internalReturnPointer ( mousePointer ) ;
166- else mousePointer = internalAddPointer ( mousePointPos ) ; // can't totally cancell mouse pointer
205+ else mousePointer = internalAddPointer ( mousePointer . Position ) ; // can't totally cancel mouse pointer
167206 return true ;
168207 }
169208 if ( pointer . Equals ( fakeMousePointer ) )
@@ -227,27 +266,62 @@ private Pointer.PointerButtonState getMouseButtons()
227266 return buttons ;
228267 }
229268
230- private void tryAddFakePointer ( Pointer . PointerButtonState newButtons )
231- {
232- if ( emulateSecondMousePointer
233- && ( Input . GetKey ( KeyCode . LeftAlt ) || Input . GetKey ( KeyCode . RightAlt ) )
234- && fakeMousePointer == null )
269+ private void updateButtons ( Pointer . PointerButtonState oldButtons , Pointer . PointerButtonState newButtons )
270+ {
271+ // pressed something
272+ if ( oldButtons == Pointer . PointerButtonState . Nothing )
235273 {
236- var up = ( uint ) ( newButtons & Pointer . PointerButtonState . AnyButtonUp ) ;
237- addFakePointer . ShouldAdd = true ;
238- addFakePointer . Flags = mousePointer . Flags | Pointer . FLAG_ARTIFICIAL ;
239- addFakePointer . Buttons = newButtons
240- & ~ Pointer . PointerButtonState . AnyButtonUp // remove up state from fake pointer
241- | ( Pointer . PointerButtonState ) ( up >> 1 ) // Add down state from pressed buttons
242- | ( Pointer . PointerButtonState ) ( up >> 2 ) ; // Add pressed state from pressed buttons
243- addFakePointer . Position = mousePointPos ;
274+ // pressed and released this frame
275+ if ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 )
276+ {
277+ // Add pressed buttons for processing
278+ mousePointer . Buttons = newButtons | ( Pointer . PointerButtonState ) ( ( uint ) ( newButtons & Pointer . PointerButtonState . AnyButtonDown ) >> 1 ) ;
279+ pressPointer ( mousePointer ) ;
280+ internalReleaseMousePointer ( newButtons ) ;
281+ }
282+ // pressed this frame
283+ else
284+ {
285+ mousePointer . Buttons = newButtons ;
286+ pressPointer ( mousePointer ) ;
287+ }
244288 }
245- }
289+ // released or button state changed
290+ else
291+ {
292+ // released this frame
293+ if ( ( newButtons & Pointer . PointerButtonState . AnyButtonPressed ) == 0 )
294+ {
295+ mousePointer . Buttons = newButtons ;
296+ internalReleaseMousePointer ( newButtons ) ;
297+ }
298+ // button state changed this frame
299+ else
300+ {
301+ mousePointer . Buttons = newButtons ;
302+ updatePointer ( mousePointer ) ;
303+ }
304+ }
305+ }
306+
307+ private bool fakeTouchReleased ( )
308+ {
309+ if ( ! Input . GetKey ( KeyCode . LeftAlt ) )
310+ {
311+ // Alt is released, need to kill the fake touch
312+ fakeMousePointer . Buttons = ( Pointer . PointerButtonState ) ( ( uint ) fakeMousePointer . Buttons << 2 ) ; // Convert current pressed buttons to UP
313+ releasePointer ( fakeMousePointer ) ;
314+ removePointer ( fakeMousePointer ) ;
315+ fakeMousePointer = null ; // Will be returned to the pool by INTERNAL_DiscardPointer
316+ return true ;
317+ }
318+ return false ;
319+ }
246320
247321 private MousePointer internalAddPointer ( Vector2 position , Pointer . PointerButtonState buttons = Pointer . PointerButtonState . Nothing , uint flags = 0 )
248322 {
249323 var pointer = mousePool . Get ( ) ;
250- pointer . Position = remapCoordinates ( position ) ;
324+ pointer . Position = position ;
251325 pointer . Buttons |= buttons ;
252326 pointer . Flags |= flags ;
253327 addPointer ( pointer ) ;
@@ -258,7 +332,6 @@ private void internalReleaseMousePointer(Pointer.PointerButtonState buttons)
258332 {
259333 mousePointer . Flags &= ~ Pointer . FLAG_RETURNED ;
260334 releasePointer ( mousePointer ) ;
261- tryAddFakePointer ( buttons ) ;
262335 }
263336
264337 private MousePointer internalReturnPointer ( MousePointer pointer )
@@ -284,13 +357,34 @@ private Vector2 remapCoordinates(Vector2 position)
284357
285358 #endregion
286359
287- private struct DelayedFakePointer
288- {
289- public bool ShouldAdd ;
290- public uint Flags ;
291- public Pointer . PointerButtonState Buttons ;
292- public Vector2 Position ;
293- }
360+ #region State logic
361+
362+ private void stateMouse ( )
363+ {
364+ setState ( State . Mouse ) ;
365+ }
366+
367+ private void stateWaitingForFake ( )
368+ {
369+ setState ( State . WaitingForFake ) ;
370+ }
371+
372+ private void stateMouseAndFake ( )
373+ {
374+ setState ( State . MouseAndFake ) ;
375+ }
376+
377+ private void stateStationaryFake ( )
378+ {
379+ setState ( State . StationaryFake ) ;
380+ }
381+
382+ private void setState ( State newState )
383+ {
384+ state = newState ;
385+ }
386+
387+ #endregion
294388
295389 }
296390}
0 commit comments