DNPEditorInternal.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. #if UNITY_EDITOR
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEditor;
  6. using TMPro;
  7. using DamageNumbersPro;
  8. using UnityEngine.Rendering;
  9. using UnityEditor.SceneManagement;
  10. namespace DamageNumbersPro.Internal {
  11. public static class DNPEditorInternal
  12. {
  13. // Public
  14. public static int currentTab;
  15. public static bool repaintViews;
  16. public static HashSet<string> hints;
  17. public static DamageNumber[] damageNumbers;
  18. public static TextMeshPro[] textMeshPros;
  19. // Private
  20. static Transform[] meshAs;
  21. static Transform[] meshBs;
  22. // Presets
  23. static Dictionary<string,DNPPreset[]> allPresets;
  24. // GUI Resources
  25. public static GUIStyle labelStyle;
  26. public static GUIStyle buttonStyle;
  27. public static GUIStyle rightTextStyle;
  28. public static GUIStyle centerTextStyle;
  29. public static GUIStyle bottomRightTextStyle;
  30. public static GUIStyle topRightTextStyle;
  31. static GUIStyle whiteBoxStyle;
  32. static Texture2D whiteBoxTexture;
  33. static Texture bannerTexture;
  34. public static float currentWidth;
  35. // External Editor
  36. static int currentEditor;
  37. static bool cleanEditor;
  38. static Material[] currentMaterials;
  39. static MaterialEditor materialEditor;
  40. static Editor textMeshProEditor;
  41. static bool generatedGUIStyles;
  42. public static void PrepareInspector(DamageNumberEditor damageNumberEditor)
  43. {
  44. // Clean Editors
  45. cleanEditor = true;
  46. generatedGUIStyles = false;
  47. // Get Damage Numbers
  48. damageNumbers = new DamageNumber[damageNumberEditor.targets.Length];
  49. for (int i = 0; i < damageNumberEditor.targets.Length; i++)
  50. {
  51. damageNumbers[i] = (DamageNumber)damageNumberEditor.targets[i];
  52. }
  53. // Type
  54. bool isMesh = damageNumbers[0].IsMesh();
  55. // Get Presets
  56. allPresets = new Dictionary<string, DNPPreset[]>();
  57. allPresets.Add("Style", Resources.LoadAll<DNPPreset>("DNP/Style"));
  58. allPresets.Add("Fade In", Resources.LoadAll<DNPPreset>("DNP/Fade In"));
  59. allPresets.Add("Fade Out", Resources.LoadAll<DNPPreset>("DNP/Fade Out"));
  60. allPresets.Add("Behaviour", Resources.LoadAll<DNPPreset>("DNP/Behaviour"));
  61. // Get Structural Objects
  62. textMeshPros = new TextMeshPro[damageNumbers.Length];
  63. meshAs = new Transform[damageNumbers.Length];
  64. meshBs = new Transform[damageNumbers.Length];
  65. if(isMesh)
  66. {
  67. for (int n = 0; n < damageNumbers.Length; n++)
  68. {
  69. Transform dnTransform = damageNumbers[n].transform;
  70. // TMP
  71. Transform textMeshProTransform = dnTransform.Find("TMP");
  72. if (textMeshProTransform != null)
  73. {
  74. textMeshPros[n] = textMeshProTransform.GetComponent<TextMeshPro>();
  75. }
  76. // MeshA
  77. meshAs[n] = dnTransform.Find("MeshA");
  78. // MeshB
  79. meshBs[n] = dnTransform.Find("MeshB");
  80. }
  81. }
  82. // Get Banner Texture
  83. if (damageNumbers != null && damageNumbers.Length > 0 && damageNumbers[0] != null)
  84. {
  85. bannerTexture = Resources.Load<Texture>("DNP/Textures/DNP_Banner");
  86. }
  87. // Create White Box Texture
  88. Color[] pixels = new Color[4];
  89. for (int n = 0; n < pixels.Length; n++)
  90. {
  91. pixels[n] = Color.white;
  92. }
  93. whiteBoxTexture = new Texture2D(2, 2);
  94. whiteBoxTexture.SetPixels(pixels);
  95. whiteBoxTexture.Apply();
  96. // Close Hints
  97. hints = new HashSet<string>();
  98. }
  99. public static void OnInspectorGUI(DamageNumberEditor damageNumberEditor)
  100. {
  101. // Prepare Inspector
  102. if (damageNumbers == null || damageNumbers.Length == 0 || damageNumbers[0] == null)
  103. {
  104. PrepareInspector(damageNumberEditor);
  105. }
  106. // Prepare Styles
  107. PrepareStyles();
  108. // Repaint
  109. if (repaintViews)
  110. {
  111. repaintViews = false;
  112. UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
  113. }
  114. }
  115. #region Inspector Top
  116. public static void DrawInspectorTop(bool isMesh)
  117. {
  118. // Banner
  119. Rect bannerRect = DrawBanner(isMesh);
  120. // Tabs
  121. DrawTabs(bannerRect);
  122. // Distance
  123. EditorGUILayout.Space(42);
  124. }
  125. static Rect DrawBanner(bool isMesh)
  126. {
  127. Rect bannerRect = default;
  128. if (bannerTexture != null)
  129. {
  130. // Banner
  131. EditorGUILayout.BeginVertical();
  132. GUILayout.Label("", GUILayout.Height(100 + 0.38f * Mathf.Min(0,EditorGUIUtility.currentViewWidth - 430)));
  133. bannerRect = GUILayoutUtility.GetLastRect();
  134. float ratio = (bannerRect.width / bannerRect.height) / 8f;
  135. Rect clipRect = new Rect((1 - ratio) * 0.5f, 0, ratio, 1);
  136. GUI.DrawTextureWithTexCoords(bannerRect, bannerTexture, clipRect, true);
  137. EditorGUILayout.EndVertical();
  138. // Version Info
  139. Rect infoRect = new Rect(bannerRect);
  140. infoRect.width -= 3;
  141. infoRect.y += 4;
  142. infoRect.height -= 8;
  143. GUI.Label(infoRect, "<color=#FFFFFF><b><size=10>v</size>" + DamageNumberEditor.version + " </b></color>", bottomRightTextStyle);
  144. // Type Info
  145. GUI.Label(infoRect, "<color=#FFFFFF><b>" + (isMesh ? "Mesh" : "GUI") + "<size=10> </size></b></color>", topRightTextStyle);
  146. // Button
  147. Rect documentationRect = GUILayoutUtility.GetLastRect();
  148. documentationRect.x += 9;
  149. documentationRect.y += 9;
  150. documentationRect.width = 56;
  151. documentationRect.height = 18;
  152. if (GUI.Button(documentationRect, "<b>Manual</b>", buttonStyle))
  153. {
  154. Application.OpenURL("https://ekincantas.com/damage-numbers-pro/");
  155. }
  156. documentationRect.y += 21;
  157. if (GUI.Button(documentationRect, "<b>Discord</b>", buttonStyle))
  158. {
  159. Application.OpenURL("https://discord.gg/nWbRkN8Zxr");
  160. }
  161. // Box
  162. BoxLastRect();
  163. EditorGUILayout.Space();
  164. // Calculate Width for GUI Scaling
  165. float newWidth = GUILayoutUtility.GetLastRect().width;
  166. if(newWidth > 50)
  167. {
  168. currentWidth = newWidth;
  169. }
  170. }
  171. return bannerRect;
  172. }
  173. static void DrawTabs(Rect lastRect)
  174. {
  175. // Position
  176. lastRect.y += lastRect.height - 3;
  177. lastRect.height = 29;
  178. // Row 1
  179. int lastTab = currentTab;
  180. currentTab = GUI.Toolbar(lastRect, currentTab, new string[] { "Main", "Text", "Fade In", "Fade Out" }, buttonStyle);
  181. lastRect.height -= 1;
  182. BoxRect(lastRect);
  183. string rotAndScaleText = "Rotation & Size";
  184. if(currentWidth < 388)
  185. {
  186. rotAndScaleText = "<size=11>Rotation & Size</size>";
  187. if(currentWidth < 356)
  188. {
  189. rotAndScaleText = "<size=10>Rotation & Size</size>";
  190. if (currentWidth < 324)
  191. {
  192. rotAndScaleText = "<size=9>Rotation & Size</size>";
  193. if (currentWidth < 303)
  194. {
  195. rotAndScaleText = "<size=8>Rotation & Size</size>";
  196. if (currentWidth < 276)
  197. {
  198. rotAndScaleText = "<size=7>Rotation & Size</size>";
  199. }
  200. }
  201. }
  202. }
  203. }
  204. string spamText = "Spam Control";
  205. if(currentWidth < 340)
  206. {
  207. spamText = "<size=11>Spam Control</size>";
  208. if (currentWidth < 324)
  209. {
  210. spamText = "<size=10>Spam Control</size>";
  211. if (currentWidth < 304)
  212. {
  213. spamText = "<size=9>Spam Control</size>";
  214. if (currentWidth < 367)
  215. {
  216. spamText = "<size=8>Spam Control</size>";
  217. }
  218. }
  219. }
  220. }
  221. string performanceText = "Performance";
  222. if(currentWidth < 336)
  223. {
  224. performanceText = "<size=11>Performance</size>";
  225. if (currentWidth < 310)
  226. {
  227. performanceText = "<size=10>Performance</size>";
  228. if (currentWidth < 292)
  229. {
  230. performanceText = "<size=9>Performance</size>";
  231. }
  232. }
  233. }
  234. string movementText = "Movement";
  235. if(currentWidth < 293)
  236. {
  237. movementText = "<size=11>Movement</size>";
  238. if (currentWidth < 282)
  239. {
  240. movementText = "<size=10>Movement</size>";
  241. if (currentWidth < 263)
  242. {
  243. movementText = "<size=9>Movement</size>";
  244. }
  245. }
  246. }
  247. // Row 2
  248. lastRect.y += lastRect.height - 3;
  249. lastRect.height = 22;
  250. currentTab = 4 + GUI.Toolbar(lastRect, currentTab - 4, new string[] { movementText, rotAndScaleText, spamText, performanceText }, buttonStyle);
  251. lastRect.height += 2;
  252. // On Switch
  253. if (currentTab != lastTab)
  254. {
  255. EditorGUIUtility.keyboardControl = EditorGUIUtility.hotControl = 0;
  256. hints = new HashSet<string>(); // Clear Hints
  257. }
  258. // Box
  259. BoxRect(lastRect, true, false);
  260. }
  261. #endregion
  262. #region Special Sections
  263. public static void FinalInformation()
  264. {
  265. Color finalInformationColor = new Color(0.93f, 0.95f, 1);
  266. GUIStyle linkStyle = new GUIStyle(labelStyle);
  267. linkStyle.normal.textColor = linkStyle.focused.textColor = linkStyle.hover.textColor = EditorGUIUtility.isProSkin ? new Color(0.8f, 0.9f, 1f, 1) : new Color(0.1f, 0.2f, 0.4f, 1);
  268. linkStyle.active.textColor = EditorGUIUtility.isProSkin ? new Color(0.6f, 0.8f, 1f, 1) : new Color(0.15f, 0.4f, 0.6f, 1);
  269. EditorGUILayout.Space(2);
  270. StartBox(finalInformationColor);
  271. EditorGUILayout.BeginVertical();
  272. GUI.color = new Color(1, 1, 1f, 0.75f);
  273. if(currentWidth < 285)
  274. {
  275. if(currentWidth < 265)
  276. {
  277. Label("<size=10><b>Thank you for using Damage Numbers Pro.</b></size>");
  278. }
  279. else
  280. {
  281. Label("<size=11><b>Thank you for using Damage Numbers Pro.</b></size>");
  282. }
  283. }
  284. else
  285. {
  286. Label("<b>Thank you for using Damage Numbers Pro.</b>");
  287. }
  288. Label("<b>Contact me if you need any help.</b>");
  289. EditorGUILayout.Space(8);
  290. EditorGUILayout.BeginHorizontal();
  291. GUI.color = new Color(1, 1, 1, 1);
  292. // Link Shrinking
  293. string docLink = "https://ekincantas.com/damage-numbers-pro/";
  294. if(currentWidth < 420f)
  295. {
  296. docLink = "https://ekincantas.com/damage-numbers...";
  297. if (currentWidth < 398)
  298. {
  299. docLink = "https://ekincantas.com/damage...";
  300. if (currentWidth < 340)
  301. {
  302. docLink = "https://ekincantas.com/...";
  303. if(currentWidth < 293)
  304. {
  305. docLink = "Open Link";
  306. }
  307. }
  308. }
  309. }
  310. string discordLink = "https://discord.gg/nWbRkN8Zxr";
  311. if (currentWidth < 335f)
  312. {
  313. discordLink = "https://discord.gg/...";
  314. if (currentWidth < 264)
  315. {
  316. discordLink = "Open Link";
  317. }
  318. }
  319. EditorGUILayout.LabelField("<b>Documentation:</b>", labelStyle, GUILayout.Width(100));
  320. if (GUILayout.Button("<b>" + docLink + "</b>", linkStyle))
  321. {
  322. Application.OpenURL("https://ekincantas.com/damage-numbers-pro/");
  323. }
  324. EditorGUILayout.EndHorizontal();
  325. EditorGUILayout.BeginHorizontal();
  326. GUI.color = new Color(1, 1, 1, 1);
  327. EditorGUILayout.LabelField("<b>Discord:</b>", labelStyle, GUILayout.Width(100));
  328. if (GUILayout.Button("<b>" + discordLink + "</b>", linkStyle))
  329. {
  330. Application.OpenURL("https://discord.gg/nWbRkN8Zxr");
  331. }
  332. EditorGUILayout.EndHorizontal();
  333. EditorGUILayout.BeginHorizontal();
  334. GUI.color = new Color(1, 1, 1, 1);
  335. string emailPrefix = "<b>Email:</b>";
  336. if(currentWidth < 259)
  337. {
  338. emailPrefix = "<size=11><b>Email:</b></size>";
  339. if(currentWidth < 256)
  340. {
  341. emailPrefix = "<size=10><b>Email:</b></size>";
  342. if (currentWidth < 254)
  343. {
  344. emailPrefix = "<size=9><b>Email:</b></size>";
  345. }
  346. }
  347. }
  348. EditorGUILayout.LabelField(emailPrefix, labelStyle, GUILayout.Width(100 + Mathf.Min(0,(currentWidth - 320))));
  349. EditorGUILayout.SelectableLabel("<b>ekincantascontact@gmail.com</b>", linkStyle, GUILayout.Height(16));
  350. EditorGUILayout.EndHorizontal();
  351. EditorGUILayout.EndVertical();
  352. GUI.backgroundColor = Color.white;
  353. CloseBox(finalInformationColor);
  354. EditorGUILayout.Space(5);
  355. }
  356. public static void Externalnspectors(bool isMesh, Object target)
  357. {
  358. EditorGUILayout.Space(2);
  359. Lines();
  360. Color externalInspectorColor = new Color(0.93f, 0.95f, 1);
  361. EditorGUILayout.Space(2);
  362. StartBox(externalInspectorColor);
  363. GUI.backgroundColor = externalInspectorColor;
  364. EditorGUILayout.BeginVertical();
  365. bool editingPrefabPreview = EditingPrefabPreview(target);
  366. if (editingPrefabPreview)
  367. {
  368. GUI.color = new Color(1, 1, 1f, 0.75f);
  369. ScalingLabel("<b>Open</b> the prefab to access the <b>presets</b>, <b>material</b> and <b>text mesh pro</b> tabs.", 440);
  370. OpenPrefabButton(target);
  371. GUI.backgroundColor = Color.white;
  372. EditorGUILayout.EndVertical();
  373. CloseBox(externalInspectorColor);
  374. return;
  375. }
  376. int previousEditor = currentEditor;
  377. if (cleanEditor)
  378. {
  379. previousEditor = -1; // Force Clean
  380. cleanEditor = false;
  381. }
  382. // Tab Names
  383. string textMeshProTab = "TextMeshPro";
  384. string materialTab = "Material";
  385. if (damageNumbers != null && damageNumbers.Length > 1)
  386. {
  387. textMeshProTab = damageNumbers.Length + " TextMeshPros";
  388. materialTab = "Materials";
  389. }
  390. if(currentWidth < 266)
  391. {
  392. textMeshProTab = "<size=11>" + textMeshProTab + "</size>";
  393. }
  394. // Tab Rect
  395. GUILayout.BeginVertical();
  396. GUILayout.Space(13);
  397. GUILayout.EndVertical();
  398. Rect tabRect = GUILayoutUtility.GetLastRect();
  399. tabRect.x -= 5;
  400. tabRect.width += 12;
  401. tabRect.y -= 5;
  402. tabRect.height = 25;
  403. // Draw Tab
  404. currentEditor = GUI.Toolbar(tabRect, currentEditor, new string[] { "Presets", materialTab , textMeshProTab });
  405. // Box Tab Rect
  406. tabRect.y += 23;
  407. tabRect.height = 3;
  408. tabRect.width -= 3;
  409. if (currentEditor == 1)
  410. {
  411. EditorGUILayout.Space(14);
  412. // Material
  413. if (previousEditor != 1)
  414. {
  415. ResetMaterials();
  416. }
  417. if (materialEditor != null)
  418. {
  419. materialEditor.DrawHeader();
  420. materialEditor.OnInspectorGUI();
  421. }
  422. }
  423. else if (currentEditor == 2)
  424. {
  425. EditorGUILayout.Space(14);
  426. if (damageNumbers.Length > 1)
  427. {
  428. GUI.color = new Color(1, 1, 1, 0.7f);
  429. Label("The fancy inspector does not work for <b>multiple</b> damage numbers.");
  430. Label("You can also <b>manually select</b> the text-mesh-pro components.");
  431. Label("- Sorry for the inconvenience.");
  432. GUI.color = Color.white;
  433. EditorGUILayout.Space(8);
  434. }
  435. if (isMesh)
  436. {
  437. // Text Mesh Pro
  438. if (previousEditor != 2)
  439. {
  440. if (textMeshProEditor != null)
  441. {
  442. Object.DestroyImmediate(textMeshProEditor);
  443. }
  444. textMeshProEditor = Editor.CreateEditor(textMeshPros, null);
  445. }
  446. // Editor
  447. if (textMeshProEditor != null)
  448. {
  449. textMeshProEditor.DrawHeader();
  450. if (textMeshPros.Length > 1)
  451. {
  452. textMeshProEditor.DrawDefaultInspector();
  453. }
  454. else
  455. {
  456. textMeshProEditor.OnInspectorGUI();
  457. }
  458. }
  459. }
  460. else
  461. {
  462. // Text Mesh Pro
  463. if (previousEditor != 2)
  464. {
  465. if (textMeshProEditor != null)
  466. {
  467. Object.DestroyImmediate(textMeshProEditor);
  468. }
  469. TextMeshProUGUI[] tmps = new TextMeshProUGUI[damageNumbers.Length];
  470. for(int i = 0; i < damageNumbers.Length; i++)
  471. {
  472. TMP_Text tmpText = damageNumbers[i].GetTextMesh();
  473. if(tmpText.GetType() == typeof(TextMeshProUGUI))
  474. {
  475. tmps[i] = (TextMeshProUGUI)tmpText;
  476. }
  477. else
  478. {
  479. return;
  480. }
  481. }
  482. textMeshProEditor = Editor.CreateEditor(tmps, null);
  483. }
  484. // Editor
  485. if (textMeshProEditor != null)
  486. {
  487. textMeshProEditor.DrawHeader();
  488. if (textMeshPros.Length > 1)
  489. {
  490. textMeshProEditor.DrawDefaultInspector();
  491. }
  492. else
  493. {
  494. textMeshProEditor.OnInspectorGUI();
  495. }
  496. // Match both TMPs
  497. foreach(DamageNumber dn in damageNumbers)
  498. {
  499. TMP_Text[] tmps = dn.GetTextMeshs();
  500. if(tmps.Length > 1)
  501. {
  502. EditorUtility.CopySerialized(((TextMeshProUGUI)tmps[0]), ((TextMeshProUGUI)tmps[1]));
  503. }
  504. }
  505. }
  506. }
  507. }
  508. else
  509. {
  510. EditorGUILayout.Space(14);
  511. ShowPresets(isMesh);
  512. }
  513. EditorGUILayout.EndVertical();
  514. GUI.backgroundColor = Color.white;
  515. CloseBox(externalInspectorColor);
  516. // Line under Tabs
  517. GUI.color = externalInspectorColor;
  518. DrawOutlineBox(tabRect);
  519. tabRect.width += 3;
  520. DrawBox(tabRect);
  521. GUI.color = Color.white;
  522. }
  523. public static void ResetMaterials()
  524. {
  525. List<Material> allMaterials = new List<Material>();
  526. foreach (DamageNumber dn in damageNumbers)
  527. {
  528. dn.GetReferencesIfNecessary();
  529. foreach (Material mat in dn.GetSharedMaterials())
  530. {
  531. if (allMaterials.Contains(mat) == false)
  532. {
  533. allMaterials.Add(mat);
  534. }
  535. }
  536. }
  537. currentMaterials = new Material[allMaterials.Count];
  538. for (int n = 0; n < allMaterials.Count; n++)
  539. {
  540. currentMaterials[n] = allMaterials[n];
  541. }
  542. if (materialEditor != null)
  543. {
  544. Object.DestroyImmediate(materialEditor);
  545. }
  546. materialEditor = (MaterialEditor)Editor.CreateEditor(currentMaterials);
  547. }
  548. static void ShowPresets(bool isMesh)
  549. {
  550. PresetCategory("Style", isMesh);
  551. EditorGUILayout.Space(12);
  552. PresetCategory("Fade In", isMesh);
  553. EditorGUILayout.Space(12);
  554. PresetCategory("Fade Out", isMesh);
  555. EditorGUILayout.Space(12);
  556. PresetCategory("Behaviour", isMesh);
  557. }
  558. static void PresetCategory(string category, bool isMesh)
  559. {
  560. GUI.color = new Color(1, 1, 1, 0.7f);
  561. EditorGUILayout.LabelField("<size=14><b> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " + category + " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </b></size>", centerTextStyle);
  562. GUI.color = Color.white;
  563. DNPPreset[] presets = allPresets[category];
  564. if(presets == null || presets.Length == 0)
  565. {
  566. GUI.color = new Color(1, 1, 1, 0.7f);
  567. Label("Presets could not be loaded.");
  568. Label("Maybe you deleted or moved a folder ?");
  569. GUI.color = Color.white;
  570. return;
  571. }
  572. int buttonsPerRow = 4;
  573. if(EditorGUIUtility.currentViewWidth < 440)
  574. {
  575. buttonsPerRow = 3;
  576. if(EditorGUIUtility.currentViewWidth < 375)
  577. {
  578. buttonsPerRow = 2;
  579. }
  580. }
  581. int currentCount = 0;
  582. foreach (DNPPreset preset in presets)
  583. {
  584. // Check Applied
  585. bool isApplied = true;
  586. foreach (DamageNumber dn in damageNumbers)
  587. {
  588. if(!preset.IsApplied(dn))
  589. {
  590. isApplied = false;
  591. break;
  592. }
  593. }
  594. if(isApplied)
  595. {
  596. GUI.enabled = false;
  597. }
  598. // Increase Count
  599. currentCount++;
  600. if (currentCount % buttonsPerRow == 1)
  601. {
  602. if(currentCount > 1)
  603. {
  604. EditorGUILayout.EndHorizontal();
  605. }
  606. EditorGUILayout.BeginHorizontal();
  607. GUILayout.Space(5);
  608. }
  609. // Apply Button
  610. if (GUILayout.Button(preset.name))
  611. {
  612. if(isMesh)
  613. {
  614. Object[] undoObjects = new Object[damageNumbers.Length + textMeshPros.Length];
  615. for (int i = 0; i < damageNumbers.Length; i++)
  616. {
  617. undoObjects[i] = damageNumbers[i];
  618. }
  619. for (int i = 0; i < textMeshPros.Length; i++)
  620. {
  621. undoObjects[i + damageNumbers.Length] = textMeshPros[i];
  622. }
  623. Undo.RecordObjects(undoObjects, "Applied the [" + preset.name + "] " + category + " Preset.");
  624. }
  625. else
  626. {
  627. Object[] undoObjects = new Object[damageNumbers.Length * 3];
  628. for (int i = 0; i < damageNumbers.Length; i += 3)
  629. {
  630. undoObjects[i] = damageNumbers[i];
  631. undoObjects[i + 1] = damageNumbers[i].GetTextMeshs()[0];
  632. undoObjects[i + 2] = damageNumbers[i].GetTextMeshs()[1];
  633. }
  634. Undo.RecordObjects(undoObjects, "Applied the [" + preset.name + "] " + category + " Preset.");
  635. }
  636. foreach(DamageNumber dn in damageNumbers)
  637. {
  638. preset.Apply(dn);
  639. }
  640. foreach(DamageNumber dn in damageNumbers)
  641. {
  642. dn.UpdateText();
  643. }
  644. }
  645. // Reenable GUI
  646. GUI.enabled = true;
  647. }
  648. GUI.enabled = false;
  649. GUI.color = new Color(0, 0, 0, 0);
  650. int modulo = currentCount % buttonsPerRow;
  651. if(modulo > 0)
  652. {
  653. for (int n = 0; n < buttonsPerRow - modulo; n++)
  654. {
  655. GUILayout.Button("- - - - -");
  656. }
  657. }
  658. GUI.color = Color.white;
  659. GUI.enabled = true;
  660. EditorGUILayout.EndHorizontal();
  661. }
  662. #endregion
  663. #region Structure
  664. public static bool CheckStructure(DamageNumberEditor damageNumberEditor)
  665. {
  666. // Type
  667. bool isMesh = damageNumbers[0].IsMesh(); ;
  668. // Check if structure is flawed
  669. bool isStructureFlawed = false;
  670. bool isOutdated = false;
  671. if(isMesh)
  672. {
  673. for (int n = 0; n < damageNumbers.Length; n++)
  674. {
  675. DamageNumber dn = damageNumbers[n];
  676. TextMeshPro tmp = textMeshPros[n];
  677. Transform meshA = meshAs[n];
  678. Transform meshB = meshBs[n];
  679. if (tmp == null || meshA == null || meshB == null)
  680. {
  681. isStructureFlawed = true;
  682. if (dn.transform.Find("TextA") != null)
  683. {
  684. isOutdated = true;
  685. }
  686. break;
  687. }
  688. }
  689. }
  690. else
  691. {
  692. for (int n = 0; n < damageNumbers.Length; n++)
  693. {
  694. DamageNumber dn = damageNumbers[n];
  695. if (dn.transform.Find("TMPA") == null || dn.transform.Find("TMPB") == null)
  696. {
  697. isStructureFlawed = true;
  698. break;
  699. }
  700. }
  701. }
  702. // Create button to fix structure
  703. if (isStructureFlawed)
  704. {
  705. // Start Box
  706. StartBox(new Color(1, 1, 0.8f));
  707. // Structure Build Button
  708. GUI.color = new Color(1, 1, 0.8f);
  709. if (GUILayout.Button(isOutdated ? "Upgrade Structure" : "Build Structure", GUILayout.Width(140)))
  710. {
  711. if(isMesh)
  712. {
  713. foreach (DamageNumber dn in damageNumbers)
  714. {
  715. PrepareMeshStructure(dn.gameObject);
  716. }
  717. }
  718. else
  719. {
  720. foreach (DamageNumber dn in damageNumbers)
  721. {
  722. PrepareGUIStructure(dn.gameObject);
  723. }
  724. }
  725. PrepareInspector(damageNumberEditor);
  726. }
  727. // Text
  728. GUI.color = new Color(1, 1, 1, 0.7f);
  729. if (isOutdated)
  730. {
  731. EditorGUILayout.LabelField("Version 4.0 has changed the structure of damage numbers.", labelStyle);
  732. EditorGUILayout.LabelField("Click the button above to <b>upgrade</b> this damage number.", labelStyle);
  733. }
  734. else
  735. {
  736. EditorGUILayout.LabelField("Important components are missing.", labelStyle);
  737. EditorGUILayout.LabelField("Click the button above to <b>prepare</b> this damage number.", labelStyle);
  738. }
  739. // Close Box
  740. CloseBox(new Color(1, 1, 0.7f));
  741. EditorGUILayout.Space();
  742. return true;
  743. }
  744. else
  745. {
  746. return false;
  747. }
  748. }
  749. public static void PrepareMeshStructure(GameObject go)
  750. {
  751. // Add Sorting Group
  752. if (go.GetComponent<SortingGroup>() == null)
  753. {
  754. go.AddComponent<SortingGroup>().sortingOrder = 1000;
  755. }
  756. // Rename TextA to TMP
  757. Transform textA = go.transform.Find("TextA");
  758. if (textA != null)
  759. {
  760. textA.gameObject.name = "TMP";
  761. }
  762. // Destroy TextB
  763. if (go.transform.Find("TextB"))
  764. {
  765. MonoBehaviour.DestroyImmediate(go.transform.Find("TextB").gameObject, true);
  766. }
  767. // Create TMP
  768. if (go.transform.Find("TMP") == null)
  769. {
  770. NewTextMesh("TMP", go.transform);
  771. }
  772. // Create MeshA
  773. if (go.transform.Find("MeshA") == null)
  774. {
  775. DamageNumber.NewMesh("MeshA", go.transform);
  776. }
  777. // Create MeshB
  778. if (go.transform.Find("MeshB") == null)
  779. {
  780. DamageNumber.NewMesh("MeshB", go.transform);
  781. }
  782. // Undo
  783. Undo.RegisterCreatedObjectUndo(go, "Create new Damage Number (Mesh).");
  784. }
  785. public static void PrepareGUIStructure(GameObject go)
  786. {
  787. // Create TMP
  788. if (go.transform.Find("TMPA") == null)
  789. {
  790. NewTextGUI("TMPA", go.transform);
  791. }
  792. if (go.transform.Find("TMPB") == null)
  793. {
  794. NewTextGUI("TMPB", go.transform);
  795. }
  796. // Add Rect Component
  797. if(go.GetComponent<RectTransform>() == null)
  798. {
  799. go.AddComponent<RectTransform>();
  800. }
  801. // Undo
  802. Undo.RegisterCreatedObjectUndo(go, "Create new Damage Number (GUI).");
  803. }
  804. public static GameObject NewTextMesh(string tmName, Transform parent)
  805. {
  806. // GameObject
  807. GameObject newTM = new GameObject();
  808. newTM.name = tmName;
  809. // TextMeshPro
  810. TextMeshPro tmp = newTM.AddComponent<TextMeshPro>();
  811. tmp.fontSize = 5;
  812. tmp.verticalAlignment = VerticalAlignmentOptions.Middle;
  813. tmp.horizontalAlignment = HorizontalAlignmentOptions.Center;
  814. tmp.text = "1";
  815. tmp.textWrappingMode = TextWrappingModes.NoWrap;
  816. // Size Delta
  817. RectTransform rectTransform = tmp.GetComponent<RectTransform>();
  818. if (rectTransform != null)
  819. {
  820. rectTransform.sizeDelta = new Vector2(4, 2);
  821. }
  822. // Transform
  823. newTM.transform.SetParent(parent, true);
  824. newTM.transform.localPosition = Vector3.zero;
  825. newTM.transform.localScale = Vector3.one;
  826. newTM.transform.localEulerAngles = Vector3.zero;
  827. return newTM;
  828. }
  829. public static GameObject NewTextGUI(string tmName, Transform parent)
  830. {
  831. // GameObject
  832. GameObject newTM = new GameObject();
  833. newTM.name = tmName;
  834. // TextMeshPro
  835. TextMeshProUGUI tmp = newTM.AddComponent<TextMeshProUGUI>();
  836. tmp.fontSize = 30;
  837. tmp.verticalAlignment = VerticalAlignmentOptions.Middle;
  838. tmp.horizontalAlignment = HorizontalAlignmentOptions.Center;
  839. tmp.text = "1";
  840. tmp.textWrappingMode = TextWrappingModes.NoWrap;
  841. tmp.raycastTarget = false;
  842. // Size Delta
  843. RectTransform rectTransform = tmp.GetComponent<RectTransform>();
  844. if (rectTransform != null)
  845. {
  846. rectTransform.sizeDelta = new Vector2(4, 2);
  847. }
  848. // Transform
  849. newTM.transform.SetParent(parent, true);
  850. newTM.transform.localPosition = Vector3.zero;
  851. newTM.transform.localScale = Vector3.one;
  852. newTM.transform.localEulerAngles = Vector3.zero;
  853. return newTM;
  854. }
  855. public static void FixTextMeshPro()
  856. {
  857. bool destroyedSomething = false;
  858. foreach (TextMeshPro textMesh in textMeshPros)
  859. {
  860. Transform tmp = textMesh.transform;
  861. tmp.localPosition = Vector3.zero;
  862. tmp.gameObject.SetActive(true);
  863. for (int n = 0; n < tmp.childCount; n++)
  864. {
  865. DestroyOrDisable(tmp.GetChild(n).gameObject);
  866. destroyedSomething = true;
  867. }
  868. tmp.gameObject.SetActive(false);
  869. }
  870. foreach(Transform meshA in meshAs)
  871. {
  872. for(int n = 0; n < meshA.childCount; n++)
  873. {
  874. Transform child = meshA.GetChild(n);
  875. if(child.GetComponent<MeshRenderer>() != null)
  876. {
  877. destroyedSomething = true;
  878. DestroyOrDisable(child.gameObject);
  879. }
  880. }
  881. }
  882. foreach (Transform meshB in meshBs)
  883. {
  884. for (int n = 0; n < meshB.childCount; n++)
  885. {
  886. Transform child = meshB.GetChild(n);
  887. if (child.GetComponent<MeshRenderer>() != null)
  888. {
  889. destroyedSomething = true;
  890. DestroyOrDisable(child.gameObject);
  891. }
  892. }
  893. }
  894. if(destroyedSomething)
  895. {
  896. foreach(DamageNumber dn in damageNumbers)
  897. {
  898. dn.GetReferences();
  899. }
  900. }
  901. }
  902. private static void DestroyOrDisable(GameObject go)
  903. {
  904. if (PrefabUtility.IsPartOfNonAssetPrefabInstance(go))
  905. {
  906. go.SetActive(false);
  907. }
  908. else
  909. {
  910. Object.DestroyImmediate(go);
  911. }
  912. }
  913. #endregion
  914. #region Miscellaneous
  915. public static void BeginInspector()
  916. {
  917. EditorGUILayout.BeginHorizontal();
  918. EditorGUILayout.BeginVertical();
  919. }
  920. public static void EndInspector()
  921. {
  922. EditorGUILayout.EndVertical();
  923. EditorGUILayout.Space(2);
  924. EditorGUILayout.EndHorizontal();
  925. }
  926. static void PrepareStyles()
  927. {
  928. if(generatedGUIStyles)
  929. {
  930. return;
  931. }
  932. // Label
  933. labelStyle = new GUIStyle(GUI.skin.label);
  934. labelStyle.richText = true;
  935. // Button
  936. buttonStyle = new GUIStyle(GUI.skin.button);
  937. buttonStyle.richText = true;
  938. buttonStyle.alignment = TextAnchor.MiddleCenter;
  939. // Right Anchor
  940. rightTextStyle = new GUIStyle(labelStyle);
  941. rightTextStyle.alignment = TextAnchor.MiddleRight;
  942. // Center Anchor
  943. centerTextStyle = new GUIStyle(labelStyle);
  944. centerTextStyle.alignment = TextAnchor.MiddleCenter;
  945. // Bottom Right Anchor
  946. bottomRightTextStyle = new GUIStyle(labelStyle);
  947. bottomRightTextStyle.alignment = TextAnchor.LowerRight;
  948. // Top Right Anchor
  949. topRightTextStyle = new GUIStyle(labelStyle);
  950. topRightTextStyle.alignment = TextAnchor.UpperRight;
  951. // White Box
  952. whiteBoxStyle = new GUIStyle(GUI.skin.box);
  953. whiteBoxStyle.normal.background = whiteBoxStyle.onNormal.background = whiteBoxStyle.active.background =
  954. whiteBoxStyle.onActive.background = whiteBoxStyle.focused.background = whiteBoxStyle.onFocused.background =
  955. whiteBoxStyle.hover.background = whiteBoxStyle.onHover.background = whiteBoxTexture;
  956. // Rich Everything
  957. for(int n = 0; n < GUI.skin.customStyles.Length; n++)
  958. {
  959. if(GUI.skin.customStyles[n] != null)
  960. {
  961. GUI.skin.customStyles[n].richText = true;
  962. }
  963. }
  964. // Finish
  965. generatedGUIStyles = true;
  966. }
  967. public static bool HintButton(string category)
  968. {
  969. bool toggled = hints.Contains(category);
  970. string buttonName = toggled ? "<size=8> </size><b>?</b>" : "?";
  971. if (GUILayout.Button(buttonName, buttonStyle, GUILayout.Width(21)))
  972. {
  973. if (hints.Contains(category))
  974. {
  975. hints.Remove(category);
  976. }
  977. else
  978. {
  979. hints.Add(category);
  980. }
  981. toggled = !toggled;
  982. }
  983. if (toggled)
  984. {
  985. GUI.color = new Color(1, 1, 1, 0.8f);
  986. GUI.Toolbar(GUILayoutUtility.GetLastRect(), 0, new string[] { buttonName }, buttonStyle);
  987. GUI.color = new Color(1, 1, 1, 1f);
  988. }
  989. return toggled;
  990. }
  991. public static void RepaintInspector()
  992. {
  993. repaintViews = true;
  994. GUI.FocusControl("");
  995. }
  996. public static bool EditingPrefabPreview(Object target)
  997. {
  998. return EditorUtility.IsPersistent(target) && PrefabStageUtility.GetCurrentPrefabStage() == null;
  999. }
  1000. public static void OpenPrefabButton(Object target)
  1001. {
  1002. GUI.color = Color.white;
  1003. if (GUILayout.Button("Click here to open the prefab."))
  1004. {
  1005. try
  1006. {
  1007. PrefabStageUtility.OpenPrefab(AssetDatabase.GetAssetPath(target));
  1008. }
  1009. catch
  1010. {
  1011. EditorUtility.DisplayDialog("Something went wrong.", "Please open the prefab manually, by double-clicking it in the project window.", "Okay");
  1012. }
  1013. }
  1014. }
  1015. #endregion
  1016. #region Label Utility
  1017. public static void Lines()
  1018. {
  1019. GUI.color = new Color(1, 1, 1, 0.5f);
  1020. EditorGUILayout.LabelField("− − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − − −", GUILayout.Height(7f));
  1021. GUI.color = new Color(1, 1, 1, 1f);
  1022. }
  1023. public static void Label(string text)
  1024. {
  1025. EditorGUILayout.LabelField(text, labelStyle);
  1026. }
  1027. public static void ScalingLabel(string text, float scaleWidth)
  1028. {
  1029. int size = Mathf.FloorToInt(Mathf.Clamp(12 * Mathf.Pow(DNPEditorInternal.currentWidth / scaleWidth, 1.525f), 9, 12));
  1030. Label("<size=" + size + ">" + text + "</size>");
  1031. }
  1032. public static string CheckmarkString(bool state)
  1033. {
  1034. if(EditorGUIUtility.isProSkin)
  1035. {
  1036. return state ? "<size=15><b><color=#00FF00>✓</color></b></size>" : "<size=16><b><color=#FF0000>✗</color></b></size>";
  1037. }
  1038. else
  1039. {
  1040. return state ? "<size=15><b><color=#00BB00>✓</color></b></size>" : "<size=16><b><color=#BB0000>✗</color></b></size>";
  1041. }
  1042. }
  1043. #endregion
  1044. #region Box Utility
  1045. public static void StartBox(Color color, bool isActivated = true)
  1046. {
  1047. GUI.color = color;
  1048. StartBox(isActivated);
  1049. GUI.color = Color.white;
  1050. }
  1051. public static void StartBox(bool isActivated = true)
  1052. {
  1053. // Start Box
  1054. if (EditorGUIUtility.isProSkin)
  1055. {
  1056. if (isActivated)
  1057. {
  1058. GUI.backgroundColor = new Color(0.3f, 0.3f, 0.3f, 1);
  1059. }
  1060. else
  1061. {
  1062. GUI.backgroundColor = new Color(0.25f, 0.25f, 0.25f, 1);
  1063. }
  1064. }
  1065. else
  1066. {
  1067. if (isActivated)
  1068. {
  1069. GUI.backgroundColor = new Color(0.68f, 0.68f, 0.68f, 1);
  1070. }
  1071. else
  1072. {
  1073. GUI.backgroundColor = new Color(0.72f, 0.72f, 0.72f, 1);
  1074. }
  1075. }
  1076. GUILayout.BeginHorizontal(whiteBoxStyle);
  1077. GUILayout.Space(5);
  1078. GUILayout.BeginVertical();
  1079. GUILayout.Space(5);
  1080. GUI.backgroundColor = Color.white;
  1081. }
  1082. public static void CloseBox(Color color, bool isActivated = true)
  1083. {
  1084. GUI.color = color;
  1085. CloseBox(isActivated);
  1086. GUI.color = Color.white;
  1087. }
  1088. public static void CloseBox(bool isActivated = true)
  1089. {
  1090. GUILayout.Space(5);
  1091. EditorGUILayout.EndVertical();
  1092. GUILayout.Space(5);
  1093. EditorGUILayout.EndHorizontal();
  1094. Rect lastRect = GUILayoutUtility.GetLastRect();
  1095. lastRect.width -= 2;
  1096. BoxLastRect(isActivated);
  1097. }
  1098. static void BoxLastRect(bool isActivated = true)
  1099. {
  1100. Rect lastRect = GUILayoutUtility.GetLastRect();
  1101. BoxRect(lastRect, isActivated);
  1102. }
  1103. static void BoxRect(Rect targetRect, bool isActivated = true, bool withTop = true)
  1104. {
  1105. Rect leftBar = new Rect(targetRect);
  1106. leftBar.width = 3;
  1107. Rect rightBar = new Rect(targetRect);
  1108. rightBar.x += rightBar.width - 3;
  1109. rightBar.width = 3;
  1110. Rect topBar = new Rect(targetRect);
  1111. topBar.height = 3;
  1112. topBar.x += 3;
  1113. topBar.width -= 6;
  1114. Rect bottomBar = new Rect(targetRect);
  1115. bottomBar.y += bottomBar.height - 3;
  1116. bottomBar.height = 3;
  1117. bottomBar.x += 3;
  1118. bottomBar.width -= 6;
  1119. DrawOutlineBox(leftBar, isActivated);
  1120. DrawOutlineBox(rightBar, isActivated);
  1121. DrawOutlineBox(bottomBar, isActivated);
  1122. if (withTop)
  1123. {
  1124. DrawOutlineBox(topBar, isActivated);
  1125. }
  1126. DrawBox(leftBar, isActivated);
  1127. DrawBox(rightBar, isActivated);
  1128. DrawBox(bottomBar, isActivated);
  1129. if (withTop)
  1130. {
  1131. DrawBox(topBar, isActivated);
  1132. }
  1133. }
  1134. static void DrawBox(Rect rectPosition, bool isActivated = true)
  1135. {
  1136. Color boxColor = default;
  1137. if (EditorGUIUtility.isProSkin)
  1138. {
  1139. if (isActivated)
  1140. {
  1141. boxColor = new Color(0.66f, 0.66f, 0.66f, 1);
  1142. }
  1143. else
  1144. {
  1145. boxColor = new Color(0.38f, 0.38f, 0.38f, 1);
  1146. }
  1147. }
  1148. else
  1149. {
  1150. if (isActivated)
  1151. {
  1152. boxColor = new Color(0.55f, 0.55f, 0.55f, 1);
  1153. }
  1154. else
  1155. {
  1156. boxColor = new Color(0.67f, 0.67f, 0.67f, 1);
  1157. }
  1158. }
  1159. DrawBox(rectPosition, boxColor);
  1160. }
  1161. static void DrawBox(Rect rectPosition, Color boxColor)
  1162. {
  1163. GUI.backgroundColor = boxColor;
  1164. GUI.Box(rectPosition, "", whiteBoxStyle);
  1165. GUI.backgroundColor = Color.white;
  1166. }
  1167. static void DrawOutlineBox(Rect rectPosition, bool isActivated = true)
  1168. {
  1169. // Adjust Position
  1170. rectPosition.width += 2;
  1171. rectPosition.height += 2;
  1172. // Draw Box
  1173. if (EditorGUIUtility.isProSkin)
  1174. {
  1175. if (isActivated)
  1176. {
  1177. DrawBox(rectPosition, new Color(0.24f, 0.24f, 0.24f, 1));
  1178. }
  1179. else
  1180. {
  1181. DrawBox(rectPosition, new Color(0.21f, 0.21f, 0.21f, 1));
  1182. }
  1183. }
  1184. else
  1185. {
  1186. if (isActivated)
  1187. {
  1188. DrawBox(rectPosition, new Color(0.35f, 0.35f, 0.35f, 1));
  1189. }
  1190. else
  1191. {
  1192. DrawBox(rectPosition, new Color(0.5f, 0.5f, 0.5f, 1));
  1193. }
  1194. }
  1195. }
  1196. #endregion
  1197. }
  1198. }
  1199. #endif