// Controller Tooltips|Prefabs|0070
namespace VRTK
{
using UnityEngine;
///
/// Event Payload
///
/// The tooltip element being affected.
public struct ControllerTooltipsEventArgs
{
public VRTK_ControllerTooltips.TooltipButtons element;
}
///
/// Event Payload
///
/// this object
///
public delegate void ControllerTooltipsEventHandler(object sender, ControllerTooltipsEventArgs e);
///
/// Adds a collection of Object Tooltips to the Controller providing information to what the controller buttons may do.
///
///
/// **Prefab Usage:**
/// * Place the `VRTK/Prefabs/ControllerTooltips/ControllerTooltips` prefab as a child of the relevant controller script alias GameObject in the scene hierarchy.
/// * If no `Button Transform Settings` are provided in the inspector at Edit time then the button transforms will attempt to be set to the transforms of the current SDK default controller model.
/// * If one of the `Button Text Settings` text options are not provided, then the tooltip for that specific button will be hidden.
///
/// > There are a number of parameters that can be set on the Prefab which are provided by the `VRTK_ControllerTooltips` script which is applied to the prefab.
///
///
/// `VRTK/Examples/029_Controller_Tooltips` displays two cubes that have an object tooltip added to them along with tooltips that have been added to the controllers.
///
public class VRTK_ControllerTooltips : MonoBehaviour
{
public enum TooltipButtons
{
None,
TriggerTooltip,
GripTooltip,
TouchpadTooltip,
TouchpadTwoTooltip,
ButtonOneTooltip,
ButtonTwoTooltip,
StartMenuTooltip
}
[Header("Button Text Settings")]
[Tooltip("The text to display for the trigger button action.")]
public string triggerText;
[Tooltip("The text to display for the grip button action.")]
public string gripText;
[Tooltip("The text to display for the touchpad action.")]
public string touchpadText;
[Tooltip("The text to display for the touchpad two action.")]
public string touchpadTwoText;
[Tooltip("The text to display for button one action.")]
public string buttonOneText;
[Tooltip("The text to display for button two action.")]
public string buttonTwoText;
[Tooltip("The text to display for the start menu action.")]
public string startMenuText;
[Header("Tooltip Colour Settings")]
[Tooltip("The colour to use for the tooltip background container.")]
public Color tipBackgroundColor = Color.black;
[Tooltip("The colour to use for the text within the tooltip.")]
public Color tipTextColor = Color.white;
[Tooltip("The colour to use for the line between the tooltip and the relevant controller button.")]
public Color tipLineColor = Color.black;
[Header("Button Transform Settings")]
[Tooltip("The transform for the position of the trigger button on the controller.")]
public Transform trigger;
[Tooltip("The transform for the position of the grip button on the controller.")]
public Transform grip;
[Tooltip("The transform for the position of the touchpad button on the controller.")]
public Transform touchpad;
[Tooltip("The transform for the position of the touchpad two button on the controller.")]
public Transform touchpadTwo;
[Tooltip("The transform for the position of button one on the controller.")]
public Transform buttonOne;
[Tooltip("The transform for the position of button two on the controller.")]
public Transform buttonTwo;
[Tooltip("The transform for the position of the start menu on the controller.")]
public Transform startMenu;
[Header("Custom Settings")]
[Tooltip("The controller to read the controller events from. If this is blank then it will attempt to get a controller events script from the same or parent GameObject.")]
public VRTK_ControllerEvents controllerEvents;
[Tooltip("The headset controller aware script to use to see if the headset is looking at the controller. If this is blank then it will attempt to get a controller events script from the same or parent GameObject.")]
public VRTK_HeadsetControllerAware headsetControllerAware;
[Tooltip("If this is checked then the tooltips will be hidden when the headset is not looking at the controller.")]
public bool hideWhenNotInView = true;
[Header("Obsolete Settings")]
[System.Obsolete("`VRTK_ControllerTooltips.retryInitMaxTries` has been deprecated as tooltip initialisation now uses the `VRTK_TrackedController.ControllerModelAvailable` event.")]
[ObsoleteInspector]
public int retryInitMaxTries = 10;
[System.Obsolete("`VRTK_ControllerTooltips.retryInitCounter` has been deprecated as tooltip initialisation now uses the `VRTK_TrackedController.ControllerModelAvailable` event.")]
[ObsoleteInspector]
public float retryInitCounter = 0.1f;
///
/// Emitted when the controller tooltip is turned on.
///
public event ControllerTooltipsEventHandler ControllerTooltipOn;
///
/// Emitted when the controller tooltip is turned off.
///
public event ControllerTooltipsEventHandler ControllerTooltipOff;
protected TooltipButtons[] availableButtons = new TooltipButtons[0];
protected VRTK_ObjectTooltip[] buttonTooltips = new VRTK_ObjectTooltip[0];
protected bool[] tooltipStates = new bool[0];
protected bool overallState = true;
protected VRTK_TrackedController trackedController;
public virtual void OnControllerTooltipOn(ControllerTooltipsEventArgs e)
{
if (ControllerTooltipOn != null)
{
ControllerTooltipOn(this, e);
}
}
public virtual void OnControllerTooltipOff(ControllerTooltipsEventArgs e)
{
if (ControllerTooltipOff != null)
{
ControllerTooltipOff(this, e);
}
}
///
/// The Reset method reinitalises the tooltips on all of the controller elements.
///
public virtual void ResetTooltip()
{
InitialiseTips();
}
///
/// The UpdateText method allows the tooltip text on a specific controller element to be updated at runtime.
///
/// The specific controller element to change the tooltip text on.
/// A string containing the text to update the tooltip to display.
public virtual void UpdateText(TooltipButtons element, string newText)
{
switch (element)
{
case TooltipButtons.ButtonOneTooltip:
buttonOneText = newText;
break;
case TooltipButtons.ButtonTwoTooltip:
buttonTwoText = newText;
break;
case TooltipButtons.StartMenuTooltip:
startMenuText = newText;
break;
case TooltipButtons.GripTooltip:
gripText = newText;
break;
case TooltipButtons.TouchpadTooltip:
touchpadText = newText;
break;
case TooltipButtons.TouchpadTwoTooltip:
touchpadTwoText = newText;
break;
case TooltipButtons.TriggerTooltip:
triggerText = newText;
break;
}
ResetTooltip();
}
///
/// The ToggleTips method will display the controller tooltips if the state is `true` and will hide the controller tooltips if the state is `false`. An optional `element` can be passed to target a specific controller tooltip to toggle otherwise all tooltips are toggled.
///
/// The state of whether to display or hide the controller tooltips, true will display and false will hide.
/// The specific element to hide the tooltip on, if it is `TooltipButtons.None` then it will hide all tooltips. Optional parameter defaults to `TooltipButtons.None`
public virtual void ToggleTips(bool state, TooltipButtons element = TooltipButtons.None)
{
if (element == TooltipButtons.None)
{
overallState = state;
for (int i = 1; i < buttonTooltips.Length; i++)
{
if (buttonTooltips[i].displayText.Length > 0)
{
buttonTooltips[i].gameObject.SetActive(state);
}
}
}
else
{
if (buttonTooltips[(int)element].displayText.Length > 0)
{
buttonTooltips[(int)element].gameObject.SetActive(state);
}
}
EmitEvent(state, element);
}
protected virtual void Awake()
{
VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
InitButtonsArray();
}
protected virtual void OnEnable()
{
controllerEvents = (controllerEvents != null ? controllerEvents : GetComponentInParent());
InitButtonsArray();
InitListeners();
ResetTooltip();
}
protected virtual void OnDisable()
{
if (controllerEvents != null)
{
controllerEvents.ControllerEnabled -= DoControllerEnabled;
controllerEvents.ControllerVisible -= DoControllerVisible;
controllerEvents.ControllerHidden -= DoControllerInvisible;
controllerEvents.ControllerModelAvailable -= DoControllerModelAvailable;
}
else if (trackedController != null)
{
trackedController.ControllerModelAvailable -= TrackedControllerDoControllerModelAvailable;
}
if (headsetControllerAware != null)
{
headsetControllerAware.ControllerGlanceEnter -= DoGlanceEnterController;
headsetControllerAware.ControllerGlanceExit -= DoGlanceExitController;
}
}
protected virtual void OnDestroy()
{
VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
}
protected virtual void EmitEvent(bool state, TooltipButtons element)
{
ControllerTooltipsEventArgs e;
e.element = element;
if (state)
{
OnControllerTooltipOn(e);
}
else
{
OnControllerTooltipOff(e);
}
}
protected virtual void InitButtonsArray()
{
availableButtons = new TooltipButtons[]
{
TooltipButtons.None,
TooltipButtons.TriggerTooltip,
TooltipButtons.GripTooltip,
TooltipButtons.TouchpadTooltip,
TooltipButtons.TouchpadTwoTooltip,
TooltipButtons.ButtonOneTooltip,
TooltipButtons.ButtonTwoTooltip,
TooltipButtons.StartMenuTooltip
};
buttonTooltips = new VRTK_ObjectTooltip[availableButtons.Length];
tooltipStates = new bool[availableButtons.Length];
for (int i = 1; i < availableButtons.Length; i++)
{
buttonTooltips[i] = transform.Find(availableButtons[i].ToString()).GetComponent();
}
}
protected virtual void InitListeners()
{
if (controllerEvents != null)
{
controllerEvents.ControllerEnabled += DoControllerEnabled;
controllerEvents.ControllerVisible += DoControllerVisible;
controllerEvents.ControllerHidden += DoControllerInvisible;
controllerEvents.ControllerModelAvailable += DoControllerModelAvailable;
}
else
{
trackedController = GetComponentInParent();
if (trackedController != null)
{
trackedController.ControllerModelAvailable += TrackedControllerDoControllerModelAvailable;
}
}
headsetControllerAware = (headsetControllerAware != null ? headsetControllerAware : FindObjectOfType());
if (headsetControllerAware != null)
{
headsetControllerAware.ControllerGlanceEnter += DoGlanceEnterController;
headsetControllerAware.ControllerGlanceExit += DoGlanceExitController;
ToggleTips(false);
}
}
protected virtual void DoControllerEnabled(object sender, ControllerInteractionEventArgs e)
{
if (controllerEvents != null)
{
GameObject actualController = VRTK_DeviceFinder.GetActualController(controllerEvents.gameObject);
if (actualController != null && actualController.activeInHierarchy)
{
ResetTooltip();
}
}
}
protected virtual void DoControllerVisible(object sender, ControllerInteractionEventArgs e)
{
for (int i = 0; i < availableButtons.Length; i++)
{
ToggleTips(tooltipStates[i], availableButtons[i]);
}
}
protected virtual void DoControllerInvisible(object sender, ControllerInteractionEventArgs e)
{
for (int i = 1; i < buttonTooltips.Length; i++)
{
tooltipStates[i] = buttonTooltips[i].gameObject.activeSelf;
}
ToggleTips(false);
}
protected virtual void DoControllerModelAvailable(object sender, ControllerInteractionEventArgs e)
{
ResetTooltip();
}
protected virtual void TrackedControllerDoControllerModelAvailable(object sender, VRTKTrackedControllerEventArgs e)
{
ResetTooltip();
}
protected virtual void DoGlanceEnterController(object sender, HeadsetControllerAwareEventArgs e)
{
if (controllerEvents != null && hideWhenNotInView)
{
VRTK_ControllerReference checkControllerReference = VRTK_ControllerReference.GetControllerReference(controllerEvents.gameObject);
if (checkControllerReference == e.controllerReference)
{
ToggleTips(true);
}
}
}
protected virtual void DoGlanceExitController(object sender, HeadsetControllerAwareEventArgs e)
{
if (controllerEvents != null && hideWhenNotInView)
{
VRTK_ControllerReference checkControllerReference = VRTK_ControllerReference.GetControllerReference(controllerEvents.gameObject);
if (checkControllerReference == e.controllerReference)
{
ToggleTips(false);
}
}
}
protected virtual void InitialiseTips()
{
VRTK_ObjectTooltip[] tooltips = GetComponentsInChildren(true);
for (int i = 0; i < tooltips.Length; i++)
{
VRTK_ObjectTooltip tooltip = tooltips[i];
string tipText = "";
Transform tipTransform = null;
switch (tooltip.name.Replace("Tooltip", "").ToLower())
{
case "trigger":
tipText = triggerText;
tipTransform = GetTransform(trigger, SDK_BaseController.ControllerElements.Trigger);
break;
case "grip":
tipText = gripText;
tipTransform = GetTransform(grip, SDK_BaseController.ControllerElements.GripLeft);
break;
case "touchpad":
tipText = touchpadText;
tipTransform = GetTransform(touchpad, SDK_BaseController.ControllerElements.Touchpad);
break;
case "touchpadtwo":
tipText = touchpadTwoText;
tipTransform = GetTransform(touchpadTwo, SDK_BaseController.ControllerElements.TouchpadTwo);
break;
case "buttonone":
tipText = buttonOneText;
tipTransform = GetTransform(buttonOne, SDK_BaseController.ControllerElements.ButtonOne);
break;
case "buttontwo":
tipText = buttonTwoText;
tipTransform = GetTransform(buttonTwo, SDK_BaseController.ControllerElements.ButtonTwo);
break;
case "startmenu":
tipText = startMenuText;
tipTransform = GetTransform(startMenu, SDK_BaseController.ControllerElements.StartMenu);
break;
}
tooltip.displayText = tipText;
tooltip.drawLineTo = tipTransform;
tooltip.containerColor = tipBackgroundColor;
tooltip.fontColor = tipTextColor;
tooltip.lineColor = tipLineColor;
tooltip.ResetTooltip();
if (tipTransform == null || tipText.Trim().Length == 0)
{
tooltip.gameObject.SetActive(false);
}
}
if (headsetControllerAware == null || !hideWhenNotInView)
{
ToggleTips(overallState);
}
}
protected virtual Transform GetTransform(Transform setTransform, SDK_BaseController.ControllerElements findElement)
{
Transform returnTransform = null;
if (setTransform != null)
{
returnTransform = setTransform;
}
else if (controllerEvents != null)
{
GameObject modelController = VRTK_DeviceFinder.GetModelAliasController(controllerEvents.gameObject);
if (modelController != null && modelController.activeInHierarchy)
{
SDK_BaseController.ControllerHand controllerHand = VRTK_DeviceFinder.GetControllerHand(controllerEvents.gameObject);
string elementPath = VRTK_SDK_Bridge.GetControllerElementPath(findElement, controllerHand, true);
returnTransform = (elementPath != null ? modelController.transform.Find(elementPath) : null);
}
}
return returnTransform;
}
}
}