|
|
- // Base Object Control Action|ObjectControlActions|25000
- namespace VRTK
- {
- using UnityEngine;
-
- /// <summary>
- /// Provides a base that all object control actions can inherit from.
- /// </summary>
- /// <remarks>
- /// **Script Usage:**
- /// > 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.
- /// </remarks>
- public abstract class VRTK_BaseObjectControlAction : MonoBehaviour
- {
- /// <summary>
- /// The axis to listen to changes on.
- /// </summary>
- public enum AxisListeners
- {
- /// <summary>
- /// Listen for changes on the horizontal X axis.
- /// </summary>
- XAxisChanged,
- /// <summary>
- /// Listen for changes on the vertical y axis.
- /// </summary>
- YAxisChanged
- }
-
- [Tooltip("The Object Control script to receive axis change events from.")]
- public VRTK_ObjectControl objectControlScript;
- [Tooltip("Determines which Object Control Axis event to listen to.")]
- public AxisListeners listenOnAxisChange;
-
- protected Collider centerCollider;
- protected Vector3 colliderCenter = Vector3.zero;
- protected float colliderRadius = 0f;
- protected float colliderHeight = 0f;
- protected Transform controlledTransform;
- protected Transform playArea;
- protected VRTK_BodyPhysics internalBodyPhysics;
-
- protected Vector3 playerHeadPositionBeforeRotation;
- protected Transform headsetTransform;
- protected bool validPlayerObject;
-
- protected abstract void Process(GameObject controlledGameObject, Transform directionDevice, Vector3 axisDirection, float axis, float deadzone, bool currentlyFalling, bool modifierActive);
-
- protected virtual void Awake()
- {
- VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
- }
-
- protected virtual void OnEnable()
- {
- playArea = VRTK_DeviceFinder.PlayAreaTransform();
- if (objectControlScript)
- {
- switch (listenOnAxisChange)
- {
- case AxisListeners.XAxisChanged:
- objectControlScript.XAxisChanged += AxisChanged;
- break;
- case AxisListeners.YAxisChanged:
- objectControlScript.YAxisChanged += AxisChanged;
- break;
- }
- }
- internalBodyPhysics = (internalBodyPhysics == null ? VRTK_SharedMethods.FindEvenInactiveComponent<VRTK_BodyPhysics>(true) : internalBodyPhysics);
- }
-
- protected virtual void OnDisable()
- {
- if (objectControlScript)
- {
- switch (listenOnAxisChange)
- {
- case AxisListeners.XAxisChanged:
- objectControlScript.XAxisChanged -= AxisChanged;
- break;
- case AxisListeners.YAxisChanged:
- objectControlScript.YAxisChanged -= AxisChanged;
- break;
- }
- }
- }
-
- protected virtual void OnDestroy()
- {
- VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
- }
-
- protected virtual void AxisChanged(object sender, ObjectControlEventArgs e)
- {
- Process(e.controlledGameObject, e.directionDevice, e.axisDirection, e.axis, e.deadzone, e.currentlyFalling, e.modifierActive);
- }
-
- protected virtual void RotateAroundPlayer(GameObject controlledGameObject, float angle)
- {
- Vector3 objectCenter = GetObjectCenter(controlledGameObject.transform);
- Vector3 objectPosition = controlledGameObject.transform.TransformPoint(objectCenter);
- controlledGameObject.transform.Rotate(Vector3.up, angle);
- objectPosition -= controlledGameObject.transform.TransformPoint(objectCenter);
- controlledGameObject.transform.position += objectPosition;
- }
-
- protected virtual void Blink(float blinkSpeed)
- {
- if (blinkSpeed > 0f)
- {
- VRTK_SDK_Bridge.HeadsetFade(Color.black, 0);
- ReleaseBlink(blinkSpeed);
- }
- }
-
- protected virtual void ReleaseBlink(float blinkSpeed)
- {
- VRTK_SDK_Bridge.HeadsetFade(Color.clear, blinkSpeed);
- }
-
- protected virtual Vector3 GetObjectCenter(Transform checkObject)
- {
- if (centerCollider == null || checkObject != controlledTransform)
- {
- controlledTransform = checkObject;
-
- if (checkObject == playArea)
- {
- bool centerColliderSet = false;
-
- if (internalBodyPhysics != null && internalBodyPhysics.GetBodyColliderContainer() != null)
- {
- CapsuleCollider playAreaCollider = internalBodyPhysics.GetBodyColliderContainer().GetComponent<CapsuleCollider>();
- centerCollider = playAreaCollider;
- if (playAreaCollider != null)
- {
- centerColliderSet = true;
- colliderRadius = playAreaCollider.radius;
- colliderHeight = playAreaCollider.height;
- colliderCenter = playAreaCollider.center;
- }
- }
-
- if (!centerColliderSet)
- {
- VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "PlayArea", "CapsuleCollider", "the same or child"));
- }
- }
- else
- {
- centerCollider = checkObject.GetComponentInChildren<Collider>();
- if (centerCollider == null)
- {
- VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "CheckObject", "Collider", "the same or child"));
- }
- colliderRadius = 0.1f;
- colliderHeight = 0.1f;
- }
- }
-
- return colliderCenter;
- }
-
- protected virtual int GetAxisDirection(float axis)
- {
- int axisDirection = 0;
- if (axis < 0)
- {
- axisDirection = -1;
- }
- else if (axis > 0)
- {
- axisDirection = 1;
- }
-
- return axisDirection;
- }
-
- protected virtual bool CanMove(VRTK_BodyPhysics givenBodyPhysics, Vector3 currentPosition, Vector3 proposedPosition)
- {
- if (givenBodyPhysics == null)
- {
- return true;
- }
-
- Vector3 proposedDirection = (proposedPosition - currentPosition).normalized;
- float distance = Vector3.Distance(currentPosition, proposedPosition);
- return !givenBodyPhysics.SweepCollision(proposedDirection, distance);
- }
-
- /// <summary>
- /// 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.
- /// Call 'CheckForPlayerAfterRotation()' to correct the player's head position offset after rotation.
- /// </summary>
- /// <param name="controlledGameObject"></param>
- protected virtual void CheckForPlayerBeforeRotation(GameObject controlledGameObject)
- {
- VRTK_PlayerObject playerObject = controlledGameObject.GetComponent<VRTK_PlayerObject>();
- if (headsetTransform == null)
- {
- headsetTransform = VRTK_DeviceFinder.HeadsetTransform();
- }
- validPlayerObject = (playerObject != null && playerObject.objectType == VRTK_PlayerObject.ObjectTypes.CameraRig && headsetTransform != null);
- if (validPlayerObject)
- {
- //Save the player's head position for use in method 'CheckForPlayerAfterRotation'.
- playerHeadPositionBeforeRotation = headsetTransform.position;
- }
- }
-
- /// <summary>
- /// Corrects the player's head position offset after rotation. Call 'CheckForPlayerBeforeRotation' before execute rotation.
- /// </summary>
- /// <param name="controlledGameObject"></param>
- protected virtual void CheckForPlayerAfterRotation(GameObject controlledGameObject)
- {
- //If necessary the player's head position will be corrected by translate the Gameobject [CameraRig] relativly.
- if (validPlayerObject)
- {
- controlledGameObject.transform.position += playerHeadPositionBeforeRotation - headsetTransform.position;
-
- //Prevents multiple calls of this method without call of 'CheckForPlayerBeforeRotation'.
- validPlayerObject = false;
- }
- }
- }
- }
|