/ Assets / TutorialInfo / Scripts / Editor / ReadmeEditor.cs
ReadmeEditor.cs
  1  using System.Collections;
  2  using System.Collections.Generic;
  3  using UnityEngine;
  4  using UnityEditor;
  5  using System;
  6  using System.IO;
  7  using System.Reflection;
  8  
  9  [CustomEditor(typeof(Readme))]
 10  [InitializeOnLoad]
 11  public class ReadmeEditor : Editor
 12  {
 13      static string s_ShowedReadmeSessionStateName = "ReadmeEditor.showedReadme";
 14      
 15      static string s_ReadmeSourceDirectory = "Assets/TutorialInfo";
 16  
 17      const float k_Space = 16f;
 18  
 19      static ReadmeEditor()
 20      {
 21          EditorApplication.delayCall += SelectReadmeAutomatically;
 22      }
 23  
 24      static void RemoveTutorial()
 25      {
 26          if (EditorUtility.DisplayDialog("Remove Readme Assets",
 27              
 28              $"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?",
 29              "Proceed",
 30              "Cancel"))
 31          {
 32              if (Directory.Exists(s_ReadmeSourceDirectory))
 33              {
 34                  FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory);
 35                  FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory + ".meta");
 36              }
 37              else
 38              {
 39                  Debug.Log($"Could not find the Readme folder at {s_ReadmeSourceDirectory}");
 40              }
 41  
 42              var readmeAsset = SelectReadme();
 43              if (readmeAsset != null)
 44              {
 45                  var path = AssetDatabase.GetAssetPath(readmeAsset);
 46                  FileUtil.DeleteFileOrDirectory(path + ".meta");
 47                  FileUtil.DeleteFileOrDirectory(path);
 48              }
 49  
 50              AssetDatabase.Refresh();
 51          }
 52      }
 53  
 54      static void SelectReadmeAutomatically()
 55      {
 56          if (!SessionState.GetBool(s_ShowedReadmeSessionStateName, false))
 57          {
 58              var readme = SelectReadme();
 59              SessionState.SetBool(s_ShowedReadmeSessionStateName, true);
 60  
 61              if (readme && !readme.loadedLayout)
 62              {
 63                  LoadLayout();
 64                  readme.loadedLayout = true;
 65              }
 66          }
 67      }
 68  
 69      static void LoadLayout()
 70      {
 71          var assembly = typeof(EditorApplication).Assembly;
 72          var windowLayoutType = assembly.GetType("UnityEditor.WindowLayout", true);
 73          var method = windowLayoutType.GetMethod("LoadWindowLayout", BindingFlags.Public | BindingFlags.Static);
 74          method.Invoke(null, new object[] { Path.Combine(Application.dataPath, "TutorialInfo/Layout.wlt"), false });
 75      }
 76  
 77      static Readme SelectReadme()
 78      {
 79          var ids = AssetDatabase.FindAssets("Readme t:Readme");
 80          if (ids.Length == 1)
 81          {
 82              var readmeObject = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(ids[0]));
 83  
 84              Selection.objects = new UnityEngine.Object[] { readmeObject };
 85  
 86              return (Readme)readmeObject;
 87          }
 88          else
 89          {
 90              Debug.Log("Couldn't find a readme");
 91              return null;
 92          }
 93      }
 94  
 95      protected override void OnHeaderGUI()
 96      {
 97          var readme = (Readme)target;
 98          Init();
 99  
100          var iconWidth = Mathf.Min(EditorGUIUtility.currentViewWidth / 3f - 20f, 128f);
101  
102          GUILayout.BeginHorizontal("In BigTitle");
103          {
104              if (readme.icon != null)
105              {
106                  GUILayout.Space(k_Space);
107                  GUILayout.Label(readme.icon, GUILayout.Width(iconWidth), GUILayout.Height(iconWidth));
108              }
109              GUILayout.Space(k_Space);
110              GUILayout.BeginVertical();
111              {
112  
113                  GUILayout.FlexibleSpace();
114                  GUILayout.Label(readme.title, TitleStyle);
115                  GUILayout.FlexibleSpace();
116              }
117              GUILayout.EndVertical();
118              GUILayout.FlexibleSpace();
119          }
120          GUILayout.EndHorizontal();
121      }
122  
123      public override void OnInspectorGUI()
124      {
125          var readme = (Readme)target;
126          Init();
127  
128          foreach (var section in readme.sections)
129          {
130              if (!string.IsNullOrEmpty(section.heading))
131              {
132                  GUILayout.Label(section.heading, HeadingStyle);
133              }
134  
135              if (!string.IsNullOrEmpty(section.text))
136              {
137                  GUILayout.Label(section.text, BodyStyle);
138              }
139  
140              if (!string.IsNullOrEmpty(section.linkText))
141              {
142                  if (LinkLabel(new GUIContent(section.linkText)))
143                  {
144                      Application.OpenURL(section.url);
145                  }
146              }
147  
148              GUILayout.Space(k_Space);
149          }
150  
151          if (GUILayout.Button("Remove Readme Assets", ButtonStyle))
152          {
153              RemoveTutorial();
154          }
155      }
156  
157      bool m_Initialized;
158  
159      GUIStyle LinkStyle
160      {
161          get { return m_LinkStyle; }
162      }
163  
164      [SerializeField]
165      GUIStyle m_LinkStyle;
166  
167      GUIStyle TitleStyle
168      {
169          get { return m_TitleStyle; }
170      }
171  
172      [SerializeField]
173      GUIStyle m_TitleStyle;
174  
175      GUIStyle HeadingStyle
176      {
177          get { return m_HeadingStyle; }
178      }
179  
180      [SerializeField]
181      GUIStyle m_HeadingStyle;
182  
183      GUIStyle BodyStyle
184      {
185          get { return m_BodyStyle; }
186      }
187  
188      [SerializeField]
189      GUIStyle m_BodyStyle;
190  
191      GUIStyle ButtonStyle
192      {
193          get { return m_ButtonStyle; }
194      }
195  
196      [SerializeField]
197      GUIStyle m_ButtonStyle;
198  
199      void Init()
200      {
201          if (m_Initialized)
202              return;
203          m_BodyStyle = new GUIStyle(EditorStyles.label);
204          m_BodyStyle.wordWrap = true;
205          m_BodyStyle.fontSize = 14;
206          m_BodyStyle.richText = true;
207  
208          m_TitleStyle = new GUIStyle(m_BodyStyle);
209          m_TitleStyle.fontSize = 26;
210  
211          m_HeadingStyle = new GUIStyle(m_BodyStyle);
212          m_HeadingStyle.fontStyle = FontStyle.Bold;
213          m_HeadingStyle.fontSize = 18;
214  
215          m_LinkStyle = new GUIStyle(m_BodyStyle);
216          m_LinkStyle.wordWrap = false;
217  
218          // Match selection color which works nicely for both light and dark skins
219          m_LinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f);
220          m_LinkStyle.stretchWidth = false;
221  
222          m_ButtonStyle = new GUIStyle(EditorStyles.miniButton);
223          m_ButtonStyle.fontStyle = FontStyle.Bold;
224  
225          m_Initialized = true;
226      }
227  
228      bool LinkLabel(GUIContent label, params GUILayoutOption[] options)
229      {
230          var position = GUILayoutUtility.GetRect(label, LinkStyle, options);
231  
232          Handles.BeginGUI();
233          Handles.color = LinkStyle.normal.textColor;
234          Handles.DrawLine(new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax));
235          Handles.color = Color.white;
236          Handles.EndGUI();
237  
238          EditorGUIUtility.AddCursorRect(position, MouseCursor.Link);
239  
240          return GUI.Button(position, label, LinkStyle);
241      }
242  }