1
|
using System;
|
2
|
using System.Collections;
|
3
|
using UnityEngine;
|
4
|
using UnityEngine.Serialization;
|
5
|
using UnityEngine.EventSystems;
|
6
|
|
7
|
/// <summary>
|
8
|
/// Interaction IM is the input module that may be used as component of the Unity-UI EventSystem.
|
9
|
/// </summary>
|
10
|
public class InteractionInputModule : PointerInputModule, InteractionListenerInterface
|
11
|
{
|
12
|
[Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")]
|
13
|
public int playerIndex = 0;
|
14
|
|
15
|
|
16
|
//private bool m_isLeftHand = false;
|
17
|
private bool m_leftHandGrip = false;
|
18
|
private bool m_rightHandGrip = false;
|
19
|
private Vector3 m_screenNormalPos = Vector3.zero;
|
20
|
|
21
|
private PointerEventData.FramePressState m_framePressState = PointerEventData.FramePressState.NotChanged;
|
22
|
private readonly MouseState m_MouseState = new MouseState();
|
23
|
|
24
|
// interaction manager for the same player
|
25
|
private InteractionManager intManager;
|
26
|
|
27
|
// The single instance of InteractionInputModule
|
28
|
private static InteractionInputModule instance;
|
29
|
|
30
|
|
31
|
/// <summary>
|
32
|
/// Gets the single InteractionInputModule instance.
|
33
|
/// </summary>
|
34
|
/// <value>The InteractionInputModule instance.</value>
|
35
|
public static InteractionInputModule Instance
|
36
|
{
|
37
|
get
|
38
|
{
|
39
|
return instance;
|
40
|
}
|
41
|
}
|
42
|
|
43
|
protected InteractionInputModule()
|
44
|
{
|
45
|
instance = this;
|
46
|
}
|
47
|
|
48
|
|
49
|
[SerializeField]
|
50
|
[FormerlySerializedAs("m_AllowActivationOnMobileDevice")]
|
51
|
private bool m_ForceModuleActive;
|
52
|
|
53
|
|
54
|
public bool forceModuleActive
|
55
|
{
|
56
|
get { return m_ForceModuleActive; }
|
57
|
set { m_ForceModuleActive = value; }
|
58
|
}
|
59
|
|
60
|
public override bool IsModuleSupported()
|
61
|
{
|
62
|
return m_ForceModuleActive || InteractionManager.Instance != null;
|
63
|
}
|
64
|
|
65
|
public override bool ShouldActivateModule()
|
66
|
{
|
67
|
if (!base.ShouldActivateModule())
|
68
|
return false;
|
69
|
|
70
|
//bool shouldActivate |= (InteractionManager.Instance != null && InteractionManager.Instance.IsInteractionInited());
|
71
|
bool shouldActivate = m_ForceModuleActive || (m_framePressState != PointerEventData.FramePressState.NotChanged);
|
72
|
|
73
|
return shouldActivate;
|
74
|
}
|
75
|
|
76
|
// public override void ActivateModule()
|
77
|
// {
|
78
|
// base.ActivateModule();
|
79
|
//
|
80
|
// var toSelect = eventSystem.currentSelectedGameObject;
|
81
|
// if (toSelect == null)
|
82
|
// toSelect = eventSystem.firstSelectedGameObject;
|
83
|
//
|
84
|
// eventSystem.SetSelectedGameObject(toSelect, GetBaseEventData());
|
85
|
// }
|
86
|
|
87
|
// public override void DeactivateModule()
|
88
|
// {
|
89
|
// base.DeactivateModule();
|
90
|
// ClearSelection();
|
91
|
// }
|
92
|
|
93
|
public override void Process()
|
94
|
{
|
95
|
if (intManager == null)
|
96
|
{
|
97
|
intManager = GetInteractionManager();
|
98
|
}
|
99
|
|
100
|
CheckGrippedCursorPosition();
|
101
|
ProcessInteractionEvent();
|
102
|
}
|
103
|
|
104
|
private InteractionManager GetInteractionManager()
|
105
|
{
|
106
|
// find the proper interaction manager
|
107
|
MonoBehaviour[] monoScripts = FindObjectsOfType(typeof(MonoBehaviour)) as MonoBehaviour[];
|
108
|
|
109
|
foreach(MonoBehaviour monoScript in monoScripts)
|
110
|
{
|
111
|
if((monoScript is InteractionManager) && monoScript.enabled)
|
112
|
{
|
113
|
InteractionManager manager = (InteractionManager)monoScript;
|
114
|
|
115
|
if (manager.playerIndex == playerIndex)
|
116
|
{
|
117
|
return manager;
|
118
|
}
|
119
|
}
|
120
|
}
|
121
|
|
122
|
// not found
|
123
|
return null;
|
124
|
}
|
125
|
|
126
|
private void CheckGrippedCursorPosition()
|
127
|
{
|
128
|
if (intManager)
|
129
|
{
|
130
|
bool bIsLeftHand = intManager.IsLeftHandPrimary();
|
131
|
|
132
|
// check for gripped hand
|
133
|
bool bHandGrip = bIsLeftHand ? m_leftHandGrip : m_rightHandGrip;
|
134
|
|
135
|
// check for cursor pos change
|
136
|
Vector2 cursorNormalPos = bIsLeftHand ? intManager.GetLeftHandScreenPos() : intManager.GetRightHandScreenPos();
|
137
|
|
138
|
if (bHandGrip && cursorNormalPos != (Vector2)m_screenNormalPos)
|
139
|
{
|
140
|
// emulate new press
|
141
|
m_framePressState = PointerEventData.FramePressState.Pressed;
|
142
|
m_screenNormalPos = cursorNormalPos;
|
143
|
}
|
144
|
}
|
145
|
}
|
146
|
|
147
|
protected void ProcessInteractionEvent()
|
148
|
{
|
149
|
// Emulate mouse data
|
150
|
var mouseData = GetMousePointerEventData(0);
|
151
|
var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
|
152
|
|
153
|
// Process the interaction data
|
154
|
ProcessHandPressRelease(leftButtonData);
|
155
|
ProcessMove(leftButtonData.buttonData);
|
156
|
ProcessDrag(leftButtonData.buttonData);
|
157
|
}
|
158
|
|
159
|
protected override MouseState GetMousePointerEventData(int id)
|
160
|
{
|
161
|
// Populate the left button...
|
162
|
PointerEventData leftData;
|
163
|
var created = GetPointerData(kMouseLeftId, out leftData, true);
|
164
|
|
165
|
leftData.Reset();
|
166
|
|
167
|
Vector2 handPos = new Vector2(m_screenNormalPos.x * Screen.width, m_screenNormalPos.y * Screen.height);
|
168
|
|
169
|
if (created)
|
170
|
{
|
171
|
leftData.position = handPos;
|
172
|
}
|
173
|
|
174
|
leftData.delta = handPos - leftData.position;
|
175
|
leftData.position = handPos;
|
176
|
//leftData.scrollDelta = 0f;
|
177
|
leftData.button = PointerEventData.InputButton.Left;
|
178
|
|
179
|
eventSystem.RaycastAll(leftData, m_RaycastResultCache);
|
180
|
var raycast = FindFirstRaycast(m_RaycastResultCache);
|
181
|
leftData.pointerCurrentRaycast = raycast;
|
182
|
m_RaycastResultCache.Clear();
|
183
|
|
184
|
m_MouseState.SetButtonState(PointerEventData.InputButton.Left, m_framePressState, leftData);
|
185
|
m_framePressState = PointerEventData.FramePressState.NotChanged;
|
186
|
|
187
|
return m_MouseState;
|
188
|
}
|
189
|
|
190
|
/// <summary>
|
191
|
/// Process the current hand press or release event.
|
192
|
/// </summary>
|
193
|
protected void ProcessHandPressRelease(MouseButtonEventData data)
|
194
|
{
|
195
|
var pointerEvent = data.buttonData;
|
196
|
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
|
197
|
|
198
|
// PointerDown notification
|
199
|
if (data.PressedThisFrame())
|
200
|
{
|
201
|
pointerEvent.eligibleForClick = true;
|
202
|
pointerEvent.delta = Vector2.zero;
|
203
|
pointerEvent.dragging = false;
|
204
|
pointerEvent.useDragThreshold = true;
|
205
|
pointerEvent.pressPosition = pointerEvent.position;
|
206
|
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
|
207
|
|
208
|
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
|
209
|
|
210
|
// search for the control that will receive the press
|
211
|
// if we can't find a press handler set the press
|
212
|
// handler to be what would receive a click.
|
213
|
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
|
214
|
|
215
|
// didnt find a press handler... search for a click handler
|
216
|
if (newPressed == null)
|
217
|
newPressed = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
218
|
|
219
|
//Debug.Log("Pressed: " + newPressed);
|
220
|
|
221
|
float time = Time.unscaledTime;
|
222
|
|
223
|
if (newPressed == pointerEvent.lastPress)
|
224
|
{
|
225
|
var diffTime = time - pointerEvent.clickTime;
|
226
|
if (diffTime < 0.3f)
|
227
|
++pointerEvent.clickCount;
|
228
|
else
|
229
|
pointerEvent.clickCount = 1;
|
230
|
|
231
|
pointerEvent.clickTime = time;
|
232
|
}
|
233
|
else
|
234
|
{
|
235
|
pointerEvent.clickCount = 1;
|
236
|
}
|
237
|
|
238
|
pointerEvent.pointerPress = newPressed;
|
239
|
pointerEvent.rawPointerPress = currentOverGo;
|
240
|
|
241
|
pointerEvent.clickTime = time;
|
242
|
|
243
|
// Save the drag handler as well
|
244
|
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
|
245
|
|
246
|
if (pointerEvent.pointerDrag != null)
|
247
|
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
|
248
|
}
|
249
|
|
250
|
// PointerUp notification
|
251
|
if (data.ReleasedThisFrame())
|
252
|
{
|
253
|
// Debug.Log("Executing pressup on: " + pointer.pointerPress);
|
254
|
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
|
255
|
|
256
|
// see if we mouse up on the same element that we clicked on...
|
257
|
var pointerUpHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
|
258
|
|
259
|
// PointerClick and Drop events
|
260
|
if (pointerEvent.pointerPress != null && pointerEvent.pointerPress == pointerUpHandler && pointerEvent.eligibleForClick)
|
261
|
{
|
262
|
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerClickHandler);
|
263
|
}
|
264
|
else if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
265
|
{
|
266
|
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
|
267
|
}
|
268
|
|
269
|
pointerEvent.eligibleForClick = false;
|
270
|
pointerEvent.pointerPress = null;
|
271
|
pointerEvent.rawPointerPress = null;
|
272
|
|
273
|
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
|
274
|
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
|
275
|
|
276
|
pointerEvent.dragging = false;
|
277
|
pointerEvent.pointerDrag = null;
|
278
|
|
279
|
// redo pointer enter / exit to refresh state
|
280
|
// so that if we moused over somethign that ignored it before
|
281
|
// due to having pressed on something else
|
282
|
// it now gets it.
|
283
|
if (currentOverGo != pointerEvent.pointerEnter)
|
284
|
{
|
285
|
HandlePointerExitAndEnter(pointerEvent, null);
|
286
|
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
|
287
|
}
|
288
|
}
|
289
|
}
|
290
|
|
291
|
|
292
|
public void HandGripDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos)
|
293
|
{
|
294
|
if (userIndex != playerIndex || !isHandInteracting)
|
295
|
return;
|
296
|
|
297
|
//Debug.Log("HandGripDetected");
|
298
|
|
299
|
m_framePressState = PointerEventData.FramePressState.Pressed;
|
300
|
//m_isLeftHand = !isRightHand;
|
301
|
m_screenNormalPos = handScreenPos;
|
302
|
|
303
|
if (!isRightHand)
|
304
|
m_leftHandGrip = true;
|
305
|
else
|
306
|
m_rightHandGrip = true;
|
307
|
}
|
308
|
|
309
|
public void HandReleaseDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos)
|
310
|
{
|
311
|
if (userIndex != playerIndex || !isHandInteracting)
|
312
|
return;
|
313
|
|
314
|
//Debug.Log("HandReleaseDetected");
|
315
|
|
316
|
m_framePressState = PointerEventData.FramePressState.Released;
|
317
|
//m_isLeftHand = !isRightHand;
|
318
|
m_screenNormalPos = handScreenPos;
|
319
|
|
320
|
if (!isRightHand)
|
321
|
m_leftHandGrip = false;
|
322
|
else
|
323
|
m_rightHandGrip = false;
|
324
|
}
|
325
|
|
326
|
public bool HandClickDetected(long userId, int userIndex, bool isRightHand, Vector3 handScreenPos)
|
327
|
{
|
328
|
if (userIndex != playerIndex)
|
329
|
return false;
|
330
|
|
331
|
//Debug.Log("HandClickDetected");
|
332
|
|
333
|
StartCoroutine(EmulateMouseClick(isRightHand, handScreenPos));
|
334
|
return true;
|
335
|
}
|
336
|
|
337
|
|
338
|
private IEnumerator EmulateMouseClick(bool isRightHand, Vector3 handScreenPos)
|
339
|
{
|
340
|
m_framePressState = PointerEventData.FramePressState.Pressed;
|
341
|
//m_isLeftHand = !isRightHand;
|
342
|
m_screenNormalPos = handScreenPos;
|
343
|
|
344
|
yield return new WaitForSeconds(0.2f);
|
345
|
|
346
|
m_framePressState = PointerEventData.FramePressState.Released;
|
347
|
//m_isLeftHand = !isRightHand;
|
348
|
m_screenNormalPos = handScreenPos;
|
349
|
|
350
|
yield return null;
|
351
|
}
|
352
|
|
353
|
|
354
|
}
|
355
|
|