CompassProPrivate.cs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using UnityEngine.Events;
  4. using UnityEngine.EventSystems;
  5. using System;
  6. using System.Text;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine.SceneManagement;
  10. #if UNITY_EDITOR
  11. using UnityEditor;
  12. #endif
  13. namespace CompassNavigatorPro {
  14. // public delegate void POIEvent (CompassProPOI poi);
  15. [ExecuteInEditMode]
  16. public partial class CompassPro : MonoBehaviour {
  17. class CompassActiveIcon {
  18. public CompassProPOI poi;
  19. public Image image, miniMapImage;
  20. public float lastPosX;
  21. public string levelName;
  22. RectTransform _rectTransform, _miniMapRectTransform;
  23. public RectTransform rectTransform {
  24. get { return _rectTransform; }
  25. set {
  26. _rectTransform = value;
  27. image = _rectTransform.GetComponent<Image> ();
  28. }
  29. }
  30. public RectTransform miniMapRectTransform {
  31. get { return _miniMapRectTransform; }
  32. set {
  33. _miniMapRectTransform = value;
  34. miniMapImage = _miniMapRectTransform.GetComponent<Image> ();
  35. }
  36. }
  37. public CompassActiveIcon (CompassProPOI poi) {
  38. this.poi = poi;
  39. this.levelName = SceneManager.GetActiveScene ().name;
  40. }
  41. }
  42. enum CompassPoint {
  43. CardinalEast = 0,
  44. HalfWindEastNorthEast = 1,
  45. OrdinalNorthEast = 2,
  46. HalfWindNorthNorthEast = 3,
  47. CardinalNorth = 4,
  48. HalfWindNorthNorthWest = 5,
  49. OrdinalNorthWest = 6,
  50. HalfWindWestNorthWest = 7,
  51. CardinalWest = 8,
  52. HalfWindWestSouthWest = 9,
  53. OrdinalSouthWest = 10,
  54. HalfWindSouthSouthWest = 11,
  55. CardinalSouth = 12,
  56. HalfWindSouthSouthEast = 13,
  57. OrdinalSouthEast = 14,
  58. HalfWindEastSouthEast = 15,
  59. }
  60. int[] cardinals = new int[] { 0, 4, 8, 12 };
  61. int[] ordinals = new int[] { 2, 6, 10, 14 };
  62. int[] halfwinds = new int[] { 1, 3, 5, 7, 9, 11, 13, 15 };
  63. struct CompassPointPOI {
  64. public Vector3 position;
  65. public float cos, sin;
  66. public Text text;
  67. public RawImage image;
  68. }
  69. #region Internal fields
  70. const float COMPASS_POI_POSITION_THRESHOLD = 0.001f;
  71. public bool isDirty;
  72. static CompassPro _instance;
  73. List<CompassActiveIcon> icons;
  74. float fadeStartTime, prevAlpha;
  75. CanvasGroup canvasGroup;
  76. RectTransform compassBackRect;
  77. Image compassBackImage;
  78. GameObject compassIconPrefab, compassMiniMapClampedPrefab;
  79. Text text, textShadow;
  80. Text title, titleShadow;
  81. float endTimeOfCurrentTextReveal;
  82. Material spriteOverlayMat;
  83. Vector3 lastCamPos, lastCamRot;
  84. int lastFrameCount;
  85. float lastTime;
  86. StringBuilder titleText;
  87. AudioSource audioSource;
  88. int poiVisibleCount;
  89. bool autoHiding;
  90. // performing autohide fade
  91. float thisAlpha;
  92. bool needUpdateBarContents;
  93. string lastDistanceText;
  94. float lastDistanceSqr;
  95. CompassPointPOI[] compassPoints;
  96. float usedNorthDegrees;
  97. const int TEXT_POOL_SIZE = 256;
  98. LetterAnimator[] textPool;
  99. int poolIndex;
  100. Transform canvasTextPool;
  101. Canvas _canvas;
  102. #endregion
  103. #region internal Minimap stuff
  104. const string SKW_COMPASS_FOG_OF_WAR = "COMPASS_FOG_OF_WAR";
  105. const string SKW_COMPASS_ROTATED = "COMPASS_ROTATED";
  106. Transform miniMapUIRoot;
  107. Transform miniMapUI, miniMapButtonsPanel;
  108. RectTransform miniMapUIRootRT;
  109. Camera miniMapCamera;
  110. Transform cameraCompass;
  111. RenderTexture miniMapTex;
  112. CanvasGroup miniMapCanvasGroup;
  113. Material miniMapOverlayMat;
  114. Vector2 miniMapAnchorMin, miniMapAnchorMax, miniMapPivot, miniMapSizeDelta;
  115. float miniMapCameraAspect;
  116. MINIMAP_STYLE miniMapCurrentStyle;
  117. float miniMapLastSnapshotTime;
  118. Vector3 miniMapLastSnapshotLocation;
  119. bool needMiniMapShot;
  120. Image miniMapImage;
  121. bool miniMapMaterialRefresh;
  122. float miniMapLastCameraRotation;
  123. Vector3 lastMiniMapCameraPos;
  124. #endregion
  125. #region Curved compass
  126. Material curvedMat, defaultUICurvedMat;
  127. #endregion
  128. #region Gameloop lifecycle
  129. #if UNITY_EDITOR
  130. [MenuItem ("GameObject/UI/Compass Navigator Pro", false)]
  131. static void CreateCompassNavigatorPro (MenuCommand menuCommand) {
  132. // Create a custom game object
  133. GameObject go = Instantiate (Resources.Load<GameObject> ("CNPro/Prefabs/CompassNavigatorPro")) as GameObject;
  134. go.name = "CompassNavigatorPro";
  135. GameObjectUtility.SetParentAndAlign (go, menuCommand.context as GameObject);
  136. Undo.RegisterCreatedObjectUndo (go, "Create " + go.name);
  137. Selection.activeObject = go;
  138. }
  139. [MenuItem ("GameObject/UI/Compass Navigator Pro", true)]
  140. static bool ValidateCreateCompassNavigatorPro (MenuCommand menuCommand) {
  141. return CompassPro.instance == null;
  142. }
  143. #endif
  144. public void OnEnable () {
  145. if (icons == null) {
  146. Init ();
  147. }
  148. // ensure there's an EventSystem gameobject is buttons are visible so they can be used
  149. // an EventSystem gameobject is automatically created when instantiating a Canvas prefab so here we go
  150. if (Application.isPlaying && _miniMapShowButtons && FindObjectOfType<EventSystem> () == null) {
  151. GameObject eventSystem = new GameObject ("EventSystem", typeof(EventSystem));
  152. eventSystem.AddComponent<StandaloneInputModule> ();
  153. }
  154. SetupTextPool ();
  155. SetupMiniMap ();
  156. if (dontDestroyOnLoad && Application.isPlaying) {
  157. if (FindObjectsOfType (GetType ()).Length > 1) {
  158. Destroy (gameObject);
  159. return;
  160. }
  161. DontDestroyOnLoad (this);
  162. SceneManager.sceneLoaded += UpdateFogOfWarOnLoadScene;
  163. }
  164. }
  165. void OnValidate () {
  166. SetupMiniMap ();
  167. }
  168. void OnDisable () {
  169. DisableMiniMap ();
  170. SceneManager.sceneLoaded -= UpdateFogOfWarOnLoadScene;
  171. }
  172. void Init () {
  173. #if UNITY_EDITOR
  174. #if UNITY_2018_3_OR_NEWER
  175. UnityEditor.PrefabInstanceStatus prefabInstanceStatus = UnityEditor.PrefabUtility.GetPrefabInstanceStatus(gameObject);
  176. if (prefabInstanceStatus != UnityEditor.PrefabInstanceStatus.NotAPrefab) {
  177. UnityEditor.PrefabUtility.UnpackPrefabInstance(gameObject, UnityEditor.PrefabUnpackMode.Completely, UnityEditor.InteractionMode.AutomatedAction);
  178. }
  179. #else
  180. UnityEditor.PrefabType prefabType = UnityEditor.PrefabUtility.GetPrefabType (gameObject);
  181. if (prefabType != UnityEditor.PrefabType.None && prefabType != UnityEditor.PrefabType.DisconnectedPrefabInstance && prefabType != UnityEditor.PrefabType.DisconnectedModelPrefabInstance) {
  182. UnityEditor.PrefabUtility.DisconnectPrefabInstance (gameObject);
  183. }
  184. #endif
  185. #endif
  186. _canvas = GetComponent<Canvas> ();
  187. icons = new List<CompassActiveIcon> (1000);
  188. audioSource = GetComponent<AudioSource> ();
  189. spriteOverlayMat = Resources.Load<Material> ("CNPro/Materials/SpriteOverlayUnlit");
  190. compassIconPrefab = Resources.Load<GameObject> ("CNPro/Prefabs/CompassIcon");
  191. compassMiniMapClampedPrefab = Resources.Load<GameObject> ("CNPro/Prefabs/CompassMiniMapClampedIcon");
  192. GameObject compassBack = transform.Find ("CompassBack").gameObject;
  193. compassBackRect = compassBack.GetComponent<RectTransform> ();
  194. compassBackImage = compassBack.GetComponent<Image> ();
  195. canvasGroup = GetCanvasGroup (compassBackRect);
  196. text = compassBackRect.transform.Find ("Text").GetComponent<Text> ();
  197. textShadow = compassBackRect.transform.Find ("TextShadow").GetComponent<Text> ();
  198. text.text = textShadow.text = "";
  199. title = compassBackRect.transform.Find ("Title").GetComponent<Text> ();
  200. titleShadow = compassBackRect.transform.Find ("TitleShadow").GetComponent<Text> ();
  201. title.text = titleShadow.text = "";
  202. canvasGroup.alpha = 0;
  203. prevAlpha = 0f;
  204. fadeStartTime = Time.time;
  205. lastDistanceText = "";
  206. lastDistanceSqr = float.MinValue;
  207. compassPoints = new CompassPointPOI[16];
  208. if (compassBackRect.transform.Find ("CardinalN") == null) {
  209. Debug.LogError ("CompassNavigatorPro gameobject has to be updated. Please delete and add prefab again to this scene.");
  210. _showCardinalPoints = false;
  211. } else {
  212. compassPoints [(int)CompassPoint.CardinalNorth].text = compassBackRect.transform.Find ("CardinalN").GetComponent<Text> ();
  213. compassPoints [(int)CompassPoint.CardinalWest].text = compassBackRect.transform.Find ("CardinalW").GetComponent<Text> ();
  214. compassPoints [(int)CompassPoint.CardinalSouth].text = compassBackRect.transform.Find ("CardinalS").GetComponent<Text> ();
  215. compassPoints [(int)CompassPoint.CardinalEast].text = compassBackRect.transform.Find ("CardinalE").GetComponent<Text> ();
  216. }
  217. if (compassBackRect.transform.Find ("InterCardinalNW") == null) {
  218. Debug.LogError ("CompassNavigatorPro gameobject has to be updated. Please delete and add prefab again to this scene.");
  219. _showOrdinalPoints = false;
  220. } else {
  221. compassPoints [(int)CompassPoint.OrdinalNorthWest].text = compassBackRect.transform.Find ("InterCardinalNW").GetComponent<Text> ();
  222. compassPoints [(int)CompassPoint.OrdinalNorthEast].text = compassBackRect.transform.Find ("InterCardinalNE").GetComponent<Text> ();
  223. compassPoints [(int)CompassPoint.OrdinalSouthWest].text = compassBackRect.transform.Find ("InterCardinalSW").GetComponent<Text> ();
  224. compassPoints [(int)CompassPoint.OrdinalSouthEast].text = compassBackRect.transform.Find ("InterCardinalSE").GetComponent<Text> ();
  225. }
  226. if (compassBackRect.transform.Find ("TickNNE") == null) {
  227. Debug.LogError ("CompassNavigatorPro gameobject has to be updated. Please delete and add prefab again to this scene.");
  228. _showHalfWinds = false;
  229. } else {
  230. compassPoints [(int)CompassPoint.HalfWindEastNorthEast].image = compassBackRect.transform.Find ("TickENE").GetComponent<RawImage> ();
  231. compassPoints [(int)CompassPoint.HalfWindEastSouthEast].image = compassBackRect.transform.Find ("TickESE").GetComponent<RawImage> ();
  232. compassPoints [(int)CompassPoint.HalfWindNorthNorthEast].image = compassBackRect.transform.Find ("TickNNE").GetComponent<RawImage> ();
  233. compassPoints [(int)CompassPoint.HalfWindNorthNorthWest].image = compassBackRect.transform.Find ("TickNNW").GetComponent<RawImage> ();
  234. compassPoints [(int)CompassPoint.HalfWindSouthSouthEast].image = compassBackRect.transform.Find ("TickSSE").GetComponent<RawImage> ();
  235. compassPoints [(int)CompassPoint.HalfWindSouthSouthWest].image = compassBackRect.transform.Find ("TickSSW").GetComponent<RawImage> ();
  236. compassPoints [(int)CompassPoint.HalfWindWestNorthWest].image = compassBackRect.transform.Find ("TickWNW").GetComponent<RawImage> ();
  237. compassPoints [(int)CompassPoint.HalfWindWestSouthWest].image = compassBackRect.transform.Find ("TickWSW").GetComponent<RawImage> ();
  238. }
  239. usedNorthDegrees = -1;
  240. ComputeCompassPointsPositions ();
  241. UpdateCompassBarAppearance ();
  242. UpdateHalfWindsAppearance ();
  243. UpdateCompassBarAlpha ();
  244. UpdateFogOfWarTexture ();
  245. }
  246. void LateUpdate () {
  247. UpdateCompassBarAlpha ();
  248. UpdateCompassBarContents ();
  249. UpdateFogOfWarPosition ();
  250. UpdateMiniMap ();
  251. }
  252. internal void BubbleEvent<T> (Action<T> a, T o) {
  253. if (a != null && o != null)
  254. a (o);
  255. }
  256. #endregion
  257. #region Internal stuff
  258. /// <summary>
  259. /// Update bar icons
  260. /// </summary>
  261. void UpdateCompassBarContents () {
  262. if (cameraMain == null) {
  263. if (_cameraMain == null)
  264. return;
  265. }
  266. // If camera has not moved, then don't refresh compass bar so often - just once each second in case one POI is moving
  267. switch (_updateInterval) {
  268. case UPDATE_INTERVAL.NumberOfFrames:
  269. if (Time.frameCount - lastFrameCount >= _updateIntervalFrameCount) {
  270. lastFrameCount = Time.frameCount;
  271. needUpdateBarContents = true;
  272. }
  273. break;
  274. case UPDATE_INTERVAL.Time:
  275. if (Time.time - lastTime >= _updateIntervalTime) {
  276. lastTime = Time.time;
  277. needUpdateBarContents = true;
  278. }
  279. break;
  280. case UPDATE_INTERVAL.Continuous:
  281. needUpdateBarContents = true;
  282. break;
  283. }
  284. if (!needUpdateBarContents) {
  285. if (lastCamPos != _cameraMain.transform.position || lastCamRot != _cameraMain.transform.eulerAngles) {
  286. needUpdateBarContents = true;
  287. }
  288. }
  289. if (!needUpdateBarContents)
  290. return;
  291. needUpdateBarContents = false;
  292. lastCamPos = _cameraMain.transform.position;
  293. lastCamRot = _cameraMain.transform.eulerAngles;
  294. float visibleDistanceSQR = _visibleDistance * _visibleDistance;
  295. float visitedDistanceSQR = _visitedDistance * _visitedDistance;
  296. float nearDistanceSQR = _nearDistance * _nearDistance;
  297. float barMax = _width * 0.5f - _endCapsWidth / _cameraMain.pixelWidth;
  298. const float visibleDistanceFallOffSQR = 25f * 25f;
  299. // Cardinal & Ordinal (ordinal) Points
  300. ComputeCompassPointsPositions ();
  301. UpdateCardinalPoints (barMax);
  302. UpdateOrdinalPoints (barMax);
  303. UpdateHalfWinds (barMax);
  304. // Update Icons
  305. poiVisibleCount = 0;
  306. float nearestPOIDistanceThisFrame = float.MaxValue;
  307. CompassProPOI nearestPOI = null;
  308. bool miniMapIsActive = _showMiniMap && miniMapUI != null;
  309. for (int p = 0; p < icons.Count; p++) {
  310. bool iconVisible = false;
  311. CompassActiveIcon activeIcon = icons [p];
  312. CompassProPOI poi = activeIcon.poi;
  313. if (poi == null) {
  314. if (activeIcon.rectTransform != null && activeIcon.rectTransform.gameObject != null) {
  315. DestroyImmediate (activeIcon.rectTransform.gameObject);
  316. }
  317. if (activeIcon.miniMapRectTransform != null && activeIcon.miniMapRectTransform.gameObject != null) {
  318. DestroyImmediate (activeIcon.miniMapRectTransform.gameObject);
  319. }
  320. icons.RemoveAt (p); // POI no longer registered; remove and exit to prevent indexing errors
  321. continue;
  322. }
  323. // Change in visibility?
  324. Vector3 poiPosition = poi.transform.position;
  325. float distanceSqr, distancePlanarSQR;
  326. distanceSqr = (poiPosition - lastCamPos).sqrMagnitude;
  327. distanceSqr -= poi.radius;
  328. if (distanceSqr <= 0)
  329. distanceSqr = 0.01f;
  330. poi.distanceToCameraSQR = distanceSqr;
  331. // Distance has changed, proceed with update...
  332. if (_use3Ddistance) {
  333. distancePlanarSQR = distanceSqr;
  334. } else {
  335. Vector2 v = new Vector2 (poiPosition.x - lastCamPos.x, poiPosition.z - lastCamPos.z);
  336. distancePlanarSQR = v.sqrMagnitude;
  337. }
  338. float distanceFactor = distancePlanarSQR / nearDistanceSQR;
  339. float alphaFactor = poi.visibility == POI_VISIBILITY.AlwaysVisible ? 1f : distanceFactor;
  340. if (poi.showPlayModeGizmo) {
  341. poi.iconAlpha = Mathf.Lerp (0.65f, 0, 5f * alphaFactor);
  342. }
  343. poi.iconScale = Misc.Vector3one * Mathf.Lerp (_maxIconSize, _minIconSize, distanceFactor);
  344. poi.miniMapIconScale = Misc.Vector3one * _miniMapIconSize;
  345. // Should we make this POI visible in the compass bar?
  346. float thisPOIVisibleDistanceSQR = poi.visibleDistanceOverride > 0 ? poi.visibleDistanceOverride * poi.visibleDistanceOverride : visibleDistanceSQR;
  347. bool isInRange = poi.distanceToCameraSQR < thisPOIVisibleDistanceSQR;
  348. bool prevVisible = poi.isVisible;
  349. poi.isVisible = ((isInRange && poi.visibility == POI_VISIBILITY.WhenInRange) || poi.visibility == POI_VISIBILITY.AlwaysVisible) && poi.isActiveAndEnabled;
  350. // Is it same scene?
  351. if (poi.isVisible && poi.dontDestroyOnLoad && !activeIcon.levelName.Equals (SceneManager.GetActiveScene ().name)) {
  352. poi.isVisible = false;
  353. }
  354. // Do we visit this POI for the first time?
  355. if (poi.isVisible && !poi.isVisited && poi.canBeVisited && poi.distanceToCameraSQR < visitedDistanceSQR) {
  356. poi.isVisited = true;
  357. if (OnPOIVisited != null)
  358. OnPOIVisited (poi);
  359. if (audioSource != null) {
  360. if (poi.visitedAudioClip != null) {
  361. audioSource.PlayOneShot (poi.visitedAudioClip);
  362. } else if (_visitedDefaultAudioClip != null) {
  363. audioSource.PlayOneShot (_visitedDefaultAudioClip);
  364. }
  365. }
  366. ShowPOIDiscoveredText (poi);
  367. if (poi.hideWhenVisited)
  368. poi.enabled = false;
  369. }
  370. // Check heartbeat
  371. if (poi.heartbeatEnabled) {
  372. bool inHeartbeatRange = poi.distanceToCameraSQR < poi.heartbeatDistance * poi.heartbeatDistance;
  373. if (!poi.heartbeatIsActive && inHeartbeatRange) {
  374. poi.StartHeartbeat ();
  375. } else if (poi.heartbeatIsActive && !inHeartbeatRange) {
  376. poi.StopHeartbeat ();
  377. }
  378. }
  379. // Notify POI visibility change
  380. if (prevVisible != poi.isVisible) {
  381. if (poi.isVisible && OnPOIVisible != null) {
  382. OnPOIVisible (poi);
  383. } else if (!poi.isVisible && OnPOIHide != null) {
  384. OnPOIHide (poi);
  385. }
  386. }
  387. // If POI is not visible, then hide and skip
  388. if (!poi.isVisible) {
  389. if (activeIcon.image != null && activeIcon.image.enabled) {
  390. activeIcon.image.enabled = false;
  391. }
  392. if (poi.spriteRenderer != null && poi.spriteRenderer.enabled) {
  393. poi.spriteRenderer.enabled = false;
  394. }
  395. } else {
  396. // POI is visible, should we create the icon in the compass bar?
  397. if (activeIcon.rectTransform == null) {
  398. GameObject iconGO = Instantiate (compassIconPrefab);
  399. iconGO.name = "CompassIcon " + poi.gameObject.name;
  400. iconGO.hideFlags = HideFlags.DontSave;
  401. iconGO.transform.SetParent (compassBackRect.transform, false);
  402. activeIcon.rectTransform = iconGO.GetComponent<RectTransform> ();
  403. poi.compassIconRectTransform = activeIcon.rectTransform;
  404. }
  405. // Check bending
  406. if (_bendAmount == 0 && activeIcon.image.material != null) {
  407. activeIcon.image.material = null;
  408. } else if (_bendAmount != 0 && activeIcon.image.material != curvedMat) {
  409. activeIcon.image.material = curvedMat;
  410. }
  411. // Position the icon on the compass bar
  412. Vector3 screenPos = GetScreenPos (poiPosition);
  413. float posX;
  414. if (Mathf.Abs (screenPos.x - activeIcon.lastPosX) > COMPASS_POI_POSITION_THRESHOLD) {
  415. needUpdateBarContents = true;
  416. posX = (screenPos.x + activeIcon.lastPosX) * 0.5f;
  417. } else {
  418. posX = screenPos.x;
  419. }
  420. activeIcon.lastPosX = posX;
  421. // Always show the focused icon in the compass bar; if out of bar, maintain it on the edge with normal scale
  422. if (poi.clampPosition) {
  423. if (screenPos.z < 0) {
  424. posX = barMax * -Mathf.Sign (screenPos.x - 0.5f);
  425. if (poi.iconScale.x > 1f)
  426. poi.iconScale = Misc.Vector3one;
  427. } else {
  428. posX = Mathf.Clamp (posX, -barMax, barMax);
  429. if (poi.iconScale.x > 1f)
  430. poi.iconScale = Misc.Vector3one;
  431. }
  432. screenPos.z = 0;
  433. }
  434. float absPosX = Mathf.Abs (posX);
  435. // Set icon position
  436. if (absPosX > barMax || screenPos.z < 0) {
  437. // Icon outside of bar
  438. if (activeIcon.image != null && activeIcon.image.enabled) {
  439. activeIcon.image.enabled = false;
  440. }
  441. } else {
  442. // Unhide icon
  443. if (activeIcon.image != null && !activeIcon.image.enabled) {
  444. activeIcon.image.enabled = true;
  445. activeIcon.poi.visibleTime = Time.time;
  446. }
  447. activeIcon.rectTransform.anchorMin = activeIcon.rectTransform.anchorMax = new Vector2 (0.5f + posX / _width, 0.5f);
  448. iconVisible = true;
  449. }
  450. // Icon is visible, manage it
  451. if (iconVisible) {
  452. poiVisibleCount++;
  453. // Check gizmo
  454. if (!poi.showPlayModeGizmo && poi.spriteRenderer != null && poi.spriteRenderer.enabled) {
  455. poi.spriteRenderer.enabled = false;
  456. } else if (poi.showPlayModeGizmo) {
  457. if (poi.spriteRenderer == null) {
  458. // Add a dummy child gameObject
  459. GameObject go = new GameObject ("POI Gizmo Renderer");
  460. go.transform.SetParent (poi.transform, false);
  461. poi.spriteRenderer = go.gameObject.AddComponent<SpriteRenderer> ();
  462. poi.spriteRenderer.material = spriteOverlayMat;
  463. poi.spriteRenderer.enabled = false;
  464. }
  465. if (poi.spriteRenderer != null) {
  466. if (!poi.spriteRenderer.enabled) {
  467. poi.spriteRenderer.enabled = true;
  468. poi.spriteRenderer.sprite = poi.iconVisited;
  469. }
  470. poi.spriteRenderer.transform.LookAt (lastCamPos);
  471. poi.spriteRenderer.transform.localScale = Misc.Vector3one * _gizmoScale;
  472. poi.spriteRenderer.color = new Color (1, 1, 1, poi.iconAlpha);
  473. }
  474. }
  475. // Assign proper icon
  476. if (activeIcon.poi.isVisited) {
  477. if (activeIcon.image != poi.iconVisited) {
  478. activeIcon.image.sprite = poi.iconVisited;
  479. }
  480. } else if (activeIcon.image != poi.iconNonVisited) {
  481. activeIcon.image.sprite = poi.iconNonVisited;
  482. }
  483. // Scale in animation
  484. if (_scaleInDuration > 0) {
  485. float t = (Time.time - activeIcon.poi.visibleTime) / _scaleInDuration;
  486. if (t < 1) {
  487. needUpdateBarContents = true;
  488. activeIcon.poi.iconScale *= t;
  489. }
  490. }
  491. // Scale icon
  492. if (activeIcon.poi.iconScale != activeIcon.rectTransform.localScale) {
  493. activeIcon.rectTransform.localScale = activeIcon.poi.iconScale;
  494. }
  495. // Set icon's color and alpha
  496. Color spriteColor = poi.tintColor;
  497. if (visibleDistanceFallOffSQR > 0) {
  498. if (poi.visibility == POI_VISIBILITY.AlwaysVisible) {
  499. spriteColor.a = 1f;
  500. } else {
  501. float t = (visibleDistanceSQR - poi.distanceToCameraSQR) / visibleDistanceFallOffSQR;
  502. spriteColor.a = Mathf.Lerp (0, 1, t);
  503. }
  504. }
  505. activeIcon.image.color = spriteColor;
  506. // Get title if POI is centered
  507. if (absPosX < _labelHotZone && distancePlanarSQR < nearestPOIDistanceThisFrame) {
  508. nearestPOI = poi;
  509. nearestPOIDistanceThisFrame = distancePlanarSQR;
  510. }
  511. }
  512. }
  513. // mini-map icon
  514. if (miniMapIsActive && (poi.miniMapVisibility == POI_VISIBILITY.AlwaysVisible || (poi.miniMapVisibility == POI_VISIBILITY.WhenInRange && isInRange))) {
  515. iconVisible = false;
  516. // POI is visible, should we create the icon in the minimap?
  517. if (activeIcon.miniMapRectTransform == null) {
  518. GameObject iconGO = Instantiate (poi.miniMapClampPosition ? compassMiniMapClampedPrefab : compassIconPrefab);
  519. iconGO.name = "MiniMap Icon " + poi.name;
  520. if (_miniMapIconEvents) {
  521. iconGO.GetComponent<Image> ().raycastTarget = true;
  522. CompassIconEventHandler eventHandler = iconGO.AddComponent<CompassIconEventHandler> ();
  523. eventHandler.poi = poi;
  524. eventHandler.compass = this;
  525. }
  526. iconGO.hideFlags = HideFlags.DontSave;
  527. iconGO.transform.SetParent (miniMapUI.transform, false);
  528. activeIcon.miniMapRectTransform = iconGO.GetComponent<RectTransform> ();
  529. poi.miniMapIconRectTransform = activeIcon.miniMapRectTransform;
  530. poi.compass = this;
  531. }
  532. // Position the icon on the mini-map area
  533. Vector2 miniMapScreenPos = GetMiniMapScreenPos (poiPosition);
  534. // Always show the focused icon in the compass bar; if out of bar, maintain it on the edge with normal scale
  535. if (poi.miniMapClampPosition) {
  536. miniMapScreenPos.x = Mathf.Clamp (miniMapScreenPos.x, _miniMapClampBorder, 1f - _miniMapClampBorder);
  537. miniMapScreenPos.y = Mathf.Clamp (miniMapScreenPos.y, _miniMapClampBorder, 1f - _miniMapClampBorder);
  538. }
  539. // Set icon position
  540. if (miniMapScreenPos.x > 1 || miniMapScreenPos.x < 0 || miniMapScreenPos.y > 1 || miniMapScreenPos.y < 0) {
  541. // Icon outside of bar
  542. if (activeIcon.miniMapImage != null && activeIcon.miniMapImage.enabled) {
  543. activeIcon.miniMapImage.enabled = false;
  544. }
  545. } else {
  546. // Unhide icon
  547. if (activeIcon.miniMapImage != null && !activeIcon.miniMapImage.enabled) {
  548. activeIcon.miniMapImage.enabled = true;
  549. }
  550. activeIcon.miniMapRectTransform.anchorMin = activeIcon.miniMapRectTransform.anchorMax = miniMapScreenPos;
  551. iconVisible = true;
  552. }
  553. // Icon is visible, manage it
  554. if (iconVisible) {
  555. // Assign proper icon
  556. if (activeIcon.poi.isVisited) {
  557. if (activeIcon.miniMapImage != poi.iconVisited) {
  558. activeIcon.miniMapImage.sprite = poi.iconVisited;
  559. }
  560. } else if (activeIcon.miniMapImage != poi.iconNonVisited) {
  561. activeIcon.miniMapImage.sprite = poi.iconNonVisited;
  562. }
  563. // tint color
  564. activeIcon.miniMapImage.color = poi.tintColor;
  565. // Scale icon
  566. if (activeIcon.poi.miniMapIconScale != activeIcon.miniMapRectTransform.localScale) {
  567. activeIcon.miniMapRectTransform.localScale = activeIcon.poi.miniMapIconScale;
  568. }
  569. }
  570. // Send events
  571. if (activeIcon.poi.miniMapIsVisible && !iconVisible) {
  572. if (OnPOIVisibleInMiniMap != null) {
  573. OnPOIVisibleInMiniMap (activeIcon.poi);
  574. }
  575. } else if (iconVisible && !activeIcon.poi.miniMapIsVisible) {
  576. if (OnPOIHidesInMiniMap != null) {
  577. OnPOIHidesInMiniMap (activeIcon.poi);
  578. }
  579. }
  580. activeIcon.poi.miniMapIsVisible = iconVisible;
  581. } else {
  582. if (activeIcon.miniMapImage != null && activeIcon.miniMapImage.enabled) {
  583. activeIcon.miniMapImage.enabled = false;
  584. }
  585. }
  586. }
  587. // Update title
  588. if (nearestPOI != null) {
  589. if (titleText == null) {
  590. titleText = new StringBuilder ();
  591. } else {
  592. if (titleText.Length > 0)
  593. titleText.Length = 0;
  594. }
  595. if (nearestPOI.isVisited || nearestPOI.titleVisibility == TITLE_VISIBILITY.Always) {
  596. titleText.Append (nearestPOI.title);
  597. }
  598. // indicate "above" or "below"
  599. bool addedAlt = false;
  600. if (nearestPOI.transform.position.y > lastCamPos.y + _sameAltitudeThreshold) {
  601. if (titleText.Length > 0)
  602. titleText.Append (" ");
  603. titleText.Append ("(Above");
  604. addedAlt = true;
  605. } else if (nearestPOI.transform.position.y < lastCamPos.y - _sameAltitudeThreshold) {
  606. if (titleText.Length > 0)
  607. titleText.Append (" ");
  608. titleText.Append ("(Below");
  609. addedAlt = true;
  610. }
  611. if (_showDistance) {
  612. if (addedAlt) {
  613. titleText.Append (", ");
  614. } else {
  615. if (titleText.Length > 0)
  616. titleText.Append (" ");
  617. titleText.Append ("(");
  618. }
  619. if (lastDistanceSqr != nearestPOIDistanceThisFrame) {
  620. lastDistanceSqr = nearestPOIDistanceThisFrame;
  621. lastDistanceText = Mathf.Sqrt (nearestPOIDistanceThisFrame).ToString (showDistanceFormat);
  622. }
  623. titleText.Append (lastDistanceText);
  624. titleText.Append (" m)");
  625. } else if (addedAlt) {
  626. titleText.Append (")");
  627. }
  628. string tt = titleText.ToString ();
  629. if (!title.text.Equals (tt)) {
  630. title.text = titleShadow.text = tt;
  631. UpdateTitleAlpha (1.0f);
  632. UpdateTitleAppearance ();
  633. }
  634. } else {
  635. title.text = titleShadow.text = "";
  636. }
  637. }
  638. Vector3 GetScreenPos (Vector3 poiPosition) {
  639. Vector3 camPos = _cameraMain.transform.position;
  640. poiPosition.y = camPos.y;
  641. Vector3 screenPos = Misc.Vector3zero;
  642. Quaternion oldRot = _cameraMain.transform.rotation;
  643. Vector3 angles = _cameraMain.transform.eulerAngles;
  644. _cameraMain.transform.eulerAngles = new Vector3 (0, angles.y, 0);
  645. switch (_worldMappingMode) {
  646. case WORLD_MAPPING_MODE.LimitedToBarWidth:
  647. screenPos = _cameraMain.WorldToViewportPoint (poiPosition);
  648. break;
  649. case WORLD_MAPPING_MODE.Full180Degrees:
  650. {
  651. Vector3 v2poi = poiPosition - camPos;
  652. Vector3 dir = new Vector3 (_cameraMain.transform.forward.x, 0, _cameraMain.transform.forward.z);
  653. float angle = (Quaternion.FromToRotation (dir, v2poi).eulerAngles.y + 180f) / 180f;
  654. screenPos.x = 0.5f + (angle % 2.0f - 1.0f) * (_width - _endCapsWidth / _cameraMain.pixelWidth) * 0.9f;
  655. }
  656. break;
  657. case WORLD_MAPPING_MODE.Full360Degrees:
  658. {
  659. Vector3 v2poi = poiPosition - camPos;
  660. Vector3 dir = new Vector3 (_cameraMain.transform.forward.x, 0, _cameraMain.transform.forward.z);
  661. float angle = (Quaternion.FromToRotation (dir, v2poi).eulerAngles.y + 180f) / 180f;
  662. screenPos.x = 0.5f + (angle % 2.0f - 1f) * 0.5f * (_width - _endCapsWidth / _cameraMain.pixelWidth) * 0.9f;
  663. }
  664. break;
  665. default: // WORLD_MAPPING_MODE.CameraFustrum:
  666. screenPos = _cameraMain.WorldToViewportPoint (poiPosition);
  667. screenPos.x = 0.5f + (screenPos.x - 0.5f) * (_width - _endCapsWidth / _cameraMain.pixelWidth) * 0.9f;
  668. break;
  669. }
  670. screenPos.x -= 0.5f;
  671. _cameraMain.transform.rotation = oldRot;
  672. return screenPos;
  673. }
  674. Vector2 GetMiniMapScreenPos (Vector3 poiPosition) {
  675. Vector2 viewportPos = miniMapCamera.WorldToViewportPoint (poiPosition);
  676. viewportPos.x = (viewportPos.x - 0.5f) / _miniMapZoomLevel + 0.5f;
  677. viewportPos.y = (viewportPos.y - 0.5f) / _miniMapZoomLevel + 0.5f;
  678. return viewportPos;
  679. }
  680. void ComputeCompassPointsPositions () {
  681. if (_cameraMain == null)
  682. return;
  683. if (_northDegrees != usedNorthDegrees) {
  684. usedNorthDegrees = _northDegrees;
  685. for (int k = 0; k < 16; k++) {
  686. float angle = (Mathf.PI * 2f * k / 16f) + _northDegrees * Mathf.Deg2Rad;
  687. compassPoints [k].cos = Mathf.Cos (angle);
  688. compassPoints [k].sin = Mathf.Sin (angle);
  689. }
  690. }
  691. Vector3 camPos = _cameraMain.transform.position;
  692. Vector3 pos;
  693. for (int k = 0; k < 16; k++) {
  694. pos = camPos;
  695. pos.x += compassPoints [k].cos;
  696. pos.z += compassPoints [k].sin;
  697. compassPoints [k].position = pos;
  698. }
  699. }
  700. /// <summary>
  701. /// If showCardinalPoints is enabled, show N, W, S, E across the compass bar
  702. /// </summary>
  703. void UpdateCardinalPoints (float barMax) {
  704. for (int i = 0; i < cardinals.Length; i++) {
  705. int k = cardinals [i];
  706. if (!_showCardinalPoints) {
  707. if (compassPoints [k].text.enabled) {
  708. compassPoints [k].text.enabled = false;
  709. }
  710. continue;
  711. }
  712. Vector3 screenPos = GetScreenPos (compassPoints [k].position);
  713. float posX = screenPos.x;
  714. float absPosX = Mathf.Abs (posX);
  715. // Set icon position
  716. if (absPosX > barMax || screenPos.z <= 0) {
  717. // Icon outside of bar
  718. if (compassPoints [k].text.enabled) {
  719. compassPoints [k].text.enabled = false;
  720. }
  721. } else {
  722. // Unhide icon
  723. if (!compassPoints [k].text.enabled) {
  724. compassPoints [k].text.enabled = true;
  725. }
  726. RectTransform rt = compassPoints [k].text.rectTransform;
  727. rt.anchorMin = rt.anchorMax = new Vector2 (0.5f + posX / _width, 0.5f + _cardinalPointsVerticalOffset / rt.sizeDelta.y);
  728. }
  729. }
  730. }
  731. /// <summary>
  732. /// If showOrdinalPoints is enabled, show NE, NW, SW, SE across the compass bar
  733. /// </summary>
  734. void UpdateOrdinalPoints (float barMax) {
  735. for (int i = 0; i < ordinals.Length; i++) {
  736. int k = ordinals [i];
  737. if (!_showOrdinalPoints) {
  738. if (compassPoints [k].text != null && compassPoints [k].text.enabled) {
  739. compassPoints [k].text.enabled = false;
  740. }
  741. continue;
  742. }
  743. Vector3 screenPos = GetScreenPos (compassPoints [k].position);
  744. float posX = screenPos.x;
  745. float absPosX = Mathf.Abs (posX);
  746. // Set icon position
  747. if (absPosX > barMax || screenPos.z <= 0) {
  748. // Icon outside of bar
  749. if (compassPoints [k].text.enabled) {
  750. compassPoints [k].text.enabled = false;
  751. }
  752. } else {
  753. // Unhide icon
  754. if (!compassPoints [k].text.enabled) {
  755. compassPoints [k].text.enabled = true;
  756. }
  757. RectTransform rt = compassPoints [k].text.rectTransform;
  758. rt.anchorMin = rt.anchorMax = new Vector2 (0.5f + posX / _width, 0.5f + _cardinalPointsVerticalOffset / rt.sizeDelta.y);
  759. }
  760. }
  761. }
  762. /// <summary>
  763. /// Manages compass bar alpha transitions
  764. /// </summary>
  765. void UpdateCompassBarAlpha () {
  766. // Alpha
  767. if (_alwaysVisibleInEditMode && !Application.isPlaying) {
  768. thisAlpha = 1.0f;
  769. } else if (_autoHide) {
  770. if (!autoHiding) {
  771. if (poiVisibleCount == 0) {
  772. if (thisAlpha > 0) {
  773. autoHiding = true;
  774. fadeStartTime = Time.time;
  775. prevAlpha = canvasGroup.alpha;
  776. thisAlpha = 0;
  777. }
  778. } else if (poiVisibleCount > 0 && thisAlpha == 0) {
  779. thisAlpha = _alpha;
  780. autoHiding = true;
  781. fadeStartTime = Time.time;
  782. prevAlpha = canvasGroup.alpha;
  783. }
  784. }
  785. } else {
  786. thisAlpha = _alpha;
  787. }
  788. if (thisAlpha != canvasGroup.alpha) {
  789. float t = Application.isPlaying ? (Time.time - fadeStartTime) / _fadeDuration : 1.0f;
  790. canvasGroup.alpha = Mathf.Lerp (prevAlpha, thisAlpha, t);
  791. if (t >= 1) {
  792. prevAlpha = canvasGroup.alpha;
  793. }
  794. } else if (autoHiding)
  795. autoHiding = false;
  796. }
  797. void UpdateCompassBarAppearance () {
  798. // Width & Vertical Position
  799. float anchorMinX = (1 - _width) * 0.5f;
  800. compassBackRect.anchorMin = new Vector2 (anchorMinX, _verticalPosition);
  801. float anchorMaxX = 1f - anchorMinX;
  802. compassBackRect.anchorMax = new Vector2 (anchorMaxX, _verticalPosition);
  803. // Style
  804. Sprite barSprite;
  805. switch (_style) {
  806. case COMPASS_STYLE.Rounded:
  807. barSprite = Resources.Load<Sprite> ("CNPro/Sprites/Bar2");
  808. break;
  809. case COMPASS_STYLE.Celtic_White:
  810. barSprite = Resources.Load<Sprite> ("CNPro/Sprites/Bar3-White");
  811. break;
  812. case COMPASS_STYLE.Celtic_Black:
  813. barSprite = Resources.Load<Sprite> ("CNPro/Sprites/Bar3-Black");
  814. break;
  815. default:
  816. barSprite = Resources.Load<Sprite> ("CNPro/Sprites/Bar1");
  817. break;
  818. }
  819. if (compassBackImage.sprite != barSprite) {
  820. compassBackImage.sprite = barSprite;
  821. }
  822. ToggleCurvedCompass ();
  823. }
  824. /// <summary>
  825. /// If showHalfWinds is enabled, show NNE, ENE, ESE, SSE, SSW, WSW, WNW, NNW marks
  826. /// </summary>
  827. void UpdateHalfWinds (float barMax) {
  828. for (int i = 0; i < halfwinds.Length; i++) {
  829. int k = halfwinds [i];
  830. if (!_showHalfWinds) {
  831. if (compassPoints [k].image.enabled) {
  832. compassPoints [k].image.enabled = false;
  833. }
  834. continue;
  835. }
  836. Vector3 screenPos = GetScreenPos (compassPoints [k].position);
  837. float posX = screenPos.x;
  838. float absPosX = Mathf.Abs (posX);
  839. // Set icon position
  840. if (absPosX > barMax || screenPos.z <= 0) {
  841. // Icon outside of bar
  842. if (compassPoints [k].image.enabled) {
  843. compassPoints [k].image.enabled = false;
  844. }
  845. } else {
  846. // Unhide icon
  847. if (!compassPoints [k].image.enabled) {
  848. compassPoints [k].image.enabled = true;
  849. }
  850. compassPoints [k].image.rectTransform.anchorMin = new Vector2 (0.5f + posX / _width, 0f);
  851. compassPoints [k].image.rectTransform.anchorMax = new Vector2 (0.5f + posX / _width, 1f);
  852. }
  853. }
  854. }
  855. void UpdateHalfWindsAppearance () {
  856. for (int i = 0; i < halfwinds.Length; i++) {
  857. int k = halfwinds [i];
  858. RawImage image = compassPoints [k].image;
  859. if (image != null) {
  860. if (!_showHalfWinds) {
  861. image.enabled = _showHalfWinds;
  862. }
  863. image.color = _halfWindsTintColor;
  864. image.transform.localScale = new Vector3 (_halfWindsWidth, _halfWindsHeight, 1f);
  865. }
  866. }
  867. }
  868. void UpdateTextAppearanceEditMode () {
  869. if (!gameObject.activeInHierarchy)
  870. return;
  871. text.text = textShadow.text = "SAMPLE TEXT";
  872. UpdateTextAlpha (1);
  873. UpdateTextAppearance ();
  874. }
  875. void UpdateTextAppearance () {
  876. // Vertical and horizontal position
  877. text.alignment = TextAnchor.MiddleCenter;
  878. Vector3 localScale = new Vector3 (_textScale, _textScale, 1f);
  879. RectTransform rt = text.GetComponent<RectTransform> ();
  880. rt.pivot = new Vector2 (0.5f, 0.5f);
  881. rt.anchoredPosition3D = new Vector3 (0, _textVerticalPosition, 0);
  882. text.transform.localScale = localScale;
  883. text.font = _textFont;
  884. textShadow.enabled = _textShadowEnabled;
  885. textShadow.alignment = TextAnchor.MiddleCenter;
  886. rt = textShadow.GetComponent<RectTransform> ();
  887. rt.pivot = new Vector2 (0.5f, 0.5f);
  888. rt.anchoredPosition3D = new Vector3 (1f, _textVerticalPosition - 1f, 0);
  889. textShadow.transform.localScale = localScale;
  890. textShadow.font = _textFont;
  891. }
  892. void UpdateTextAlpha (float t) {
  893. text.color = new Color (text.color.r, text.color.g, text.color.b, t);
  894. textShadow.color = new Color (0, 0, 0, t);
  895. }
  896. void UpdateTitleAppearanceEditMode () {
  897. if (!gameObject.activeInHierarchy)
  898. return;
  899. title.text = titleShadow.text = "SAMPLE TITLE";
  900. UpdateTitleAlpha (1);
  901. UpdateTitleAppearance ();
  902. }
  903. void UpdateTitleAppearance () {
  904. // Vertical and horizontal position
  905. title.GetComponent<RectTransform> ().anchoredPosition3D = new Vector3 (0, _titleVerticalPosition, 0);
  906. Vector3 localScale = new Vector3 (_titleScale, _titleScale, 1f);
  907. title.transform.localScale = localScale;
  908. title.font = _titleFont;
  909. titleShadow.enabled = _titleShadowEnabled;
  910. titleShadow.GetComponent<RectTransform> ().anchoredPosition3D = new Vector3 (1f, _titleVerticalPosition - 1f, 0);
  911. titleShadow.transform.localScale = localScale;
  912. titleShadow.font = _titleFont;
  913. }
  914. void UpdateTitleAlpha (float t) {
  915. title.color = new Color (title.color.r, title.color.g, title.color.b, t);
  916. titleShadow.color = new Color (0, 0, 0, t);
  917. }
  918. void SetupTextPool () {
  919. if (!Application.isPlaying)
  920. return;
  921. text.text = textShadow.text = "";
  922. UpdateTextAppearance ();
  923. if (textPool == null || textPool.Length != TEXT_POOL_SIZE) {
  924. textPool = new LetterAnimator[TEXT_POOL_SIZE];
  925. }
  926. GameObject o = GameObject.Find ("CompassProTextPool");
  927. if (o == null) {
  928. o = new GameObject ("CompassProTextPool");
  929. }
  930. canvasTextPool = o.transform;
  931. for (int k = 0; k < textPool.Length; k++) {
  932. GameObject letterShadow = Instantiate (textShadow.gameObject);
  933. letterShadow.transform.SetParent (canvasTextPool);
  934. letterShadow.name = "TextShadowPool";
  935. Text lts = letterShadow.GetComponent<Text> ();
  936. GameObject letter = Instantiate (text.gameObject);
  937. letter.transform.SetParent (canvasTextPool);
  938. letter.name = "TextPool";
  939. Text lt = letter.GetComponent<Text> ();
  940. LetterAnimator animator = lts.gameObject.AddComponent<LetterAnimator> ();
  941. animator.poolIndex = k;
  942. animator.text = lt;
  943. animator.textShadow = lts;
  944. animator.OnAnimationEnds += PushTextToPool;
  945. animator.used = false;
  946. textPool [k] = animator;
  947. }
  948. }
  949. void FetchTextFromPool (out Text lt, out Text lts) {
  950. for (int k = 0; k < TEXT_POOL_SIZE; k++) {
  951. ++poolIndex;
  952. if (poolIndex >= TEXT_POOL_SIZE) {
  953. poolIndex = 0;
  954. }
  955. if (!textPool [poolIndex].used) {
  956. break;
  957. }
  958. }
  959. // Setup shadow (first, so it goes behind white text)
  960. lts = textPool [poolIndex].textShadow;
  961. lts.transform.SetParent (text.transform.parent, false);
  962. lt = textPool [poolIndex].text;
  963. lt.transform.SetParent (text.transform.parent, false);
  964. textPool [poolIndex].used = true;
  965. }
  966. void PushTextToPool (int index) {
  967. textPool [index].text.transform.SetParent (canvasTextPool);
  968. textPool [index].textShadow.transform.SetParent (canvasTextPool);
  969. textPool [index].used = false;
  970. }
  971. void ShowPOIDiscoveredText (CompassProPOI poi) {
  972. if (poi.visitedText == null || !_textRevealEnabled)
  973. return;
  974. StartCoroutine (AnimateDiscoverText (poi.visitedText));
  975. }
  976. IEnumerator AnimateDiscoverText (string discoverText) {
  977. int len = discoverText.Length;
  978. if (len == 0 || _cameraMain == null || textPool == null || textPool.Length != TEXT_POOL_SIZE)
  979. yield break;
  980. while (Time.time < endTimeOfCurrentTextReveal) {
  981. yield return new WaitForSeconds (1);
  982. }
  983. float now = Time.time;
  984. endTimeOfCurrentTextReveal = now + _textRevealDuration + _textDuration + _textFadeOutDuration * 0.5f;
  985. text.text = textShadow.text = "";
  986. UpdateTextAppearance ();
  987. // initial pos of text
  988. string discoverTextSpread = discoverText.Replace (" ", "A");
  989. float posX = -text.cachedTextGenerator.GetPreferredWidth (discoverTextSpread, text.GetGenerationSettings (Misc.Vector2zero)) * 0.5f * _textScale;
  990. float acum = 0;
  991. TextGenerationSettings settings = new TextGenerationSettings ();
  992. for (int k = 0; k < len; k++) {
  993. Text lts, lt;
  994. string ch = discoverText.Substring (k, 1);
  995. FetchTextFromPool (out lt, out lts);
  996. lts.text = ch;
  997. lt.text = ch;
  998. float letw = 0;
  999. if (k == 0) {
  1000. settings = lt.GetGenerationSettings (Misc.Vector2max);
  1001. }
  1002. if (ch.Equals (" ")) {
  1003. letw = lt.cachedTextGenerator.GetPreferredWidth ("A", settings) * _textScale;
  1004. } else {
  1005. letw = lt.cachedTextGenerator.GetPreferredWidth (ch, settings) * _textScale;
  1006. }
  1007. RectTransform letterRT = lt.GetComponent<RectTransform> ();
  1008. letterRT.anchoredPosition3D = new Vector3 (posX + acum + letw * 0.5f, letterRT.anchoredPosition3D.y, 0);
  1009. RectTransform shadowRT = lts.GetComponent<RectTransform> ();
  1010. shadowRT.anchoredPosition3D = new Vector3 (posX + acum + letw * 0.5f + 1f, shadowRT.anchoredPosition3D.y, 0);
  1011. acum += letw;
  1012. // Trigger animator
  1013. LetterAnimator anim = textPool [poolIndex];
  1014. anim.startTime = now + k * _textRevealLetterDelay;
  1015. anim.revealDuration = _textRevealDuration;
  1016. anim.startFadeTime = now + _textRevealDuration + _textDuration;
  1017. anim.fadeDuration = _textFadeOutDuration;
  1018. anim.enabled = true;
  1019. anim.Play ();
  1020. }
  1021. }
  1022. #endregion
  1023. #region MiniMap
  1024. void SetupMiniMap () {
  1025. if (miniMapFollow == null && _cameraMain != null) {
  1026. miniMapFollow = _cameraMain.transform;
  1027. }
  1028. miniMapUIRoot = transform.Find ("MiniMap Root");
  1029. if (_showMiniMap) {
  1030. miniMapUI = transform.Find ("MiniMap");
  1031. // if there exists an old minimap at root or the minimap root does not exist at root, remove anything and recreate
  1032. bool rebuildMiniMap = false;
  1033. if (miniMapUI != null || miniMapUIRoot == null) {
  1034. rebuildMiniMap = true;
  1035. }
  1036. // check buttons
  1037. if (miniMapUIRoot != null) {
  1038. miniMapButtonsPanel = miniMapUIRoot.Find ("Buttons");
  1039. if (miniMapButtonsPanel == null) {
  1040. rebuildMiniMap = true;
  1041. }
  1042. }
  1043. if (rebuildMiniMap) {
  1044. if (miniMapUI != null) {
  1045. DestroyImmediate (miniMapUI.gameObject);
  1046. }
  1047. if (miniMapUIRoot != null) {
  1048. DestroyImmediate (miniMapUIRoot.gameObject);
  1049. }
  1050. miniMapUIRoot = null;
  1051. }
  1052. if (miniMapUIRoot == null) {
  1053. // rebuild from prefab
  1054. GameObject pb = Resources.Load<GameObject> ("CNPro/Prefabs/CompassNavigatorPro");
  1055. Transform pt = pb.transform.Find ("MiniMap Root");
  1056. GameObject minimapRootChild = null;
  1057. if (pt != null) {
  1058. minimapRootChild = pt.gameObject;
  1059. }
  1060. if (minimapRootChild != null) {
  1061. GameObject minimapRootGO = Instantiate<GameObject> (minimapRootChild, transform);
  1062. minimapRootGO.name = "MiniMap Root";
  1063. if (minimapRootGO != null) {
  1064. miniMapUIRoot = minimapRootGO.transform;
  1065. }
  1066. }
  1067. miniMapButtonsPanel = miniMapUIRoot.Find ("Buttons");
  1068. }
  1069. // check buttons
  1070. ToggleButtonEventHandler ("ZoomIn", () => {
  1071. MiniMapZoomIn ();
  1072. }, true);
  1073. ToggleButtonEventHandler ("ZoomOut", () => {
  1074. MiniMapZoomOut ();
  1075. }, true);
  1076. ToggleButtonEventHandler ("ToggleFull", () => {
  1077. miniMapZoomState = !miniMapZoomState;
  1078. }, false);
  1079. miniMapUIRoot = transform.Find ("MiniMap Root");
  1080. miniMapUI = miniMapUIRoot.Find ("MiniMap");
  1081. if (miniMapCamera == null) {
  1082. miniMapCamera = transform.GetComponentInChildren<Camera> (true);
  1083. }
  1084. if (miniMapCamera != null) {
  1085. miniMapCamera.enabled = false;
  1086. }
  1087. if (miniMapCamera != null && miniMapUIRoot != null) {
  1088. miniMapUIRootRT = miniMapUIRoot.GetComponent<RectTransform> ();
  1089. // set mini-map position
  1090. if (_miniMapLocation != MINIMAP_LOCATION.Custom) {
  1091. switch (_miniMapLocation) {
  1092. case MINIMAP_LOCATION.TopLeft:
  1093. miniMapUIRootRT.anchorMin = new Vector2 (0, 1);
  1094. miniMapUIRootRT.anchorMax = new Vector2 (0, 1);
  1095. miniMapUIRootRT.pivot = new Vector2 (0, 1);
  1096. break;
  1097. case MINIMAP_LOCATION.TopCenter:
  1098. miniMapUIRootRT.anchorMin = new Vector2 (0.5f, 1f);
  1099. miniMapUIRootRT.anchorMax = new Vector2 (0.5f, 1);
  1100. miniMapUIRootRT.pivot = new Vector2 (0.5f, 1);
  1101. break;
  1102. case MINIMAP_LOCATION.TopRight:
  1103. miniMapUIRootRT.anchorMin = new Vector2 (1, 1);
  1104. miniMapUIRootRT.anchorMax = new Vector2 (1, 1);
  1105. miniMapUIRootRT.pivot = new Vector2 (1, 1);
  1106. break;
  1107. case MINIMAP_LOCATION.MiddleLeft:
  1108. miniMapUIRootRT.anchorMin = new Vector2 (0, 0.5f);
  1109. miniMapUIRootRT.anchorMax = new Vector2 (0, 0.5f);
  1110. miniMapUIRootRT.pivot = new Vector2 (0, 0.5f);
  1111. break;
  1112. case MINIMAP_LOCATION.MiddleCenter:
  1113. miniMapUIRootRT.anchorMin = new Vector2 (0.5f, 0.5f);
  1114. miniMapUIRootRT.anchorMax = new Vector2 (0.5f, 0.5f);
  1115. miniMapUIRootRT.pivot = new Vector2 (0.5f, 0.5f);
  1116. break;
  1117. case MINIMAP_LOCATION.MiddleRight:
  1118. miniMapUIRootRT.anchorMin = new Vector2 (1, 0.5f);
  1119. miniMapUIRootRT.anchorMax = new Vector2 (1, 0.5f);
  1120. miniMapUIRootRT.pivot = new Vector2 (1, 0.5f);
  1121. break;
  1122. case MINIMAP_LOCATION.BottomLeft:
  1123. miniMapUIRootRT.anchorMin = new Vector2 (0, 0);
  1124. miniMapUIRootRT.anchorMax = new Vector2 (0, 0);
  1125. miniMapUIRootRT.pivot = new Vector2 (0, 0);
  1126. break;
  1127. case MINIMAP_LOCATION.BottomCenter:
  1128. miniMapUIRootRT.anchorMin = new Vector2 (0.5f, 0);
  1129. miniMapUIRootRT.anchorMax = new Vector2 (0.5f, 0);
  1130. miniMapUIRootRT.pivot = new Vector2 (0.5f, 0);
  1131. break;
  1132. case MINIMAP_LOCATION.BottomRight:
  1133. miniMapUIRootRT.anchorMin = new Vector2 (1, 0);
  1134. miniMapUIRootRT.anchorMax = new Vector2 (1, 0);
  1135. miniMapUIRootRT.pivot = new Vector2 (1, 0);
  1136. break;
  1137. }
  1138. if (_miniMapLocation != MINIMAP_LOCATION.Custom) {
  1139. miniMapUIRootRT.anchoredPosition = _miniMapLocationOffset;
  1140. }
  1141. }
  1142. // set mini-map size
  1143. float screenSize = _cameraMain != null ? _cameraMain.pixelHeight * _miniMapSize : Screen.height * _miniMapSize;
  1144. miniMapUIRootRT.sizeDelta = new Vector2 (screenSize, screenSize);
  1145. miniMapUIRoot.gameObject.SetActive (true);
  1146. // set minimap viewer properties
  1147. switch (_miniMapStyle) {
  1148. case MINIMAP_STYLE.TornPaper:
  1149. _miniMapBorderTexture = Resources.Load<Texture2D> ("CNPro/Textures/MiniMapBorder");
  1150. _miniMapMaskSprite = Resources.Load<Sprite> ("CNPro/Sprites/MiniMapMask");
  1151. break;
  1152. case MINIMAP_STYLE.SolidBox:
  1153. _miniMapBorderTexture = Resources.Load<Texture2D> ("CNPro/Textures/MiniMapBorderSolidBox");
  1154. _miniMapMaskSprite = null;
  1155. break;
  1156. case MINIMAP_STYLE.SolidCircle:
  1157. _miniMapBorderTexture = Resources.Load<Texture2D> ("CNPro/Textures/MiniMapBorderSolidCircle");
  1158. _miniMapMaskSprite = Resources.Load<Sprite> ("CNPro/Sprites/MiniMapMaskSolidCircle");
  1159. break;
  1160. default:
  1161. break;
  1162. }
  1163. if (miniMapOverlayMat == null) {
  1164. miniMapOverlayMat = Instantiate<Material> (Resources.Load<Material> ("CNPro/Materials/MiniMapOverlayUnlit"));
  1165. }
  1166. if (_miniMapCameraMode == MINIMAP_CAMERA_MODE.Perspective) {
  1167. miniMapCameraSnapshotFrequency = MINIMAP_CAMERA_SNAPSHOT_FREQUENCY.Continuous;
  1168. }
  1169. if (miniMapUI != null) {
  1170. miniMapImage = miniMapUI.GetComponent<Image> ();
  1171. if (miniMapImage != null) {
  1172. miniMapImage.sprite = _miniMapMaskSprite;
  1173. miniMapImage.material = miniMapOverlayMat;
  1174. Material mat = miniMapImage.materialForRendering;
  1175. mat.SetTexture ("_BorderTex", _miniMapBorderTexture);
  1176. if (_fogOfWarEnabled && _miniMapCameraMode == MINIMAP_CAMERA_MODE.Orthographic) {
  1177. mat.EnableKeyword (SKW_COMPASS_FOG_OF_WAR);
  1178. } else {
  1179. mat.DisableKeyword (SKW_COMPASS_FOG_OF_WAR);
  1180. }
  1181. if (_miniMapKeepStraight) {
  1182. mat.DisableKeyword (SKW_COMPASS_ROTATED);
  1183. } else {
  1184. mat.EnableKeyword (SKW_COMPASS_ROTATED);
  1185. }
  1186. }
  1187. }
  1188. // setup render texture
  1189. MiniMapResizeRenderTexture (_miniMapResolutionNormalSize, _miniMapResolutionNormalSize);
  1190. #if UNITY_5_6_OR_NEWER
  1191. miniMapCamera.allowHDR = false;
  1192. miniMapCamera.allowMSAA = false;
  1193. #endif
  1194. miniMapCamera.clearFlags = CameraClearFlags.SolidColor;
  1195. miniMapCamera.backgroundColor = Color.black;
  1196. miniMapCamera.orthographic = (_miniMapCameraMode == MINIMAP_CAMERA_MODE.Orthographic);
  1197. miniMapCamera.cullingMask = _miniMapLayerMask;
  1198. cameraCompass = miniMapUIRoot.Find ("CameraCompass");
  1199. } else {
  1200. Debug.LogError ("Mini Map prefab element could not be intialized.");
  1201. _showMiniMap = false;
  1202. }
  1203. if (miniMapCanvasGroup == null) {
  1204. miniMapCanvasGroup = GetCanvasGroup (miniMapUIRoot);
  1205. }
  1206. miniMapCanvasGroup.interactable = miniMapCanvasGroup.blocksRaycasts = _miniMapShowButtons;
  1207. } else {
  1208. if (miniMapUIRoot != null) {
  1209. miniMapUIRoot.gameObject.SetActive (false);
  1210. }
  1211. }
  1212. needUpdateBarContents = true;
  1213. needMiniMapShot = true;
  1214. }
  1215. void MiniMapResizeRenderTexture (int width, int height) {
  1216. if (miniMapCamera == null || miniMapCamera == null)
  1217. return;
  1218. if (miniMapTex == null || miniMapTex.width != width || miniMapTex.height != height) {
  1219. if (miniMapTex != null) {
  1220. miniMapTex.Release ();
  1221. }
  1222. miniMapTex = new RenderTexture (width, height, 24, RenderTextureFormat.ARGB32);
  1223. }
  1224. miniMapCamera.targetTexture = miniMapTex;
  1225. if (miniMapImage != null) {
  1226. miniMapImage.materialForRendering.SetTexture ("_MiniMapTex", miniMapTex);
  1227. }
  1228. }
  1229. void DisableMiniMap () {
  1230. if (miniMapUIRoot != null && miniMapUIRoot.gameObject.activeSelf) {
  1231. miniMapUIRoot.gameObject.SetActive (false);
  1232. }
  1233. if (miniMapCamera != null) {
  1234. miniMapCamera.enabled = false;
  1235. }
  1236. if (miniMapTex != null) {
  1237. miniMapTex.Release ();
  1238. }
  1239. }
  1240. void UpdateMiniMap () {
  1241. if (!_showMiniMap || miniMapCamera == null || miniMapFollow == null)
  1242. return;
  1243. Vector3 followPos = miniMapFollow.position;
  1244. if (_miniMapCameraMode == MINIMAP_CAMERA_MODE.Orthographic) {
  1245. miniMapCamera.transform.position = new Vector3 (followPos.x, followPos.y + _miniMapCameraHeightVSFollow + 0.1f, followPos.z);
  1246. if (_miniMapZoomMin < 0.001f) {
  1247. _miniMapZoomMin = 0.001f;
  1248. }
  1249. if (_miniMapZoomMax < _miniMapZoomMin) {
  1250. _miniMapZoomMax = _miniMapZoomMin;
  1251. }
  1252. _miniMapZoomLevel = Mathf.Clamp (_miniMapZoomLevel, _miniMapZoomMin, _miniMapZoomMax);
  1253. miniMapCamera.orthographicSize = _miniMapCaptureSize * 0.5f;
  1254. } else {
  1255. float altitude = _miniMapCameraMinAltitude + (_miniMapCameraMaxAltitude - _miniMapCameraMinAltitude) * _miniMapZoomLevel;
  1256. if (_miniMapCameraMaxAltitude < _miniMapCameraMinAltitude) {
  1257. _miniMapCameraMaxAltitude = _miniMapCameraMinAltitude;
  1258. }
  1259. miniMapCamera.transform.position = new Vector3 (followPos.x, followPos.y + altitude, followPos.z);
  1260. }
  1261. if (miniMapCanvasGroup.alpha != _miniMapAlpha) {
  1262. miniMapCanvasGroup.alpha = _miniMapAlpha;
  1263. }
  1264. // snapshot control
  1265. switch (_miniMapCameraSnapshotFrequency) {
  1266. case MINIMAP_CAMERA_SNAPSHOT_FREQUENCY.TimeInterval:
  1267. if (Time.time - miniMapLastSnapshotTime > _miniMapSnapshotInterval) {
  1268. needMiniMapShot = true;
  1269. }
  1270. break;
  1271. case MINIMAP_CAMERA_SNAPSHOT_FREQUENCY.DistanceTravelled:
  1272. if ((miniMapLastSnapshotLocation - miniMapCamera.transform.position).sqrMagnitude > _miniMapSnapshotDistance * _miniMapSnapshotDistance) {
  1273. needMiniMapShot = true;
  1274. }
  1275. break;
  1276. case MINIMAP_CAMERA_SNAPSHOT_FREQUENCY.Continuous:
  1277. needMiniMapShot = true;
  1278. break;
  1279. }
  1280. // minimapp camera rotation
  1281. float rotation = 0;
  1282. if (_miniMapKeepStraight) {
  1283. miniMapCamera.transform.eulerAngles = new Vector3 (90f, 0, 0);
  1284. if (cameraCompass != null) {
  1285. Vector3 angles = miniMapFollow.rotation.eulerAngles;
  1286. angles.z = 180f - angles.y;
  1287. angles.x = angles.y = 0;
  1288. cameraCompass.eulerAngles = angles;
  1289. }
  1290. } else {
  1291. Vector3 forward = miniMapFollow.forward;
  1292. forward.y = 0;
  1293. miniMapCamera.transform.LookAt (followPos, forward);
  1294. rotation = miniMapFollow.rotation.eulerAngles.y * Mathf.Deg2Rad;
  1295. }
  1296. if (miniMapLastCameraRotation != rotation) {
  1297. miniMapLastCameraRotation = rotation;
  1298. miniMapMaterialRefresh = true;
  1299. }
  1300. // capture map
  1301. if (needMiniMapShot) {
  1302. needMiniMapShot = false;
  1303. Quaternion oldRot = miniMapCamera.transform.rotation;
  1304. miniMapCamera.transform.eulerAngles = new Vector3 (90f, 0, 0);
  1305. if (!_miniMapEnableShadows) {
  1306. ShadowQuality sq = QualitySettings.shadows;
  1307. QualitySettings.shadows = ShadowQuality.Disable;
  1308. miniMapCamera.Render ();
  1309. QualitySettings.shadows = sq;
  1310. } else {
  1311. miniMapCamera.Render ();
  1312. }
  1313. miniMapLastSnapshotTime = Time.time;
  1314. miniMapLastSnapshotLocation = miniMapCamera.transform.position;
  1315. miniMapCamera.transform.rotation = oldRot;
  1316. miniMapMaterialRefresh = true;
  1317. }
  1318. // Set mini-map shader properties
  1319. // mini-map uv
  1320. Vector3 miniMapCameraPos = miniMapCamera.transform.position;
  1321. if (miniMapCameraPos != lastMiniMapCameraPos) {
  1322. miniMapMaterialRefresh = true;
  1323. lastMiniMapCameraPos = miniMapCameraPos;
  1324. }
  1325. Vector3 uvOffset = miniMapLastSnapshotLocation - miniMapCameraPos;
  1326. float camSize = miniMapCamera.orthographicSize * 2f;
  1327. uvOffset.x = uvOffset.x / camSize;
  1328. uvOffset.y = uvOffset.z / camSize;
  1329. uvOffset.z = _miniMapZoomLevel;
  1330. // fog of war shader properties
  1331. Vector4 uvFogOffset = _fogOfWarCenter - miniMapCameraPos;
  1332. uvFogOffset.x = (uvFogOffset.x / camSize) / _miniMapZoomLevel;
  1333. uvFogOffset.y = (uvFogOffset.z / camSize) / _miniMapZoomLevel;
  1334. uvFogOffset.z = _miniMapZoomLevel * camSize / _fogOfWarSize.x;
  1335. uvFogOffset.w = _miniMapZoomLevel * camSize / _fogOfWarSize.z;
  1336. // update material
  1337. if (miniMapMaterialRefresh && miniMapImage != null) {
  1338. miniMapMaterialRefresh = false;
  1339. Material mat = miniMapImage.materialForRendering;
  1340. mat.SetFloat ("_Rotation", rotation);
  1341. mat.SetVector ("_UVOffset", uvOffset);
  1342. mat.SetVector ("_UVFogOffset", uvFogOffset);
  1343. mat.SetTexture ("_FogOfWarTex", fogOfWarTexture);
  1344. mat.SetColor ("_FogOfWarTintColor", _fogOfWarColor);
  1345. mat.SetVector ("_Effects", new Vector3 (_miniMapBrightness, _miniMapContrast, 0));
  1346. }
  1347. }
  1348. CanvasGroup GetCanvasGroup (Transform transform) {
  1349. if (transform == null) {
  1350. return null;
  1351. }
  1352. CanvasGroup canvasGroup = transform.GetComponent<CanvasGroup> ();
  1353. if (canvasGroup == null) {
  1354. canvasGroup = transform.gameObject.AddComponent<CanvasGroup> ();
  1355. canvasGroup.blocksRaycasts = false;
  1356. }
  1357. return canvasGroup;
  1358. }
  1359. void ToggleButtonEventHandler (string buttonName, UnityAction handler, bool continuous) {
  1360. if (miniMapButtonsPanel == null)
  1361. return;
  1362. Transform t = miniMapButtonsPanel.Find (buttonName);
  1363. if (t == null)
  1364. return;
  1365. if (!_miniMapShowButtons) {
  1366. t.gameObject.SetActive (false);
  1367. return;
  1368. }
  1369. t.gameObject.SetActive (true);
  1370. Button button = t.GetComponent<Button> ();
  1371. if (button == null)
  1372. return;
  1373. if (continuous) {
  1374. CompassButtonHandler buttonHandler = button.GetComponent<CompassButtonHandler> ();
  1375. if (buttonHandler == null) {
  1376. buttonHandler = button.gameObject.AddComponent<CompassButtonHandler> ();
  1377. }
  1378. buttonHandler.actionHandler = handler;
  1379. } else {
  1380. button.onClick.RemoveListener (handler);
  1381. button.onClick.AddListener (handler);
  1382. }
  1383. }
  1384. void MiniMapZoomToggle (bool state) {
  1385. if (miniMapUIRoot == null || cameraMain == null)
  1386. return;
  1387. RectTransform rt = miniMapUIRoot.GetComponent<RectTransform> ();
  1388. _miniMapZoomState = state;
  1389. if (state) {
  1390. miniMapAnchorMin = rt.anchorMin;
  1391. miniMapAnchorMax = rt.anchorMax;
  1392. miniMapPivot = rt.pivot;
  1393. miniMapSizeDelta = rt.sizeDelta;
  1394. miniMapCurrentStyle = _miniMapStyle;
  1395. miniMapCameraAspect = miniMapCamera.aspect;
  1396. if (_miniMapStyle != MINIMAP_STYLE.SolidBox) {
  1397. miniMapStyle = MINIMAP_STYLE.SolidBox;
  1398. }
  1399. float padding = (1f - _miniMapFullScreenSize) * 0.5f;
  1400. float minX, minY, maxX, maxY;
  1401. minY = padding;
  1402. maxY = 1f - padding;
  1403. int height = (int)(cameraMain.pixelHeight * _miniMapFullScreenSize);
  1404. int width = _miniMapKeepAspectRatio ? height : (int)(cameraMain.pixelWidth * _miniMapFullScreenSize);
  1405. if (_miniMapKeepAspectRatio) {
  1406. float paddingW = (1f - _miniMapFullScreenSize / cameraMain.aspect) * 0.5f;
  1407. minX = paddingW;
  1408. maxX = 1f - paddingW;
  1409. } else {
  1410. minX = minY;
  1411. maxX = maxY;
  1412. miniMapCamera.aspect = (float)width / height;
  1413. }
  1414. rt.anchorMin = new Vector3 (minX, minY);
  1415. rt.anchorMax = new Vector3 (maxX, maxY);
  1416. rt.pivot = new Vector2 (0.5f, 0.5f);
  1417. rt.anchoredPosition = Vector2.zero;
  1418. rt.sizeDelta = new Vector2 (0, 0);
  1419. MiniMapResizeRenderTexture (width, height);
  1420. if (_miniMapFullScreenSize >= 1f && _miniMapDisableMainCameraInFullScreen && !_miniMapKeepAspectRatio) {
  1421. _cameraMain.enabled = false;
  1422. }
  1423. } else {
  1424. rt.anchorMin = miniMapAnchorMin;
  1425. rt.anchorMax = miniMapAnchorMax;
  1426. rt.pivot = miniMapPivot;
  1427. rt.sizeDelta = miniMapSizeDelta;
  1428. if (_miniMapStyle != miniMapCurrentStyle) {
  1429. miniMapStyle = miniMapCurrentStyle;
  1430. }
  1431. miniMapCamera.aspect = miniMapCameraAspect;
  1432. MiniMapResizeRenderTexture (_miniMapResolutionNormalSize, _miniMapResolutionNormalSize);
  1433. if (_miniMapFullScreenSize >= 1f && _miniMapDisableMainCameraInFullScreen && !_miniMapKeepAspectRatio) {
  1434. _cameraMain.enabled = true;
  1435. }
  1436. }
  1437. }
  1438. #endregion
  1439. #region Curved compass
  1440. void ToggleCurvedCompass () {
  1441. if (compassBackRect == null) {
  1442. return;
  1443. }
  1444. CompassBarMeshModifier m = compassBackImage.GetComponent<CompassBarMeshModifier> ();
  1445. if (_bendAmount == 0 && _edgeFadeOutWidth == 0) {
  1446. if (m != null) {
  1447. DestroyImmediate (m);
  1448. }
  1449. Image[] ii = compassBackRect.GetComponentsInChildren<Image> (true);
  1450. for (int k = 0; k < ii.Length; k++) {
  1451. ii [k].material = null;
  1452. }
  1453. // Adjust texts
  1454. Text[] tt = compassBackRect.GetComponentsInChildren<Text> (true);
  1455. for (int k = 0; k < tt.Length; k++) {
  1456. tt [k].material = null;
  1457. }
  1458. // Adjust ticks
  1459. RawImage[] im = compassBackRect.GetComponentsInChildren<RawImage> (true);
  1460. for (int k = 0; k < im.Length; k++) {
  1461. im [k].material = null;
  1462. }
  1463. } else {
  1464. if (curvedMat == null) {
  1465. curvedMat = Resources.Load<Material> ("CNPro/Materials/SpriteCurved");
  1466. }
  1467. if (defaultUICurvedMat == null) {
  1468. defaultUICurvedMat = Resources.Load<Material> ("CNPro/Materials/UIDefaultCurved");
  1469. }
  1470. Vector4 fxData = new Vector4 (_bendAmount, _width, _edgeFadeOutWidth, _edgeFadeOutStart);
  1471. curvedMat.SetVector ("_FXData", fxData);
  1472. defaultUICurvedMat.SetVector ("_FXData", fxData);
  1473. if (m == null) {
  1474. compassBackImage.gameObject.AddComponent<CompassBarMeshModifier> ();
  1475. }
  1476. // Images
  1477. Image[] ii = compassBackRect.GetComponentsInChildren<Image> (true);
  1478. for (int k = 0; k < ii.Length; k++) {
  1479. ii [k].material = curvedMat;
  1480. }
  1481. // Adjust texts
  1482. Text[] tt = compassBackRect.GetComponentsInChildren<Text> (true);
  1483. for (int k = 0; k < tt.Length; k++) {
  1484. tt [k].material = defaultUICurvedMat;
  1485. }
  1486. // Adjust ticks
  1487. RawImage[] im = compassBackRect.GetComponentsInChildren<RawImage> (true);
  1488. for (int k = 0; k < im.Length; k++) {
  1489. im [k].material = defaultUICurvedMat;
  1490. }
  1491. }
  1492. }
  1493. #endregion
  1494. }
  1495. }