ControllerButtonHints.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Displays text and button hints on the controllers
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine.UI;
  10. using System.Text;
  11. namespace Valve.VR.InteractionSystem
  12. {
  13. //-------------------------------------------------------------------------
  14. public class ControllerButtonHints : MonoBehaviour
  15. {
  16. public Material controllerMaterial;
  17. public Color flashColor = new Color( 1.0f, 0.557f, 0.0f );
  18. public GameObject textHintPrefab;
  19. public SteamVR_Action_Vibration hapticFlash = SteamVR_Input.GetAction<SteamVR_Action_Vibration>("Haptic");
  20. [Header( "Debug" )]
  21. public bool debugHints = false;
  22. private SteamVR_RenderModel renderModel;
  23. private Player player;
  24. private List<MeshRenderer> renderers = new List<MeshRenderer>();
  25. private List<MeshRenderer> flashingRenderers = new List<MeshRenderer>();
  26. private float startTime;
  27. private float tickCount;
  28. private enum OffsetType
  29. {
  30. Up,
  31. Right,
  32. Forward,
  33. Back
  34. }
  35. //Info for each of the buttons
  36. private class ActionHintInfo
  37. {
  38. public string componentName;
  39. public List<MeshRenderer> renderers;
  40. public Transform localTransform;
  41. //Text hint
  42. public GameObject textHintObject;
  43. public Transform textStartAnchor;
  44. public Transform textEndAnchor;
  45. public Vector3 textEndOffsetDir;
  46. public Transform canvasOffset;
  47. public Text text;
  48. public TextMesh textMesh;
  49. public Canvas textCanvas;
  50. public LineRenderer line;
  51. public float distanceFromCenter;
  52. public bool textHintActive = false;
  53. }
  54. private Dictionary<ISteamVR_Action_In_Source, ActionHintInfo> actionHintInfos;
  55. private Transform textHintParent;
  56. private int colorID;
  57. public bool initialized { get; private set; }
  58. private Vector3 centerPosition = Vector3.zero;
  59. SteamVR_Events.Action renderModelLoadedAction;
  60. protected SteamVR_Input_Sources inputSource;
  61. //-------------------------------------------------
  62. void Awake()
  63. {
  64. renderModelLoadedAction = SteamVR_Events.RenderModelLoadedAction( OnRenderModelLoaded );
  65. colorID = Shader.PropertyToID( "_Color" );
  66. }
  67. //-------------------------------------------------
  68. void Start()
  69. {
  70. player = Player.instance;
  71. }
  72. //-------------------------------------------------
  73. private void HintDebugLog( string msg )
  74. {
  75. if ( debugHints )
  76. {
  77. Debug.Log("<b>[SteamVR Interaction]</b> Hints: " + msg );
  78. }
  79. }
  80. //-------------------------------------------------
  81. void OnEnable()
  82. {
  83. renderModelLoadedAction.enabled = true;
  84. }
  85. //-------------------------------------------------
  86. void OnDisable()
  87. {
  88. renderModelLoadedAction.enabled = false;
  89. Clear();
  90. }
  91. //-------------------------------------------------
  92. private void OnParentHandInputFocusLost()
  93. {
  94. //Hide all the hints when the controller is no longer the primary attached object
  95. HideAllButtonHints();
  96. HideAllText();
  97. }
  98. public virtual void SetInputSource(SteamVR_Input_Sources newInputSource)
  99. {
  100. inputSource = newInputSource;
  101. if (renderModel != null)
  102. renderModel.SetInputSource(newInputSource);
  103. }
  104. //-------------------------------------------------
  105. // Gets called when the hand has been initialized and a render model has been set
  106. //-------------------------------------------------
  107. private void OnHandInitialized(int deviceIndex)
  108. {
  109. //Create a new render model for the controller hints
  110. renderModel = new GameObject( "SteamVR_RenderModel" ).AddComponent<SteamVR_RenderModel>();
  111. renderModel.transform.parent = transform;
  112. renderModel.transform.localPosition = Vector3.zero;
  113. renderModel.transform.localRotation = Quaternion.identity;
  114. renderModel.transform.localScale = Vector3.one;
  115. renderModel.SetInputSource(inputSource);
  116. renderModel.SetDeviceIndex(deviceIndex);
  117. if ( !initialized )
  118. {
  119. //The controller hint render model needs to be active to get accurate transforms for all the individual components
  120. renderModel.gameObject.SetActive( true );
  121. }
  122. }
  123. private Dictionary<string, Transform> componentTransformMap = new Dictionary<string, Transform>();
  124. //-------------------------------------------------
  125. void OnRenderModelLoaded(SteamVR_RenderModel renderModel, bool succeess)
  126. {
  127. //Only initialize when the render model for the controller hints has been loaded
  128. if (renderModel == this.renderModel)
  129. {
  130. //Debug.Log("<b>[SteamVR Interaction]</b> OnRenderModelLoaded: " + this.renderModel.renderModelName);
  131. if (initialized)
  132. {
  133. Destroy(textHintParent.gameObject);
  134. componentTransformMap.Clear();
  135. flashingRenderers.Clear();
  136. }
  137. renderModel.SetMeshRendererState(false);
  138. StartCoroutine(DoInitialize(renderModel));
  139. }
  140. }
  141. private IEnumerator DoInitialize(SteamVR_RenderModel renderModel)
  142. {
  143. while (renderModel.initializedAttachPoints == false)
  144. yield return null;
  145. textHintParent = new GameObject("Text Hints").transform;
  146. textHintParent.SetParent(this.transform);
  147. textHintParent.localPosition = Vector3.zero;
  148. textHintParent.localRotation = Quaternion.identity;
  149. textHintParent.localScale = Vector3.one;
  150. //Get the button mask for each component of the render model
  151. var renderModels = OpenVR.RenderModels;
  152. if (renderModels != null)
  153. {
  154. string renderModelDebug = "";
  155. if (debugHints)
  156. renderModelDebug = "Components for render model " + renderModel.index;
  157. for (int childIndex = 0; childIndex < renderModel.transform.childCount; childIndex++)
  158. {
  159. Transform child = renderModel.transform.GetChild(childIndex);
  160. if (componentTransformMap.ContainsKey(child.name))
  161. {
  162. if (debugHints)
  163. renderModelDebug += "\n\t! Child component already exists with name: " + child.name;
  164. }
  165. else
  166. componentTransformMap.Add(child.name, child);
  167. if (debugHints)
  168. renderModelDebug += "\n\t" + child.name + ".";
  169. }
  170. //Uncomment to show the button mask for each component of the render model
  171. HintDebugLog(renderModelDebug);
  172. }
  173. actionHintInfos = new Dictionary<ISteamVR_Action_In_Source, ActionHintInfo>();
  174. for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsNonPoseNonSkeletonIn.Length; actionIndex++)
  175. {
  176. ISteamVR_Action_In action = SteamVR_Input.actionsNonPoseNonSkeletonIn[actionIndex];
  177. if (action.GetActive(inputSource))
  178. CreateAndAddButtonInfo(action, inputSource);
  179. }
  180. ComputeTextEndTransforms();
  181. initialized = true;
  182. //Set the controller hints render model to not active
  183. renderModel.SetMeshRendererState(true);
  184. renderModel.gameObject.SetActive(false);
  185. }
  186. //-------------------------------------------------
  187. private void CreateAndAddButtonInfo(ISteamVR_Action_In action, SteamVR_Input_Sources inputSource)
  188. {
  189. Transform buttonTransform = null;
  190. List<MeshRenderer> buttonRenderers = new List<MeshRenderer>();
  191. StringBuilder buttonDebug = new StringBuilder();
  192. buttonDebug.Append("Looking for action: ");
  193. buttonDebug.AppendLine(action.GetShortName());
  194. buttonDebug.Append("Action localized origin: ");
  195. buttonDebug.AppendLine(action.GetLocalizedOrigin(inputSource));
  196. string actionComponentName = action.GetRenderModelComponentName(inputSource);
  197. if (componentTransformMap.ContainsKey(actionComponentName))
  198. {
  199. buttonDebug.AppendLine(string.Format("Found component: {0} for {1}", actionComponentName, action.GetShortName()));
  200. Transform componentTransform = componentTransformMap[actionComponentName];
  201. buttonTransform = componentTransform;
  202. buttonDebug.AppendLine(string.Format("Found componentTransform: {0}. buttonTransform: {1}", componentTransform, buttonTransform));
  203. buttonRenderers.AddRange(componentTransform.GetComponentsInChildren<MeshRenderer>());
  204. }
  205. else
  206. {
  207. buttonDebug.AppendLine(string.Format("Can't find component transform for action: {0}. Component name: \"{1}\"", action.GetShortName(), actionComponentName));
  208. }
  209. buttonDebug.AppendLine(string.Format("Found {0} renderers for {1}", buttonRenderers.Count, action.GetShortName()));
  210. foreach ( MeshRenderer renderer in buttonRenderers )
  211. {
  212. buttonDebug.Append("\t");
  213. buttonDebug.AppendLine(renderer.name);
  214. }
  215. HintDebugLog( buttonDebug.ToString() );
  216. if ( buttonTransform == null )
  217. {
  218. HintDebugLog( "Couldn't find buttonTransform for " + action.GetShortName());
  219. return;
  220. }
  221. ActionHintInfo hintInfo = new ActionHintInfo();
  222. actionHintInfos.Add( action, hintInfo );
  223. hintInfo.componentName = buttonTransform.name;
  224. hintInfo.renderers = buttonRenderers;
  225. //Get the local transform for the button
  226. for (int childIndex = 0; childIndex < buttonTransform.childCount; childIndex++)
  227. {
  228. Transform child = buttonTransform.GetChild(childIndex);
  229. if (child.name == SteamVR_RenderModel.k_localTransformName)
  230. hintInfo.localTransform = child;
  231. }
  232. OffsetType offsetType = OffsetType.Right;
  233. /*
  234. switch ( buttonID )
  235. {
  236. case EVRButtonId.k_EButton_SteamVR_Trigger:
  237. {
  238. offsetType = OffsetType.Right;
  239. }
  240. break;
  241. case EVRButtonId.k_EButton_ApplicationMenu:
  242. {
  243. offsetType = OffsetType.Right;
  244. }
  245. break;
  246. case EVRButtonId.k_EButton_System:
  247. {
  248. offsetType = OffsetType.Right;
  249. }
  250. break;
  251. case Valve.VR.EVRButtonId.k_EButton_Grip:
  252. {
  253. offsetType = OffsetType.Forward;
  254. }
  255. break;
  256. case Valve.VR.EVRButtonId.k_EButton_SteamVR_Touchpad:
  257. {
  258. offsetType = OffsetType.Up;
  259. }
  260. break;
  261. }
  262. */
  263. //Offset for the text end transform
  264. switch ( offsetType )
  265. {
  266. case OffsetType.Forward:
  267. hintInfo.textEndOffsetDir = hintInfo.localTransform.forward;
  268. break;
  269. case OffsetType.Back:
  270. hintInfo.textEndOffsetDir = -hintInfo.localTransform.forward;
  271. break;
  272. case OffsetType.Right:
  273. hintInfo.textEndOffsetDir = hintInfo.localTransform.right;
  274. break;
  275. case OffsetType.Up:
  276. hintInfo.textEndOffsetDir = hintInfo.localTransform.up;
  277. break;
  278. }
  279. //Create the text hint object
  280. Vector3 hintStartPos = hintInfo.localTransform.position + ( hintInfo.localTransform.forward * 0.01f );
  281. hintInfo.textHintObject = GameObject.Instantiate( textHintPrefab, hintStartPos, Quaternion.identity ) as GameObject;
  282. hintInfo.textHintObject.name = "Hint_" + hintInfo.componentName + "_Start";
  283. hintInfo.textHintObject.transform.SetParent( textHintParent );
  284. hintInfo.textHintObject.layer = gameObject.layer;
  285. hintInfo.textHintObject.tag = gameObject.tag;
  286. //Get all the relevant child objects
  287. hintInfo.textStartAnchor = hintInfo.textHintObject.transform.Find( "Start" );
  288. hintInfo.textEndAnchor = hintInfo.textHintObject.transform.Find( "End" );
  289. hintInfo.canvasOffset = hintInfo.textHintObject.transform.Find( "CanvasOffset" );
  290. hintInfo.line = hintInfo.textHintObject.transform.Find( "Line" ).GetComponent<LineRenderer>();
  291. hintInfo.textCanvas = hintInfo.textHintObject.GetComponentInChildren<Canvas>();
  292. hintInfo.text = hintInfo.textCanvas.GetComponentInChildren<Text>();
  293. hintInfo.textMesh = hintInfo.textCanvas.GetComponentInChildren<TextMesh>();
  294. hintInfo.textHintObject.SetActive( false );
  295. hintInfo.textStartAnchor.position = hintStartPos;
  296. if ( hintInfo.text != null )
  297. {
  298. hintInfo.text.text = hintInfo.componentName;
  299. }
  300. if ( hintInfo.textMesh != null )
  301. {
  302. hintInfo.textMesh.text = hintInfo.componentName;
  303. }
  304. centerPosition += hintInfo.textStartAnchor.position;
  305. // Scale hint components to match player size
  306. hintInfo.textCanvas.transform.localScale = Vector3.Scale( hintInfo.textCanvas.transform.localScale, player.transform.localScale );
  307. hintInfo.textStartAnchor.transform.localScale = Vector3.Scale( hintInfo.textStartAnchor.transform.localScale, player.transform.localScale );
  308. hintInfo.textEndAnchor.transform.localScale = Vector3.Scale( hintInfo.textEndAnchor.transform.localScale, player.transform.localScale );
  309. hintInfo.line.transform.localScale = Vector3.Scale( hintInfo.line.transform.localScale, player.transform.localScale );
  310. }
  311. //-------------------------------------------------
  312. private void ComputeTextEndTransforms()
  313. {
  314. //This is done as a separate step after all the ButtonHintInfos have been initialized
  315. //to make the text hints fan out appropriately based on the button's position on the controller.
  316. centerPosition /= actionHintInfos.Count;
  317. float maxDistanceFromCenter = 0.0f;
  318. foreach ( var hintInfo in actionHintInfos )
  319. {
  320. hintInfo.Value.distanceFromCenter = Vector3.Distance( hintInfo.Value.textStartAnchor.position, centerPosition );
  321. if ( hintInfo.Value.distanceFromCenter > maxDistanceFromCenter )
  322. {
  323. maxDistanceFromCenter = hintInfo.Value.distanceFromCenter;
  324. }
  325. }
  326. foreach ( var hintInfo in actionHintInfos )
  327. {
  328. Vector3 centerToButton = hintInfo.Value.textStartAnchor.position - centerPosition;
  329. centerToButton.Normalize();
  330. centerToButton = Vector3.Project( centerToButton, renderModel.transform.forward );
  331. //Spread out the text end positions based on the distance from the center
  332. float t = hintInfo.Value.distanceFromCenter / maxDistanceFromCenter;
  333. float scale = hintInfo.Value.distanceFromCenter * Mathf.Pow( 2, 10 * ( t - 1.0f ) ) * 20.0f;
  334. //Flip the direction of the end pos based on which hand this is
  335. float endPosOffset = 0.1f;
  336. Vector3 hintEndPos = hintInfo.Value.textStartAnchor.position + ( hintInfo.Value.textEndOffsetDir * endPosOffset ) + ( centerToButton * scale * 0.1f );
  337. if (SteamVR_Utils.IsValid(hintEndPos))
  338. {
  339. hintInfo.Value.textEndAnchor.position = hintEndPos;
  340. hintInfo.Value.canvasOffset.position = hintEndPos;
  341. }
  342. else
  343. {
  344. Debug.LogWarning("<b>[SteamVR Interaction]</b> Invalid end position for: " + hintInfo.Value.textStartAnchor.name, hintInfo.Value.textStartAnchor.gameObject);
  345. }
  346. hintInfo.Value.canvasOffset.localRotation = Quaternion.identity;
  347. }
  348. }
  349. //-------------------------------------------------
  350. private void ShowButtonHint( params ISteamVR_Action_In_Source[] actions )
  351. {
  352. renderModel.gameObject.SetActive( true );
  353. renderModel.GetComponentsInChildren<MeshRenderer>( renderers );
  354. for ( int i = 0; i < renderers.Count; i++ )
  355. {
  356. Texture mainTexture = renderers[i].material.mainTexture;
  357. renderers[i].sharedMaterial = controllerMaterial;
  358. renderers[i].material.mainTexture = mainTexture;
  359. // This is to poke unity into setting the correct render queue for the model
  360. renderers[i].material.renderQueue = controllerMaterial.shader.renderQueue;
  361. }
  362. for ( int i = 0; i < actions.Length; i++ )
  363. {
  364. if ( actionHintInfos.ContainsKey( actions[i] ) )
  365. {
  366. ActionHintInfo hintInfo = actionHintInfos[actions[i]];
  367. foreach ( MeshRenderer renderer in hintInfo.renderers )
  368. {
  369. if ( !flashingRenderers.Contains( renderer ) )
  370. {
  371. flashingRenderers.Add( renderer );
  372. }
  373. }
  374. }
  375. }
  376. startTime = Time.realtimeSinceStartup;
  377. tickCount = 0.0f;
  378. }
  379. //-------------------------------------------------
  380. private void HideAllButtonHints()
  381. {
  382. Clear();
  383. if (renderModel != null && renderModel.gameObject != null)
  384. renderModel.gameObject.SetActive( false );
  385. }
  386. //-------------------------------------------------
  387. private void HideButtonHint( params ISteamVR_Action_In_Source[] actions )
  388. {
  389. Color baseColor = controllerMaterial.GetColor( colorID );
  390. for ( int i = 0; i < actions.Length; i++ )
  391. {
  392. if ( actionHintInfos.ContainsKey(actions[i] ) )
  393. {
  394. ActionHintInfo hintInfo = actionHintInfos[actions[i]];
  395. foreach ( MeshRenderer renderer in hintInfo.renderers )
  396. {
  397. renderer.material.color = baseColor;
  398. flashingRenderers.Remove( renderer );
  399. }
  400. }
  401. }
  402. if ( flashingRenderers.Count == 0 )
  403. {
  404. renderModel.gameObject.SetActive( false );
  405. }
  406. }
  407. //-------------------------------------------------
  408. private bool IsButtonHintActive(ISteamVR_Action_In_Source action )
  409. {
  410. if ( actionHintInfos.ContainsKey(action) )
  411. {
  412. ActionHintInfo hintInfo = actionHintInfos[action];
  413. foreach ( MeshRenderer buttonRenderer in hintInfo.renderers )
  414. {
  415. if ( flashingRenderers.Contains( buttonRenderer ) )
  416. {
  417. return true;
  418. }
  419. }
  420. }
  421. return false;
  422. }
  423. //-------------------------------------------------
  424. private IEnumerator TestButtonHints()
  425. {
  426. while ( true )
  427. {
  428. for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsNonPoseNonSkeletonIn.Length; actionIndex++)
  429. {
  430. ISteamVR_Action_In action = SteamVR_Input.actionsNonPoseNonSkeletonIn[actionIndex];
  431. if (action.GetActive(inputSource))
  432. {
  433. ShowButtonHint(action);
  434. yield return new WaitForSeconds(1.0f);
  435. }
  436. yield return null;
  437. }
  438. }
  439. }
  440. //-------------------------------------------------
  441. private IEnumerator TestTextHints()
  442. {
  443. while ( true )
  444. {
  445. for (int actionIndex = 0; actionIndex < SteamVR_Input.actionsNonPoseNonSkeletonIn.Length; actionIndex++)
  446. {
  447. ISteamVR_Action_In action = SteamVR_Input.actionsNonPoseNonSkeletonIn[actionIndex];
  448. if (action.GetActive(inputSource))
  449. {
  450. ShowText(action, action.GetShortName());
  451. yield return new WaitForSeconds(3.0f);
  452. }
  453. yield return null;
  454. }
  455. HideAllText();
  456. yield return new WaitForSeconds( 3.0f );
  457. }
  458. }
  459. //-------------------------------------------------
  460. void Update()
  461. {
  462. if ( renderModel != null && renderModel.gameObject.activeInHierarchy && flashingRenderers.Count > 0 )
  463. {
  464. Color baseColor = controllerMaterial.GetColor( colorID );
  465. float flash = ( Time.realtimeSinceStartup - startTime ) * Mathf.PI * 2.0f;
  466. flash = Mathf.Cos( flash );
  467. flash = Util.RemapNumberClamped( flash, -1.0f, 1.0f, 0.0f, 1.0f );
  468. float ticks = ( Time.realtimeSinceStartup - startTime );
  469. if ( ticks - tickCount > 1.0f )
  470. {
  471. tickCount += 1.0f;
  472. hapticFlash.Execute(0, 0.005f, 0.005f, 1, inputSource);
  473. }
  474. for ( int i = 0; i < flashingRenderers.Count; i++ )
  475. {
  476. Renderer r = flashingRenderers[i];
  477. r.material.SetColor( colorID, Color.Lerp( baseColor, flashColor, flash ) );
  478. }
  479. if ( initialized )
  480. {
  481. foreach ( var hintInfo in actionHintInfos )
  482. {
  483. if ( hintInfo.Value.textHintActive )
  484. {
  485. UpdateTextHint( hintInfo.Value );
  486. }
  487. }
  488. }
  489. }
  490. }
  491. //-------------------------------------------------
  492. private void UpdateTextHint( ActionHintInfo hintInfo )
  493. {
  494. Transform playerTransform = player.hmdTransform;
  495. Vector3 vDir = playerTransform.position - hintInfo.canvasOffset.position;
  496. Quaternion standardLookat = Quaternion.LookRotation( vDir, Vector3.up );
  497. Quaternion upsideDownLookat = Quaternion.LookRotation( vDir, playerTransform.up );
  498. float flInterp;
  499. if ( playerTransform.forward.y > 0.0f )
  500. {
  501. flInterp = Util.RemapNumberClamped( playerTransform.forward.y, 0.6f, 0.4f, 1.0f, 0.0f );
  502. }
  503. else
  504. {
  505. flInterp = Util.RemapNumberClamped( playerTransform.forward.y, -0.8f, -0.6f, 1.0f, 0.0f );
  506. }
  507. hintInfo.canvasOffset.rotation = Quaternion.Slerp( standardLookat, upsideDownLookat, flInterp );
  508. Transform lineTransform = hintInfo.line.transform;
  509. hintInfo.line.useWorldSpace = false;
  510. hintInfo.line.SetPosition( 0, lineTransform.InverseTransformPoint( hintInfo.textStartAnchor.position ) );
  511. hintInfo.line.SetPosition( 1, lineTransform.InverseTransformPoint( hintInfo.textEndAnchor.position ) );
  512. }
  513. //-------------------------------------------------
  514. private void Clear()
  515. {
  516. renderers.Clear();
  517. flashingRenderers.Clear();
  518. }
  519. //-------------------------------------------------
  520. private void ShowText(ISteamVR_Action_In_Source action, string text, bool highlightButton = true )
  521. {
  522. if ( actionHintInfos.ContainsKey(action) )
  523. {
  524. ActionHintInfo hintInfo = actionHintInfos[action];
  525. hintInfo.textHintObject.SetActive( true );
  526. hintInfo.textHintActive = true;
  527. if ( hintInfo.text != null )
  528. {
  529. hintInfo.text.text = text;
  530. }
  531. if ( hintInfo.textMesh != null )
  532. {
  533. hintInfo.textMesh.text = text;
  534. }
  535. UpdateTextHint( hintInfo );
  536. if ( highlightButton )
  537. {
  538. ShowButtonHint(action);
  539. }
  540. renderModel.gameObject.SetActive( true );
  541. }
  542. }
  543. //-------------------------------------------------
  544. private void HideText(ISteamVR_Action_In_Source action)
  545. {
  546. if ( actionHintInfos.ContainsKey(action) )
  547. {
  548. ActionHintInfo hintInfo = actionHintInfos[action];
  549. hintInfo.textHintObject.SetActive( false );
  550. hintInfo.textHintActive = false;
  551. HideButtonHint(action);
  552. }
  553. }
  554. //-------------------------------------------------
  555. private void HideAllText()
  556. {
  557. if (actionHintInfos != null)
  558. {
  559. foreach (var hintInfo in actionHintInfos)
  560. {
  561. hintInfo.Value.textHintObject.SetActive(false);
  562. hintInfo.Value.textHintActive = false;
  563. }
  564. HideAllButtonHints();
  565. }
  566. }
  567. //-------------------------------------------------
  568. private string GetActiveHintText(ISteamVR_Action_In_Source action )
  569. {
  570. if ( actionHintInfos.ContainsKey(action) )
  571. {
  572. ActionHintInfo hintInfo = actionHintInfos[action];
  573. if ( hintInfo.textHintActive )
  574. {
  575. return hintInfo.text.text;
  576. }
  577. }
  578. return string.Empty;
  579. }
  580. //-------------------------------------------------
  581. // These are the static functions which are used to show/hide the hints
  582. //-------------------------------------------------
  583. //-------------------------------------------------
  584. private static ControllerButtonHints GetControllerButtonHints( Hand hand )
  585. {
  586. if ( hand != null )
  587. {
  588. ControllerButtonHints hints = hand.GetComponentInChildren<ControllerButtonHints>();
  589. if ( hints != null && hints.initialized )
  590. {
  591. return hints;
  592. }
  593. }
  594. return null;
  595. }
  596. //-------------------------------------------------
  597. public static void ShowButtonHint( Hand hand, params ISteamVR_Action_In_Source[] actions )
  598. {
  599. ControllerButtonHints hints = GetControllerButtonHints( hand );
  600. if ( hints != null )
  601. {
  602. hints.ShowButtonHint( actions );
  603. }
  604. }
  605. //-------------------------------------------------
  606. public static void HideButtonHint( Hand hand, params ISteamVR_Action_In_Source[] actions )
  607. {
  608. ControllerButtonHints hints = GetControllerButtonHints( hand );
  609. if ( hints != null )
  610. {
  611. hints.HideButtonHint( actions );
  612. }
  613. }
  614. //-------------------------------------------------
  615. public static void HideAllButtonHints( Hand hand )
  616. {
  617. ControllerButtonHints hints = GetControllerButtonHints( hand );
  618. if ( hints != null )
  619. {
  620. hints.HideAllButtonHints();
  621. }
  622. }
  623. //-------------------------------------------------
  624. public static bool IsButtonHintActive( Hand hand, ISteamVR_Action_In_Source action )
  625. {
  626. ControllerButtonHints hints = GetControllerButtonHints( hand );
  627. if ( hints != null )
  628. {
  629. return hints.IsButtonHintActive(action);
  630. }
  631. return false;
  632. }
  633. //-------------------------------------------------
  634. public static void ShowTextHint( Hand hand, ISteamVR_Action_In_Source action, string text, bool highlightButton = true )
  635. {
  636. ControllerButtonHints hints = GetControllerButtonHints( hand );
  637. if ( hints != null )
  638. {
  639. hints.ShowText(action, text, highlightButton );
  640. }
  641. }
  642. //-------------------------------------------------
  643. public static void HideTextHint( Hand hand, ISteamVR_Action_In_Source action)
  644. {
  645. ControllerButtonHints hints = GetControllerButtonHints( hand );
  646. if ( hints != null )
  647. {
  648. hints.HideText(action);
  649. }
  650. }
  651. //-------------------------------------------------
  652. public static void HideAllTextHints( Hand hand )
  653. {
  654. ControllerButtonHints hints = GetControllerButtonHints( hand );
  655. if ( hints != null )
  656. {
  657. hints.HideAllText();
  658. }
  659. }
  660. //-------------------------------------------------
  661. public static string GetActiveHintText( Hand hand, ISteamVR_Action_In_Source action)
  662. {
  663. ControllerButtonHints hints = GetControllerButtonHints( hand );
  664. if ( hints != null )
  665. {
  666. return hints.GetActiveHintText(action);
  667. }
  668. return string.Empty;
  669. }
  670. }
  671. }