SkyProfileEditor.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6. using UnityEditor;
  7. using UnityEngine.SceneManagement;
  8. namespace Funly.SkyStudio
  9. {
  10. [CustomEditor(typeof(SkyProfile))]
  11. public class SkyProfileEditor : Editor
  12. {
  13. private static string SHADER_NAME_PREFIX = "Funly/Sky Studio/Skybox";
  14. private SkyProfile m_Profile;
  15. private SkyBuilder m_Builder;
  16. private Texture2D m_SectionHeaderBg;
  17. private Dictionary<string, ProfileFeatureSection> m_Sections;
  18. private const float k_IconSize = 20.0f;
  19. private const int k_TitleSize = 12;
  20. private const int k_HeaderHeight = 20;
  21. private string m_SpherePointSelectionToken;
  22. // The setup window will set this value to force the first load rebuild.
  23. public static int forceRebuildProfileId;
  24. private void OnEnable()
  25. {
  26. serializedObject.Update();
  27. m_Profile = (SkyProfile)target;
  28. m_SectionHeaderBg = CreateColorImage(SectionColorForEditorSkin());
  29. // Make the sure the profile's features are in sync with shader material.
  30. ApplyKeywordsToMaterial();
  31. }
  32. public override void OnInspectorGUI()
  33. {
  34. serializedObject.Update();
  35. m_Profile = (SkyProfile)target;
  36. // For new profiles we'll automatically build them.
  37. if (forceRebuildProfileId != -1 && forceRebuildProfileId == m_Profile.GetInstanceID()) {
  38. RebuildSkySystem();
  39. forceRebuildProfileId = -1;
  40. }
  41. if (RenderSkyboxMaterial() == false) {
  42. serializedObject.ApplyModifiedProperties();
  43. return;
  44. }
  45. if (m_Sections == null) {
  46. m_Sections = new Dictionary<string, ProfileFeatureSection>();
  47. }
  48. foreach (ProfileFeatureSection section in m_Profile.featureDefinitions) {
  49. m_Sections[section.sectionKey] = section;
  50. }
  51. bool didChangeProfile = false;
  52. // Features.
  53. if (RenderFeatureSection()) {
  54. didChangeProfile = true;
  55. }
  56. // Timeline.
  57. if (RenderTimelineList()) {
  58. didChangeProfile = true;
  59. }
  60. // Properties.
  61. if (RenderProfileDefinitions()) {
  62. didChangeProfile = true;
  63. }
  64. TimeOfDayController tc = GameObject.FindObjectOfType<TimeOfDayController>();
  65. if (tc != null) {
  66. tc.UpdateSkyForCurrentTime();
  67. }
  68. serializedObject.ApplyModifiedProperties();
  69. if (didChangeProfile) {
  70. EditorUtility.SetDirty(m_Profile);
  71. }
  72. }
  73. private Color SectionColorForEditorSkin()
  74. {
  75. if (EditorGUIUtility.isProSkin)
  76. {
  77. float gray = 190.0f / 225.0f;
  78. return new Color(gray, gray, gray, 1.0f);
  79. }
  80. else
  81. {
  82. float gray = 222.0f / 225.0f;
  83. return new Color(gray, gray, gray, 1.0f);
  84. }
  85. }
  86. private bool RenderProfileDefinitions()
  87. {
  88. bool didChangeProfile = false;
  89. foreach (ProfileGroupSection groupSection in m_Profile.groupDefinitions)
  90. {
  91. if (groupSection.dependsOnFeature != null &&
  92. groupSection.dependsOnValue != m_Profile.IsFeatureEnabled(groupSection.dependsOnFeature)) {
  93. continue;
  94. }
  95. bool valueChanged = RenderSection(groupSection.sectionKey);
  96. if (valueChanged) {
  97. didChangeProfile = true;
  98. }
  99. }
  100. return didChangeProfile;
  101. }
  102. private bool RenderSkyboxMaterial()
  103. {
  104. EditorGUILayout.PropertyField(serializedObject.FindProperty("m_SkyboxMaterial"));
  105. if (SkyboxMaterial() == null)
  106. {
  107. EditorGUILayout.HelpBox("You need to assign a Funly Sky Studio skybox material" +
  108. " before you can edit the sky profile.", MessageType.Info);
  109. return false;
  110. }
  111. if (SkyboxMaterial().shader.name.Contains(SHADER_NAME_PREFIX) == false)
  112. {
  113. EditorGUILayout.HelpBox("Skybox material has an unsupported shader. You need to use a shader" +
  114. " in the Funly/Sky/ directory.", MessageType.Error);
  115. return false;
  116. }
  117. return true;
  118. }
  119. private void RebuildSkySystem()
  120. {
  121. if (m_Builder != null)
  122. {
  123. m_Builder.CancelBuild();
  124. m_Builder = null;
  125. }
  126. m_Builder = CreateSkyBuilder();
  127. if (m_Builder.IsComplete == false) {
  128. return;
  129. }
  130. m_Builder.BuildSkySystem();
  131. }
  132. private bool RenderFeatureSection()
  133. {
  134. RenderSectionTitle("Features", "FeatureSectionIcon");
  135. bool didChangeProfile = false;
  136. string[] rebuildSkyKeywords = new string[]
  137. {
  138. ShaderKeywords.StarLayer1,
  139. ShaderKeywords.StarLayer2,
  140. ShaderKeywords.StarLayer3
  141. };
  142. if (m_Sections.ContainsKey(ProfileSectionKeys.FeaturesSectionKey) == false)
  143. {
  144. Debug.LogError("Shader definition is missing a features dictionary");
  145. return didChangeProfile;
  146. }
  147. ProfileFeatureSection section = m_Sections[ProfileSectionKeys.FeaturesSectionKey];
  148. foreach (ProfileFeatureDefinition def in section.featureDefinitions)
  149. {
  150. if (def.dependsOnFeature != null) {
  151. if (m_Profile.IsFeatureEnabled(def.dependsOnFeature) != def.dependsOnValue) {
  152. m_Profile.SetFeatureEnabled(def.featureKey, false);
  153. didChangeProfile = true;
  154. continue;
  155. }
  156. }
  157. bool valueChanged;
  158. RenderFeatureCheckbox(
  159. def,
  160. m_Profile.IsFeatureEnabled(def.featureKey),
  161. out valueChanged);
  162. if (valueChanged && rebuildSkyKeywords.Contains(def.shaderKeyword)) {
  163. RebuildSkySystem();
  164. }
  165. if (valueChanged) {
  166. didChangeProfile = true;
  167. }
  168. }
  169. return didChangeProfile;
  170. }
  171. private bool RenderFeatureCheckbox(ProfileFeatureDefinition def, bool keywordValue, out bool valueChanged)
  172. {
  173. EditorGUI.BeginChangeCheck();
  174. bool value = EditorGUILayout.Toggle(def.name, keywordValue);
  175. if (EditorGUI.EndChangeCheck())
  176. {
  177. // FIXME - Why doesn't the sky profile do this for us when we enable the feature?
  178. if (def.featureType == ProfileFeatureDefinition.FeatureType.ShaderKeyword) {
  179. SetShaderKeyword(def.shaderKeyword, value);
  180. }
  181. m_Profile.SetFeatureEnabled(def.featureKey, value);
  182. valueChanged = true;
  183. } else {
  184. valueChanged = false;
  185. }
  186. return value;
  187. }
  188. private Material SkyboxMaterial()
  189. {
  190. if (serializedObject.FindProperty("m_SkyboxMaterial") == null)
  191. {
  192. return null;
  193. }
  194. return serializedObject.FindProperty("m_SkyboxMaterial").objectReferenceValue as Material;
  195. }
  196. private void ApplyKeywordsToMaterial() {
  197. if (SkyboxMaterial() == null) {
  198. return;
  199. }
  200. ApplyKeywordsToMaterial(m_Profile, SkyboxMaterial());
  201. }
  202. public static void ApplyKeywordsToMaterial(SkyProfile profile, Material skyboxMaterial)
  203. {
  204. foreach (ProfileFeatureSection section in profile.featureDefinitions)
  205. {
  206. foreach (ProfileFeatureDefinition definition in section.featureDefinitions)
  207. {
  208. SetShaderKeyword(
  209. definition.shaderKeyword,
  210. profile.IsFeatureEnabled(definition.featureKey),
  211. skyboxMaterial);
  212. }
  213. }
  214. }
  215. private void SetShaderKeyword(string keyword, bool value)
  216. {
  217. SetShaderKeyword(keyword, value, SkyboxMaterial());
  218. }
  219. private static void SetShaderKeyword(string keyword, bool value, Material skyboxMaterial)
  220. {
  221. if (value)
  222. {
  223. skyboxMaterial.EnableKeyword(keyword);
  224. }
  225. else
  226. {
  227. skyboxMaterial.DisableKeyword(keyword);
  228. }
  229. }
  230. private bool RenderTimelineList()
  231. {
  232. bool didChangeProfile = false;
  233. RenderSectionTitle("Timeline Animated Properties", "TimelineSectionIcon");
  234. EditorGUILayout.Space();
  235. List<ProfileGroupDefinition> onTimeline = m_Profile.GetGroupDefinitionsManagedByTimeline();
  236. List<ProfileGroupDefinition> offTimeline = m_Profile.GetGroupDefinitionsNotManagedByTimeline();
  237. int deleteIndex = -1;
  238. bool didSwapRows = false;
  239. int swapIndex1 = -1;
  240. int swapIndex2 = -1;
  241. if (onTimeline.Count == 0)
  242. {
  243. // Show definition message if no items added yet.
  244. EditorGUILayout.HelpBox("You can animate properties by adding them to the timeline.", MessageType.None);
  245. }
  246. else
  247. {
  248. EditorGUI.BeginChangeCheck();
  249. List<string> timelineTitles = GetTitlesForGroups(onTimeline);
  250. StringTableListGUI.RenderTableList(
  251. timelineTitles,
  252. out deleteIndex,
  253. out didSwapRows,
  254. out swapIndex1,
  255. out swapIndex2);
  256. // Check for table modification events (remove, reorder, etc.)
  257. if (EditorGUI.EndChangeCheck()) {
  258. didChangeProfile = true;
  259. if (deleteIndex != -1) {
  260. string deleteGroupKey = onTimeline[deleteIndex].propertyKey;
  261. IKeyframeGroup group = m_Profile.GetGroup(deleteGroupKey);
  262. if (SkyEditorUtility.IsGroupSelectedOnTimeline(group.id)) {
  263. TimelineSelection.Clear();
  264. // If we deleted a sphere point group make sure to hide the debug dots.
  265. if (group is SpherePointKeyframeGroup && m_Profile.skyboxMaterial != null) {
  266. m_Profile.skyboxMaterial.DisableKeyword(ShaderKeywords.RenderDebugPoints);
  267. }
  268. }
  269. m_Profile.timelineManagedKeys.Remove(deleteGroupKey);
  270. m_Profile.TrimGroupToSingleKeyframe(deleteGroupKey);
  271. } else if (didSwapRows) {
  272. string tmp = m_Profile.timelineManagedKeys[swapIndex2];
  273. m_Profile.timelineManagedKeys[swapIndex2] = m_Profile.timelineManagedKeys[swapIndex1];
  274. m_Profile.timelineManagedKeys[swapIndex1] = tmp;
  275. }
  276. }
  277. }
  278. EditorGUILayout.BeginHorizontal();
  279. GUILayout.FlexibleSpace();
  280. if (GUILayout.Button(new GUIContent("Open Timeline"))) {
  281. SkyTimelineWindow.ShowWindow();
  282. }
  283. if (GUILayout.Button(new GUIContent("Add to Timeline"))) {
  284. SkyGUITimelineMenu.ShowAddTimelinePropertyMenu(m_Profile, offTimeline);
  285. }
  286. EditorGUILayout.EndHorizontal();
  287. return didChangeProfile;
  288. }
  289. // Render all properties for a section.
  290. public bool RenderSection(string sectionKey, params string[] ignoreGroups)
  291. {
  292. ProfileGroupSection sectionInfo = m_Profile.GetSectionInfo(sectionKey);
  293. RenderSectionTitle(sectionInfo.sectionTitle, sectionInfo.sectionIcon);
  294. bool didChangeProfile = false;
  295. // Render all the feature checkboxes for the section.
  296. if (m_Sections.ContainsKey(sectionKey)) {
  297. ProfileFeatureSection keywordSection = m_Sections[sectionKey];
  298. foreach (ProfileFeatureDefinition def in keywordSection.featureDefinitions)
  299. {
  300. // Check for keyword dependencies.
  301. if (def.dependsOnFeature != null) {
  302. if (m_Profile.IsFeatureEnabled(def.dependsOnFeature) != def.dependsOnValue) {
  303. continue;
  304. }
  305. }
  306. // Render the feature UI.
  307. bool valueChanged = false;
  308. if (def.featureType == ProfileFeatureDefinition.FeatureType.BooleanValue ||
  309. def.featureType == ProfileFeatureDefinition.FeatureType.ShaderKeyword) {
  310. RenderFeatureCheckbox(
  311. def,
  312. m_Profile.IsFeatureEnabled(def.featureKey),
  313. out valueChanged);
  314. } else if (def.featureType == ProfileFeatureDefinition.FeatureType.ShaderKeywordDropdown) {
  315. RenderDropdownShaderFeature(
  316. def,
  317. out valueChanged);
  318. }
  319. if (valueChanged) {
  320. didChangeProfile = true;
  321. }
  322. }
  323. }
  324. // Render all the property groups for this section.
  325. foreach (ProfileGroupDefinition groupInfo in sectionInfo.groups)
  326. {
  327. bool shouldIgnore = false;
  328. foreach (string ignoreName in ignoreGroups)
  329. {
  330. if (groupInfo.groupName.Contains(ignoreName))
  331. {
  332. shouldIgnore = true;
  333. break;
  334. }
  335. }
  336. if (shouldIgnore)
  337. {
  338. continue;
  339. }
  340. bool valueChanged = RenderProfileGroup(groupInfo);
  341. if (valueChanged) {
  342. didChangeProfile = true;
  343. }
  344. }
  345. // Render any section specific non-timeline properties.
  346. if (sectionKey == ProfileSectionKeys.LightningSectionKey) {
  347. EditorGUILayout.ObjectField(serializedObject.FindProperty("lightningArtSet"));
  348. } else if (sectionKey == ProfileSectionKeys.RainSplashSectionKey) {
  349. EditorGUILayout.ObjectField(serializedObject.FindProperty("rainSplashArtSet"));
  350. }
  351. return didChangeProfile;
  352. }
  353. private void RenderDropdownShaderFeature(ProfileFeatureDefinition def, out bool valueChanged)
  354. {
  355. valueChanged = false;
  356. int currentIndex = def.dropdownSelectedIndex;
  357. // State is maintained in the feature flags, so find the one that's enabled.
  358. for (int i = 0; i < def.featureKeys.Length; i++) {
  359. string feature = def.featureKeys[i];
  360. if (m_Profile.IsFeatureEnabled(feature)) {
  361. currentIndex = i;
  362. break;
  363. }
  364. }
  365. EditorGUI.BeginChangeCheck();
  366. int selectedIndex = EditorGUILayout.Popup(def.name, currentIndex, def.dropdownLabels);
  367. if (EditorGUI.EndChangeCheck()) {
  368. valueChanged = true;
  369. // Clear and set new shader keyword for this dropdown.
  370. SetShaderKeywordAndFeatureFlag(def.shaderKeywords[currentIndex], def.featureKeys[currentIndex], false);
  371. SetShaderKeywordAndFeatureFlag(def.shaderKeywords[selectedIndex], def.featureKeys[selectedIndex], true);
  372. }
  373. }
  374. public void SetShaderKeywordAndFeatureFlag(string shaderKeyword, string featureKey, bool value)
  375. {
  376. SetShaderKeyword(shaderKeyword, value);
  377. m_Profile.SetFeatureEnabled(featureKey, value);
  378. }
  379. // Render all properties in a group.
  380. public bool RenderProfileGroup(ProfileGroupDefinition groupDefinition)
  381. {
  382. if (groupDefinition.dependsOnFeature != null &&
  383. m_Profile.IsFeatureEnabled(groupDefinition.dependsOnFeature) != groupDefinition.dependsOnValue)
  384. {
  385. return false;
  386. }
  387. bool valueChanged = false;
  388. if (groupDefinition.type == ProfileGroupDefinition.GroupType.Color)
  389. {
  390. valueChanged = RenderColorGroupProperty(groupDefinition);
  391. } else if (groupDefinition.type == ProfileGroupDefinition.GroupType.Number)
  392. {
  393. valueChanged = RenderNumericGroupProperty(groupDefinition);
  394. } else if (groupDefinition.type == ProfileGroupDefinition.GroupType.Texture)
  395. {
  396. valueChanged = RenderTextureGroupProperty(groupDefinition);
  397. } else if (groupDefinition.type == ProfileGroupDefinition.GroupType.SpherePoint)
  398. {
  399. valueChanged = RenderSpherePointPropertyGroup(groupDefinition);
  400. } else if (groupDefinition.type == ProfileGroupDefinition.GroupType.Boolean) {
  401. valueChanged = RenderBooleanPropertyGroup(groupDefinition);
  402. }
  403. // Check if this property needs to rebuild the sky.
  404. if (valueChanged && groupDefinition.rebuildType == ProfileGroupDefinition.RebuildType.Stars)
  405. {
  406. RebuildSkySystem();
  407. }
  408. return valueChanged;
  409. }
  410. // Render color property.
  411. public bool RenderColorGroupProperty(ProfileGroupDefinition def)
  412. {
  413. EditorGUILayout.BeginHorizontal();
  414. ColorKeyframeGroup group = m_Profile.GetGroup<ColorKeyframeGroup>(def.propertyKey);
  415. EditorGUILayout.PrefixLabel(new GUIContent(group.name, def.tooltip));
  416. bool valueChanged = false;
  417. if (m_Profile.IsManagedByTimeline(def.propertyKey))
  418. {
  419. RenderManagedOnTimlineMessage();
  420. }
  421. else
  422. {
  423. ColorKeyframe frame = group.GetKeyframe(0);
  424. EditorGUI.BeginChangeCheck();
  425. Color selectedColor = EditorGUILayout.ColorField(frame.color);
  426. if (EditorGUI.EndChangeCheck())
  427. {
  428. Undo.RecordObject(m_Profile, "Changed color keyframe value");
  429. frame.color = selectedColor;
  430. valueChanged = true;
  431. }
  432. }
  433. EditorGUILayout.EndHorizontal();
  434. return valueChanged;
  435. }
  436. // Render numeric properties with a slider.
  437. public bool RenderNumericGroupProperty(ProfileGroupDefinition def)
  438. {
  439. EditorGUILayout.BeginHorizontal();
  440. NumberKeyframeGroup group = m_Profile.GetGroup<NumberKeyframeGroup>(def.propertyKey);
  441. EditorGUILayout.PrefixLabel(new GUIContent(group.name, def.tooltip));
  442. bool valueChanged = false;
  443. if (m_Profile.IsManagedByTimeline(def.propertyKey))
  444. {
  445. RenderManagedOnTimlineMessage();
  446. }
  447. else
  448. {
  449. NumberKeyframe frame = group.GetKeyframe(0);
  450. if (def.formatStyle == ProfileGroupDefinition.FormatStyle.Integer)
  451. {
  452. EditorGUI.BeginChangeCheck();
  453. int value = EditorGUILayout.IntField((int) frame.value);
  454. if (EditorGUI.EndChangeCheck())
  455. {
  456. Undo.RecordObject(m_Profile, "Changed int keyframe value");
  457. frame.value = (int) Mathf.Clamp(value, group.minValue, group.maxValue);
  458. valueChanged = true;
  459. }
  460. }
  461. else
  462. {
  463. EditorGUI.BeginChangeCheck();
  464. float value = EditorGUILayout.Slider(frame.value, group.minValue, group.maxValue);
  465. if (EditorGUI.EndChangeCheck())
  466. {
  467. Undo.RecordObject(m_Profile, "Changed float keyframe value");
  468. frame.value = value;
  469. valueChanged = true;
  470. }
  471. }
  472. }
  473. EditorGUILayout.EndHorizontal();
  474. return valueChanged;
  475. }
  476. // Render texture property.
  477. public bool RenderTextureGroupProperty(ProfileGroupDefinition def)
  478. {
  479. EditorGUILayout.BeginHorizontal();
  480. TextureKeyframeGroup group = m_Profile.GetGroup<TextureKeyframeGroup>(def.propertyKey);
  481. EditorGUILayout.PrefixLabel(new GUIContent(group.name, def.tooltip));
  482. bool valueChanged = false;
  483. if (m_Profile.IsManagedByTimeline(def.propertyKey))
  484. {
  485. RenderManagedOnTimlineMessage();
  486. }
  487. else
  488. {
  489. TextureKeyframe frame = group.GetKeyframe(0);
  490. EditorGUI.BeginChangeCheck();
  491. Texture assignedTexture = (Texture) EditorGUILayout.ObjectField(frame.texture, typeof(Texture), true);
  492. if (EditorGUI.EndChangeCheck())
  493. {
  494. Undo.RecordObject(m_Profile, "Changed texture keyframe value");
  495. frame.texture = assignedTexture;
  496. valueChanged = true;
  497. }
  498. }
  499. EditorGUILayout.EndHorizontal();
  500. return valueChanged;
  501. }
  502. private bool RenderBooleanPropertyGroup(ProfileGroupDefinition def)
  503. {
  504. EditorGUILayout.BeginHorizontal();
  505. BoolKeyframeGroup group = m_Profile.GetGroup<BoolKeyframeGroup>(def.propertyKey);
  506. EditorGUILayout.PrefixLabel(new GUIContent(group.name, def.tooltip));
  507. bool valueChanged = false;
  508. if (m_Profile.IsManagedByTimeline(def.propertyKey)) {
  509. RenderManagedOnTimlineMessage();
  510. } else {
  511. BoolKeyframe frame = group.GetKeyframe(0);
  512. EditorGUI.BeginChangeCheck();
  513. bool assignedValue = EditorGUILayout.Toggle(frame.value);
  514. if (EditorGUI.EndChangeCheck()) {
  515. Undo.RecordObject(m_Profile, "Changed bool keyframe value");
  516. frame.value = assignedValue;
  517. valueChanged = true;
  518. }
  519. }
  520. EditorGUILayout.EndHorizontal();
  521. return valueChanged;
  522. }
  523. private bool RenderSpherePointPropertyGroup(ProfileGroupDefinition def)
  524. {
  525. EditorGUILayout.BeginHorizontal();
  526. bool valueChanged = false;
  527. SpherePointKeyframeGroup group = m_Profile.GetGroup<SpherePointKeyframeGroup>(def.propertyKey);
  528. if (m_Profile.IsManagedByTimeline(def.propertyKey))
  529. {
  530. EditorGUILayout.PrefixLabel(new GUIContent(def.groupName, def.tooltip));
  531. RenderManagedOnTimlineMessage();
  532. }
  533. else
  534. {
  535. SpherePointKeyframe frame = group.GetKeyframe(0);
  536. EditorGUILayout.BeginVertical();
  537. EditorGUILayout.BeginHorizontal();
  538. EditorGUILayout.LabelField(new GUIContent(group.name, def.tooltip));
  539. GUILayout.FlexibleSpace();
  540. EditorGUILayout.EndHorizontal();
  541. EditorGUI.BeginChangeCheck();
  542. EditorGUI.indentLevel += 1;
  543. SpherePoint selectedPoint = SpherePointGUI.SpherePointField(
  544. frame.spherePoint, true, frame.id);
  545. EditorGUI.indentLevel -= 1;
  546. if (EditorGUI.EndChangeCheck())
  547. {
  548. Undo.RecordObject(m_Profile, "Changed sphere point");
  549. frame.spherePoint = selectedPoint;
  550. }
  551. EditorGUILayout.EndVertical();
  552. }
  553. EditorGUILayout.EndHorizontal();
  554. return valueChanged;
  555. }
  556. private void RenderManagedOnTimlineMessage()
  557. {
  558. GUIStyle style = new GUIStyle(GUI.skin.label);
  559. style.fontStyle = FontStyle.Italic;
  560. EditorGUILayout.LabelField("Managed on timeline", style);
  561. }
  562. private void RenderSectionTitle(string title, string iconName)
  563. {
  564. GUIStyle bgStyle = new GUIStyle();
  565. bgStyle.normal.background = m_SectionHeaderBg;
  566. bgStyle.margin = new RectOffset(0, 0, 20, 7);
  567. bgStyle.padding = new RectOffset(0, 0, 0, 0);
  568. GUIStyle titleStyle = new GUIStyle(GUI.skin.label);
  569. titleStyle.normal.textColor = Color.black;
  570. titleStyle.fontStyle = FontStyle.Bold;
  571. titleStyle.fontSize = k_TitleSize;
  572. titleStyle.margin = new RectOffset(0, 0, 0, 0);
  573. titleStyle.padding = new RectOffset(0, 0, 3, 0);
  574. GUIStyle iconStyle = new GUIStyle();
  575. iconStyle.margin = new RectOffset(0, 0, 0, 0);
  576. iconStyle.padding = new RectOffset(0, 0, 0, 0);
  577. EditorGUILayout.BeginHorizontal(bgStyle, GUILayout.Height(k_HeaderHeight));
  578. // Default to a placeholder icon if we don't have one.
  579. string loadIconFile = iconName != null ? iconName : "UnknownSectionIcon";
  580. Texture icon = SkyEditorUtility.LoadEditorResourceTexture(loadIconFile);
  581. EditorGUILayout.LabelField(new GUIContent(icon), iconStyle, GUILayout.Width(k_IconSize), GUILayout.Height(k_IconSize));
  582. EditorGUILayout.LabelField(new GUIContent(title), titleStyle);
  583. GUILayout.FlexibleSpace();
  584. EditorGUILayout.EndHorizontal();
  585. }
  586. private Texture2D CreateColorImage(Color c)
  587. {
  588. Texture2D tex = new Texture2D(1, 1);
  589. tex.SetPixel(0, 0, c);
  590. tex.Apply();
  591. return tex;
  592. }
  593. private SkyBuilder CreateSkyBuilder()
  594. {
  595. SkyBuilder b = new SkyBuilder();
  596. b.profile = m_Profile;
  597. b.starLayer1Enabled = m_Profile.IsFeatureEnabled(ProfileFeatureKeys.StarLayer1Feature);
  598. b.starLayer2Enabled = m_Profile.IsFeatureEnabled(ProfileFeatureKeys.StarLayer2Feature); ;
  599. b.starLayer3Enabled = m_Profile.IsFeatureEnabled(ProfileFeatureKeys.StarLayer3Feature); ;
  600. b.starLayer1Density = m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star1DensityKey).GetFirstValue();
  601. b.starLayer2Density = m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star2DensityKey).GetFirstValue();
  602. b.starLayer3Density = m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star3DensityKey).GetFirstValue();
  603. b.starLayer1MaxRadius = GetMaxValueForGroup(m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star1SizeKey));
  604. b.starLayer2MaxRadius = GetMaxValueForGroup(m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star2SizeKey));
  605. b.starLayer3MaxRadius = GetMaxValueForGroup(m_Profile.GetGroup<NumberKeyframeGroup>(ProfilePropertyKeys.Star3SizeKey));
  606. b.skyboxMaterial = m_Profile.skyboxMaterial;
  607. b.completionCallback += BuilderCompletion;
  608. return b;
  609. }
  610. private float GetMaxValueForGroup(NumberKeyframeGroup group) {
  611. float maxValue = 0;
  612. for (int i = 0; i < group.keyframes.Count; i++) {
  613. if (i == 0 || group.keyframes[i].value > maxValue) {
  614. maxValue = group.keyframes[i].value;
  615. }
  616. }
  617. return maxValue;
  618. }
  619. private void BuilderCompletion(SkyBuilder builder, bool successful)
  620. {
  621. m_Builder.completionCallback -= BuilderCompletion;
  622. m_Builder = null;
  623. if (m_Profile)
  624. {
  625. EditorUtility.SetDirty(m_Profile);
  626. }
  627. TimeOfDayController tc = GameObject.FindObjectOfType<TimeOfDayController>();
  628. if (tc != null)
  629. {
  630. tc.UpdateSkyForCurrentTime();
  631. }
  632. }
  633. private List<string> GetTitlesForGroups(List<ProfileGroupDefinition> groups) {
  634. List<string> titles = new List<string>();
  635. foreach (ProfileGroupDefinition group in groups) {
  636. titles.Add(group.groupName);
  637. }
  638. return titles;
  639. }
  640. }
  641. }