EditorTools.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using UnityEditor;
  6. using UnityEditor.SceneManagement;
  7. using UnityEngine;
  8. using UnityEngine.SceneManagement;
  9. using Object = UnityEngine.Object;
  10. namespace I2.Loc
  11. {
  12. public class GUITools
  13. {
  14. static public Color White = Color.white;
  15. static public Color LightGray = Color.Lerp(Color.gray, Color.white, 0.5f);
  16. static public Color DarkGray = Color.Lerp(Color.gray, Color.white, 0.2f);
  17. static public Color LightYellow = Color.Lerp(Color.yellow, Color.white, 0.5f);
  18. static public GUILayoutOption DontExpandWidth = GUILayout.ExpandWidth(false);
  19. static public GUIContent EmptyContent = new GUIContent ();
  20. static List<Action> mDelayedEditorCallbacks = new List<Action>();
  21. #region Delayed Editor Callback
  22. public static void DelayedCall( Action action )
  23. {
  24. if (mDelayedEditorCallbacks.Count == 0)
  25. EditorApplication.update += OnDelayedCall;
  26. mDelayedEditorCallbacks.Add(action);
  27. }
  28. static void OnDelayedCall()
  29. {
  30. EditorApplication.update -= OnDelayedCall;
  31. var calls = mDelayedEditorCallbacks.ToArray();
  32. mDelayedEditorCallbacks.Clear();
  33. foreach (var call in calls)
  34. call();
  35. }
  36. #endregion
  37. #region Header
  38. public delegate void fnOnToggled(bool enabled);
  39. static public bool DrawHeader (string text, string key, bool ShowToggle=false, bool ToggleState=false, fnOnToggled OnToggle = null, string HelpURL=default(string), Color disabledColor = default(Color))
  40. {
  41. bool state = EditorPrefs.GetBool(key, false);
  42. bool newState = DrawHeader (text, state, ShowToggle, ToggleState, OnToggle, HelpURL, disabledColor);
  43. if (state!=newState) EditorPrefs.SetBool(key, newState);
  44. return newState;
  45. }
  46. static public bool DrawHeader (string text, bool state, bool ShowToggle=false, bool ToggleState=false, fnOnToggled OnToggle = null, string HelpURL=default(string), Color disabledColor = default(Color), bool allowCollapsing = true)
  47. {
  48. GUIStyle Style = new GUIStyle(EditorStyles.foldout);
  49. Style.richText = true;
  50. EditorStyles.foldout.richText = true;
  51. if (state)
  52. {
  53. //GUI.backgroundColor=DarkGray;
  54. GUILayout.BeginVertical(LocalizeInspector.GUIStyle_OldTextArea/*, GUILayout.Height(1)*/);
  55. GUILayout.BeginHorizontal();
  56. if (!string.IsNullOrEmpty(text))
  57. {
  58. if (allowCollapsing)
  59. state = GUILayout.Toggle(state, text, Style, GUILayout.ExpandWidth(true));
  60. else
  61. GUILayout.Label(text, GUILayout.ExpandWidth(true));
  62. }
  63. if (!string.IsNullOrEmpty(HelpURL))
  64. {
  65. if (GUILayout.Button (Icon_Help, EditorStyles.label, GUILayout.ExpandWidth(false)))
  66. Application.OpenURL(HelpURL);
  67. }
  68. if (ShowToggle)
  69. {
  70. GUI.changed = false;
  71. bool newBool = GUILayout.Toggle(ToggleState, "", "OL Toggle", GUILayout.ExpandWidth(false));
  72. if (GUI.changed && OnToggle!=null)
  73. OnToggle(newBool);
  74. }
  75. GUILayout.EndHorizontal();
  76. GUILayout.Space(2);
  77. //GUI.backgroundColor = Color.white;
  78. }
  79. else
  80. {
  81. if (ShowToggle && !ToggleState)
  82. GUI.color = disabledColor;
  83. GUILayout.BeginHorizontal("Box");
  84. //GUILayout.BeginHorizontal(EditorStyles.toolbar);
  85. state = GUILayout.Toggle(state, text, Style, GUILayout.ExpandWidth(true));
  86. if (ShowToggle)
  87. {
  88. GUI.changed = false;
  89. bool newBool = GUILayout.Toggle(ToggleState, "", "OL Toggle", GUILayout.ExpandWidth(false));
  90. if (GUI.changed && OnToggle!=null)
  91. OnToggle(newBool);
  92. }
  93. GUILayout.EndHorizontal();
  94. GUI.color = White;
  95. }
  96. return state;
  97. }
  98. static public void CloseHeader()
  99. {
  100. GUILayout.EndHorizontal();
  101. }
  102. public static void OnGUI_Footer(string pluginName, string pluginVersion, string helpURL, string documentationURL, string assetStoreURL)
  103. {
  104. GUILayout.BeginHorizontal();
  105. string versionTip = "";
  106. /*if (I2Analytics.HasNewVersion(pluginName))
  107. {
  108. versionTip = "There is a new version of " + pluginName + ".\nClick here for more details";
  109. if (GUILayout.Button(new GUIContent("", versionTip), EditorStyles.label, GUILayout.Width(25)))
  110. I2AboutWindow.DoShowScreen();
  111. var rect = GUILayoutUtility.GetLastRect();
  112. rect.yMin = rect.yMax - 25;
  113. rect.xMax = rect.xMin + 25;
  114. rect.y += 3;
  115. GUITools.DrawSkinIcon(rect, "CN EntryWarnIcon", "CN EntryWarn");
  116. }*/
  117. if (GUILayout.Button(new GUIContent("v" + pluginVersion, versionTip), EditorStyles.miniLabel))
  118. {
  119. Application.OpenURL(assetStoreURL);
  120. //I2AboutWindow.DoShowScreen();
  121. }
  122. GUILayout.FlexibleSpace();
  123. if (GUILayout.Button("Ask a Question", EditorStyles.miniLabel))
  124. Application.OpenURL(helpURL);
  125. GUILayout.Space(10);
  126. if (GUILayout.Button("Documentation", EditorStyles.miniLabel))
  127. Application.OpenURL(documentationURL);
  128. GUILayout.EndHorizontal();
  129. }
  130. #endregion
  131. #region Content
  132. static public void BeginContents ()
  133. {
  134. EditorGUILayout.BeginHorizontal(LocalizeInspector.GUIStyle_OldTextArea, GUILayout.MinHeight(10f));
  135. GUILayout.Space(2f);
  136. EditorGUILayout.BeginVertical();
  137. GUILayout.Space(2f);
  138. }
  139. static public void EndContents () { EndContents(true); }
  140. static public void EndContents ( bool closeHeader )
  141. {
  142. GUILayout.Space(2f);
  143. EditorGUILayout.EndVertical();
  144. GUILayout.Space(3f);
  145. GUILayout.EndHorizontal();
  146. if (closeHeader) CloseHeader();
  147. }
  148. #endregion
  149. #region Tabs
  150. static public void DrawTabs( SerializedProperty mProperty, GUIStyle Style=null, int height=25 )
  151. {
  152. int curIndex = mProperty.enumValueIndex;
  153. int newIndex = DrawTabs( curIndex, mProperty.enumNames, Style, height);
  154. if (curIndex!=newIndex)
  155. mProperty.enumValueIndex = newIndex;
  156. }
  157. static public int DrawTabs( int Index, string[] Tabs, GUIStyle Style=null, int height=25, bool expand = true)
  158. {
  159. GUIStyle MyStyle = new GUIStyle(Style!=null?Style:GUI.skin.FindStyle("dragtab"));
  160. MyStyle.fixedHeight=0;
  161. GUILayout.BeginHorizontal();
  162. for (int i=0; i<Tabs.Length; ++i)
  163. {
  164. int idx = Tabs[i].IndexOf('|');
  165. if (idx>0)
  166. {
  167. string text = Tabs[i].Substring(0, idx);
  168. string tooltip = Tabs[i].Substring(idx+1);
  169. if ( GUILayout.Toggle(Index==i, new GUIContent(text, tooltip), MyStyle, GUILayout.Height(height), GUILayout.ExpandWidth(expand)) && Index!=i)
  170. {
  171. Index=i;
  172. GUI.FocusControl(string.Empty);
  173. }
  174. }
  175. else
  176. {
  177. if ( GUILayout.Toggle(Index==i, Tabs[i], MyStyle, GUILayout.Height(height), GUILayout.ExpandWidth(expand)) && Index!=i)
  178. {
  179. Index=i;
  180. GUI.FocusControl(string.Empty);
  181. }
  182. }
  183. }
  184. GUILayout.EndHorizontal();
  185. return Index;
  186. }
  187. static public void DrawShadowedTabs( SerializedProperty mProperty, GUIStyle Style=null, int height=25, bool expand=true )
  188. {
  189. int curIndex = mProperty.enumValueIndex;
  190. int newIndex = DrawShadowedTabs( curIndex, mProperty.enumNames, height, expand);
  191. if (curIndex!=newIndex)
  192. mProperty.enumValueIndex = newIndex;
  193. }
  194. static public int DrawShadowedTabs( int Index, string[] Tabs, int height = 25, bool expand=true )
  195. {
  196. GUI.backgroundColor=Color.Lerp (Color.gray, Color.white, 0.2f);
  197. GUILayout.BeginVertical(LocalizeInspector.GUIStyle_OldTextArea, GUILayout.Height(1));
  198. GUI.backgroundColor=Color.white;
  199. GUILayout.Space(2);
  200. Index = DrawTabs( Index, Tabs, height: height, expand:expand );
  201. GUILayout.EndVertical();
  202. return Index;
  203. }
  204. static public int DrawTabs( int Index, Texture2D[] Tabs, GUIStyle Style, int height )
  205. {
  206. GUIStyle MyStyle = new GUIStyle(Style!=null?Style:GUI.skin.FindStyle("dragtab"));
  207. MyStyle.fixedHeight=0;
  208. //width = Mathf.Max (width, height * Tabs[0].width/(float)Tabs[0].height);
  209. GUILayout.BeginHorizontal();
  210. float width = (EditorGUIUtility.currentViewWidth-(MyStyle.border.left+MyStyle.border.right)*(Tabs.Length-1)) / Tabs.Length;
  211. for (int i=0; i<Tabs.Length; ++i)
  212. {
  213. if ( GUILayout.Toggle(Index==i, Tabs[i], MyStyle, GUILayout.Height(height), GUILayout.Width(width)) && Index!=i)
  214. {
  215. Index=i;
  216. GUI.changed = true;
  217. }
  218. }
  219. GUILayout.EndHorizontal();
  220. return Index;
  221. }
  222. #endregion
  223. #region Object Array
  224. static public bool DrawObjectsArray( SerializedProperty PropArray, bool allowDuplicates=false, bool allowResources=false, bool allowSceneObj=false, Object testAdd=null, Object testReplace=null, int testReplaceIndex=-1, int testDeleteIndex=-1 )
  225. {
  226. bool hasChanged = false;
  227. GUILayout.BeginVertical();
  228. int DeleteElement = -1, MoveUpElement = -1;
  229. for (int i=0, imax=PropArray.arraySize; i<imax; ++i)
  230. {
  231. SerializedProperty Prop = PropArray.GetArrayElementAtIndex(i);
  232. GUILayout.BeginHorizontal();
  233. //--[ Delete Button ]-------------------
  234. if (GUILayout.Button("X", EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)) || i == testDeleteIndex)
  235. DeleteElement = i;
  236. GUILayout.Space(2);
  237. //--[ Object ]--------------------------
  238. GUILayout.BeginHorizontal(EditorStyles.toolbar);
  239. GUI.changed = false;
  240. Object Obj = EditorGUILayout.ObjectField( Prop.objectReferenceValue, typeof(Object), allowSceneObj, GUILayout.ExpandWidth(true));
  241. if (testReplaceIndex == i)
  242. {
  243. Obj = testReplace;
  244. GUI.changed = true;
  245. }
  246. if (!allowResources && Obj != null)
  247. {
  248. var path = AssetDatabase.GetAssetPath(Obj);
  249. if (path != null && path.Contains("/Resources/"))
  250. Obj = null;
  251. }
  252. if (Obj==null)
  253. DeleteElement = i;
  254. else
  255. if (GUI.changed && (allowDuplicates || !ObjectsArrayHasReference(PropArray, Obj)))
  256. {
  257. Prop.objectReferenceValue = Obj;
  258. hasChanged = true;
  259. }
  260. GUILayout.EndHorizontal();
  261. //--[ MoveUp Button ]-------------------
  262. if (i==0)
  263. {
  264. if (imax>1)
  265. GUILayout.Space (18);
  266. }
  267. else
  268. {
  269. if (GUILayout.Button( "\u25B2", EditorStyles.toolbarButton, GUILayout.Width(18)))
  270. MoveUpElement = i;
  271. }
  272. GUILayout.EndHorizontal();
  273. }
  274. GUILayout.BeginHorizontal(EditorStyles.toolbar);
  275. Object NewObj = EditorGUILayout.ObjectField( null, typeof(Object), allowSceneObj, GUILayout.ExpandWidth(true));
  276. if (testAdd != null)
  277. {
  278. NewObj = testAdd;
  279. }
  280. if (!allowResources && NewObj != null)
  281. {
  282. var path = AssetDatabase.GetAssetPath(NewObj);
  283. if (path != null && path.Contains("/Resources/"))
  284. NewObj = null;
  285. }
  286. if (NewObj && (allowDuplicates || !ObjectsArrayHasReference(PropArray, NewObj)))
  287. {
  288. int Index = PropArray.arraySize;
  289. PropArray.InsertArrayElementAtIndex( Index );
  290. PropArray.GetArrayElementAtIndex(Index).objectReferenceValue = NewObj;
  291. hasChanged = true;
  292. }
  293. GUILayout.EndHorizontal();
  294. if (DeleteElement>=0)
  295. {
  296. PropArray.DeleteArrayElementAtIndex( DeleteElement );
  297. //PropArray.DeleteArrayElementAtIndex( DeleteElement );
  298. hasChanged = true;
  299. }
  300. if (MoveUpElement>=0)
  301. {
  302. PropArray.MoveArrayElement(MoveUpElement, MoveUpElement-1);
  303. hasChanged = true;
  304. }
  305. GUILayout.EndVertical();
  306. return hasChanged;
  307. }
  308. static public bool ObjectsArrayHasReference(SerializedProperty PropArray, Object obj)
  309. {
  310. for (int i = 0, imax = PropArray.arraySize; i < imax; ++i)
  311. {
  312. SerializedProperty Prop = PropArray.GetArrayElementAtIndex(i);
  313. if (Prop.objectReferenceValue == obj)
  314. return true;
  315. }
  316. return false;
  317. }
  318. #endregion
  319. #region Toggle
  320. static public int ToggleToolbar( int Index, string[] Options )
  321. {
  322. GUILayout.BeginHorizontal();
  323. for (int i=0; i<Options.Length; ++i)
  324. {
  325. if ( GUILayout.Toggle(Index==i, Options[i], EditorStyles.toolbarButton))
  326. Index=i;
  327. }
  328. GUILayout.EndHorizontal();
  329. return Index;
  330. }
  331. static public void ToggleToolbar( SerializedProperty EnumVar )
  332. {
  333. int index = ToggleToolbar( EnumVar.enumValueIndex, EnumVar.enumNames);
  334. if (EnumVar.enumValueIndex != index)
  335. EnumVar.enumValueIndex = index;
  336. }
  337. #endregion
  338. #region Misc
  339. public static bool ObjectExistInScene( GameObject Obj )
  340. {
  341. return Obj.scene.IsValid() && Obj.scene.isLoaded;
  342. /* //if (Obj.transform.root != Obj.transform)
  343. // continue;
  344. // We are only interested in GameObjects that are visible in the Hierachy panel and are persitent
  345. if ((Obj.hideFlags & (HideFlags.DontSave|HideFlags.HideInHierarchy)) > 0)
  346. return false;
  347. // We are not interested in Prefab, unless they are Prefab Instances
  348. PrefabType pfType = PrefabUtility.GetPrefabType(Obj);
  349. if(pfType == PrefabType.Prefab || pfType == PrefabType.ModelPrefab)
  350. return false;
  351. // If the database contains the object then its not an scene object,
  352. // but the previous test should get rid of them, so I will just comment this
  353. // unless an false positive object is found in the future
  354. //if (AssetDatabase.Contains(Obj))
  355. // return false;
  356. return true;*/
  357. }
  358. public static IEnumerable<GameObject> SceneRoots()
  359. {
  360. var prop = new HierarchyProperty(HierarchyType.GameObjects);
  361. var expanded = new int[0];
  362. while (prop.Next(expanded)) {
  363. yield return prop.pptrValue as GameObject;
  364. }
  365. }
  366. public static List<GameObject> SceneRootsList()
  367. {
  368. return new List<GameObject>(SceneRoots());
  369. }
  370. public static IEnumerable<Transform> AllSceneObjects()
  371. {
  372. var queue = new Queue<Transform>();
  373. foreach (var root in SceneRoots()) {
  374. var tf = root.transform;
  375. yield return tf;
  376. queue.Enqueue(tf);
  377. }
  378. while (queue.Count > 0) {
  379. foreach (Transform child in queue.Dequeue()) {
  380. yield return child;
  381. queue.Enqueue(child);
  382. }
  383. }
  384. }
  385. public static string GetScenePath(Transform tr)
  386. {
  387. if (tr==null)
  388. return string.Empty;
  389. string path = tr.name;
  390. while (tr.parent != null)
  391. {
  392. tr = tr.parent;
  393. path = tr.name + "/" + path;
  394. }
  395. return path;
  396. }
  397. public static Transform FindObjectInEditor( string scenePath )
  398. {
  399. if (string.IsNullOrEmpty(scenePath))
  400. return null;
  401. int index = scenePath.IndexOfAny("/\\".ToCharArray());
  402. string first = index<0 ? scenePath : scenePath.Substring(0, index);
  403. foreach (var root in AllSceneObjects())
  404. if (root.name==first)
  405. {
  406. if (index<0)
  407. return root;
  408. return root.Find(scenePath.Substring(index+1));
  409. }
  410. return null;
  411. }
  412. public static GUIContent Icon_Help {
  413. get{
  414. if (mIconHelp == null)
  415. mIconHelp = EditorGUIUtility.IconContent("_Help");
  416. return mIconHelp;
  417. }
  418. }
  419. static GUIContent mIconHelp;
  420. public static GUIStyle FindSkinStyle(string name)
  421. {
  422. var allStyles = GUI.skin.customStyles;
  423. for (int i = 0, imax = allStyles.Length; i < imax; ++i)
  424. {
  425. if (allStyles[i].name == name)
  426. return allStyles[i];
  427. }
  428. return null;
  429. }
  430. public static void DrawSkinIcon(Rect rect, params string[] iconNames)
  431. {
  432. foreach (var icon in iconNames)
  433. {
  434. var style = FindSkinStyle(icon);
  435. if (style == null || style.normal == null || style.normal.background == null)
  436. continue;
  437. GUI.DrawTexture(rect, style.normal.background);
  438. return;
  439. }
  440. //Debug.Log("unable to find icon");
  441. }
  442. #endregion
  443. #region Angle Drawer
  444. private static Vector2 mAngle_lastMousePosition;
  445. static Texture mAngle_TextureCircle;
  446. static Texture pAngle_TextureCircle {
  447. get{
  448. if (mAngle_TextureCircle) return mAngle_TextureCircle;
  449. mAngle_TextureCircle = GUI.skin.GetStyle("CN CountBadge").normal.background;
  450. return mAngle_TextureCircle;
  451. }
  452. }
  453. public static float FloatAngle(Rect rect, float value)
  454. {
  455. return FloatAngle(rect, value, -1, -1, -1);
  456. }
  457. public static float FloatAngle(Rect rect, float value, float snap)
  458. {
  459. return FloatAngle(rect, value, snap, -1, -1);
  460. }
  461. public static float FloatAngle(Rect rect, float value, float snap, float min, float max)
  462. {
  463. int id = GUIUtility.GetControlID(FocusType.Passive, rect);
  464. Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
  465. float delta;
  466. if (min != max)
  467. delta = (max - min) / 360;
  468. else
  469. delta = 1;
  470. if (Event.current != null)
  471. {
  472. if (Event.current.type == EventType.MouseDown && knobRect.Contains(Event.current.mousePosition))
  473. {
  474. GUIUtility.hotControl = id;
  475. mAngle_lastMousePosition = Event.current.mousePosition;
  476. }
  477. else if (Event.current.type == EventType.MouseUp && GUIUtility.hotControl == id)
  478. GUIUtility.hotControl = -1;
  479. else if (Event.current.type == EventType.MouseDrag && GUIUtility.hotControl == id)
  480. {
  481. Vector2 move = mAngle_lastMousePosition - Event.current.mousePosition;
  482. value += delta * (-move.x - move.y);
  483. if (snap > 0)
  484. {
  485. float mod = value % snap;
  486. if (mod < delta * 3 || Mathf.Abs(mod - snap) < delta * 3)
  487. value = Mathf.Round(value / snap) * snap;
  488. }
  489. mAngle_lastMousePosition = Event.current.mousePosition;
  490. GUI.changed = true;
  491. }
  492. }
  493. if (pAngle_TextureCircle) GUI.DrawTexture(knobRect, pAngle_TextureCircle);
  494. Matrix4x4 matrix = GUI.matrix;
  495. if (min != max)
  496. GUIUtility.RotateAroundPivot(value * (360 / (max - min)), knobRect.center);
  497. else
  498. GUIUtility.RotateAroundPivot(value, knobRect.center);
  499. knobRect.height = 5;
  500. knobRect.width = 5;
  501. if (pAngle_TextureCircle) GUI.DrawTexture(knobRect, pAngle_TextureCircle);
  502. GUI.matrix = matrix;
  503. Rect label = new Rect(rect.x + rect.height, rect.y + rect.height / 2 - 9, rect.height, 18);
  504. value = EditorGUI.FloatField(label, value);
  505. if (min != max)
  506. value = Mathf.Clamp(value, min, max);
  507. return value;
  508. }
  509. public static float AngleCircle(Rect rect, float angle, float snap, float min, float max, Texture background=null, Texture knobLine=null)
  510. {
  511. Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
  512. float delta;
  513. if (min != max)
  514. delta = (max - min) / 360;
  515. else
  516. delta = 1;
  517. if (Event.current != null && GUIUtility.hotControl<=0 && (Event.current.type==EventType.MouseDown || Event.current.type==EventType.MouseDrag) && knobRect.Contains(Event.current.mousePosition))
  518. {
  519. angle = Vector2.Angle( Vector2.right, Event.current.mousePosition-knobRect.center);
  520. if (Event.current.mousePosition.y<knobRect.center.y) angle = 360-angle;
  521. if (Event.current.alt || Event.current.control)
  522. snap = 5;
  523. if (snap > 0)
  524. {
  525. float mod = Mathf.Repeat(angle, snap);
  526. if (mod < delta * 3 || Mathf.Abs(mod - snap) < delta * 3)
  527. angle = Mathf.Round(angle / snap) * snap;
  528. }
  529. GUI.changed = true;
  530. }
  531. if (background==null) background = pAngle_TextureCircle;
  532. if (background) GUI.DrawTexture (knobRect, background);
  533. Matrix4x4 matrix = GUI.matrix;
  534. if (min != max)
  535. GUIUtility.RotateAroundPivot(angle * (360 / (max - min))+90, knobRect.center);
  536. else
  537. GUIUtility.RotateAroundPivot(angle+90, knobRect.center);
  538. float Radius = Mathf.Min (knobRect.width, knobRect.height) * 0.5f;
  539. knobRect.x = knobRect.x + 0.5f * knobRect.width - 4;
  540. knobRect.y += 2;
  541. knobRect.width = 8;
  542. knobRect.height = Radius+2;
  543. if (knobLine == null)
  544. knobLine = GUI.skin.FindStyle ("MeBlendPosition").normal.background;
  545. if (knobLine) GUI.DrawTexture(knobRect, knobLine);
  546. GUI.matrix = matrix;
  547. return Mathf.Repeat(angle, 360);
  548. }
  549. #endregion
  550. #region Unity Version branching
  551. public static string Editor_GetCurrentScene()
  552. {
  553. #if UNITY_4_6 || UNITY_4_7 || UNITY_4_8 || UNITY_4_9 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
  554. return EditorApplication.currentScene;
  555. #else
  556. return SceneManager.GetActiveScene().path;
  557. #endif
  558. }
  559. public static void Editor_MarkSceneDirty()
  560. {
  561. #if UNITY_5_3 || UNITY_5_3_OR_NEWER
  562. EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
  563. #else
  564. EditorApplication.MarkSceneDirty();
  565. #endif
  566. }
  567. public static void Editor_SaveScene()
  568. {
  569. #if UNITY_4_6 || UNITY_4_7 || UNITY_4_8 || UNITY_4_9 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
  570. EditorApplication.SaveScene ();
  571. #else
  572. EditorSceneManager.SaveOpenScenes();
  573. #endif
  574. }
  575. public static void Editor_OpenScene( string sceneName )
  576. {
  577. #if UNITY_4_6 || UNITY_4_7 || UNITY_4_8 || UNITY_4_9 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
  578. EditorApplication.OpenScene( sceneName );
  579. #else
  580. EditorSceneManager.OpenScene(sceneName);
  581. #endif
  582. }
  583. #endregion
  584. #region Reflection
  585. static public object Reflection_InvokeMethod ( object instanceObject, string methodName, params object[] p_args )
  586. {
  587. BindingFlags _flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
  588. MethodInfo mi = instanceObject.GetType().GetMethods( _flags ).Where( x => x.Name==methodName ).FirstOrDefault();
  589. if (mi == null) return null;
  590. return mi.Invoke( instanceObject, p_args );
  591. }
  592. static public object Reflection_InvokeMethod ( Type targetType, string methodName, params object[] p_args )
  593. {
  594. BindingFlags _flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;
  595. MethodInfo mi = targetType.GetMethods( _flags ).Where( x => x.Name==methodName ).FirstOrDefault();
  596. if (mi == null) return null;
  597. return mi.Invoke( null, p_args );
  598. }
  599. public static object s_RecycledEditor;
  600. public static string TextField ( Rect position, string text, int maxLength, GUIStyle style, int controlID )
  601. {
  602. if (s_RecycledEditor==null)
  603. {
  604. FieldInfo info = typeof(EditorGUI).GetField("s_RecycledEditor", BindingFlags.NonPublic | BindingFlags.Static);
  605. s_RecycledEditor = info.GetValue(null);
  606. }
  607. if (s_RecycledEditor == null)
  608. return "";
  609. return Reflection_InvokeMethod( typeof( EditorGUI ), "DoTextField", s_RecycledEditor, controlID, position, text, style, null, false, false, false, false ) as string;
  610. }
  611. static public void RepaintInspectors()
  612. {
  613. EditorApplication.update -= RepaintInspectors;
  614. var assemblyEditor = Assembly.GetAssembly(typeof(Editor));
  615. var typeInspectorWindow = assemblyEditor.GetType("UnityEditor.InspectorWindow");
  616. typeInspectorWindow.GetMethod("RepaintAllInspectors", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
  617. }
  618. public static void ScheduleRepaintInspectors()
  619. {
  620. EditorApplication.update += RepaintInspectors;
  621. }
  622. #endregion
  623. }
  624. }