Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

439 lines
23 KiB

  1. // Drag World|Locomotion|20150
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. /// <summary>
  6. /// Provides the ability to move, rotate and scale the PlayArea by dragging the world with the controllers.
  7. /// </summary>
  8. /// <remarks>
  9. /// **Script Usage:**
  10. /// * Place the `VRTK_DragWorld` script on any active scene GameObject.
  11. ///
  12. /// > If only one controller is being used to track the rotation mechanism, then the rotation will be based on the perpendicual (yaw) axis angular velocity of the tracking controller.
  13. /// > If both controllers are being used to track the rotation mechanism, then the rotation will be based on pushing one controller forward, whilst pulling the other controller backwards.
  14. /// </remarks>
  15. [AddComponentMenu("VRTK/Scripts/Locomotion/VRTK_DragWorld")]
  16. public class VRTK_DragWorld : MonoBehaviour
  17. {
  18. /// <summary>
  19. /// The controller on which to determine as the activation requirement for the control mechanism.
  20. /// </summary>
  21. public enum ActivationRequirement
  22. {
  23. /// <summary>
  24. /// Only pressing the activation button on the left controller will activate the mechanism, if the right button is held down then the mechanism will not be activated.
  25. /// </summary>
  26. LeftControllerOnly,
  27. /// <summary>
  28. /// Only pressing the activation button on the right controller will activate the mechanism, if the left button is held down then the mechanism will not be activated.
  29. /// </summary>
  30. RightControllerOnly,
  31. /// <summary>
  32. /// Pressing the activation button on the left controller is all that is required to activate the mechanism.
  33. /// </summary>
  34. LeftController,
  35. /// <summary>
  36. /// Pressing the activation button on the right controller is all that is required to activate the mechanism.
  37. /// </summary>
  38. RightController,
  39. /// <summary>
  40. /// Pressing the activation button on the either controller is all that is required to activate the mechanism.
  41. /// </summary>
  42. EitherController,
  43. /// <summary>
  44. /// Pressing the activation button on both controllers is required to activate the mechanism.
  45. /// </summary>
  46. BothControllers
  47. }
  48. /// <summary>
  49. /// The controllers which to track when performing the mechanism.
  50. /// </summary>
  51. public enum TrackingController
  52. {
  53. /// <summary>
  54. /// Only track the left controller.
  55. /// </summary>
  56. LeftController,
  57. /// <summary>
  58. /// Only track the right controller.
  59. /// </summary>
  60. RightController,
  61. /// <summary>
  62. /// Track either the left or the right controller.
  63. /// </summary>
  64. EitherController,
  65. /// <summary>
  66. /// Only track both controllers at the same time.
  67. /// </summary>
  68. BothControllers
  69. }
  70. [Header("Movement Settings")]
  71. [Tooltip("The controller button to press to activate the movement mechanism.")]
  72. public VRTK_ControllerEvents.ButtonAlias movementActivationButton = VRTK_ControllerEvents.ButtonAlias.GripPress;
  73. [Tooltip("The controller(s) on which the activation button is to be pressed to consider the movement mechanism active.")]
  74. public ActivationRequirement movementActivationRequirement = ActivationRequirement.EitherController;
  75. [Tooltip("The controller(s) on which to track position of to determine if a valid move has taken place.")]
  76. public TrackingController movementTrackingController = TrackingController.BothControllers;
  77. [Tooltip("The amount to multply the movement by.")]
  78. public float movementMultiplier = 3f;
  79. [Tooltip("The axes to lock to prevent movement across.")]
  80. public Vector3State movementPositionLock = new Vector3State(false, true, false);
  81. [Header("Rotation Settings")]
  82. [Tooltip("The controller button to press to activate the rotation mechanism.")]
  83. public VRTK_ControllerEvents.ButtonAlias rotationActivationButton = VRTK_ControllerEvents.ButtonAlias.GripPress;
  84. [Tooltip("The controller(s) on which the activation button is to be pressed to consider the rotation mechanism active.")]
  85. public ActivationRequirement rotationActivationRequirement = ActivationRequirement.BothControllers;
  86. [Tooltip("The controller(s) on which to determine how rotation should occur. `BothControllers` requires both controllers to be pushed/pulled to rotate, whereas any other setting will base rotation on the rotation of the activating controller.")]
  87. public TrackingController rotationTrackingController = TrackingController.BothControllers;
  88. [Tooltip("The amount to multply the rotation angle by.")]
  89. public float rotationMultiplier = 0.75f;
  90. [Tooltip("The threshold the rotation angle has to be above to consider a valid rotation amount.")]
  91. public float rotationActivationThreshold = 0.1f;
  92. [Header("Scale Settings")]
  93. [Tooltip("The controller button to press to activate the scale mechanism.")]
  94. public VRTK_ControllerEvents.ButtonAlias scaleActivationButton = VRTK_ControllerEvents.ButtonAlias.TriggerPress;
  95. [Tooltip("The controller(s) on which the activation button is to be pressed to consider the scale mechanism active.")]
  96. public ActivationRequirement scaleActivationRequirement = ActivationRequirement.BothControllers;
  97. [Tooltip("The controller(s) on which to determine how scaling should occur.")]
  98. public TrackingController scaleTrackingController = TrackingController.BothControllers;
  99. [Tooltip("The amount to multply the scale factor by.")]
  100. public float scaleMultiplier = 3f;
  101. [Tooltip("The threshold the distance between the scale objects has to be above to consider a valid scale operation.")]
  102. public float scaleActivationThreshold = 0.002f;
  103. [Tooltip("the minimum scale amount that can be applied.")]
  104. public Vector3 minimumScale = Vector3.one;
  105. [Tooltip("the maximum scale amount that can be applied.")]
  106. public Vector3 maximumScale = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
  107. [Header("Custom Settings")]
  108. [Tooltip("The transform to apply the control mechanisms to. If this is left blank then the PlayArea will be controlled.")]
  109. public Transform controllingTransform;
  110. [Tooltip("Uses the specified `Offset Transform` when dealing with rotational offsets.")]
  111. public bool useOffsetTransform = true;
  112. [Tooltip("The transform to use when dealing with rotational offsets. If this is left blank then the Headset will be used as the offset.")]
  113. public Transform offsetTransform;
  114. protected VRTK_ControllerReference leftControllerReference;
  115. protected VRTK_ControllerReference rightControllerReference;
  116. protected VRTK_ControllerEvents leftControllerEvents;
  117. protected VRTK_ControllerEvents rightControllerEvents;
  118. protected Transform playArea;
  119. protected Transform headset;
  120. protected VRTK_ControllerEvents.ButtonAlias subscribedMovementActivationButton;
  121. protected Vector3 previousLeftControllerPosition = Vector3.zero;
  122. protected Vector3 previousRightControllerPosition = Vector3.zero;
  123. protected bool movementLeftControllerActivated;
  124. protected bool movementRightControllerActivated;
  125. protected bool movementActivated;
  126. protected VRTK_ControllerEvents.ButtonAlias subscribedRotationActivationButton;
  127. protected Vector2 previousRotationAngle = Vector2.zero;
  128. protected bool rotationLeftControllerActivated;
  129. protected bool rotationRightControllerActivated;
  130. protected bool rotationActivated;
  131. protected VRTK_ControllerEvents.ButtonAlias subscribedScaleActivationButton;
  132. protected float previousControllerDistance;
  133. protected bool scaleLeftControllerActivated;
  134. protected bool scaleRightControllerActivated;
  135. protected bool scaleActivated;
  136. protected virtual void Awake()
  137. {
  138. VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
  139. }
  140. protected virtual void OnEnable()
  141. {
  142. playArea = VRTK_DeviceFinder.PlayAreaTransform();
  143. headset = VRTK_DeviceFinder.HeadsetTransform();
  144. controllingTransform = (controllingTransform != null ? controllingTransform : playArea);
  145. offsetTransform = (offsetTransform != null ? offsetTransform : headset);
  146. leftControllerEvents = GetControllerEvents(VRTK_DeviceFinder.GetControllerLeftHand());
  147. rightControllerEvents = GetControllerEvents(VRTK_DeviceFinder.GetControllerRightHand());
  148. movementActivated = false;
  149. rotationActivated = false;
  150. scaleActivated = false;
  151. ManageActivationListeners(true);
  152. SetControllerReferences();
  153. }
  154. protected virtual void OnDisable()
  155. {
  156. ManageActivationListeners(false);
  157. }
  158. protected virtual void OnDestroy()
  159. {
  160. VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
  161. }
  162. protected virtual void FixedUpdate()
  163. {
  164. Scale();
  165. Rotate();
  166. Move();
  167. ManageActivationListeners(true);
  168. }
  169. protected virtual VRTK_ControllerEvents GetControllerEvents(GameObject controllerObject)
  170. {
  171. return (controllerObject != null ? controllerObject.GetComponentInChildren<VRTK_ControllerEvents>() : null);
  172. }
  173. protected virtual void ManageActivationListeners(bool state)
  174. {
  175. ManageActivationListener(state, ref movementActivationButton, ref subscribedMovementActivationButton, MovementActivationButtonPressed, MovementActivationButtonReleased);
  176. ManageActivationListener(state, ref rotationActivationButton, ref subscribedRotationActivationButton, RotationActivationButtonPressed, RotationActivationButtonReleased);
  177. ManageActivationListener(state, ref scaleActivationButton, ref subscribedScaleActivationButton, ScaleActivationButtonPressed, ScaleActivationButtonReleased);
  178. }
  179. protected virtual void ManageActivationListener(bool state, ref VRTK_ControllerEvents.ButtonAlias activationButton, ref VRTK_ControllerEvents.ButtonAlias subscribedActivationButton, ControllerInteractionEventHandler buttonPressedCallback, ControllerInteractionEventHandler buttonReleasedCallback)
  180. {
  181. if (subscribedActivationButton == VRTK_ControllerEvents.ButtonAlias.Undefined && (!state || activationButton != subscribedActivationButton))
  182. {
  183. if (leftControllerEvents != null)
  184. {
  185. leftControllerEvents.UnsubscribeToButtonAliasEvent(subscribedActivationButton, true, buttonPressedCallback);
  186. leftControllerEvents.UnsubscribeToButtonAliasEvent(subscribedActivationButton, false, buttonReleasedCallback);
  187. leftControllerEvents.ControllerModelAvailable -= ControllerModelAvailable;
  188. }
  189. if (rightControllerEvents != null)
  190. {
  191. rightControllerEvents.UnsubscribeToButtonAliasEvent(subscribedActivationButton, true, buttonPressedCallback);
  192. rightControllerEvents.UnsubscribeToButtonAliasEvent(subscribedActivationButton, false, buttonReleasedCallback);
  193. rightControllerEvents.ControllerModelAvailable -= ControllerModelAvailable;
  194. }
  195. subscribedActivationButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
  196. }
  197. if (state && subscribedActivationButton == VRTK_ControllerEvents.ButtonAlias.Undefined && activationButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
  198. {
  199. bool subscribed = false;
  200. if (leftControllerEvents != null)
  201. {
  202. leftControllerEvents.SubscribeToButtonAliasEvent(activationButton, true, buttonPressedCallback);
  203. leftControllerEvents.SubscribeToButtonAliasEvent(activationButton, false, buttonReleasedCallback);
  204. leftControllerEvents.ControllerModelAvailable += ControllerModelAvailable;
  205. subscribed = true;
  206. }
  207. if (rightControllerEvents != null)
  208. {
  209. rightControllerEvents.SubscribeToButtonAliasEvent(activationButton, true, buttonPressedCallback);
  210. rightControllerEvents.SubscribeToButtonAliasEvent(activationButton, false, buttonReleasedCallback);
  211. rightControllerEvents.ControllerModelAvailable += ControllerModelAvailable;
  212. subscribed = true;
  213. }
  214. if (subscribed)
  215. {
  216. subscribedActivationButton = activationButton;
  217. }
  218. }
  219. }
  220. protected virtual void ControllerModelAvailable(object sender, ControllerInteractionEventArgs e)
  221. {
  222. SetControllerReferences();
  223. }
  224. protected virtual void SetControllerReferences()
  225. {
  226. leftControllerReference = VRTK_DeviceFinder.GetControllerReferenceLeftHand();
  227. rightControllerReference = VRTK_DeviceFinder.GetControllerReferenceRightHand();
  228. }
  229. protected virtual void ManageActivationState(SDK_BaseController.ControllerHand hand, ActivationRequirement activationRequirement, bool pressedState, ref bool leftActivationState, ref bool rightActivationState, ref bool activated)
  230. {
  231. switch (hand)
  232. {
  233. case SDK_BaseController.ControllerHand.Left:
  234. leftActivationState = pressedState; ;
  235. break;
  236. case SDK_BaseController.ControllerHand.Right:
  237. rightActivationState = pressedState; ;
  238. break;
  239. }
  240. switch (activationRequirement)
  241. {
  242. case ActivationRequirement.LeftControllerOnly:
  243. activated = (rightActivationState ? false : leftActivationState);
  244. break;
  245. case ActivationRequirement.RightControllerOnly:
  246. activated = (leftActivationState ? false : rightActivationState);
  247. break;
  248. case ActivationRequirement.LeftController:
  249. activated = leftActivationState;
  250. break;
  251. case ActivationRequirement.RightController:
  252. activated = rightActivationState;
  253. break;
  254. case ActivationRequirement.EitherController:
  255. activated = (leftActivationState || rightActivationState);
  256. break;
  257. case ActivationRequirement.BothControllers:
  258. activated = (leftActivationState && rightActivationState);
  259. break;
  260. }
  261. }
  262. protected virtual void MovementActivationButtonPressed(object sender, ControllerInteractionEventArgs e)
  263. {
  264. ManageActivationState(e.controllerReference.hand, movementActivationRequirement, true, ref movementLeftControllerActivated, ref movementRightControllerActivated, ref movementActivated);
  265. SetControllerPositions();
  266. }
  267. protected virtual void MovementActivationButtonReleased(object sender, ControllerInteractionEventArgs e)
  268. {
  269. ManageActivationState(e.controllerReference.hand, movementActivationRequirement, false, ref movementLeftControllerActivated, ref movementRightControllerActivated, ref movementActivated);
  270. }
  271. protected virtual void RotationActivationButtonPressed(object sender, ControllerInteractionEventArgs e)
  272. {
  273. ManageActivationState(e.controllerReference.hand, rotationActivationRequirement, true, ref rotationLeftControllerActivated, ref rotationRightControllerActivated, ref rotationActivated);
  274. previousRotationAngle = GetControllerRotation();
  275. }
  276. protected virtual void RotationActivationButtonReleased(object sender, ControllerInteractionEventArgs e)
  277. {
  278. ManageActivationState(e.controllerReference.hand, rotationActivationRequirement, false, ref rotationLeftControllerActivated, ref rotationRightControllerActivated, ref rotationActivated);
  279. }
  280. protected virtual void ScaleActivationButtonPressed(object sender, ControllerInteractionEventArgs e)
  281. {
  282. ManageActivationState(e.controllerReference.hand, scaleActivationRequirement, true, ref scaleLeftControllerActivated, ref scaleRightControllerActivated, ref scaleActivated);
  283. previousControllerDistance = GetControllerDistance();
  284. }
  285. protected virtual void ScaleActivationButtonReleased(object sender, ControllerInteractionEventArgs e)
  286. {
  287. ManageActivationState(e.controllerReference.hand, scaleActivationRequirement, false, ref scaleLeftControllerActivated, ref scaleRightControllerActivated, ref scaleActivated);
  288. }
  289. protected virtual Vector3 GetLeftControllerPosition()
  290. {
  291. return (VRTK_ControllerReference.IsValid(leftControllerReference) ? leftControllerReference.actual.transform.localPosition : Vector3.zero);
  292. }
  293. protected virtual Vector3 GetRightControllerPosition()
  294. {
  295. return (VRTK_ControllerReference.IsValid(rightControllerReference) ? rightControllerReference.actual.transform.localPosition : Vector3.zero);
  296. }
  297. protected virtual void SetControllerPositions()
  298. {
  299. previousLeftControllerPosition = GetLeftControllerPosition();
  300. previousRightControllerPosition = GetRightControllerPosition();
  301. }
  302. protected virtual Vector2 GetControllerRotation()
  303. {
  304. return new Vector2((GetLeftControllerPosition() - GetRightControllerPosition()).x, (GetLeftControllerPosition() - GetRightControllerPosition()).z);
  305. }
  306. protected virtual float GetControllerDistance()
  307. {
  308. switch (scaleTrackingController)
  309. {
  310. case TrackingController.BothControllers:
  311. return Vector3.Distance(GetLeftControllerPosition(), GetRightControllerPosition());
  312. case TrackingController.LeftController:
  313. return Vector3.Distance(GetLeftControllerPosition(), offsetTransform.localPosition);
  314. case TrackingController.RightController:
  315. return Vector3.Distance(GetRightControllerPosition(), offsetTransform.localPosition);
  316. case TrackingController.EitherController:
  317. return Vector3.Distance(GetLeftControllerPosition(), offsetTransform.localPosition) + Vector3.Distance(GetRightControllerPosition(), offsetTransform.localPosition);
  318. }
  319. return 0f;
  320. }
  321. protected virtual bool TrackingControllerEnabled(TrackingController trackingController, TrackingController hand, bool handActivated)
  322. {
  323. return (trackingController == TrackingController.BothControllers || trackingController == hand || (trackingController == TrackingController.EitherController && handActivated));
  324. }
  325. protected virtual void Move()
  326. {
  327. if (!movementActivated)
  328. {
  329. return;
  330. }
  331. Vector3 leftMovementOffset = (TrackingControllerEnabled(movementTrackingController, TrackingController.LeftController, movementLeftControllerActivated) ? GetLeftControllerPosition() - previousLeftControllerPosition : Vector3.zero);
  332. Vector3 rightMovementOffset = (TrackingControllerEnabled(movementTrackingController, TrackingController.RightController, movementRightControllerActivated) ? GetRightControllerPosition() - previousRightControllerPosition : Vector3.zero);
  333. Vector3 movementOffset = controllingTransform.localRotation * (leftMovementOffset + rightMovementOffset);
  334. Vector3 newPosition = controllingTransform.localPosition - Vector3.Scale((movementOffset * movementMultiplier), controllingTransform.localScale);
  335. controllingTransform.localPosition = new Vector3((movementPositionLock.xState ? controllingTransform.localPosition.x : newPosition.x), (movementPositionLock.yState ? controllingTransform.localPosition.y : newPosition.y), (movementPositionLock.zState ? controllingTransform.localPosition.z : newPosition.z));
  336. SetControllerPositions();
  337. }
  338. protected virtual void Rotate()
  339. {
  340. if (!rotationActivated)
  341. {
  342. return;
  343. }
  344. if (rotationTrackingController == TrackingController.BothControllers && VRTK_ControllerReference.IsValid(leftControllerReference) && VRTK_ControllerReference.IsValid(rightControllerReference))
  345. {
  346. Vector2 currentRotationAngle = GetControllerRotation();
  347. float newAngle = Vector2.Angle(currentRotationAngle, previousRotationAngle)*Mathf.Sign(Vector3.Cross(currentRotationAngle, previousRotationAngle).z);
  348. RotateByAngle(newAngle);
  349. previousRotationAngle = currentRotationAngle;
  350. }
  351. else
  352. {
  353. float leftControllerAngle = (TrackingControllerEnabled(rotationTrackingController, TrackingController.LeftController, rotationLeftControllerActivated) ? VRTK_DeviceFinder.GetControllerAngularVelocity(leftControllerReference).y : 0f);
  354. float rightControllerAngle = (TrackingControllerEnabled(rotationTrackingController, TrackingController.RightController, rotationRightControllerActivated) ? VRTK_DeviceFinder.GetControllerAngularVelocity(rightControllerReference).y : 0f);
  355. RotateByAngle(leftControllerAngle + rightControllerAngle);
  356. }
  357. }
  358. protected virtual void RotateByAngle(float angle)
  359. {
  360. if (Mathf.Abs(angle) >= rotationActivationThreshold)
  361. {
  362. if (useOffsetTransform)
  363. {
  364. controllingTransform.RotateAround(offsetTransform.position, Vector3.up, angle * rotationMultiplier);
  365. }
  366. else
  367. {
  368. controllingTransform.Rotate(Vector3.up * (angle * rotationMultiplier));
  369. }
  370. }
  371. }
  372. protected virtual void Scale()
  373. {
  374. if (!scaleActivated)
  375. {
  376. return;
  377. }
  378. float currentDistance = GetControllerDistance();
  379. float distanceDelta = currentDistance - previousControllerDistance;
  380. if (Mathf.Abs(distanceDelta) >= scaleActivationThreshold)
  381. {
  382. controllingTransform.localScale += (Vector3.one * Time.deltaTime * Mathf.Sign(distanceDelta) * scaleMultiplier);
  383. controllingTransform.localScale = new Vector3(Mathf.Clamp(controllingTransform.localScale.x, minimumScale.x, maximumScale.x), Mathf.Clamp(controllingTransform.localScale.y, minimumScale.y, maximumScale.y), Mathf.Clamp(controllingTransform.localScale.z, minimumScale.z, maximumScale.z));
  384. }
  385. previousControllerDistance = currentDistance;
  386. }
  387. }
  388. }