You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
13 KiB

  1. using UnityEngine;
  2. using UnityEditor;
  3. using System.Collections;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. /**
  7. * INSTRUCTIONS
  8. *
  9. * - Only modify properties in the USER SETTINGS region.
  10. * - All content is loaded from external files (pc_AboutEntry_YourProduct. Use the templates!
  11. */
  12. /**
  13. * Used to pop up the window on import.
  14. */
  15. public class pg_AboutWindowSetup : AssetPostprocessor
  16. {
  17. #region Initialization
  18. static void OnPostprocessAllAssets (
  19. string[] importedAssets,
  20. string[] deletedAssets,
  21. string[] movedAssets,
  22. string[] movedFromAssetPaths)
  23. {
  24. string[] entries = System.Array.FindAll(importedAssets, name => name.Contains("pc_AboutEntry") && !name.EndsWith(".meta"));
  25. foreach(string str in entries)
  26. if( pg_AboutWindow.Init(str, false) )
  27. break;
  28. }
  29. // [MenuItem("Edit/Preferences/Clear About Version: " + AboutWindow.PRODUCT_IDENTIFIER)]
  30. // public static void MenuClearVersionPref()
  31. // {
  32. // EditorPrefs.DeleteKey(AboutWindow.PRODUCT_IDENTIFIER);
  33. // }
  34. #endregion
  35. }
  36. public class pg_AboutWindow : EditorWindow
  37. {
  38. /**
  39. * Modify these constants to customize about screen.
  40. */
  41. #region User Settings
  42. /* Path to the root folder */
  43. const string ABOUT_ROOT = "Assets/ProCore/ProGrids/About";
  44. /**
  45. * Changelog.txt file should follow this format:
  46. *
  47. * | -- Product Name 2.1.0 -
  48. * |
  49. * | # Features
  50. * | - All kinds of awesome stuff
  51. * | - New flux capacitor design achieves time travel at lower velocities.
  52. * | - Dark matter reactor recalibrated.
  53. * |
  54. * | # Bug Fixes
  55. * | - No longer explodes when spacebar is pressed.
  56. * | - Fix rolling issue in Rickmeter.
  57. * |
  58. * | # Changes
  59. * | - Changed Blue to Red.
  60. * | - Enter key now causes explosions.
  61. *
  62. * This path is relative to the PRODUCT_ROOT path.
  63. *
  64. * Note that your changelog may contain multiple entries. Only the top-most
  65. * entry will be displayed.
  66. */
  67. /**
  68. * Advertisement thumb constructor is:
  69. * new AdvertisementThumb( PathToAdImage : string, URLToPurchase : string, ProductDescription : string )
  70. * Provide as many or few (or none) as desired.
  71. *
  72. * Notes - The http:// part is required. Partial URLs do not work on Mac.
  73. */
  74. [SerializeField]
  75. public static AdvertisementThumb[] advertisements = new AdvertisementThumb[] {
  76. new AdvertisementThumb( ABOUT_ROOT + "/Images/ProBuilder_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/probuilder/", "Build and Texture Geometry In-Editor"),
  77. new AdvertisementThumb( ABOUT_ROOT + "/Images/ProGrids_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/progrids/", "True Grids and Grid-Snapping"),
  78. new AdvertisementThumb( ABOUT_ROOT + "/Images/ProGroups_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/progroups/", "Hide, Freeze, Group, & Organize"),
  79. new AdvertisementThumb( ABOUT_ROOT + "/Images/Prototype_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/prototype/", "Design and Build With Zero Lag"),
  80. new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickBrush_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickbrush/", "Quickly Add Detail Geometry"),
  81. new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickDecals_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickdecals/", "Add Dirt, Splatters, Posters, etc"),
  82. new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickEdit_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickedit/", "Edit Imported Meshes!"),
  83. };
  84. #endregion
  85. /* Recommend you do not modify these. */
  86. #region Private Fields (automatically populated)
  87. private string AboutEntryPath = "";
  88. private string ProductName = "";
  89. // private string ProductIdentifer = "";
  90. private string ProductVersion = "";
  91. private string ChangelogPath = "";
  92. private string BannerPath = ABOUT_ROOT + "/Images/Banner.png";
  93. const int AD_HEIGHT = 96;
  94. /**
  95. * Struct containing data for use in Advertisement shelf.
  96. */
  97. [System.Serializable]
  98. public struct AdvertisementThumb
  99. {
  100. public Texture2D image;
  101. public string url;
  102. public string about;
  103. public GUIContent guiContent;
  104. public AdvertisementThumb(string imagePath, string url, string about)
  105. {
  106. guiContent = new GUIContent("", about);
  107. this.image = (Texture2D) AssetDatabase.LoadAssetAtPath(imagePath, typeof(Texture2D));
  108. guiContent.image = this.image;
  109. this.url = url;
  110. this.about = about;
  111. }
  112. }
  113. Texture2D banner;
  114. // populated by first entry in changelog
  115. string changelog = "";
  116. #endregion
  117. #region Init
  118. // [MenuItem("Tools/Test Search About Window", false, 0)]
  119. // public static void MenuInit()
  120. // {
  121. // // this could be slow in large projects?
  122. // string[] allFiles = System.IO.Directory.GetFiles("Assets/", "*.*", System.IO.SearchOption.AllDirectories);
  123. // string[] entries = System.Array.FindAll(allFiles, name => name.Contains("pc_AboutEntry"));
  124. // if(entries.Length > 0)
  125. // AboutWindow.Init(entries[0], true);
  126. // }
  127. /**
  128. * Return true if Init took place, false if not.
  129. */
  130. public static bool Init (string aboutEntryPath, bool fromMenu)
  131. {
  132. string identifier, version;
  133. if( !GetField(aboutEntryPath, "version: ", out version) || !GetField(aboutEntryPath, "identifier: ", out identifier))
  134. return false;
  135. if(fromMenu || EditorPrefs.GetString(identifier) != version)
  136. {
  137. string tname;
  138. pg_AboutWindow win;
  139. if(!GetField(aboutEntryPath, "name: ", out tname) || !tname.Contains("ProGrids"))
  140. return false;
  141. win = (pg_AboutWindow)EditorWindow.GetWindow(typeof(pg_AboutWindow), true, tname, true);
  142. win.SetAboutEntryPath(aboutEntryPath);
  143. win.ShowUtility();
  144. EditorPrefs.SetString(identifier, version);
  145. return true;
  146. }
  147. else
  148. {
  149. return false;
  150. }
  151. }
  152. public void OnEnable()
  153. {
  154. banner = (Texture2D)AssetDatabase.LoadAssetAtPath(BannerPath, typeof(Texture2D));
  155. // With Unity 4 (on PC) if you have different values for minSize and maxSize,
  156. // they do not apply restrictions to window size.
  157. this.minSize = new Vector2(banner.width + 12, banner.height * 7);
  158. this.maxSize = new Vector2(banner.width + 12, banner.height * 7);
  159. }
  160. public void SetAboutEntryPath(string path)
  161. {
  162. AboutEntryPath = path;
  163. PopulateDataFields(AboutEntryPath);
  164. }
  165. #endregion
  166. #region GUI
  167. Color LinkColor = new Color(0f, .682f, .937f, 1f);
  168. GUIStyle boldTextStyle,
  169. headerTextStyle,
  170. linkTextStyle;
  171. GUIStyle advertisementStyle;
  172. Vector2 scroll = Vector2.zero, adScroll = Vector2.zero;
  173. // int mm = 32;
  174. void OnGUI()
  175. {
  176. headerTextStyle = headerTextStyle ?? new GUIStyle( EditorStyles.boldLabel );//GUI.skin.label);
  177. headerTextStyle.fontSize = 16;
  178. linkTextStyle = linkTextStyle ?? new GUIStyle( GUI.skin.label );//GUI.skin.label);
  179. linkTextStyle.normal.textColor = LinkColor;
  180. linkTextStyle.alignment = TextAnchor.MiddleLeft;
  181. boldTextStyle = boldTextStyle ?? new GUIStyle( GUI.skin.label );//GUI.skin.label);
  182. boldTextStyle.fontStyle = FontStyle.Bold;
  183. boldTextStyle.alignment = TextAnchor.MiddleLeft;
  184. // #if UNITY_4
  185. // richTextLabel.richText = true;
  186. // #endif
  187. advertisementStyle = advertisementStyle ?? new GUIStyle(GUI.skin.button);
  188. advertisementStyle.normal.background = null;
  189. if(banner != null)
  190. GUILayout.Label(banner);
  191. // mm = EditorGUI.IntField(new Rect(Screen.width - 200, 100, 200, 18), "W: ", mm);
  192. {
  193. GUILayout.Label("Thank you for purchasing " + ProductName + ". Your support allows us to keep developing this and future tools for everyone.", EditorStyles.wordWrappedLabel);
  194. GUILayout.Space(2);
  195. GUILayout.Label("Read these quick \"ProTips\" before starting:", headerTextStyle);
  196. GUILayout.BeginHorizontal();
  197. GUILayout.Label("1) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16));
  198. GUILayout.Label("Register", boldTextStyle, GUILayout.MinWidth(58), GUILayout.MaxWidth(58));
  199. GUILayout.Label("for instant email updates, send your invoice # to", GUILayout.MinWidth(284), GUILayout.MaxWidth(284));
  200. if( GUILayout.Button("contact@procore3d.com", linkTextStyle, GUILayout.MinWidth(142), GUILayout.MaxWidth(142)) )
  201. Application.OpenURL("mailto:contact@procore3d.com?subject=Sign me up for the Beta!");
  202. GUILayout.EndHorizontal();
  203. GUILayout.BeginHorizontal();
  204. GUILayout.Label("2) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16));
  205. GUILayout.Label("Report bugs", boldTextStyle, GUILayout.MinWidth(82), GUILayout.MaxWidth(82));
  206. GUILayout.Label("to the ProCore Forum at", GUILayout.MinWidth(144), GUILayout.MaxWidth(144));
  207. if( GUILayout.Button("www.procore3d.com/forum", linkTextStyle, GUILayout.MinWidth(162), GUILayout.MaxWidth(162)) )
  208. Application.OpenURL("http://www.procore3d.com/forum");
  209. GUILayout.EndHorizontal();
  210. GUILayout.BeginHorizontal();
  211. GUILayout.Label("3) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16));
  212. GUILayout.Label("Customize!", boldTextStyle, GUILayout.MinWidth(74), GUILayout.MaxWidth(74));
  213. GUILayout.Label("Click on \"Edit > Preferences\" then \"" + ProductName + "\"", GUILayout.MinWidth(276), GUILayout.MaxWidth(276));
  214. GUILayout.EndHorizontal();
  215. GUILayout.BeginHorizontal();
  216. GUILayout.Label("4) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16));
  217. GUILayout.Label("Documentation", boldTextStyle, GUILayout.MinWidth(102), GUILayout.MaxWidth(102));
  218. GUILayout.Label("Tutorials, & more info:", GUILayout.MinWidth(132), GUILayout.MaxWidth(132));
  219. if( GUILayout.Button("www.procore3d.com/" + ProductName.ToLower(), linkTextStyle, GUILayout.MinWidth(190), GUILayout.MaxWidth(190)) )
  220. Application.OpenURL("http://www.procore3d.com/" + ProductName.ToLower());
  221. GUILayout.EndHorizontal();
  222. GUILayout.Space(4);
  223. GUILayout.BeginHorizontal(GUILayout.MaxWidth(50));
  224. GUILayout.Label("Links:", boldTextStyle);
  225. linkTextStyle.fontStyle = FontStyle.Italic;
  226. linkTextStyle.alignment = TextAnchor.MiddleCenter;
  227. if( GUILayout.Button("procore3d.com", linkTextStyle))
  228. Application.OpenURL("http://www.procore3d.com");
  229. if( GUILayout.Button("facebook", linkTextStyle))
  230. Application.OpenURL("http://www.facebook.com/probuilder3d");
  231. if( GUILayout.Button("twitter", linkTextStyle))
  232. Application.OpenURL("http://www.twitter.com/probuilder3d");
  233. linkTextStyle.fontStyle = FontStyle.Normal;
  234. GUILayout.EndHorizontal();
  235. GUILayout.Space(4);
  236. }
  237. HorizontalLine();
  238. // always bold the first line (cause it's the version info stuff)
  239. scroll = EditorGUILayout.BeginScrollView(scroll);
  240. GUILayout.Label(ProductName + " | version: " + ProductVersion, EditorStyles.boldLabel);
  241. GUILayout.Label("\n" + changelog);
  242. EditorGUILayout.EndScrollView();
  243. HorizontalLine();
  244. GUILayout.Label("More ProCore Products", EditorStyles.boldLabel);
  245. int pad = advertisements.Length * AD_HEIGHT > Screen.width ? 22 : 6;
  246. adScroll = EditorGUILayout.BeginScrollView(adScroll, false, false, GUILayout.MinHeight(AD_HEIGHT + pad), GUILayout.MaxHeight(AD_HEIGHT + pad));
  247. GUILayout.BeginHorizontal();
  248. foreach(AdvertisementThumb ad in advertisements)
  249. {
  250. if(ad.url.ToLower().Contains(ProductName.ToLower()))
  251. continue;
  252. if(GUILayout.Button(ad.guiContent, advertisementStyle,
  253. GUILayout.MinWidth(AD_HEIGHT), GUILayout.MaxWidth(AD_HEIGHT),
  254. GUILayout.MinHeight(AD_HEIGHT), GUILayout.MaxHeight(AD_HEIGHT)))
  255. {
  256. Application.OpenURL(ad.url);
  257. }
  258. }
  259. GUILayout.EndHorizontal();
  260. EditorGUILayout.EndScrollView();
  261. /* shill other products */
  262. }
  263. /**
  264. * Draw a horizontal line across the screen and update the guilayout.
  265. */
  266. void HorizontalLine()
  267. {
  268. Rect r = GUILayoutUtility.GetLastRect();
  269. Color og = GUI.backgroundColor;
  270. GUI.backgroundColor = Color.black;
  271. GUI.Box(new Rect(0f, r.y + r.height + 2, Screen.width, 2f), "");
  272. GUI.backgroundColor = og;
  273. GUILayout.Space(6);
  274. }
  275. #endregion
  276. #region Data Parsing
  277. /* rich text ain't wuurkin' in unity 3.5 */
  278. const string RemoveBraketsRegex = "(\\<.*?\\>)";
  279. /**
  280. * Open VersionInfo and Changelog and pull out text to populate vars for OnGUI to display.
  281. */
  282. void PopulateDataFields(string entryPath)
  283. {
  284. /* Get data from VersionInfo.txt */
  285. TextAsset versionInfo = (TextAsset)AssetDatabase.LoadAssetAtPath( entryPath, typeof(TextAsset));
  286. ProductName = "";
  287. // ProductIdentifer = "";
  288. ProductVersion = "";
  289. ChangelogPath = "";
  290. if(versionInfo != null)
  291. {
  292. string[] txt = versionInfo.text.Split('\n');
  293. foreach(string cheese in txt)
  294. {
  295. if(cheese.StartsWith("name:"))
  296. ProductName = cheese.Replace("name: ", "").Trim();
  297. else
  298. if(cheese.StartsWith("version:"))
  299. ProductVersion = cheese.Replace("version: ", "").Trim();
  300. else
  301. if(cheese.StartsWith("changelog:"))
  302. ChangelogPath = cheese.Replace("changelog: ", "").Trim();
  303. }
  304. }
  305. // notes = notes.Trim();
  306. /* Get first entry in changelog.txt */
  307. TextAsset changelogText = (TextAsset)AssetDatabase.LoadAssetAtPath( ChangelogPath, typeof(TextAsset));
  308. if(changelogText)
  309. {
  310. string[] split = changelogText.text.Split( new string[] {"--"}, System.StringSplitOptions.RemoveEmptyEntries );
  311. StringBuilder sb = new StringBuilder();
  312. string[] newLineSplit = split[0].Trim().Split('\n');
  313. for(int i = 2; i < newLineSplit.Length; i++)
  314. sb.AppendLine(newLineSplit[i]);
  315. changelog = sb.ToString();
  316. }
  317. }
  318. private static bool GetField(string path, string field, out string value)
  319. {
  320. TextAsset entry = (TextAsset)AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset));
  321. value = "";
  322. if(!entry) return false;
  323. foreach(string str in entry.text.Split('\n'))
  324. {
  325. if(str.Contains(field))
  326. {
  327. value = str.Replace(field, "").Trim();
  328. return true;
  329. }
  330. }
  331. return false;
  332. }
  333. #endregion
  334. }