5 using System.Collections.Generic;
10 namespace HoloToolkit.Unity.InputModule.Utilities.Interactions
22 [Tooltip(
"Transform that will be dragged. Defaults to the object of the component.")]
23 private Transform hostTransform = null;
25 public Transform HostTransform
27 get {
return hostTransform; }
28 set { hostTransform = value; }
32 [Tooltip(
"To visualize the object bounding box, drop the HoloToolkit/UX/Prefabs/BoundingBoxes/BoundingBoxBasic.prefab here. This is optional.")]
40 set { boundingBoxPrefab = value; }
41 get {
return boundingBoxPrefab; }
45 [Tooltip(
"What manipulation will two hands perform?")]
50 get {
return manipulationMode; }
51 set { manipulationMode = value; }
55 [Tooltip(
"Constrain rotation along an axis")]
60 get {
return rotationConstraint; }
63 rotationConstraint = value;
69 [Tooltip(
"If true, grabbing the object with one hand will initiate movement.")]
70 private bool enableOneHandMovement =
true;
72 public bool EnableEnableOneHandedMovement
74 get {
return enableOneHandMovement; }
75 set { enableOneHandMovement = value; }
79 #region Transform Info 87 #endregion Transform Info 92 private readonly Dictionary<uint, Vector3> handsPressedLocationsMap =
new Dictionary<uint, Vector3>();
97 private readonly Dictionary<uint, IInputSource> handsPressedInputSourceMap =
new Dictionary<uint, IInputSource>();
102 private bool ShowBoundingBox
106 if (boundingBoxPrefab != null)
108 if (boundingBoxInstance == null)
111 boundingBoxInstance = Instantiate(boundingBoxPrefab) as
BoundingBox;
116 boundingBoxInstance.
Target = HostTransform.gameObject;
117 boundingBoxInstance.gameObject.SetActive(
true);
121 boundingBoxInstance.
Target = null;
122 boundingBoxInstance.gameObject.SetActive(
false);
131 [
System.Obsolete(
"Use ManipulationMode.")]
134 manipulationMode = mode;
146 if (hostTransform == null)
148 hostTransform = transform;
152 private void Update()
155 foreach (var key
in handsPressedInputSourceMap.Keys)
157 var inputSource = handsPressedInputSourceMap[key];
158 Vector3 inputPosition;
159 if (inputSource.TryGetGripPosition(key, out inputPosition))
161 handsPressedLocationsMap[key] = inputPosition;
167 UpdateStateMachine();
178 private void RemoveSourceIdFromHandMap(uint sourceId)
180 if (handsPressedLocationsMap.ContainsKey(sourceId))
182 handsPressedLocationsMap.Remove(sourceId);
185 if (handsPressedInputSourceMap.ContainsKey(sourceId))
187 handsPressedInputSourceMap.Remove(sourceId);
197 handsPressedLocationsMap[eventData.
SourceId] = GetInputPosition(eventData);
199 UpdateStateMachine();
208 RemoveSourceIdFromHandMap(eventData.
SourceId);
209 UpdateStateMachine();
223 RemoveSourceIdFromHandMap(eventData.
SourceId);
224 UpdateStateMachine();
231 private void UpdateStateMachine()
233 var handsPressedCount = handsPressedLocationsMap.Count;
236 switch (currentState)
240 if (handsPressedCount == 0)
244 else if (handsPressedCount == 1)
248 else if (handsPressedCount > 1)
250 newState = manipulationMode;
259 if (handsPressedCount == 0)
263 else if (handsPressedCount == 1)
270 InvokeStateUpdateFunctions(currentState, newState);
271 currentState = newState;
276 if (newState != oldState)
281 OnManipulationEnded();
284 OnOneHandMoveStarted();
292 OnTwoHandManipulationStarted(newState);
299 OnManipulationStarted();
309 OnTwoHandManipulationEnded();
320 OnOneHandMoveUpdated();
328 OnTwoHandManipulationUpdated();
334 private void OnTwoHandManipulationUpdated()
336 #if UNITY_2017_2_OR_NEWER 337 var targetRotation = hostTransform.rotation;
338 var targetPosition = hostTransform.position;
339 var targetScale = hostTransform.localScale;
343 targetPosition = moveLogic.
Update(GetHandsCentroid(), targetPosition);
348 targetRotation = rotateLogic.
Update(handsPressedLocationsMap, hostTransform, targetRotation);
353 targetScale = scaleLogic.
UpdateMap(handsPressedLocationsMap);
356 hostTransform.position = targetPosition;
357 hostTransform.rotation = targetRotation;
358 hostTransform.localScale = targetScale;
359 #endif // UNITY_2017_2_OR_NEWER 362 private void OnOneHandMoveUpdated()
364 var targetPosition = moveLogic.
Update(handsPressedLocationsMap.Values.First(), hostTransform.position);
366 hostTransform.position = targetPosition;
369 private void OnTwoHandManipulationEnded()
371 #if UNITY_2017_2_OR_NEWER 373 #endif // UNITY_2017_2_OR_NEWER 376 private Vector3 GetHandsCentroid()
378 Vector3 result = handsPressedLocationsMap.Values.Aggregate(Vector3.zero, (current, state) => current + state);
379 return result / handsPressedLocationsMap.Count;
384 #if UNITY_2017_2_OR_NEWER 387 rotateLogic.
Setup(handsPressedLocationsMap, hostTransform);
392 moveLogic.
Setup(GetHandsCentroid(), hostTransform);
397 scaleLogic.
Setup(handsPressedLocationsMap, hostTransform);
399 #endif // UNITY_2017_2_OR_NEWER 402 private void OnOneHandMoveStarted()
404 Assert.IsTrue(handsPressedLocationsMap.Count == 1);
406 moveLogic.
Setup(handsPressedLocationsMap.Values.First(), hostTransform);
409 private void OnManipulationStarted()
414 ShowBoundingBox =
true;
417 private void OnManipulationEnded()
422 ShowBoundingBox =
false;