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.

226 lines
9.3 KiB

  1. // Base Object Control Action|ObjectControlActions|25000
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. /// <summary>
  6. /// Provides a base that all object control actions can inherit from.
  7. /// </summary>
  8. /// <remarks>
  9. /// **Script Usage:**
  10. /// > This is an abstract class that is to be inherited to a concrete class that provides object control action functionality, therefore this script should not be directly used.
  11. /// </remarks>
  12. public abstract class VRTK_BaseObjectControlAction : MonoBehaviour
  13. {
  14. /// <summary>
  15. /// The axis to listen to changes on.
  16. /// </summary>
  17. public enum AxisListeners
  18. {
  19. /// <summary>
  20. /// Listen for changes on the horizontal X axis.
  21. /// </summary>
  22. XAxisChanged,
  23. /// <summary>
  24. /// Listen for changes on the vertical y axis.
  25. /// </summary>
  26. YAxisChanged
  27. }
  28. [Tooltip("The Object Control script to receive axis change events from.")]
  29. public VRTK_ObjectControl objectControlScript;
  30. [Tooltip("Determines which Object Control Axis event to listen to.")]
  31. public AxisListeners listenOnAxisChange;
  32. protected Collider centerCollider;
  33. protected Vector3 colliderCenter = Vector3.zero;
  34. protected float colliderRadius = 0f;
  35. protected float colliderHeight = 0f;
  36. protected Transform controlledTransform;
  37. protected Transform playArea;
  38. protected VRTK_BodyPhysics internalBodyPhysics;
  39. protected Vector3 playerHeadPositionBeforeRotation;
  40. protected Transform headsetTransform;
  41. protected bool validPlayerObject;
  42. protected abstract void Process(GameObject controlledGameObject, Transform directionDevice, Vector3 axisDirection, float axis, float deadzone, bool currentlyFalling, bool modifierActive);
  43. protected virtual void Awake()
  44. {
  45. VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
  46. }
  47. protected virtual void OnEnable()
  48. {
  49. playArea = VRTK_DeviceFinder.PlayAreaTransform();
  50. if (objectControlScript)
  51. {
  52. switch (listenOnAxisChange)
  53. {
  54. case AxisListeners.XAxisChanged:
  55. objectControlScript.XAxisChanged += AxisChanged;
  56. break;
  57. case AxisListeners.YAxisChanged:
  58. objectControlScript.YAxisChanged += AxisChanged;
  59. break;
  60. }
  61. }
  62. internalBodyPhysics = (internalBodyPhysics == null ? VRTK_SharedMethods.FindEvenInactiveComponent<VRTK_BodyPhysics>(true) : internalBodyPhysics);
  63. }
  64. protected virtual void OnDisable()
  65. {
  66. if (objectControlScript)
  67. {
  68. switch (listenOnAxisChange)
  69. {
  70. case AxisListeners.XAxisChanged:
  71. objectControlScript.XAxisChanged -= AxisChanged;
  72. break;
  73. case AxisListeners.YAxisChanged:
  74. objectControlScript.YAxisChanged -= AxisChanged;
  75. break;
  76. }
  77. }
  78. }
  79. protected virtual void OnDestroy()
  80. {
  81. VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
  82. }
  83. protected virtual void AxisChanged(object sender, ObjectControlEventArgs e)
  84. {
  85. Process(e.controlledGameObject, e.directionDevice, e.axisDirection, e.axis, e.deadzone, e.currentlyFalling, e.modifierActive);
  86. }
  87. protected virtual void RotateAroundPlayer(GameObject controlledGameObject, float angle)
  88. {
  89. Vector3 objectCenter = GetObjectCenter(controlledGameObject.transform);
  90. Vector3 objectPosition = controlledGameObject.transform.TransformPoint(objectCenter);
  91. controlledGameObject.transform.Rotate(Vector3.up, angle);
  92. objectPosition -= controlledGameObject.transform.TransformPoint(objectCenter);
  93. controlledGameObject.transform.position += objectPosition;
  94. }
  95. protected virtual void Blink(float blinkSpeed)
  96. {
  97. if (blinkSpeed > 0f)
  98. {
  99. VRTK_SDK_Bridge.HeadsetFade(Color.black, 0);
  100. ReleaseBlink(blinkSpeed);
  101. }
  102. }
  103. protected virtual void ReleaseBlink(float blinkSpeed)
  104. {
  105. VRTK_SDK_Bridge.HeadsetFade(Color.clear, blinkSpeed);
  106. }
  107. protected virtual Vector3 GetObjectCenter(Transform checkObject)
  108. {
  109. if (centerCollider == null || checkObject != controlledTransform)
  110. {
  111. controlledTransform = checkObject;
  112. if (checkObject == playArea)
  113. {
  114. bool centerColliderSet = false;
  115. if (internalBodyPhysics != null && internalBodyPhysics.GetBodyColliderContainer() != null)
  116. {
  117. CapsuleCollider playAreaCollider = internalBodyPhysics.GetBodyColliderContainer().GetComponent<CapsuleCollider>();
  118. centerCollider = playAreaCollider;
  119. if (playAreaCollider != null)
  120. {
  121. centerColliderSet = true;
  122. colliderRadius = playAreaCollider.radius;
  123. colliderHeight = playAreaCollider.height;
  124. colliderCenter = playAreaCollider.center;
  125. }
  126. }
  127. if (!centerColliderSet)
  128. {
  129. VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "PlayArea", "CapsuleCollider", "the same or child"));
  130. }
  131. }
  132. else
  133. {
  134. centerCollider = checkObject.GetComponentInChildren<Collider>();
  135. if (centerCollider == null)
  136. {
  137. VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "CheckObject", "Collider", "the same or child"));
  138. }
  139. colliderRadius = 0.1f;
  140. colliderHeight = 0.1f;
  141. }
  142. }
  143. return colliderCenter;
  144. }
  145. protected virtual int GetAxisDirection(float axis)
  146. {
  147. int axisDirection = 0;
  148. if (axis < 0)
  149. {
  150. axisDirection = -1;
  151. }
  152. else if (axis > 0)
  153. {
  154. axisDirection = 1;
  155. }
  156. return axisDirection;
  157. }
  158. protected virtual bool CanMove(VRTK_BodyPhysics givenBodyPhysics, Vector3 currentPosition, Vector3 proposedPosition)
  159. {
  160. if (givenBodyPhysics == null)
  161. {
  162. return true;
  163. }
  164. Vector3 proposedDirection = (proposedPosition - currentPosition).normalized;
  165. float distance = Vector3.Distance(currentPosition, proposedPosition);
  166. return !givenBodyPhysics.SweepCollision(proposedDirection, distance);
  167. }
  168. /// <summary>
  169. /// Since rotation scripts may rotate the game object '[CameraRig]' in order to rotate the player and the player's head does not always have the local position (0,0,0), the rotation will result in a position offset of player's head. The game object '[CameraRig]' will moved relativly to compensate that. Therefore it will save the player's head position in this method.
  170. /// Call 'CheckForPlayerAfterRotation()' to correct the player's head position offset after rotation.
  171. /// </summary>
  172. /// <param name="controlledGameObject"></param>
  173. protected virtual void CheckForPlayerBeforeRotation(GameObject controlledGameObject)
  174. {
  175. VRTK_PlayerObject playerObject = controlledGameObject.GetComponent<VRTK_PlayerObject>();
  176. if (headsetTransform == null)
  177. {
  178. headsetTransform = VRTK_DeviceFinder.HeadsetTransform();
  179. }
  180. validPlayerObject = (playerObject != null && playerObject.objectType == VRTK_PlayerObject.ObjectTypes.CameraRig && headsetTransform != null);
  181. if (validPlayerObject)
  182. {
  183. //Save the player's head position for use in method 'CheckForPlayerAfterRotation'.
  184. playerHeadPositionBeforeRotation = headsetTransform.position;
  185. }
  186. }
  187. /// <summary>
  188. /// Corrects the player's head position offset after rotation. Call 'CheckForPlayerBeforeRotation' before execute rotation.
  189. /// </summary>
  190. /// <param name="controlledGameObject"></param>
  191. protected virtual void CheckForPlayerAfterRotation(GameObject controlledGameObject)
  192. {
  193. //If necessary the player's head position will be corrected by translate the Gameobject [CameraRig] relativly.
  194. if (validPlayerObject)
  195. {
  196. controlledGameObject.transform.position += playerHeadPositionBeforeRotation - headsetTransform.position;
  197. //Prevents multiple calls of this method without call of 'CheckForPlayerBeforeRotation'.
  198. validPlayerObject = false;
  199. }
  200. }
  201. }
  202. }