CurvedUISettings.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. #define CURVEDUI_PRESENT //If you're an asset creator and want to see if CurvedUI is imported, just use "#if CURVEDUI_PRESENT [your code] #endif"
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using UnityEngine.EventSystems;
  5. using System.Collections.Generic;
  6. #if CURVEDUI_TMP || TMP_PRESENT
  7. using TMPro;
  8. #endif
  9. /// <summary>
  10. /// This class stores settings for the entire canvas. It also stores useful methods for converting cooridinates to and from 2d canvas to curved canvas, or world space.
  11. /// CurvedUIVertexEffect components (added to every canvas gameobject)ask this class for per-canvas settings when applying their curve effect.
  12. /// </summary>
  13. namespace CurvedUI
  14. {
  15. [AddComponentMenu("CurvedUI/CurvedUISettings")]
  16. [RequireComponent(typeof(Canvas))]
  17. public class CurvedUISettings : MonoBehaviour
  18. {
  19. public const string Version = "3.0";
  20. #region SETTINGS
  21. //Global settings
  22. [SerializeField]
  23. CurvedUIShape shape;
  24. [SerializeField]
  25. float quality = 1f;
  26. [SerializeField]
  27. bool interactable = true;
  28. [SerializeField]
  29. bool blocksRaycasts = true;
  30. [SerializeField]
  31. bool raycastMyLayerOnly = true;
  32. [SerializeField]
  33. bool forceUseBoxCollider = false;
  34. //Cyllinder settings
  35. [SerializeField]
  36. int angle = 90;
  37. [SerializeField]
  38. bool preserveAspect = true;
  39. //Sphere settings
  40. [SerializeField]
  41. int vertAngle = 90;
  42. //ring settings
  43. [SerializeField]
  44. float ringFill = 0.5f;
  45. [SerializeField]
  46. int ringExternalDiamater = 1000;
  47. [SerializeField]
  48. bool ringFlipVertical = false;
  49. //internal system settings
  50. int baseCircleSegments = 16;
  51. //stored variables
  52. Vector2 savedRectSize;
  53. float savedRadius;
  54. Canvas myCanvas;
  55. RectTransform m_rectTransform;
  56. #endregion
  57. #region LIFECYCLE
  58. void Awake()
  59. {
  60. // If this canvas is on Default layer, switch it to UI layer..
  61. // this is to make sure that when using raycasting to detect interactions,
  62. // nothing will interfere with it.
  63. if (RaycastMyLayerOnly && gameObject.layer == 0)
  64. this.gameObject.layer = 5;
  65. //save initial variables
  66. savedRectSize = RectTransform.rect.size;
  67. }
  68. void Start()
  69. {
  70. if (Application.isPlaying)
  71. {
  72. // lets get rid of any raycasters and add our custom one
  73. // It will be responsible for handling interactions.
  74. BaseRaycaster[] raycasters = GetComponents<BaseRaycaster>();
  75. foreach(BaseRaycaster caster in raycasters)
  76. {
  77. if (!(caster is CurvedUIRaycaster))
  78. caster.enabled = false;
  79. }
  80. this.gameObject.AddComponentIfMissing<CurvedUIRaycaster>();
  81. //find if there are any child canvases that may break interactions
  82. Canvas[] canvases = GetComponentsInChildren<Canvas>();
  83. foreach(Canvas cnv in canvases)
  84. {
  85. if (cnv.gameObject != this.gameObject)
  86. {
  87. Transform trans = cnv.transform;
  88. string hierarchyName = trans.name;
  89. while(trans.parent != null)
  90. {
  91. hierarchyName = trans.parent.name + "/" + hierarchyName;
  92. trans = trans.parent;
  93. }
  94. Debug.LogWarning("CURVEDUI: Interactions on nested canvases are not supported. You won't be able to interact with any child object of [" + hierarchyName + "]", cnv.gameObject);
  95. }
  96. }
  97. }
  98. //find needed references
  99. if (myCanvas == null)
  100. myCanvas = GetComponent<Canvas>();
  101. savedRadius = GetCyllinderRadiusInCanvasSpace();
  102. }
  103. void OnEnable()
  104. {
  105. //Redraw canvas object on enable.
  106. foreach (UnityEngine.UI.Graphic graph in (this).GetComponentsInChildren<UnityEngine.UI.Graphic>())
  107. {
  108. graph.SetAllDirty();
  109. }
  110. }
  111. void OnDisable()
  112. {
  113. foreach (UnityEngine.UI.Graphic graph in (this).GetComponentsInChildren<UnityEngine.UI.Graphic>())
  114. {
  115. graph.SetAllDirty();
  116. }
  117. }
  118. void Update()
  119. {
  120. //recreate the geometry if entire canvas has been resized
  121. if (RectTransform.rect.size != savedRectSize)
  122. {
  123. savedRectSize = RectTransform.rect.size;
  124. SetUIAngle(angle);
  125. }
  126. //check for improper canvas size
  127. if (savedRectSize.x == 0 || savedRectSize.y == 0)
  128. Debug.LogError("CurvedUI: Your Canvas size must be bigger than 0!");
  129. }
  130. #endregion
  131. #region PRIVATE
  132. /// <summary>
  133. /// Changes the horizontal angle of the canvas.
  134. /// </summary>
  135. /// <param name="newAngle"></param>
  136. void SetUIAngle(int newAngle) {
  137. if (myCanvas == null)
  138. myCanvas = GetComponent<Canvas>();
  139. //temp fix to make interactions with angle 0 possible
  140. if (newAngle == 0) newAngle = 1;
  141. angle = newAngle;
  142. savedRadius = GetCyllinderRadiusInCanvasSpace();
  143. foreach (CurvedUIVertexEffect ve in GetComponentsInChildren<CurvedUIVertexEffect>())
  144. ve.SetDirty();
  145. foreach (Graphic graph in GetComponentsInChildren<Graphic>())
  146. graph.SetAllDirty();
  147. if (Application.isPlaying && GetComponent<CurvedUIRaycaster>() != null)
  148. //tell raycaster to update its collider now that angle has changed.
  149. GetComponent<CurvedUIRaycaster>().RebuildCollider();
  150. }
  151. Vector3 CanvasToCyllinder(Vector3 pos)
  152. {
  153. float theta = (pos.x / savedRectSize.x) * Angle * Mathf.Deg2Rad;
  154. pos.x = Mathf.Sin(theta) * (SavedRadius + pos.z);
  155. pos.z += Mathf.Cos(theta) * (SavedRadius + pos.z) - (SavedRadius + pos.z);
  156. return pos;
  157. }
  158. Vector3 CanvasToCyllinderVertical(Vector3 pos)
  159. {
  160. float theta = (pos.y / savedRectSize.y) * Angle * Mathf.Deg2Rad;
  161. pos.y = Mathf.Sin(theta) * (SavedRadius + pos.z);
  162. pos.z += Mathf.Cos(theta) * (SavedRadius + pos.z) - (SavedRadius + pos.z);
  163. return pos;
  164. }
  165. Vector3 CanvasToRing(Vector3 pos)
  166. {
  167. float r = pos.y.Remap(savedRectSize.y * 0.5f * (RingFlipVertical ? 1 : -1), -savedRectSize.y * 0.5f * (RingFlipVertical ? 1 : -1), RingExternalDiameter * (1 - RingFill) * 0.5f, RingExternalDiameter * 0.5f);
  168. float theta = (pos.x / savedRectSize.x).Remap(-0.5f, 0.5f, Mathf.PI / 2.0f, angle * Mathf.Deg2Rad + Mathf.PI / 2.0f);
  169. pos.x = r * Mathf.Cos(theta);
  170. pos.y = r * Mathf.Sin(theta);
  171. return pos;
  172. }
  173. Vector3 CanvasToSphere(Vector3 pos)
  174. {
  175. float radius = SavedRadius;
  176. float vAngle = VerticalAngle;
  177. if (PreserveAspect)
  178. {
  179. vAngle = angle * (savedRectSize.y / savedRectSize.x);
  180. radius += Angle > 0 ? -pos.z : pos.z;
  181. }
  182. else {
  183. radius = savedRectSize.x / 2.0f + pos.z;
  184. if (vAngle == 0) return Vector3.zero;
  185. }
  186. //convert planar coordinates to spherical coordinates
  187. float theta = (pos.x / savedRectSize.x).Remap(-0.5f, 0.5f, (180 - angle) / 2.0f - 90, 180 - (180 - angle) / 2.0f - 90);
  188. theta *= Mathf.Deg2Rad;
  189. float gamma = (pos.y / savedRectSize.y).Remap(-0.5f, 0.5f, (180 - vAngle) / 2.0f, 180 - (180 - vAngle) / 2.0f);
  190. gamma *= Mathf.Deg2Rad;
  191. pos.z = Mathf.Sin(gamma) * Mathf.Cos(theta) * radius;
  192. pos.y = -radius * Mathf.Cos(gamma);
  193. pos.x = Mathf.Sin(gamma) * Mathf.Sin(theta) * radius;
  194. if (PreserveAspect)
  195. pos.z -= radius;
  196. return pos;
  197. }
  198. #endregion
  199. #region PUBLIC
  200. RectTransform RectTransform {
  201. get
  202. {
  203. if (m_rectTransform == null) m_rectTransform = transform as RectTransform;
  204. return m_rectTransform;
  205. }
  206. }
  207. /// <summary>
  208. /// Adds the CurvedUIVertexEffect component to every child gameobject that requires it.
  209. /// CurvedUIVertexEffect creates the curving effect.
  210. /// </summary>
  211. public void AddEffectToChildren()
  212. {
  213. foreach (UnityEngine.UI.Graphic graph in GetComponentsInChildren<UnityEngine.UI.Graphic>(true))
  214. {
  215. if (graph.GetComponent<CurvedUIVertexEffect>() == null)
  216. {
  217. graph.gameObject.AddComponent<CurvedUIVertexEffect>();
  218. graph.SetAllDirty();
  219. }
  220. }
  221. //additional script that will create a curved caret for input fields
  222. foreach(UnityEngine.UI.InputField iField in GetComponentsInChildren<UnityEngine.UI.InputField>(true))
  223. {
  224. if (iField.GetComponent<CurvedUIInputFieldCaret>() == null)
  225. {
  226. iField.gameObject.AddComponent<CurvedUIInputFieldCaret>();
  227. }
  228. }
  229. //TextMeshPro experimental support. Go to CurvedUITMP.cs to learn how to enable it.
  230. #if CURVEDUI_TMP || TMP_PRESENT
  231. foreach(TextMeshProUGUI tmp in GetComponentsInChildren<TextMeshProUGUI>(true)){
  232. if(tmp.GetComponent<CurvedUITMP>() == null){
  233. tmp.gameObject.AddComponent<CurvedUITMP>();
  234. tmp.SetAllDirty();
  235. }
  236. }
  237. foreach (TMP_InputField tmp in GetComponentsInChildren<TMP_InputField>(true))
  238. {
  239. tmp.AddComponentIfMissing<CurvedUITMPInputFieldCaret>();
  240. }
  241. #endif
  242. }
  243. /// <summary>
  244. /// Maps a world space vector to a curved canvas.
  245. /// Operates in Canvas's local space.
  246. /// </summary>
  247. /// <param name="pos">World space vector</param>
  248. /// <returns>
  249. /// A vector on curved canvas in canvas's local space
  250. /// </returns>
  251. public Vector3 VertexPositionToCurvedCanvas(Vector3 pos)
  252. {
  253. switch (Shape)
  254. {
  255. case CurvedUIShape.CYLINDER:
  256. {
  257. return CanvasToCyllinder(pos);
  258. }
  259. case CurvedUIShape.CYLINDER_VERTICAL:
  260. {
  261. return CanvasToCyllinderVertical(pos);
  262. }
  263. case CurvedUIShape.RING:
  264. {
  265. return CanvasToRing(pos);
  266. }
  267. case CurvedUIShape.SPHERE:
  268. {
  269. return CanvasToSphere(pos);
  270. }
  271. default:
  272. {
  273. return Vector3.zero;
  274. }
  275. }
  276. }
  277. /// <summary>
  278. /// Converts a point in Canvas space to a point on Curved surface in world space units.
  279. /// </summary>
  280. /// <param name="pos">Position on canvas in canvas space</param>
  281. /// <returns>
  282. /// Position on curved canvas in world space.
  283. /// </returns>
  284. public Vector3 CanvasToCurvedCanvas(Vector3 pos)
  285. {
  286. pos = VertexPositionToCurvedCanvas(pos);
  287. if (float.IsNaN(pos.x) || float.IsInfinity(pos.x)) return Vector3.zero;
  288. else return transform.localToWorldMatrix.MultiplyPoint3x4(pos);
  289. }
  290. /// <summary>
  291. /// Returns a normal direction on curved canvas for a given point on flat canvas. Works in canvas' local space.
  292. /// </summary>
  293. /// <param name="pos"></param>
  294. /// <returns></returns>
  295. public Vector3 CanvasToCurvedCanvasNormal(Vector3 pos)
  296. {
  297. //find the position in canvas space
  298. pos = VertexPositionToCurvedCanvas(pos);
  299. switch (Shape)
  300. {
  301. case CurvedUIShape.CYLINDER:
  302. {
  303. // find the direction to the center of cyllinder on flat XZ plane
  304. return transform.localToWorldMatrix.MultiplyVector((pos - new Vector3(0, 0, -GetCyllinderRadiusInCanvasSpace())).ModifyY(0)).normalized;
  305. }
  306. case CurvedUIShape.CYLINDER_VERTICAL:
  307. {
  308. // find the direction to the center of cyllinder on flat YZ plane
  309. return transform.localToWorldMatrix.MultiplyVector((pos - new Vector3(0, 0, -GetCyllinderRadiusInCanvasSpace())).ModifyX(0)).normalized;
  310. }
  311. case CurvedUIShape.RING:
  312. {
  313. // just return the back direction of the canvas
  314. return -transform.forward;
  315. }
  316. case CurvedUIShape.SPHERE:
  317. {
  318. //return the direction towards the sphere's center
  319. Vector3 center = (PreserveAspect ? new Vector3(0, 0, -GetCyllinderRadiusInCanvasSpace()) : Vector3.zero);
  320. return transform.localToWorldMatrix.MultiplyVector((pos - center)).normalized;
  321. }
  322. default:
  323. {
  324. return Vector3.zero;
  325. }
  326. }
  327. }
  328. /// <summary>
  329. /// Raycasts along the given ray and returns the intersection with the flat canvas.
  330. /// Use to convert from world space to flat canvas space.
  331. /// </summary>
  332. /// <param name="ray"></param>
  333. /// <returns>
  334. /// Returns the true if ray hits the CurvedCanvas.
  335. /// Outputs intersection point in flat canvas space.
  336. /// </returns>
  337. public bool RaycastToCanvasSpace(Ray ray, out Vector2 o_positionOnCanvas)
  338. {
  339. CurvedUIRaycaster caster = this.GetComponent<CurvedUIRaycaster>();
  340. o_positionOnCanvas = Vector2.zero;
  341. switch (Shape)
  342. {
  343. case CurvedUISettings.CurvedUIShape.CYLINDER:
  344. {
  345. return caster.RaycastToCyllinderCanvas(ray, out o_positionOnCanvas, true);
  346. }
  347. case CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL:
  348. {
  349. return caster.RaycastToCyllinderVerticalCanvas(ray, out o_positionOnCanvas, true);
  350. }
  351. case CurvedUISettings.CurvedUIShape.RING:
  352. {
  353. return caster.RaycastToRingCanvas(ray, out o_positionOnCanvas, true);
  354. }
  355. case CurvedUISettings.CurvedUIShape.SPHERE:
  356. {
  357. return caster.RaycastToSphereCanvas(ray, out o_positionOnCanvas, true);
  358. }
  359. default:
  360. {
  361. return false;
  362. }
  363. }
  364. }
  365. /// <summary>
  366. /// Returns the radius of curved canvas cyllinder, expressed in Cavas's local space units.
  367. /// </summary>
  368. public float GetCyllinderRadiusInCanvasSpace()
  369. {
  370. float ret;
  371. if (PreserveAspect)
  372. {
  373. if(shape == CurvedUIShape.CYLINDER_VERTICAL)
  374. ret = (RectTransform.rect.size.y / ((2 * Mathf.PI) * (angle / 360.0f)));
  375. else
  376. ret = (RectTransform.rect.size.x / ((2 * Mathf.PI) * (angle / 360.0f)));
  377. }
  378. else
  379. ret = (RectTransform.rect.size.x * 0.5f) / Mathf.Sin(Mathf.Clamp(angle, -180.0f, 180.0f) * 0.5f * Mathf.Deg2Rad);
  380. return angle == 0 ? 0 : ret;
  381. }
  382. /// <summary>
  383. /// Tells you how big UI quads can get before they should be tesselate to look good on current canvas settings.
  384. /// Used by CurvedUIVertexEffect to determine how many quads need to be created for each graphic.
  385. /// </summary>
  386. public Vector2 GetTesslationSize(bool modifiedByQuality = true)
  387. {
  388. Vector2 ret = RectTransform.rect.size;
  389. if (Angle != 0 || (!PreserveAspect && vertAngle != 0))
  390. {
  391. switch (shape)
  392. {
  393. case CurvedUIShape.CYLINDER: ret /= GetSegmentsByAngle(angle); break;
  394. case CurvedUIShape.CYLINDER_VERTICAL: goto case CurvedUIShape.CYLINDER;
  395. case CurvedUIShape.RING: goto case CurvedUIShape.CYLINDER;
  396. case CurvedUIShape.SPHERE:
  397. {
  398. ret.x /= GetSegmentsByAngle(angle);
  399. if (PreserveAspect)
  400. ret.y = ret.x * RectTransform.rect.size.y / RectTransform.rect.size.x;
  401. else
  402. ret.y /= GetSegmentsByAngle(VerticalAngle);
  403. break;
  404. }
  405. }
  406. }
  407. //Debug.Log(this.gameObject.name + " returning size " + ret + " which is " + ret * this.transform.localScale.x + " in world space.", this.gameObject);
  408. return ret / (modifiedByQuality ? Mathf.Clamp(Quality, 0.01f, 10.0f) : 1);
  409. }
  410. float GetSegmentsByAngle(float angle)
  411. {
  412. if (angle.Abs() <= 1)
  413. return 1;
  414. else if (angle.Abs() < 90)//proportionaly twice as many segments for small angle canvases
  415. return baseCircleSegments * (Mathf.Abs(angle).Remap(0, 90, 0.01f, 0.5f));
  416. else
  417. return baseCircleSegments * (Mathf.Abs(angle).Remap(90, 360.0f, 0.5f, 1));
  418. }
  419. /// <summary>
  420. /// Tells you how many segmetens should the entire 360 deg. cyllinder or sphere consist of.
  421. /// Used by CurvedUIVertexEffect
  422. /// </summary>
  423. public int BaseCircleSegments {
  424. get { return baseCircleSegments; }
  425. }
  426. /// <summary>
  427. /// The measure of the arc of the Canvas.
  428. /// </summary>
  429. public int Angle {
  430. get { return angle; }
  431. set {
  432. if (angle != value)
  433. SetUIAngle(value);
  434. }
  435. }
  436. /// <summary>
  437. /// Multiplier used to deremine how many segments a base curve of a shape has.
  438. /// Default 1. Lower values greatly increase performance. Higher values give you sharper curve.
  439. /// </summary>
  440. public float Quality {
  441. get { return quality; }
  442. set {
  443. if (quality != value)
  444. {
  445. quality = value;
  446. SetUIAngle(angle);
  447. }
  448. }
  449. }
  450. /// <summary>
  451. /// Current Shape of the canvas
  452. /// </summary>
  453. public CurvedUIShape Shape {
  454. get { return shape; }
  455. set {
  456. if (shape != value)
  457. {
  458. shape = value;
  459. SetUIAngle(angle);
  460. }
  461. }
  462. }
  463. /// <summary>
  464. /// Vertical angle of the canvas. Used in sphere shape and ring shape.
  465. /// </summary>
  466. public int VerticalAngle {
  467. get { return vertAngle; }
  468. set {
  469. if (vertAngle != value)
  470. {
  471. vertAngle = value;
  472. SetUIAngle(angle);
  473. }
  474. }
  475. }
  476. /// <summary>
  477. /// Fill of a ring in ring shaped canvas. 0-1
  478. /// </summary>
  479. public float RingFill {
  480. get { return ringFill; }
  481. set {
  482. if (ringFill != value)
  483. {
  484. ringFill = value;
  485. SetUIAngle(angle);
  486. }
  487. }
  488. }
  489. /// <summary>
  490. /// Calculated radius of the curved canvas.
  491. /// </summary>
  492. public float SavedRadius {
  493. get {
  494. if (savedRadius == 0)
  495. savedRadius = GetCyllinderRadiusInCanvasSpace();
  496. return savedRadius;
  497. }
  498. }
  499. /// <summary>
  500. /// External diameter of the ring shaped canvas.
  501. /// </summary>
  502. public int RingExternalDiameter {
  503. get { return ringExternalDiamater; }
  504. set {
  505. if (ringExternalDiamater != value)
  506. {
  507. ringExternalDiamater = value;
  508. SetUIAngle(angle);
  509. }
  510. }
  511. }
  512. /// <summary>
  513. /// Whether the center of the ring should be bottom or top of the canvas.
  514. /// </summary>
  515. public bool RingFlipVertical {
  516. get { return ringFlipVertical; }
  517. set {
  518. if (ringFlipVertical != value)
  519. {
  520. ringFlipVertical = value;
  521. SetUIAngle(angle);
  522. }
  523. }
  524. }
  525. /// <summary>
  526. /// If enabled, CurvedUI will try to preserve aspect ratio of original canvas.
  527. /// </summary>
  528. public bool PreserveAspect {
  529. get { return preserveAspect; }
  530. set {
  531. if (preserveAspect != value)
  532. {
  533. preserveAspect = value;
  534. SetUIAngle(angle);
  535. }
  536. }
  537. }
  538. /// <summary>
  539. /// Can the canvas be interacted with?
  540. /// </summary>
  541. public bool Interactable {
  542. get { return interactable; }
  543. set { interactable = value; }
  544. }
  545. /// <summary>
  546. /// Should The collider for this canvas be created using more expensive box colliders?
  547. /// DEfault false.
  548. /// </summary>
  549. public bool ForceUseBoxCollider {
  550. get { return forceUseBoxCollider; }
  551. set { forceUseBoxCollider = value; }
  552. }
  553. /// <summary>
  554. /// Will the canvas block raycasts
  555. /// Settings this to false will destroy the canvas' collider.
  556. /// </summary>
  557. public bool BlocksRaycasts {
  558. get { return blocksRaycasts; }
  559. set
  560. {
  561. if (blocksRaycasts != value) {
  562. blocksRaycasts = value;
  563. //tell raycaster to update its collider now that angle has changed.
  564. if (Application.isPlaying && GetComponent<CurvedUIRaycaster>() != null)
  565. GetComponent<CurvedUIRaycaster>().RebuildCollider();
  566. }
  567. }
  568. }
  569. /// <summary>
  570. /// Should the raycaster take other layers into account to determine if canvas has been interacted with.
  571. /// </summary>
  572. public bool RaycastMyLayerOnly {
  573. get { return raycastMyLayerOnly; }
  574. set { raycastMyLayerOnly = value; }
  575. }
  576. /// <summary>
  577. /// Forces all child CurvedUI objects to recalculate
  578. /// </summary>
  579. /// <param name="calculateCurvedOnly"> Forces children to recalculate only the curvature. Will not make them retesselate vertices. Much faster.</param>
  580. public void SetAllChildrenDirty(bool recalculateCurveOnly = false)
  581. {
  582. foreach (CurvedUIVertexEffect eff in this.GetComponentsInChildren<CurvedUIVertexEffect>())
  583. {
  584. if (recalculateCurveOnly)
  585. eff.SetDirty();
  586. else
  587. eff.CurvingRequired = true;
  588. }
  589. }
  590. #endregion
  591. #region SHORTCUTS
  592. /// <summary>
  593. /// Returns true if user's pointer is currently pointing inside this canvas.
  594. /// This is a shortcut to CurvedUIRaycaster's PointingAtCanvas bool.
  595. /// </summary>
  596. public bool PointingAtCanvas {
  597. get {
  598. if (GetComponent<CurvedUIRaycaster>() != null)
  599. return GetComponent<CurvedUIRaycaster>().PointingAtCanvas;
  600. else {
  601. Debug.LogWarning("CURVEDUI: Can't check if user is pointing at this canvas - No CurvedUIRaycaster is added to this canvas.");
  602. return false;
  603. }
  604. }
  605. }
  606. /// <summary>
  607. /// Sends OnClick event to every Button under pointer.
  608. /// This is a shortcut to CurvedUIRaycaster's Click method.
  609. /// </summary>
  610. public void Click()
  611. {
  612. if (GetComponent<CurvedUIRaycaster>() != null)
  613. GetComponent<CurvedUIRaycaster>().Click();
  614. }
  615. /// <summary>
  616. /// Current controller mode. Decides how user can interact with the canvas.
  617. /// This is a shortcut to CurvedUIInputModule's property.
  618. /// </summary>
  619. public CurvedUIInputModule.CUIControlMethod ControlMethod {
  620. get { return CurvedUIInputModule.ControlMethod; }
  621. set { CurvedUIInputModule.ControlMethod = value; }
  622. }
  623. /// <summary>
  624. /// Returns all objects currently under the pointer.
  625. /// This is a shortcut to CurvedUIInputModule's method.
  626. /// </summary>
  627. public List<GameObject> GetObjectsUnderPointer()
  628. {
  629. if (GetComponent<CurvedUIRaycaster>() != null)
  630. return GetComponent<CurvedUIRaycaster>().GetObjectsUnderPointer();
  631. else return new List<GameObject>();
  632. }
  633. /// <summary>
  634. /// Returns all the canvas objects that are visible under given Screen Position of EventCamera
  635. /// This is a shortcut to CurvedUIInputModule's method.
  636. /// </summary>
  637. public List<GameObject> GetObjectsUnderScreenPos(Vector2 pos, Camera eventCamera = null)
  638. {
  639. if (eventCamera == null)
  640. eventCamera = myCanvas.worldCamera;
  641. if (GetComponent<CurvedUIRaycaster>() != null)
  642. return GetComponent<CurvedUIRaycaster>().GetObjectsUnderScreenPos(pos, eventCamera);
  643. else return new List<GameObject>();
  644. }
  645. /// <summary>
  646. /// Returns all the canvas objects that are intersected by given ray.
  647. /// This is a shortcut to CurvedUIInputModule's method.
  648. /// </summary>
  649. public List<GameObject> GetObjectsHitByRay(Ray ray)
  650. {
  651. if (GetComponent<CurvedUIRaycaster>() != null)
  652. return GetComponent<CurvedUIRaycaster>().GetObjectsHitByRay(ray);
  653. else return new List<GameObject>();
  654. }
  655. /// <summary>
  656. /// Gaze Control Method. Should execute OnClick events on button after user points at them?
  657. /// This is a shortcut to CurvedUIInputModule's property.
  658. /// </summary>
  659. public bool GazeUseTimedClick {
  660. get { return CurvedUIInputModule.Instance.GazeUseTimedClick; }
  661. set { CurvedUIInputModule.Instance.GazeUseTimedClick = value; }
  662. }
  663. /// <summary>
  664. /// Gaze Control Method. How long after user points on a button should we click it?
  665. /// This is a shortcut to CurvedUIInputModule's property.
  666. /// </summary>
  667. public float GazeClickTimer {
  668. get { return CurvedUIInputModule.Instance.GazeClickTimer; }
  669. set { CurvedUIInputModule.Instance.GazeClickTimer = value; }
  670. }
  671. /// <summary>
  672. /// Gaze Control Method. How long after user looks at a button should we start the timer? Default 1 second.
  673. /// This is a shortcut to CurvedUIInputModule's property.
  674. /// </summary>
  675. public float GazeClickTimerDelay {
  676. get { return CurvedUIInputModule.Instance.GazeClickTimerDelay; }
  677. set { CurvedUIInputModule.Instance.GazeClickTimerDelay = value; }
  678. }
  679. /// <summary>
  680. /// Gaze Control Method. How long till Click method is executed on Buttons under gaze? Goes 0-1.
  681. /// This is a shortcut to CurvedUIInputModule's property.
  682. /// </summary>
  683. public float GazeTimerProgress {
  684. get { return CurvedUIInputModule.Instance.GazeTimerProgress; }
  685. }
  686. #endregion
  687. #region ENUMS
  688. public enum CurvedUIShape
  689. {
  690. CYLINDER = 0,
  691. RING = 1,
  692. SPHERE = 2,
  693. CYLINDER_VERTICAL = 3,
  694. }
  695. #endregion
  696. }
  697. }