/Assets/GoogleVR/Scripts/UI/GvrReticlePointerImpl.cs

https://bitbucket.org/gcgmm/mm_2017-1_not_equipe-6 · C# · 177 lines · 92 code · 32 blank · 53 comment · 6 complexity · 6edbc9669baf75e5802c1d4677292ff0 MD5 · raw file

  1. // Copyright 2017 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. using UnityEngine;
  15. using UnityEngine.EventSystems;
  16. /// Draws a circular reticle in front of any object that the user points at.
  17. /// The circle dilates if the object is clickable.
  18. public class GvrReticlePointerImpl : GvrBasePointer {
  19. // The constants below are expsed for testing.
  20. // Minimum inner angle of the reticle (in degrees).
  21. public const float RETICLE_MIN_INNER_ANGLE = 0.0f;
  22. // Minimum outer angle of the reticle (in degrees).
  23. public const float RETICLE_MIN_OUTER_ANGLE = 0.5f;
  24. // Angle at which to expand the reticle when intersecting with an object
  25. // (in degrees).
  26. public const float RETICLE_GROWTH_ANGLE = 1.5f;
  27. // Minimum distance of the reticle (in meters).
  28. public const float RETICLE_DISTANCE_MIN = 0.45f;
  29. // Maximum distance of the reticle (in meters).
  30. public const float RETICLE_DISTANCE_MAX = 10.0f;
  31. /// Growth speed multiplier for the reticle.
  32. public float ReticleGrowthSpeed { private get; set; }
  33. public Material MaterialComp { private get; set; }
  34. // Current inner angle of the reticle (in degrees).
  35. // Exposed for testing.
  36. public float ReticleInnerAngle { get; private set; }
  37. // Current outer angle of the reticle (in degrees).
  38. // Exposed for testing.
  39. public float ReticleOuterAngle { get; private set; }
  40. // Current distance of the reticle (in meters).
  41. // Getter exposed for testing.
  42. public float ReticleDistanceInMeters { get; private set; }
  43. // Current inner and outer diameters of the reticle, before distance multiplication.
  44. // Getters exposed for testing.
  45. public float ReticleInnerDiameter { get; private set; }
  46. public float ReticleOuterDiameter { get; private set; }
  47. private Vector3 targetPoint = Vector3.zero;
  48. public override Vector3 LineEndPoint { get { return targetPoint; } }
  49. public override float MaxPointerDistance { get { return RETICLE_DISTANCE_MAX; } }
  50. public GvrReticlePointerImpl() {
  51. ReticleGrowthSpeed = 8.0f;
  52. ReticleInnerAngle = 0.0f;
  53. ReticleOuterAngle = 0.5f;
  54. ReticleDistanceInMeters = 10.0f;
  55. ReticleInnerDiameter = 0.0f;
  56. ReticleOuterDiameter = 0.0f;
  57. }
  58. public override void OnStart () {
  59. base.OnStart();
  60. }
  61. /// This is called when the 'BaseInputModule' system should be enabled.
  62. public override void OnInputModuleEnabled() {}
  63. /// This is called when the 'BaseInputModule' system should be disabled.
  64. public override void OnInputModuleDisabled() {}
  65. /// Called when the user is pointing at valid GameObject. This can be a 3D
  66. /// or UI element.
  67. ///
  68. /// The targetObject is the object the user is pointing at.
  69. /// The intersectionPosition is where the ray intersected with the targetObject.
  70. /// The intersectionRay is the ray that was cast to determine the intersection.
  71. public override void OnPointerEnter(RaycastResult rayastResult, Ray ray,
  72. bool isInteractive) {
  73. SetPointerTarget(rayastResult.worldPosition, isInteractive);
  74. }
  75. /// Called every frame the user is still pointing at a valid GameObject. This
  76. /// can be a 3D or UI element.
  77. ///
  78. /// The targetObject is the object the user is pointing at.
  79. /// The intersectionPosition is where the ray intersected with the targetObject.
  80. /// The intersectionRay is the ray that was cast to determine the intersection.
  81. public override void OnPointerHover(RaycastResult rayastResult, Ray ray,
  82. bool isInteractive) {
  83. SetPointerTarget(rayastResult.worldPosition, isInteractive);
  84. }
  85. /// Called when the user's look no longer intersects an object previously
  86. /// intersected with a ray projected from the camera.
  87. /// This is also called just before **OnInputModuleDisabled** and may have have any of
  88. /// the values set as **null**.
  89. public override void OnPointerExit(GameObject previousObject) {
  90. ReticleDistanceInMeters = RETICLE_DISTANCE_MAX;
  91. ReticleInnerAngle = RETICLE_MIN_INNER_ANGLE;
  92. ReticleOuterAngle = RETICLE_MIN_OUTER_ANGLE;
  93. }
  94. /// Called when a trigger event is initiated. This is practically when
  95. /// the user begins pressing the trigger.
  96. public override void OnPointerClickDown() {}
  97. /// Called when a trigger event is finished. This is practically when
  98. /// the user releases the trigger.
  99. public override void OnPointerClickUp() {}
  100. public override void GetPointerRadius(out float enterRadius, out float exitRadius) {
  101. float min_inner_angle_radians = Mathf.Deg2Rad * RETICLE_MIN_INNER_ANGLE;
  102. float max_inner_angle_radians = Mathf.Deg2Rad * (RETICLE_MIN_INNER_ANGLE + RETICLE_GROWTH_ANGLE);
  103. enterRadius = 2.0f * Mathf.Tan(min_inner_angle_radians);
  104. exitRadius = 2.0f * Mathf.Tan(max_inner_angle_radians);
  105. }
  106. public void UpdateDiameters() {
  107. ReticleDistanceInMeters =
  108. Mathf.Clamp(ReticleDistanceInMeters, RETICLE_DISTANCE_MIN, RETICLE_DISTANCE_MAX);
  109. if (ReticleInnerAngle < RETICLE_MIN_INNER_ANGLE) {
  110. ReticleInnerAngle = RETICLE_MIN_INNER_ANGLE;
  111. }
  112. if (ReticleOuterAngle < RETICLE_MIN_OUTER_ANGLE) {
  113. ReticleOuterAngle = RETICLE_MIN_OUTER_ANGLE;
  114. }
  115. float inner_half_angle_radians = Mathf.Deg2Rad * ReticleInnerAngle * 0.5f;
  116. float outer_half_angle_radians = Mathf.Deg2Rad * ReticleOuterAngle * 0.5f;
  117. float inner_diameter = 2.0f * Mathf.Tan(inner_half_angle_radians);
  118. float outer_diameter = 2.0f * Mathf.Tan(outer_half_angle_radians);
  119. ReticleInnerDiameter =
  120. Mathf.Lerp(ReticleInnerDiameter, inner_diameter, Time.deltaTime * ReticleGrowthSpeed);
  121. ReticleOuterDiameter =
  122. Mathf.Lerp(ReticleOuterDiameter, outer_diameter, Time.deltaTime * ReticleGrowthSpeed);
  123. MaterialComp.SetFloat("_InnerDiameter", ReticleInnerDiameter * ReticleDistanceInMeters);
  124. MaterialComp.SetFloat("_OuterDiameter", ReticleOuterDiameter * ReticleDistanceInMeters);
  125. MaterialComp.SetFloat("_DistanceInMeters", ReticleDistanceInMeters);
  126. }
  127. private bool SetPointerTarget(Vector3 target, bool interactive) {
  128. if (base.PointerTransform == null) {
  129. Debug.LogWarning("Cannot operate on a null pointer transform");
  130. return false;
  131. }
  132. targetPoint = target;
  133. Vector3 targetLocalPosition = base.PointerTransform.InverseTransformPoint(target);
  134. ReticleDistanceInMeters =
  135. Mathf.Clamp(targetLocalPosition.z, RETICLE_DISTANCE_MIN, RETICLE_DISTANCE_MAX);
  136. if (interactive) {
  137. ReticleInnerAngle = RETICLE_MIN_INNER_ANGLE + RETICLE_GROWTH_ANGLE;
  138. ReticleOuterAngle = RETICLE_MIN_OUTER_ANGLE + RETICLE_GROWTH_ANGLE;
  139. } else {
  140. ReticleInnerAngle = RETICLE_MIN_INNER_ANGLE;
  141. ReticleOuterAngle = RETICLE_MIN_OUTER_ANGLE;
  142. }
  143. return true;
  144. }
  145. }