EnviroTimeModule.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. namespace Enviro
  6. {
  7. [Serializable]
  8. public class EnviroTime
  9. {
  10. public bool simulate;
  11. public DateTime date = new DateTime(1,1,1,0,0,0);
  12. [SerializeField]
  13. public int secSerial, minSerial, hourSerial, daySerial, monthSerial, yearSerial;
  14. public float timeOfDay;
  15. [Range(-90, 90)]
  16. [Tooltip("-90, 90 Horizontal earth lines")]
  17. public float latitude;
  18. [Range(-180, 180)]
  19. [Tooltip("-180, 180 Vertical earth line")]
  20. public float longitude;
  21. [Range(-13, 13)]
  22. [Tooltip("Time offset for timezones")]
  23. public int utcOffset;
  24. [Tooltip("Realtime minutes for a 24h game time cycle.")]
  25. public float cycleLengthInMinutes = 10f;
  26. [Tooltip("Day length modifier will increase/decrease time progression speed at daytime.")]
  27. [Range(0.1f, 10f)]
  28. public float dayLengthModifier = 1f;
  29. [Tooltip("Night length modifier will increase/decrease time progression speed at nighttime.")]
  30. [Range(0.1f, 10f)]
  31. public float nightLengthModifier = 1f;
  32. }
  33. [Serializable]
  34. [ExecuteInEditMode]
  35. public class EnviroTimeModule : EnviroModule
  36. {
  37. public Enviro.EnviroTime Settings;
  38. public EnviroTimeModule preset;
  39. public bool showTimeControls,showLocationControls;
  40. private float LST;
  41. private float internalTimeOverflow;
  42. ///////// Time
  43. public void SetDateTime (int sec, int min, int hours, int day, int month, int year)
  44. {
  45. if(year == 0)
  46. year = 1;
  47. if(month == 0)
  48. month = 1;
  49. if(day == 0)
  50. day = 1;
  51. Settings.secSerial = sec;
  52. Settings.minSerial = min;
  53. Settings.hourSerial = hours;
  54. Settings.daySerial = day;
  55. Settings.monthSerial = month;
  56. Settings.yearSerial = year;
  57. DateTime curTime = new DateTime(1,1,1,0,0,0);
  58. curTime = curTime.AddYears(Settings.yearSerial-1);
  59. curTime = curTime.AddMonths(Settings.monthSerial-1);
  60. curTime = curTime.AddDays(Settings.daySerial-1);
  61. curTime = curTime.AddHours(Settings.hourSerial);
  62. curTime = curTime.AddMinutes(Settings.minSerial);
  63. curTime = curTime.AddSeconds(Settings.secSerial);
  64. //Events
  65. if(EnviroManager.instance.Events != null && EnviroManager.instance.notFirstFrame && Application.isPlaying)
  66. {
  67. if(Settings.date.Hour != curTime.Hour)
  68. EnviroManager.instance.NotifyHourPassed();
  69. if(Settings.date.Day != curTime.Day)
  70. EnviroManager.instance.NotifyDayPassed();
  71. if(Settings.date.Year != curTime.Year)
  72. EnviroManager.instance.NotifyYearPassed();
  73. }
  74. Settings.date = curTime;
  75. Settings.secSerial = Settings.date.Second;
  76. Settings.minSerial = Settings.date.Minute;
  77. Settings.hourSerial = Settings.date.Hour;
  78. Settings.daySerial = Settings.date.Day;
  79. Settings.monthSerial = Settings.date.Month;
  80. Settings.yearSerial = Settings.date.Year;
  81. Settings.timeOfDay = Settings.date.Hour + (Settings.date.Minute * 0.0166667f) + (Settings.date.Second * 0.000277778f);
  82. }
  83. //Time
  84. public int seconds
  85. {
  86. get
  87. {
  88. return Settings.date.Second;
  89. }
  90. set
  91. {
  92. //Settings.secSerial = value;
  93. SetDateTime(value,Settings.minSerial,Settings.hourSerial,Settings.daySerial,Settings.monthSerial,Settings.yearSerial);
  94. }
  95. }
  96. public int minutes
  97. {
  98. get
  99. {
  100. return Settings.date.Minute;
  101. }
  102. set
  103. {
  104. //Settings.minSerial = value;
  105. SetDateTime(Settings.secSerial,value,Settings.hourSerial,Settings.daySerial,Settings.monthSerial,Settings.yearSerial);
  106. }
  107. }
  108. public int hours
  109. {
  110. get
  111. {
  112. return Settings.date.Hour;
  113. }
  114. set
  115. {
  116. //Settings.hourSerial = value;
  117. SetDateTime(Settings.secSerial,Settings.minSerial,value,Settings.daySerial,Settings.monthSerial,Settings.yearSerial);
  118. }
  119. }
  120. public int days
  121. {
  122. get
  123. {
  124. return Settings.date.Day;
  125. }
  126. set
  127. {
  128. //Settings.daySerial = value;
  129. SetDateTime(Settings.secSerial,Settings.minSerial,Settings.hourSerial,value,Settings.monthSerial,Settings.yearSerial);
  130. }
  131. }
  132. public int months
  133. {
  134. get
  135. {
  136. return Settings.date.Month;
  137. }
  138. set
  139. {
  140. //Settings.monthSerial = value;
  141. SetDateTime(Settings.secSerial,Settings.minSerial,Settings.hourSerial,Settings.daySerial,value,Settings.yearSerial);
  142. }
  143. }
  144. public int years
  145. {
  146. get
  147. {
  148. return Settings.date.Year;
  149. }
  150. set
  151. {
  152. //Settings.yearSerial = value;
  153. SetDateTime(Settings.secSerial,Settings.minSerial,Settings.hourSerial,Settings.daySerial,Settings.monthSerial,value);
  154. }
  155. }
  156. // Update Method
  157. public override void UpdateModule ()
  158. {
  159. if(Settings.simulate && Application.isPlaying)
  160. {
  161. float t = 0f;
  162. float timeProgressionModifier = 1f;
  163. if(!EnviroManager.instance.isNight)
  164. {
  165. timeProgressionModifier = Settings.dayLengthModifier;
  166. }
  167. else
  168. {
  169. timeProgressionModifier = Settings.nightLengthModifier;
  170. }
  171. t = (24.0f / 60.0f) / (Settings.cycleLengthInMinutes * timeProgressionModifier);
  172. t = t * 3600f * Time.deltaTime;
  173. if(t < 1f)
  174. {
  175. internalTimeOverflow += t;
  176. }
  177. else
  178. {
  179. internalTimeOverflow = t;
  180. }
  181. seconds += (int)(internalTimeOverflow);
  182. if(internalTimeOverflow >= 1f)
  183. internalTimeOverflow = 0f;
  184. }
  185. SetDateTime(Settings.secSerial,Settings.minSerial,Settings.hourSerial,Settings.daySerial,Settings.monthSerial,Settings.yearSerial);
  186. UpdateSunAndMoonPosition();
  187. }
  188. public void UpdateSunAndMoonPosition()
  189. {
  190. float d = 367 * years - 7 * (years + (months / 12 + 9) / 12) / 4 + 275 * months / 9 + days - 730530;
  191. d += (GetUniversalTimeOfDay() / 24f); //Universal ToD
  192. float ecl = 23.4393f - 3.563E-7f * d;
  193. if(EnviroManager.instance.Sky != null)
  194. {
  195. if(EnviroManager.instance.Sky.Settings.moonMode == EnviroSky.MoonMode.Simple)
  196. {
  197. CalculateSunPosition(d, ecl, true);
  198. }
  199. else
  200. {
  201. CalculateSunPosition(d, ecl, false);
  202. CalculateMoonPosition(d, ecl);
  203. }
  204. }
  205. else
  206. {
  207. CalculateSunPosition(d, ecl, false);
  208. CalculateMoonPosition(d, ecl);
  209. }
  210. CalculateStarsPosition(LST);
  211. }
  212. /// <summary>
  213. /// Get current time in hours. UTC0 (12.5 = 12:30)
  214. /// </summary>
  215. /// <returns>The the current time of day in hours.</returns>
  216. public float GetUniversalTimeOfDay()
  217. {
  218. return Settings.timeOfDay - Settings.utcOffset;
  219. }
  220. /// <summary>
  221. /// Get current time in hours with UTC time offset.
  222. /// </summary>
  223. /// <returns>The the current time of day in hours.</returns>
  224. public float GetTimeOfDay()
  225. {
  226. return Settings.timeOfDay;
  227. }
  228. /// <summary>
  229. /// Get current date in hours.
  230. /// </summary>
  231. /// <returns>The date in hour format</returns>
  232. public double GetDateInHours()
  233. {
  234. double dateInHours = Settings.timeOfDay + (days * 24f) + ((years * 365) * 24f);
  235. return dateInHours;
  236. }
  237. /// <summary>
  238. /// Set the time of day in hours. (12.5 = 12:30)
  239. /// </summary>
  240. public void SetTimeOfDay(float tod)
  241. {
  242. Settings.timeOfDay = tod;
  243. hours = (int)(tod);
  244. tod -= hours;
  245. minutes = (int)(tod * 60f);
  246. tod -= minutes * 0.0166667f;
  247. seconds = (int)(tod * 3600f);
  248. }
  249. public Vector3 OrbitalToLocal(float theta, float phi)
  250. {
  251. Vector3 pos;
  252. float sinTheta = Mathf.Sin(theta);
  253. float cosTheta = Mathf.Cos(theta);
  254. float sinPhi = Mathf.Sin(phi);
  255. float cosPhi = Mathf.Cos(phi);
  256. pos.z = sinTheta * cosPhi;
  257. pos.y = cosTheta;
  258. pos.x = sinTheta * sinPhi;
  259. return pos;
  260. }
  261. public float Remap(float value, float from1, float to1, float from2, float to2)
  262. {
  263. return (value - from1) / (to1 - from1) * (to2 - from2) + from2;
  264. }
  265. public void CalculateSunPosition(float d, float ecl, bool simpleMoon)
  266. {
  267. /////http://www.stjarnhimlen.se/comp/ppcomp.html#5////
  268. ///////////////////////// SUN ////////////////////////
  269. float w = 282.9404f + 4.70935E-5f * d;
  270. float e = 0.016709f - 1.151E-9f * d;
  271. float M = 356.0470f + 0.9856002585f * d;
  272. float E = M + e * Mathf.Rad2Deg * Mathf.Sin(Mathf.Deg2Rad * M) * (1 + e * Mathf.Cos(Mathf.Deg2Rad * M));
  273. float xv = Mathf.Cos(Mathf.Deg2Rad * E) - e;
  274. float yv = Mathf.Sin(Mathf.Deg2Rad * E) * Mathf.Sqrt(1 - e * e);
  275. float v = Mathf.Rad2Deg * Mathf.Atan2(yv, xv);
  276. float r = Mathf.Sqrt(xv * xv + yv * yv);
  277. float l = v + w;
  278. float xs = r * Mathf.Cos(Mathf.Deg2Rad * l);
  279. float ys = r * Mathf.Sin(Mathf.Deg2Rad * l);
  280. float xe = xs;
  281. float ye = ys * Mathf.Cos(Mathf.Deg2Rad * ecl);
  282. float ze = ys * Mathf.Sin(Mathf.Deg2Rad * ecl);
  283. float decl_rad = Mathf.Atan2(ze, Mathf.Sqrt(xe * xe + ye * ye));
  284. float decl_sin = Mathf.Sin(decl_rad);
  285. float decl_cos = Mathf.Cos(decl_rad);
  286. float GMST0 = (l + 180);
  287. float GMST = GMST0 + GetUniversalTimeOfDay() * 15;
  288. LST = GMST + Settings.longitude;
  289. float HA_deg = LST - Mathf.Rad2Deg * Mathf.Atan2(ye, xe);
  290. float HA_rad = Mathf.Deg2Rad * HA_deg;
  291. float HA_sin = Mathf.Sin(HA_rad);
  292. float HA_cos = Mathf.Cos(HA_rad);
  293. float x = HA_cos * decl_cos;
  294. float y = HA_sin * decl_cos;
  295. float z = decl_sin;
  296. float sin_Lat = Mathf.Sin(Mathf.Deg2Rad * Settings.latitude);
  297. float cos_Lat = Mathf.Cos(Mathf.Deg2Rad * Settings.latitude);
  298. float xhor = x * sin_Lat - z * cos_Lat;
  299. float yhor = y;
  300. float zhor = x * cos_Lat + z * sin_Lat;
  301. float azimuth = Mathf.Atan2(yhor, xhor) + Mathf.Deg2Rad * 180;
  302. float altitude = Mathf.Atan2(zhor, Mathf.Sqrt(xhor * xhor + yhor * yhor));
  303. float sunTheta = (90 * Mathf.Deg2Rad) - altitude;
  304. float sunPhi = azimuth;
  305. //Set SolarTime: 1 = mid-day (sun directly above you), 0.5 = sunset/dawn, 0 = midnight;
  306. EnviroManager.instance.solarTime = Mathf.Clamp01(Remap(sunTheta, -1.5f, 0f, 1.5f, 1f));
  307. EnviroManager.instance.Objects.sun.transform.localPosition = OrbitalToLocal(sunTheta, sunPhi);
  308. EnviroManager.instance.Objects.sun.transform.LookAt(EnviroManager.instance.transform);
  309. if (simpleMoon)
  310. {
  311. EnviroManager.instance.Objects.moon.transform.localPosition = OrbitalToLocal(sunTheta - Mathf.PI, sunPhi);
  312. EnviroManager.instance.lunarTime = Mathf.Clamp01(Remap(sunTheta - Mathf.PI, -3.0f, 0f, 0f, 1f));
  313. EnviroManager.instance.Objects.moon.transform.LookAt(EnviroManager.instance.transform);
  314. }
  315. }
  316. public void CalculateMoonPosition(float d, float ecl)
  317. {
  318. float N = 125.1228f - 0.0529538083f * d;
  319. float i = 5.1454f;
  320. float w = 318.0634f + 0.1643573223f * d;
  321. float a = 60.2666f;
  322. float e = 0.054900f;
  323. float M = 115.3654f + 13.0649929509f * d;
  324. float rad_M = Mathf.Deg2Rad * M;
  325. float E = rad_M + e * Mathf.Sin(rad_M) * (1f + e * Mathf.Cos(rad_M));
  326. float xv = a * (Mathf.Cos(E) - e);
  327. float yv = a * (Mathf.Sqrt(1f - e * e) * Mathf.Sin(E));
  328. float v = Mathf.Rad2Deg * Mathf.Atan2(yv, xv);
  329. float r = Mathf.Sqrt(xv * xv + yv * yv);
  330. float rad_N = Mathf.Deg2Rad * N;
  331. float sin_N = Mathf.Sin(rad_N);
  332. float cos_N = Mathf.Cos(rad_N);
  333. float l = Mathf.Deg2Rad * (v + w);
  334. float sin_l = Mathf.Sin(l);
  335. float cos_l = Mathf.Cos(l);
  336. float rad_i = Mathf.Deg2Rad * i;
  337. float cos_i = Mathf.Cos(rad_i);
  338. float xh = r * (cos_N * cos_l - sin_N * sin_l * cos_i);
  339. float yh = r * (sin_N * cos_l + cos_N * sin_l * cos_i);
  340. float zh = r * (sin_l * Mathf.Sin(rad_i));
  341. float cos_ecl = Mathf.Cos(Mathf.Deg2Rad * ecl);
  342. float sin_ecl = Mathf.Sin(Mathf.Deg2Rad * ecl);
  343. float xe = xh;
  344. float ye = yh * cos_ecl - zh * sin_ecl;
  345. float ze = yh * sin_ecl + zh * cos_ecl;
  346. float ra = Mathf.Atan2(ye, xe);
  347. float decl = Mathf.Atan2(ze, Mathf.Sqrt(xe * xe + ye * ye));
  348. float HA = Mathf.Deg2Rad * LST - ra;
  349. float x = Mathf.Cos(HA) * Mathf.Cos(decl);
  350. float y = Mathf.Sin(HA) * Mathf.Cos(decl);
  351. float z = Mathf.Sin(decl);
  352. float latitude = Mathf.Deg2Rad * Settings.latitude;
  353. float sin_latitude = Mathf.Sin(latitude);
  354. float cos_latitude = Mathf.Cos(latitude);
  355. float xhor = x * sin_latitude - z * cos_latitude;
  356. float yhor = y;
  357. float zhor = x * cos_latitude + z * sin_latitude;
  358. float azimuth = Mathf.Atan2(yhor, xhor) + Mathf.Deg2Rad * 180f;
  359. float altitude = Mathf.Atan2(zhor, Mathf.Sqrt(xhor * xhor + yhor * yhor));
  360. float MoonTheta = (90f * Mathf.Deg2Rad) - altitude;
  361. float MoonPhi = azimuth;
  362. EnviroManager.instance.Objects.moon.transform.localPosition = OrbitalToLocal(MoonTheta, MoonPhi);
  363. EnviroManager.instance.lunarTime = Mathf.Clamp01(Remap(MoonTheta, -1.5f, 0f, 1.5f, 1f));
  364. EnviroManager.instance.Objects.moon.transform.LookAt(EnviroManager.instance.transform.position);
  365. }
  366. public void CalculateStarsPosition(float siderealTime)
  367. {
  368. if (siderealTime > 24) siderealTime -= 24;
  369. else if (siderealTime < 0) siderealTime += 24;
  370. Quaternion starsRotation = Quaternion.Euler(90 - Settings.latitude, Mathf.Deg2Rad * Settings.longitude, 0);
  371. starsRotation *= Quaternion.Euler(0, siderealTime, 0);
  372. EnviroManager.instance.Objects.stars.transform.localRotation = starsRotation;
  373. Shader.SetGlobalMatrix("_StarsMatrix", EnviroManager.instance.Objects.stars.transform.worldToLocalMatrix);
  374. }
  375. //Save and Load
  376. public void LoadModuleValues ()
  377. {
  378. if(preset != null)
  379. {
  380. Settings = JsonUtility.FromJson<Enviro.EnviroTime>(JsonUtility.ToJson(preset.Settings));
  381. }
  382. else
  383. {
  384. Debug.Log("Please assign a saved module to load from!");
  385. }
  386. }
  387. public void SaveModuleValues ()
  388. {
  389. #if UNITY_EDITOR
  390. EnviroTimeModule t = ScriptableObject.CreateInstance<EnviroTimeModule>();
  391. t.name = "Time Preset";
  392. t.Settings = JsonUtility.FromJson<Enviro.EnviroTime>(JsonUtility.ToJson(Settings));
  393. string assetPathAndName = UnityEditor.AssetDatabase.GenerateUniqueAssetPath("Assets/Enviro 3" + "/New " + t.name + ".asset");
  394. UnityEditor.AssetDatabase.CreateAsset(t, assetPathAndName);
  395. UnityEditor.AssetDatabase.SaveAssets();
  396. UnityEditor.AssetDatabase.Refresh();
  397. #endif
  398. }
  399. public void SaveModuleValues (EnviroTimeModule module)
  400. {
  401. module.Settings = JsonUtility.FromJson<Enviro.EnviroTime>(JsonUtility.ToJson(Settings));
  402. #if UNITY_EDITOR
  403. UnityEditor.EditorUtility.SetDirty(module);
  404. UnityEditor.AssetDatabase.SaveAssets();
  405. #endif
  406. }
  407. }
  408. }