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.

1670 lines
48 KiB

  1. /**
  2. * 7/8/2013
  3. */
  4. #define PRO
  5. using UnityEngine;
  6. using UnityEditor;
  7. using System.Collections.Generic;
  8. using System.Reflection;
  9. using System;
  10. using System.Linq;
  11. namespace ProGrids
  12. {
  13. [InitializeOnLoad]
  14. public static class pg_Initializer
  15. {
  16. /**
  17. * When opening Unity, remember whether or not ProGrids was open when Unity was shut down last.
  18. */
  19. static pg_Initializer()
  20. {
  21. if (EditorPrefs.GetBool(pg_Constant.ProGridsIsEnabled))
  22. {
  23. if (pg_Editor.instance == null)
  24. pg_Editor.InitProGrids();
  25. else
  26. EditorApplication.delayCall += pg_Editor.instance.Initialize;
  27. }
  28. }
  29. }
  30. public class pg_Editor : ScriptableObject, ISerializationCallbackReceiver
  31. {
  32. #region MEMBERS
  33. public static pg_Editor instance
  34. {
  35. get
  36. {
  37. if (_instance == null)
  38. {
  39. pg_Editor[] editor = Resources.FindObjectsOfTypeAll<pg_Editor>();
  40. if (editor != null && editor.Length > 0)
  41. {
  42. _instance = editor[0];
  43. for (int i = 1; i < editor.Length; i++)
  44. {
  45. GameObject.DestroyImmediate(editor[i]);
  46. }
  47. }
  48. }
  49. return _instance;
  50. }
  51. set
  52. {
  53. _instance = value;
  54. }
  55. }
  56. private static pg_Editor _instance;
  57. Color oldColor;
  58. private bool useAxisConstraints
  59. {
  60. get { return EditorPrefs.GetBool(pg_Constant.UseAxisConstraints); }
  61. set { EditorPrefs.SetBool(pg_Constant.UseAxisConstraints, value); }
  62. }
  63. [SerializeField]
  64. private bool snapEnabled = true;
  65. [SerializeField]
  66. private SnapUnit snapUnit = SnapUnit.Meter;
  67. #if PRO
  68. private float snapValue = 1f; // the actual snap value, taking into account unit size
  69. private float t_snapValue = 1f; // what the user sees
  70. #else
  71. private float snapValue = .25f;
  72. private float t_snapValue = .25f;
  73. #endif
  74. private bool drawGrid = true;
  75. private bool drawAngles = false;
  76. public float angleValue = 45f;
  77. private bool gridRepaint = true;
  78. public bool predictiveGrid = true;
  79. private bool _snapAsGroup = true;
  80. public bool snapAsGroup
  81. {
  82. get
  83. {
  84. return EditorPrefs.HasKey(pg_Constant.SnapAsGroup) ? EditorPrefs.GetBool(pg_Constant.SnapAsGroup) : true;
  85. }
  86. set
  87. {
  88. _snapAsGroup = value;
  89. EditorPrefs.SetBool(pg_Constant.SnapAsGroup, _snapAsGroup);
  90. }
  91. }
  92. public bool fullGrid { get; private set; }
  93. private bool _scaleSnapEnabled = false;
  94. public bool ScaleSnapEnabled
  95. {
  96. get
  97. {
  98. return EditorPrefs.HasKey(pg_Constant.SnapScale) ? EditorPrefs.GetBool(pg_Constant.SnapScale) : false;
  99. }
  100. set
  101. {
  102. _scaleSnapEnabled = value;
  103. EditorPrefs.SetBool(pg_Constant.SnapScale, _scaleSnapEnabled);
  104. }
  105. }
  106. private KeyCode m_IncreaseGridSizeShortcut = KeyCode.Equals;
  107. private KeyCode m_DecreaseGridSizeShortcut = KeyCode.Minus;
  108. private KeyCode m_NudgePerspectiveBackwardShortcut = KeyCode.LeftBracket;
  109. private KeyCode m_NudgePerspectiveForwardShortcut = KeyCode.RightBracket;
  110. private KeyCode m_NudgePerspectiveResetShortcut = KeyCode.Alpha0;
  111. private KeyCode m_CyclePerspectiveShortcut = KeyCode.Backslash;
  112. bool lockGrid = false;
  113. private Axis renderPlane = Axis.Y;
  114. #if PG_DEBUG
  115. private GameObject _pivotGo;
  116. public GameObject pivotGo
  117. {
  118. get
  119. {
  120. if(_pivotGo == null)
  121. {
  122. GameObject find = GameObject.Find("PG_PIVOT_CUBE");
  123. if(find == null)
  124. {
  125. _pivotGo = GameObject.CreatePrimitive(PrimitiveType.Cube);
  126. _pivotGo.name = "PG_PIVOT_CUBE";
  127. }
  128. else
  129. _pivotGo = find;
  130. }
  131. return _pivotGo;
  132. }
  133. set
  134. {
  135. _pivotGo = value;
  136. }
  137. }
  138. #endif
  139. #endregion
  140. #region CONSTANT
  141. const int VERSION = 22;
  142. #if PRO
  143. const int WINDOW_HEIGHT = 240;
  144. #else
  145. const int WINDOW_HEIGHT = 260;
  146. #endif
  147. const int DEFAULT_SNAP_MULTIPLIER = 2048;
  148. const int MAX_LINES = 150; // the maximum amount of lines to display on screen in either direction
  149. public static float alphaBump; // Every tenth line gets an alpha bump by this amount
  150. const int BUTTON_SIZE = 46;
  151. private Texture2D icon_extendoClose, icon_extendoOpen;
  152. [SerializeField]
  153. private pg_ToggleContent gc_SnapToGrid = new pg_ToggleContent("Snap", "", "Snaps all selected objects to grid.");
  154. [SerializeField]
  155. private pg_ToggleContent gc_GridEnabled = new pg_ToggleContent("Hide", "Show", "Toggles drawing of guide lines on or off. Note that object snapping is not affected by this setting.");
  156. [SerializeField]
  157. private pg_ToggleContent gc_SnapEnabled = new pg_ToggleContent("On", "Off", "Toggles snapping on or off.");
  158. [SerializeField]
  159. private pg_ToggleContent gc_LockGrid = new pg_ToggleContent("Lock", "Unlck", "Lock the perspective grid center in place.");
  160. [SerializeField]
  161. private pg_ToggleContent gc_AngleEnabled = new pg_ToggleContent("> On", "> Off", "If on, ProGrids will draw angled line guides. Angle is settable in degrees.");
  162. [SerializeField]
  163. private pg_ToggleContent gc_RenderPlaneX = new pg_ToggleContent("X", "X", "Renders a grid on the X plane.");
  164. [SerializeField]
  165. private pg_ToggleContent gc_RenderPlaneY = new pg_ToggleContent("Y", "Y", "Renders a grid on the Y plane.");
  166. [SerializeField]
  167. private pg_ToggleContent gc_RenderPlaneZ = new pg_ToggleContent("Z", "Z", "Renders a grid on the Z plane.");
  168. [SerializeField]
  169. private pg_ToggleContent gc_RenderPerspectiveGrid = new pg_ToggleContent("Full", "Plane", "Renders a 3d grid in perspective mode.");
  170. [SerializeField]
  171. private GUIContent gc_ExtendMenu = new GUIContent("", "Show or hide the scene view menu.");
  172. [SerializeField]
  173. private GUIContent gc_SnapIncrement = new GUIContent("", "Set the snap increment.");
  174. #endregion
  175. #region PREFERENCES
  176. /** Settings **/
  177. public Color gridColorX, gridColorY, gridColorZ;
  178. public Color gridColorX_primary, gridColorY_primary, gridColorZ_primary;
  179. // private bool lockOrthographic;
  180. public void LoadPreferences()
  181. {
  182. if ((EditorPrefs.HasKey(pg_Constant.PGVersion) ? EditorPrefs.GetInt(pg_Constant.PGVersion) : 0) != VERSION)
  183. {
  184. EditorPrefs.SetInt(pg_Constant.PGVersion, VERSION);
  185. pg_Preferences.ResetPrefs();
  186. }
  187. if (EditorPrefs.HasKey(pg_Constant.SnapEnabled))
  188. {
  189. snapEnabled = EditorPrefs.GetBool(pg_Constant.SnapEnabled);
  190. }
  191. menuOpen = EditorPrefs.GetBool(pg_Constant.ProGridsIsExtended, true);
  192. SetSnapValue(
  193. EditorPrefs.HasKey(pg_Constant.GridUnit) ? (SnapUnit)EditorPrefs.GetInt(pg_Constant.GridUnit) : SnapUnit.Meter,
  194. EditorPrefs.HasKey(pg_Constant.SnapValue) ? EditorPrefs.GetFloat(pg_Constant.SnapValue) : 1,
  195. EditorPrefs.HasKey(pg_Constant.SnapMultiplier) ? EditorPrefs.GetInt(pg_Constant.SnapMultiplier) : DEFAULT_SNAP_MULTIPLIER
  196. );
  197. m_IncreaseGridSizeShortcut = EditorPrefs.HasKey("pg_Editor::IncreaseGridSize")
  198. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::IncreaseGridSize")
  199. : KeyCode.Equals;
  200. m_DecreaseGridSizeShortcut = EditorPrefs.HasKey("pg_Editor::DecreaseGridSize")
  201. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::DecreaseGridSize")
  202. : KeyCode.Minus;
  203. m_NudgePerspectiveBackwardShortcut = EditorPrefs.HasKey("pg_Editor::NudgePerspectiveBackward")
  204. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::NudgePerspectiveBackward")
  205. : KeyCode.LeftBracket;
  206. m_NudgePerspectiveForwardShortcut = EditorPrefs.HasKey("pg_Editor::NudgePerspectiveForward")
  207. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::NudgePerspectiveForward")
  208. : KeyCode.RightBracket;
  209. m_NudgePerspectiveResetShortcut = EditorPrefs.HasKey("pg_Editor::NudgePerspectiveReset")
  210. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::NudgePerspectiveReset")
  211. : KeyCode.Alpha0;
  212. m_CyclePerspectiveShortcut = EditorPrefs.HasKey("pg_Editor::CyclePerspective")
  213. ? (KeyCode)EditorPrefs.GetInt("pg_Editor::CyclePerspective")
  214. : KeyCode.Backslash;
  215. lockGrid = EditorPrefs.GetBool(pg_Constant.LockGrid);
  216. if (lockGrid)
  217. {
  218. if (EditorPrefs.HasKey(pg_Constant.LockedGridPivot))
  219. {
  220. string piv = EditorPrefs.GetString(pg_Constant.LockedGridPivot);
  221. string[] pivsplit = piv.Replace("(", "").Replace(")", "").Split(',');
  222. float x, y, z;
  223. if (!float.TryParse(pivsplit[0], out x)) goto NoParseForYou;
  224. if (!float.TryParse(pivsplit[1], out y)) goto NoParseForYou;
  225. if (!float.TryParse(pivsplit[2], out z)) goto NoParseForYou;
  226. pivot.x = x;
  227. pivot.y = y;
  228. pivot.z = z;
  229. NoParseForYou:
  230. ; // appease the compiler
  231. }
  232. }
  233. fullGrid = EditorPrefs.GetBool(pg_Constant.PerspGrid);
  234. renderPlane = EditorPrefs.HasKey(pg_Constant.GridAxis) ? (Axis)EditorPrefs.GetInt(pg_Constant.GridAxis) : Axis.Y;
  235. alphaBump = (EditorPrefs.HasKey("pg_alphaBump")) ? EditorPrefs.GetFloat("pg_alphaBump") : pg_Preferences.ALPHA_BUMP;
  236. gridColorX = (EditorPrefs.HasKey("gridColorX")) ? pg_Util.ColorWithString(EditorPrefs.GetString("gridColorX")) : pg_Preferences.GRID_COLOR_X;
  237. gridColorX_primary = new Color(gridColorX.r, gridColorX.g, gridColorX.b, gridColorX.a + alphaBump);
  238. gridColorY = (EditorPrefs.HasKey("gridColorY")) ? pg_Util.ColorWithString(EditorPrefs.GetString("gridColorY")) : pg_Preferences.GRID_COLOR_Y;
  239. gridColorY_primary = new Color(gridColorY.r, gridColorY.g, gridColorY.b, gridColorY.a + alphaBump);
  240. gridColorZ = (EditorPrefs.HasKey("gridColorZ")) ? pg_Util.ColorWithString(EditorPrefs.GetString("gridColorZ")) : pg_Preferences.GRID_COLOR_Z;
  241. gridColorZ_primary = new Color(gridColorZ.r, gridColorZ.g, gridColorZ.b, gridColorZ.a + alphaBump);
  242. drawGrid = (EditorPrefs.HasKey("showgrid")) ? EditorPrefs.GetBool("showgrid") : pg_Preferences.SHOW_GRID;
  243. predictiveGrid = EditorPrefs.HasKey(pg_Constant.PredictiveGrid) ? EditorPrefs.GetBool(pg_Constant.PredictiveGrid) : true;
  244. _snapAsGroup = snapAsGroup;
  245. _scaleSnapEnabled = ScaleSnapEnabled;
  246. }
  247. private GUISkin sixBySevenSkin;
  248. #endregion
  249. #region MENU
  250. [MenuItem("Tools/ProGrids/About", false, 0)]
  251. public static void MenuAboutProGrids()
  252. {
  253. pg_AboutWindow.Init("Assets/ProCore/ProGrids/About/pc_AboutEntry_ProGrids.txt", true);
  254. }
  255. [MenuItem("Tools/ProGrids/ProGrids Window", false, 15)]
  256. public static void InitProGrids()
  257. {
  258. if (instance == null)
  259. {
  260. EditorPrefs.SetBool(pg_Constant.ProGridsIsEnabled, true);
  261. instance = ScriptableObject.CreateInstance<pg_Editor>();
  262. instance.hideFlags = HideFlags.DontSave;
  263. EditorApplication.delayCall += instance.Initialize;
  264. }
  265. else
  266. {
  267. CloseProGrids();
  268. }
  269. SceneView.RepaintAll();
  270. }
  271. [MenuItem("Tools/ProGrids/Close ProGrids", true, 200)]
  272. public static bool VerifyCloseProGrids()
  273. {
  274. return instance != null || Resources.FindObjectsOfTypeAll<pg_Editor>().Length > 0;
  275. }
  276. [MenuItem("Tools/ProGrids/Close ProGrids")]
  277. public static void CloseProGrids()
  278. {
  279. foreach (pg_Editor editor in Resources.FindObjectsOfTypeAll<pg_Editor>())
  280. editor.Close();
  281. }
  282. [MenuItem("Tools/ProGrids/Cycle SceneView Projection", false, 101)]
  283. public static void CyclePerspective()
  284. {
  285. if (instance == null) return;
  286. SceneView scnvw = SceneView.lastActiveSceneView;
  287. if (scnvw == null) return;
  288. int nextOrtho = EditorPrefs.GetInt(pg_Constant.LastOrthoToggledRotation);
  289. switch (nextOrtho)
  290. {
  291. case 0:
  292. scnvw.orthographic = true;
  293. scnvw.LookAt(scnvw.pivot, Quaternion.Euler(Vector3.zero));
  294. nextOrtho++;
  295. break;
  296. case 1:
  297. scnvw.orthographic = true;
  298. scnvw.LookAt(scnvw.pivot, Quaternion.Euler(Vector3.up * -90f));
  299. nextOrtho++;
  300. break;
  301. case 2:
  302. scnvw.orthographic = true;
  303. scnvw.LookAt(scnvw.pivot, Quaternion.Euler(Vector3.right * 90f));
  304. nextOrtho++;
  305. break;
  306. case 3:
  307. scnvw.orthographic = false;
  308. scnvw.LookAt(scnvw.pivot, new Quaternion(-0.1f, 0.9f, -0.2f, -0.4f));
  309. nextOrtho = 0;
  310. break;
  311. }
  312. EditorPrefs.SetInt(pg_Constant.LastOrthoToggledRotation, nextOrtho);
  313. }
  314. [MenuItem("Tools/ProGrids/Cycle SceneView Projection", true, 101)]
  315. [MenuItem("Tools/ProGrids/Increase Grid Size", true, 203)]
  316. [MenuItem("Tools/ProGrids/Decrease Grid Size", true, 202)]
  317. public static bool VerifyGridSizeAdjustment()
  318. {
  319. return instance != null;
  320. }
  321. [MenuItem("Tools/ProGrids/Decrease Grid Size", false, 202)]
  322. public static void DecreaseGridSize()
  323. {
  324. if (instance == null) return;
  325. int multiplier = EditorPrefs.HasKey(pg_Constant.SnapMultiplier) ? EditorPrefs.GetInt(pg_Constant.SnapMultiplier) : DEFAULT_SNAP_MULTIPLIER;
  326. float val = EditorPrefs.HasKey(pg_Constant.SnapValue) ? EditorPrefs.GetFloat(pg_Constant.SnapValue) : 1f;
  327. if (multiplier > 1)
  328. multiplier /= 2;
  329. instance.SetSnapValue(instance.snapUnit, val, multiplier);
  330. SceneView.RepaintAll();
  331. }
  332. [MenuItem("Tools/ProGrids/Increase Grid Size", false, 203)]
  333. public static void IncreaseGridSize()
  334. {
  335. if (instance == null) return;
  336. int multiplier = EditorPrefs.HasKey(pg_Constant.SnapMultiplier) ? EditorPrefs.GetInt(pg_Constant.SnapMultiplier) : DEFAULT_SNAP_MULTIPLIER;
  337. float val = EditorPrefs.HasKey(pg_Constant.SnapValue) ? EditorPrefs.GetFloat(pg_Constant.SnapValue) : 1f;
  338. if (multiplier < int.MaxValue / 2)
  339. multiplier *= 2;
  340. instance.SetSnapValue(instance.snapUnit, val, multiplier);
  341. SceneView.RepaintAll();
  342. }
  343. [MenuItem("Tools/ProGrids/Nudge Perspective Backward", true, 304)]
  344. [MenuItem("Tools/ProGrids/Nudge Perspective Forward", true, 305)]
  345. [MenuItem("Tools/ProGrids/Reset Perspective Nudge", true, 306)]
  346. public static bool VerifyMenuNudgePerspective()
  347. {
  348. return instance != null && !instance.fullGrid && !instance.ortho && instance.lockGrid;
  349. }
  350. [MenuItem("Tools/ProGrids/Nudge Perspective Backward", false, 304)]
  351. public static void MenuNudgePerspectiveBackward()
  352. {
  353. if (!instance.lockGrid) return;
  354. instance.offset -= instance.snapValue;
  355. instance.gridRepaint = true;
  356. SceneView.RepaintAll();
  357. }
  358. [MenuItem("Tools/ProGrids/Nudge Perspective Forward", false, 305)]
  359. public static void MenuNudgePerspectiveForward()
  360. {
  361. if (!instance.lockGrid) return;
  362. instance.offset += instance.snapValue;
  363. instance.gridRepaint = true;
  364. SceneView.RepaintAll();
  365. }
  366. [MenuItem("Tools/ProGrids/Reset Perspective Nudge", false, 306)]
  367. public static void MenuNudgePerspectiveReset()
  368. {
  369. if (!instance.lockGrid) return;
  370. instance.offset = 0;
  371. instance.gridRepaint = true;
  372. SceneView.RepaintAll();
  373. }
  374. public static void ForceRepaint()
  375. {
  376. if (instance != null)
  377. {
  378. instance.gridRepaint = true;
  379. SceneView.RepaintAll();
  380. }
  381. }
  382. #endregion
  383. #region INITIALIZATION / SERIALIZATION
  384. public void OnBeforeSerialize() { }
  385. public void OnAfterDeserialize()
  386. {
  387. instance = this;
  388. SceneView.onSceneGUIDelegate += OnSceneGUI;
  389. EditorApplication.update += Update;
  390. EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
  391. }
  392. void OnEnable()
  393. {
  394. instance.LoadGUIResources();
  395. #if !UNITY_4_6 && !UNITY_4_7 && !UNITY_5_0 && !UNITY_5_1
  396. Selection.selectionChanged += OnSelectionChange;
  397. #endif
  398. }
  399. public void Initialize()
  400. {
  401. SceneView.onSceneGUIDelegate -= OnSceneGUI;
  402. EditorApplication.update -= Update;
  403. EditorApplication.hierarchyWindowChanged -= HierarchyWindowChanged;
  404. SceneView.onSceneGUIDelegate += OnSceneGUI;
  405. EditorApplication.update += Update;
  406. EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
  407. LoadGUIResources();
  408. LoadPreferences();
  409. instance = this;
  410. pg_GridRenderer.Init();
  411. SetMenuIsExtended(menuOpen);
  412. lastTime = Time.realtimeSinceStartup;
  413. // reset colors without changing anything
  414. menuOpen = !menuOpen;
  415. ToggleMenuVisibility();
  416. if (drawGrid)
  417. pg_Util.SetUnityGridEnabled(false);
  418. gridRepaint = true;
  419. RepaintSceneView();
  420. }
  421. void OnDestroy()
  422. {
  423. this.Close(true);
  424. }
  425. public void Close()
  426. {
  427. EditorPrefs.SetBool(pg_Constant.ProGridsIsEnabled, false);
  428. GameObject.DestroyImmediate(this);
  429. #if !UNITY_4_6 && !UNITY_4_7 && !UNITY_5_0 && !UNITY_5_1
  430. Selection.selectionChanged -= OnSelectionChange;
  431. #endif
  432. }
  433. public void Close(bool isBeingDestroyed)
  434. {
  435. pg_GridRenderer.Destroy();
  436. SceneView.onSceneGUIDelegate -= OnSceneGUI;
  437. EditorApplication.update -= Update;
  438. EditorApplication.hierarchyWindowChanged -= HierarchyWindowChanged;
  439. instance = null;
  440. foreach (System.Action<bool> listener in toolbarEventSubscribers)
  441. listener(false);
  442. pg_Util.SetUnityGridEnabled(true);
  443. SceneView.RepaintAll();
  444. }
  445. private void LoadGUIResources()
  446. {
  447. if (gc_GridEnabled.image_on == null)
  448. gc_GridEnabled.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_Vis_On.png");
  449. if (gc_GridEnabled.image_off == null)
  450. gc_GridEnabled.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_Vis_Off.png");
  451. if (gc_SnapEnabled.image_on == null)
  452. gc_SnapEnabled.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_Snap_On.png");
  453. if (gc_SnapEnabled.image_off == null)
  454. gc_SnapEnabled.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_Snap_Off.png");
  455. if (gc_SnapToGrid.image_on == null)
  456. gc_SnapToGrid.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PushToGrid_Normal.png");
  457. if (gc_LockGrid.image_on == null)
  458. gc_LockGrid.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Lock_On.png");
  459. if (gc_LockGrid.image_off == null)
  460. gc_LockGrid.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Lock_Off.png");
  461. if (gc_AngleEnabled.image_on == null)
  462. gc_AngleEnabled.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_AngleVis_On.png");
  463. if (gc_AngleEnabled.image_off == null)
  464. gc_AngleEnabled.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_AngleVis_Off.png");
  465. if (gc_RenderPlaneX.image_on == null)
  466. gc_RenderPlaneX.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_X_On.png");
  467. if (gc_RenderPlaneX.image_off == null)
  468. gc_RenderPlaneX.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_X_Off.png");
  469. if (gc_RenderPlaneY.image_on == null)
  470. gc_RenderPlaneY.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Y_On.png");
  471. if (gc_RenderPlaneY.image_off == null)
  472. gc_RenderPlaneY.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Y_Off.png");
  473. if (gc_RenderPlaneZ.image_on == null)
  474. gc_RenderPlaneZ.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Z_On.png");
  475. if (gc_RenderPlaneZ.image_off == null)
  476. gc_RenderPlaneZ.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_Z_Off.png");
  477. if (gc_RenderPerspectiveGrid.image_on == null)
  478. gc_RenderPerspectiveGrid.image_on = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_3D_On.png");
  479. if (gc_RenderPerspectiveGrid.image_off == null)
  480. gc_RenderPerspectiveGrid.image_off = pg_IconUtility.LoadIcon("ProGrids2_GUI_PGrid_3D_Off.png");
  481. if (icon_extendoOpen == null)
  482. icon_extendoOpen = pg_IconUtility.LoadIcon("ProGrids2_MenuExtendo_Open.png");
  483. if (icon_extendoClose == null)
  484. icon_extendoClose = pg_IconUtility.LoadIcon("ProGrids2_MenuExtendo_Close.png");
  485. }
  486. #endregion
  487. #region INTERFACE
  488. GUIStyle gridButtonStyle = new GUIStyle();
  489. GUIStyle extendoStyle = new GUIStyle();
  490. GUIStyle gridButtonStyleBlank = new GUIStyle();
  491. GUIStyle backgroundStyle = new GUIStyle();
  492. bool guiInitialized = false;
  493. public float GetSnapIncrement()
  494. {
  495. return t_snapValue;
  496. }
  497. public void SetSnapIncrement(float inc)
  498. {
  499. SetSnapValue(snapUnit, Mathf.Max(inc, .001f), DEFAULT_SNAP_MULTIPLIER);
  500. }
  501. void RepaintSceneView()
  502. {
  503. SceneView.RepaintAll();
  504. }
  505. int MENU_HIDDEN { get { return menuIsOrtho ? -192 : -173; } }
  506. const int MENU_EXTENDED = 8;
  507. const int PAD = 3;
  508. Rect r = new Rect(8, MENU_EXTENDED, 42, 16);
  509. Rect backgroundRect = new Rect(00, 0, 0, 0);
  510. Rect extendoButtonRect = new Rect(0, 0, 0, 0);
  511. bool menuOpen = true;
  512. float menuStart = MENU_EXTENDED;
  513. const float MENU_SPEED = 500f;
  514. float deltaTime = 0f;
  515. float lastTime = 0f;
  516. const float FADE_SPEED = 2.5f;
  517. float backgroundFade = 1f;
  518. bool mouseOverMenu = false;
  519. Color menuBackgroundColor = new Color(0f, 0f, 0f, .5f);
  520. Color extendoNormalColor = new Color(.9f, .9f, .9f, .7f);
  521. Color extendoHoverColor = new Color(0f, 1f, .4f, 1f);
  522. bool extendoButtonHovering = false;
  523. bool menuIsOrtho = false;
  524. void Update()
  525. {
  526. deltaTime = Time.realtimeSinceStartup - lastTime;
  527. lastTime = Time.realtimeSinceStartup;
  528. if ((menuOpen && menuStart < MENU_EXTENDED) || (!menuOpen && menuStart > MENU_HIDDEN))
  529. {
  530. menuStart += deltaTime * MENU_SPEED * (menuOpen ? 1f : -1f);
  531. menuStart = Mathf.Clamp(menuStart, MENU_HIDDEN, MENU_EXTENDED);
  532. RepaintSceneView();
  533. }
  534. float a = menuBackgroundColor.a;
  535. backgroundFade = (mouseOverMenu || !menuOpen) ? FADE_SPEED : -FADE_SPEED;
  536. menuBackgroundColor.a = Mathf.Clamp(menuBackgroundColor.a + backgroundFade * deltaTime, 0f, .5f);
  537. extendoNormalColor.a = menuBackgroundColor.a;
  538. extendoHoverColor.a = (menuBackgroundColor.a / .5f);
  539. if (!Mathf.Approximately(menuBackgroundColor.a, a))
  540. RepaintSceneView();
  541. }
  542. void DrawSceneGUI()
  543. {
  544. GUI.backgroundColor = menuBackgroundColor;
  545. backgroundRect.x = r.x - 4;
  546. backgroundRect.y = 0;
  547. backgroundRect.width = r.width + 8;
  548. backgroundRect.height = r.y + r.height + PAD;
  549. GUI.Box(backgroundRect, "", backgroundStyle);
  550. // when hit testing mouse for showing the background, add some leeway
  551. backgroundRect.width += 32f;
  552. backgroundRect.height += 32f;
  553. GUI.backgroundColor = Color.white;
  554. if (!guiInitialized)
  555. {
  556. extendoStyle.normal.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  557. extendoStyle.hover.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  558. guiInitialized = true;
  559. backgroundStyle.normal.background = EditorGUIUtility.whiteTexture;
  560. Texture2D icon_button_normal = pg_IconUtility.LoadIcon("ProGrids2_Button_Normal.png");
  561. Texture2D icon_button_hover = pg_IconUtility.LoadIcon("ProGrids2_Button_Hover.png");
  562. if (icon_button_normal == null)
  563. {
  564. gridButtonStyleBlank = new GUIStyle("button");
  565. }
  566. else
  567. {
  568. gridButtonStyleBlank.normal.background = icon_button_normal;
  569. gridButtonStyleBlank.hover.background = icon_button_hover;
  570. gridButtonStyleBlank.normal.textColor = icon_button_normal != null ? Color.white : Color.black;
  571. gridButtonStyleBlank.hover.textColor = new Color(.7f, .7f, .7f, 1f);
  572. }
  573. gridButtonStyleBlank.padding = new RectOffset(1, 2, 1, 2);
  574. gridButtonStyleBlank.alignment = TextAnchor.MiddleCenter;
  575. }
  576. r.y = menuStart;
  577. gc_SnapIncrement.text = t_snapValue.ToString("#.####");
  578. if (GUI.Button(r, gc_SnapIncrement, gridButtonStyleBlank))
  579. {
  580. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
  581. // On Mac ShowAsDropdown and ShowAuxWindow both throw stack pop exceptions when initialized.
  582. pg_ParameterWindow options = EditorWindow.GetWindow<pg_ParameterWindow>(true, "ProGrids Settings", true);
  583. Rect screenRect = SceneView.lastActiveSceneView.position;
  584. options.editor = this;
  585. options.position = new Rect(screenRect.x + r.x + r.width + PAD,
  586. screenRect.y + r.y + 24,
  587. 256,
  588. 174);
  589. #else
  590. pg_ParameterWindow options = ScriptableObject.CreateInstance<pg_ParameterWindow>();
  591. Rect screenRect = SceneView.lastActiveSceneView.position;
  592. options.editor = this;
  593. options.ShowAsDropDown(new Rect(screenRect.x + r.x + r.width + PAD,
  594. screenRect.y + r.y + 24,
  595. 0,
  596. 0),
  597. new Vector2(256, 174));
  598. #endif
  599. }
  600. r.y += r.height + PAD;
  601. // Draw grid
  602. if (pg_ToggleContent.ToggleButton(r, gc_GridEnabled, drawGrid, gridButtonStyle, EditorStyles.miniButton))
  603. SetGridEnabled(!drawGrid);
  604. r.y += r.height + PAD;
  605. // Snap enabled
  606. if (pg_ToggleContent.ToggleButton(r, gc_SnapEnabled, snapEnabled, gridButtonStyle, EditorStyles.miniButton))
  607. SetSnapEnabled(!snapEnabled);
  608. r.y += r.height + PAD;
  609. // Push to grid
  610. if (pg_ToggleContent.ToggleButton(r, gc_SnapToGrid, true, gridButtonStyle, EditorStyles.miniButton))
  611. SnapToGrid(Selection.transforms);
  612. r.y += r.height + PAD;
  613. // Lock grid
  614. if (pg_ToggleContent.ToggleButton(r, gc_LockGrid, lockGrid, gridButtonStyle, EditorStyles.miniButton))
  615. {
  616. lockGrid = !lockGrid;
  617. EditorPrefs.SetBool(pg_Constant.LockGrid, lockGrid);
  618. EditorPrefs.SetString(pg_Constant.LockedGridPivot, pivot.ToString());
  619. // if we've modified the nudge value, reset the pivot here
  620. if (!lockGrid)
  621. offset = 0f;
  622. gridRepaint = true;
  623. RepaintSceneView();
  624. }
  625. if (menuIsOrtho)
  626. {
  627. r.y += r.height + PAD;
  628. if (pg_ToggleContent.ToggleButton(r, gc_AngleEnabled, drawAngles, gridButtonStyle, EditorStyles.miniButton))
  629. SetDrawAngles(!drawAngles);
  630. }
  631. /**
  632. * Perspective Toggles
  633. */
  634. r.y += r.height + PAD + 4;
  635. if (pg_ToggleContent.ToggleButton(r, gc_RenderPlaneX, (renderPlane & Axis.X) == Axis.X && !fullGrid, gridButtonStyle, EditorStyles.miniButton))
  636. SetRenderPlane(Axis.X);
  637. r.y += r.height + PAD;
  638. if (pg_ToggleContent.ToggleButton(r, gc_RenderPlaneY, (renderPlane & Axis.Y) == Axis.Y && !fullGrid, gridButtonStyle, EditorStyles.miniButton))
  639. SetRenderPlane(Axis.Y);
  640. r.y += r.height + PAD;
  641. if (pg_ToggleContent.ToggleButton(r, gc_RenderPlaneZ, (renderPlane & Axis.Z) == Axis.Z && !fullGrid, gridButtonStyle, EditorStyles.miniButton))
  642. SetRenderPlane(Axis.Z);
  643. r.y += r.height + PAD;
  644. if (pg_ToggleContent.ToggleButton(r, gc_RenderPerspectiveGrid, fullGrid, gridButtonStyle, EditorStyles.miniButton))
  645. {
  646. fullGrid = !fullGrid;
  647. gridRepaint = true;
  648. EditorPrefs.SetBool(pg_Constant.PerspGrid, fullGrid);
  649. RepaintSceneView();
  650. }
  651. r.y += r.height + PAD;
  652. extendoButtonRect.x = r.x;
  653. extendoButtonRect.y = r.y;
  654. extendoButtonRect.width = r.width;
  655. extendoButtonRect.height = r.height;
  656. GUI.backgroundColor = extendoButtonHovering ? extendoHoverColor : extendoNormalColor;
  657. gc_ExtendMenu.text = icon_extendoOpen == null ? (menuOpen ? "Close" : "Open") : "";
  658. if (GUI.Button(r, gc_ExtendMenu, icon_extendoOpen ? extendoStyle : gridButtonStyleBlank))
  659. {
  660. ToggleMenuVisibility();
  661. extendoButtonHovering = false;
  662. }
  663. GUI.backgroundColor = Color.white;
  664. }
  665. void ToggleMenuVisibility()
  666. {
  667. menuOpen = !menuOpen;
  668. EditorPrefs.SetBool(pg_Constant.ProGridsIsExtended, menuOpen);
  669. extendoStyle.normal.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  670. extendoStyle.hover.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  671. foreach (System.Action<bool> listener in toolbarEventSubscribers)
  672. listener(menuOpen);
  673. RepaintSceneView();
  674. }
  675. // skip color fading and stuff
  676. void SetMenuIsExtended(bool isExtended)
  677. {
  678. menuOpen = isExtended;
  679. menuIsOrtho = ortho;
  680. menuStart = menuOpen ? MENU_EXTENDED : MENU_HIDDEN;
  681. menuBackgroundColor.a = 0f;
  682. extendoNormalColor.a = menuBackgroundColor.a;
  683. extendoHoverColor.a = (menuBackgroundColor.a / .5f);
  684. extendoStyle.normal.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  685. extendoStyle.hover.background = menuOpen ? icon_extendoClose : icon_extendoOpen;
  686. foreach (System.Action<bool> listener in toolbarEventSubscribers)
  687. listener(menuOpen);
  688. EditorPrefs.SetBool(pg_Constant.ProGridsIsExtended, menuOpen);
  689. }
  690. private void OpenProGridsPopup()
  691. {
  692. if (EditorUtility.DisplayDialog(
  693. "Upgrade to ProGrids", // Title
  694. "Enables all kinds of super-cool features, like different snap values, more units of measurement, and angles.", // Message
  695. "Upgrade", // Okay
  696. "Cancel" // Cancel
  697. ))
  698. // #if UNITY_4
  699. // AssetStore.OpenURL(pg_Constant.ProGridsUpgradeURL);
  700. // #else
  701. Application.OpenURL(pg_Constant.ProGridsUpgradeURL);
  702. // #endif
  703. }
  704. #endregion
  705. #region ONSCENEGUI
  706. private Transform lastTransform;
  707. const string AXIS_CONSTRAINT_KEY = "s";
  708. const string TEMP_DISABLE_KEY = "d";
  709. private bool toggleAxisConstraint = false;
  710. private bool toggleTempSnap = false;
  711. private Vector3 lastPosition = Vector3.zero;
  712. // private Vector3 lastRotation = Vector3.zero;
  713. private Vector3 lastScale = Vector3.one;
  714. private Vector3 pivot = Vector3.zero, lastPivot = Vector3.zero;
  715. private Vector3 camDir = Vector3.zero, prevCamDir = Vector3.zero;
  716. // Distance from camera to pivot at the last time the grid mesh was updated.
  717. private float lastDistance = 0f;
  718. public float offset = 0f;
  719. private bool firstMove = true;
  720. #if PROFILE_TIMES
  721. pb_Profiler profiler = new pb_Profiler();
  722. #endif
  723. public bool ortho { get; private set; }
  724. private bool prevOrtho = false;
  725. float planeGridDrawDistance = 0f;
  726. public void OnSceneGUI(SceneView scnview)
  727. {
  728. bool isCurrentView = scnview == SceneView.lastActiveSceneView;
  729. if (isCurrentView)
  730. {
  731. Handles.BeginGUI();
  732. DrawSceneGUI();
  733. Handles.EndGUI();
  734. }
  735. // don't snap stuff in play mode
  736. if (EditorApplication.isPlayingOrWillChangePlaymode)
  737. return;
  738. Event e = Event.current;
  739. // repaint scene gui if mouse is near controls
  740. if (isCurrentView && e.type == EventType.MouseMove)
  741. {
  742. bool tmp = extendoButtonHovering;
  743. extendoButtonHovering = extendoButtonRect.Contains(e.mousePosition);
  744. if (extendoButtonHovering != tmp)
  745. RepaintSceneView();
  746. mouseOverMenu = backgroundRect.Contains(e.mousePosition);
  747. }
  748. if (e.Equals(Event.KeyboardEvent(AXIS_CONSTRAINT_KEY)))
  749. {
  750. toggleAxisConstraint = true;
  751. }
  752. if (e.Equals(Event.KeyboardEvent(TEMP_DISABLE_KEY)))
  753. {
  754. toggleTempSnap = true;
  755. }
  756. if (e.isKey)
  757. {
  758. toggleAxisConstraint = false;
  759. toggleTempSnap = false;
  760. bool used = true;
  761. if (e.keyCode == m_IncreaseGridSizeShortcut)
  762. {
  763. if (e.type == EventType.KeyUp)
  764. IncreaseGridSize();
  765. }
  766. else if (e.keyCode == m_DecreaseGridSizeShortcut)
  767. {
  768. if (e.type == EventType.KeyUp)
  769. DecreaseGridSize();
  770. }
  771. else if (e.keyCode == m_NudgePerspectiveBackwardShortcut)
  772. {
  773. if (e.type == EventType.KeyUp && VerifyMenuNudgePerspective())
  774. MenuNudgePerspectiveBackward();
  775. }
  776. else if (e.keyCode == m_NudgePerspectiveForwardShortcut)
  777. {
  778. if (e.type == EventType.KeyUp && VerifyMenuNudgePerspective())
  779. MenuNudgePerspectiveForward();
  780. }
  781. else if (e.keyCode == m_NudgePerspectiveResetShortcut)
  782. {
  783. if (e.type == EventType.KeyUp && VerifyMenuNudgePerspective())
  784. MenuNudgePerspectiveReset();
  785. }
  786. else if (e.keyCode == m_CyclePerspectiveShortcut)
  787. {
  788. if (e.type == EventType.KeyUp)
  789. CyclePerspective();
  790. }
  791. else
  792. {
  793. used = false;
  794. }
  795. if (used)
  796. e.Use();
  797. }
  798. Camera cam = Camera.current;
  799. if (cam == null)
  800. return;
  801. ortho = cam.orthographic && IsRounded(scnview.rotation.eulerAngles.normalized);
  802. camDir = pg_Util.CeilFloor(pivot - cam.transform.position);
  803. if (ortho && !prevOrtho || ortho != menuIsOrtho)
  804. OnSceneBecameOrtho(isCurrentView);
  805. if (!ortho && prevOrtho)
  806. OnSceneBecamePersp(isCurrentView);
  807. prevOrtho = ortho;
  808. float camDistance = Vector3.Distance(cam.transform.position, lastPivot); // distance from camera to pivot
  809. if (fullGrid)
  810. {
  811. pivot = lockGrid || Selection.activeTransform == null ? pivot : Selection.activeTransform.position;
  812. }
  813. else
  814. {
  815. Vector3 sceneViewPlanePivot = pivot;
  816. Ray ray = new Ray(cam.transform.position, cam.transform.forward);
  817. Plane plane = new Plane(Vector3.up, pivot);
  818. float dist;
  819. // the only time a locked grid should ever move is if it's pivot is out
  820. // of the camera's frustum.
  821. if ((lockGrid && !cam.InFrustum(pivot)) || !lockGrid || scnview != SceneView.lastActiveSceneView)
  822. {
  823. if (plane.Raycast(ray, out dist))
  824. sceneViewPlanePivot = ray.GetPoint(Mathf.Min(dist, planeGridDrawDistance / 2f));
  825. else
  826. sceneViewPlanePivot = ray.GetPoint(Mathf.Min(cam.farClipPlane / 2f, planeGridDrawDistance / 2f));
  827. }
  828. if (lockGrid)
  829. {
  830. pivot = pg_Enum.InverseAxisMask(sceneViewPlanePivot, renderPlane) + pg_Enum.AxisMask(pivot, renderPlane);
  831. }
  832. else
  833. {
  834. pivot = Selection.activeTransform == null ? pivot : Selection.activeTransform.position;
  835. if (Selection.activeTransform == null || !cam.InFrustum(pivot))
  836. {
  837. pivot = pg_Enum.InverseAxisMask(sceneViewPlanePivot, renderPlane) + pg_Enum.AxisMask(Selection.activeTransform == null ? pivot : Selection.activeTransform.position, renderPlane);
  838. }
  839. }
  840. }
  841. #if PG_DEBUG
  842. pivotGo.transform.position = pivot;
  843. #endif
  844. if (drawGrid)
  845. {
  846. if (ortho)
  847. {
  848. // ortho don't care about pivots
  849. DrawGridOrthographic(cam);
  850. }
  851. else
  852. {
  853. #if PROFILE_TIMES
  854. profiler.LogStart("DrawGridPerspective");
  855. #endif
  856. if (gridRepaint || pivot != lastPivot || Mathf.Abs(camDistance - lastDistance) > lastDistance / 2 || camDir != prevCamDir)
  857. {
  858. prevCamDir = camDir;
  859. gridRepaint = false;
  860. lastPivot = pivot;
  861. lastDistance = camDistance;
  862. if (fullGrid)
  863. {
  864. // if perspective and 3d, use pivot like normal
  865. pg_GridRenderer.DrawGridPerspective(cam, pivot, snapValue, new Color[3] { gridColorX, gridColorY, gridColorZ }, alphaBump);
  866. }
  867. else
  868. {
  869. if ((renderPlane & Axis.X) == Axis.X)
  870. planeGridDrawDistance = pg_GridRenderer.DrawPlane(cam, pivot + Vector3.right * offset, Vector3.up, Vector3.forward, snapValue, gridColorX, alphaBump);
  871. if ((renderPlane & Axis.Y) == Axis.Y)
  872. planeGridDrawDistance = pg_GridRenderer.DrawPlane(cam, pivot + Vector3.up * offset, Vector3.right, Vector3.forward, snapValue, gridColorY, alphaBump);
  873. if ((renderPlane & Axis.Z) == Axis.Z)
  874. planeGridDrawDistance = pg_GridRenderer.DrawPlane(cam, pivot + Vector3.forward * offset, Vector3.up, Vector3.right, snapValue, gridColorZ, alphaBump);
  875. }
  876. }
  877. #if PROFILE_TIMES
  878. profiler.LogFinish("DrawGridPerspective");
  879. #endif
  880. }
  881. }
  882. // Always keep track of the selection
  883. if (!Selection.transforms.Contains(lastTransform))
  884. {
  885. if (Selection.activeTransform)
  886. {
  887. lastTransform = Selection.activeTransform;
  888. lastPosition = Selection.activeTransform.position;
  889. lastScale = Selection.activeTransform.localScale;
  890. }
  891. }
  892. if (e.type == EventType.MouseUp)
  893. firstMove = true;
  894. if (!snapEnabled || GUIUtility.hotControl < 1)
  895. return;
  896. // Bugger.SetKey("Toggle Snap Off", toggleTempSnap);
  897. /**
  898. * Snapping (for all the junk in PG, this method is literally the only code that actually affects anything).
  899. */
  900. if (Selection.activeTransform && pg_Util.SnapIsEnabled(Selection.activeTransform))
  901. {
  902. if (!FuzzyEquals(lastTransform.position, lastPosition))
  903. {
  904. Transform selected = lastTransform;
  905. if (!toggleTempSnap)
  906. {
  907. Vector3 old = selected.position;
  908. Vector3 mask = old - lastPosition;
  909. bool constraintsOn = toggleAxisConstraint ? !useAxisConstraints : useAxisConstraints;
  910. if (constraintsOn)
  911. selected.position = pg_Util.SnapValue(old, mask, snapValue);
  912. else
  913. selected.position = pg_Util.SnapValue(old, snapValue);
  914. Vector3 offset = selected.position - old;
  915. if (predictiveGrid && firstMove && !fullGrid)
  916. {
  917. firstMove = false;
  918. Axis dragAxis = pg_Util.CalcDragAxis(offset, scnview.camera);
  919. if (dragAxis != Axis.None && dragAxis != renderPlane)
  920. SetRenderPlane(dragAxis);
  921. }
  922. if (_snapAsGroup)
  923. {
  924. OffsetTransforms(Selection.transforms, selected, offset);
  925. }
  926. else
  927. {
  928. foreach (Transform t in Selection.transforms)
  929. t.position = constraintsOn ? pg_Util.SnapValue(t.position, mask, snapValue) : pg_Util.SnapValue(t.position, snapValue);
  930. }
  931. }
  932. lastPosition = selected.position;
  933. }
  934. if (!FuzzyEquals(lastTransform.localScale, lastScale) && _scaleSnapEnabled)
  935. {
  936. if (!toggleTempSnap)
  937. {
  938. Vector3 old = lastTransform.localScale;
  939. Vector3 mask = old - lastScale;
  940. if (predictiveGrid)
  941. {
  942. Axis dragAxis = pg_Util.CalcDragAxis(Selection.activeTransform.TransformDirection(mask), scnview.camera);
  943. if (dragAxis != Axis.None && dragAxis != renderPlane)
  944. SetRenderPlane(dragAxis);
  945. }
  946. foreach (Transform t in Selection.transforms)
  947. t.localScale = pg_Util.SnapValue(t.localScale, mask, snapValue);
  948. lastScale = lastTransform.localScale;
  949. }
  950. }
  951. }
  952. }
  953. void OnSelectionChange()
  954. {
  955. // Means we don't have to wait for script reloads
  956. // to respect IgnoreSnap attribute, and keeps the
  957. // cache small.
  958. pg_Util.ClearSnapEnabledCache();
  959. }
  960. void OnSceneBecameOrtho(bool isCurrentView)
  961. {
  962. pg_GridRenderer.Destroy();
  963. if (isCurrentView && ortho != menuIsOrtho)
  964. SetMenuIsExtended(menuOpen);
  965. }
  966. void OnSceneBecamePersp(bool isCurrentView)
  967. {
  968. if (isCurrentView && ortho != menuIsOrtho)
  969. SetMenuIsExtended(menuOpen);
  970. }
  971. #endregion
  972. #region GRAPHICS
  973. GameObject go;
  974. private void DrawGridOrthographic(Camera cam)
  975. {
  976. Axis camAxis = AxisWithVector(Camera.current.transform.TransformDirection(Vector3.forward).normalized);
  977. if (drawGrid)
  978. {
  979. switch (camAxis)
  980. {
  981. case Axis.X:
  982. case Axis.NegX:
  983. DrawGridOrthographic(cam, camAxis, gridColorX_primary, gridColorX);
  984. break;
  985. case Axis.Y:
  986. case Axis.NegY:
  987. DrawGridOrthographic(cam, camAxis, gridColorY_primary, gridColorY);
  988. break;
  989. case Axis.Z:
  990. case Axis.NegZ:
  991. DrawGridOrthographic(cam, camAxis, gridColorZ_primary, gridColorZ);
  992. break;
  993. }
  994. }
  995. }
  996. int PRIMARY_COLOR_INCREMENT = 10;
  997. Color previousColor;
  998. private void DrawGridOrthographic(Camera cam, Axis camAxis, Color primaryColor, Color secondaryColor)
  999. {
  1000. previousColor = Handles.color;
  1001. Handles.color = primaryColor;
  1002. Vector3 bottomLeft = pg_Util.SnapToFloor(cam.ScreenToWorldPoint(Vector2.zero), snapValue);
  1003. Vector3 bottomRight = pg_Util.SnapToFloor(cam.ScreenToWorldPoint(new Vector2(cam.pixelWidth, 0f)), snapValue);
  1004. Vector3 topLeft = pg_Util.SnapToFloor(cam.ScreenToWorldPoint(new Vector2(0f, cam.pixelHeight)), snapValue);
  1005. Vector3 topRight = pg_Util.SnapToFloor(cam.ScreenToWorldPoint(new Vector2(cam.pixelWidth, cam.pixelHeight)), snapValue);
  1006. Vector3 axis = VectorWithAxis(camAxis);
  1007. float width = Vector3.Distance(bottomLeft, bottomRight);
  1008. float height = Vector3.Distance(bottomRight, topRight);
  1009. // Shift lines to 10m forward of the camera
  1010. bottomLeft += axis * 10f;
  1011. topRight += axis * 10f;
  1012. bottomRight += axis * 10f;
  1013. topLeft += axis * 10f;
  1014. /**
  1015. * Draw Vertical Lines
  1016. */
  1017. Vector3 cam_right = cam.transform.right;
  1018. Vector3 cam_up = cam.transform.up;
  1019. float _snapVal = snapValue;
  1020. int segs = (int)Mathf.Ceil(width / _snapVal) + 2;
  1021. float n = 2f;
  1022. while (segs > MAX_LINES)
  1023. {
  1024. _snapVal = _snapVal * n;
  1025. segs = (int)Mathf.Ceil(width / _snapVal) + 2;
  1026. n++;
  1027. }
  1028. /// Screen start and end
  1029. Vector3 bl = cam_right.Sum() > 0 ? pg_Util.SnapToFloor(bottomLeft, cam_right, _snapVal * PRIMARY_COLOR_INCREMENT) : pg_Util.SnapToCeil(bottomLeft, cam_right, _snapVal * PRIMARY_COLOR_INCREMENT);
  1030. Vector3 start = bl - cam_up * (height + _snapVal * 2);
  1031. Vector3 end = bl + cam_up * (height + _snapVal * 2);
  1032. segs += PRIMARY_COLOR_INCREMENT;
  1033. /// The current line start and end
  1034. Vector3 line_start = Vector3.zero;
  1035. Vector3 line_end = Vector3.zero;
  1036. for (int i = -1; i < segs; i++)
  1037. {
  1038. line_start = start + (i * (cam_right * _snapVal));
  1039. line_end = end + (i * (cam_right * _snapVal));
  1040. Handles.color = i % PRIMARY_COLOR_INCREMENT == 0 ? primaryColor : secondaryColor;
  1041. Handles.DrawLine(line_start, line_end);
  1042. }
  1043. /**
  1044. * Draw Horizontal Lines
  1045. */
  1046. segs = (int)Mathf.Ceil(height / _snapVal) + 2;
  1047. n = 2;
  1048. while (segs > MAX_LINES)
  1049. {
  1050. _snapVal = _snapVal * n;
  1051. segs = (int)Mathf.Ceil(height / _snapVal) + 2;
  1052. n++;
  1053. }
  1054. Vector3 tl = cam_up.Sum() > 0 ? pg_Util.SnapToCeil(topLeft, cam_up, _snapVal * PRIMARY_COLOR_INCREMENT) : pg_Util.SnapToFloor(topLeft, cam_up, _snapVal * PRIMARY_COLOR_INCREMENT);
  1055. start = tl - cam_right * (width + _snapVal * 2);
  1056. end = tl + cam_right * (width + _snapVal * 2);
  1057. segs += (int)PRIMARY_COLOR_INCREMENT;
  1058. for (int i = -1; i < segs; i++)
  1059. {
  1060. line_start = start + (i * (-cam_up * _snapVal));
  1061. line_end = end + (i * (-cam_up * _snapVal));
  1062. Handles.color = i % PRIMARY_COLOR_INCREMENT == 0 ? primaryColor : secondaryColor;
  1063. Handles.DrawLine(line_start, line_end);
  1064. }
  1065. #if PRO
  1066. if (drawAngles)
  1067. {
  1068. Vector3 cen = pg_Util.SnapValue(((topRight + bottomLeft) / 2f), snapValue);
  1069. float half = (width > height) ? width : height;
  1070. float opposite = Mathf.Tan(Mathf.Deg2Rad * angleValue) * half;
  1071. Vector3 up = cam.transform.up * opposite;
  1072. Vector3 right = cam.transform.right * half;
  1073. Vector3 bottomLeftAngle = cen - (up + right);
  1074. Vector3 topRightAngle = cen + (up + right);
  1075. Vector3 bottomRightAngle = cen + (right - up);
  1076. Vector3 topLeftAngle = cen + (up - right);
  1077. Handles.color = primaryColor;
  1078. // y = 1x+1
  1079. Handles.DrawLine(bottomLeftAngle, topRightAngle);
  1080. // y = -1x-1
  1081. Handles.DrawLine(topLeftAngle, bottomRightAngle);
  1082. }
  1083. #endif
  1084. Handles.color = previousColor;
  1085. }
  1086. #endregion
  1087. #region ENUM UTILITY
  1088. public SnapUnit SnapUnitWithString(string str)
  1089. {
  1090. foreach (SnapUnit su in SnapUnit.GetValues(typeof(SnapUnit)))
  1091. {
  1092. if (su.ToString() == str)
  1093. return su;
  1094. }
  1095. return (SnapUnit)0;
  1096. }
  1097. public Axis AxisWithVector(Vector3 val)
  1098. {
  1099. Vector3 v = new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z));
  1100. if (v.x > v.y && v.x > v.z)
  1101. {
  1102. if (val.x > 0)
  1103. return Axis.X;
  1104. else
  1105. return Axis.NegX;
  1106. }
  1107. else
  1108. if (v.y > v.x && v.y > v.z)
  1109. {
  1110. if (val.y > 0)
  1111. return Axis.Y;
  1112. else
  1113. return Axis.NegY;
  1114. }
  1115. else
  1116. {
  1117. if (val.z > 0)
  1118. return Axis.Z;
  1119. else
  1120. return Axis.NegZ;
  1121. }
  1122. }
  1123. public Vector3 VectorWithAxis(Axis axis)
  1124. {
  1125. switch (axis)
  1126. {
  1127. case Axis.X:
  1128. return Vector3.right;
  1129. case Axis.Y:
  1130. return Vector3.up;
  1131. case Axis.Z:
  1132. return Vector3.forward;
  1133. case Axis.NegX:
  1134. return -Vector3.right;
  1135. case Axis.NegY:
  1136. return -Vector3.up;
  1137. case Axis.NegZ:
  1138. return -Vector3.forward;
  1139. default:
  1140. return Vector3.forward;
  1141. }
  1142. }
  1143. public bool IsRounded(Vector3 v)
  1144. {
  1145. return (Mathf.Approximately(v.x, 1f) || Mathf.Approximately(v.y, 1f) || Mathf.Approximately(v.z, 1f)) || v == Vector3.zero;
  1146. }
  1147. public Vector3 RoundAxis(Vector3 v)
  1148. {
  1149. return VectorWithAxis(AxisWithVector(v));
  1150. }
  1151. #endregion
  1152. #region MOVING TRANSFORMS
  1153. static bool FuzzyEquals(Vector3 lhs, Vector3 rhs)
  1154. {
  1155. return Mathf.Abs(lhs.x - rhs.x) < .001f && Mathf.Abs(lhs.y - rhs.y) < .001f && Mathf.Abs(lhs.z - rhs.z) < .001f;
  1156. }
  1157. public void OffsetTransforms(Transform[] trsfrms, Transform ignore, Vector3 offset)
  1158. {
  1159. foreach (Transform t in trsfrms)
  1160. {
  1161. if (t != ignore)
  1162. t.position += offset;
  1163. }
  1164. }
  1165. void HierarchyWindowChanged()
  1166. {
  1167. if (Selection.activeTransform != null)
  1168. lastPosition = Selection.activeTransform.position;
  1169. }
  1170. #endregion
  1171. #region SETTINGS
  1172. public void SetSnapEnabled(bool enable)
  1173. {
  1174. EditorPrefs.SetBool(pg_Constant.SnapEnabled, enable);
  1175. if (Selection.activeTransform)
  1176. {
  1177. lastTransform = Selection.activeTransform;
  1178. lastPosition = Selection.activeTransform.position;
  1179. }
  1180. snapEnabled = enable;
  1181. gridRepaint = true;
  1182. RepaintSceneView();
  1183. }
  1184. public void SetSnapValue(SnapUnit su, float val, int multiplier)
  1185. {
  1186. int clamp_multiplier = (int)(Mathf.Min(Mathf.Max(1, multiplier), int.MaxValue));
  1187. float value_multiplier = clamp_multiplier / (float)DEFAULT_SNAP_MULTIPLIER;
  1188. /**
  1189. * multiplier is a value modifies the snap val. 100 = no change,
  1190. * 50 is half val, 200 is double val, etc.
  1191. */
  1192. snapValue = pg_Enum.SnapUnitValue(su) * val * value_multiplier;
  1193. RepaintSceneView();
  1194. EditorPrefs.SetInt(pg_Constant.GridUnit, (int)su);
  1195. EditorPrefs.SetFloat(pg_Constant.SnapValue, val);
  1196. EditorPrefs.SetInt(pg_Constant.SnapMultiplier, clamp_multiplier);
  1197. // update gui (only necessary when calling with editorpref values)
  1198. t_snapValue = val * value_multiplier;
  1199. snapUnit = su;
  1200. switch (su)
  1201. {
  1202. case SnapUnit.Inch:
  1203. PRIMARY_COLOR_INCREMENT = 12; // blasted imperial units
  1204. break;
  1205. case SnapUnit.Foot:
  1206. PRIMARY_COLOR_INCREMENT = 3;
  1207. break;
  1208. default:
  1209. PRIMARY_COLOR_INCREMENT = 10;
  1210. break;
  1211. }
  1212. if (EditorPrefs.GetBool(pg_Constant.SyncUnitySnap, true))
  1213. {
  1214. EditorPrefs.SetFloat("MoveSnapX", snapValue);
  1215. EditorPrefs.SetFloat("MoveSnapY", snapValue);
  1216. EditorPrefs.SetFloat("MoveSnapZ", snapValue);
  1217. if (EditorPrefs.GetBool(pg_Constant.SnapScale, true))
  1218. EditorPrefs.SetFloat("ScaleSnap", snapValue);
  1219. // If Unity snap sync is enabled, refresh the Snap Settings window if it's open.
  1220. Type snapSettings = typeof(EditorWindow).Assembly.GetType("UnityEditor.SnapSettings");
  1221. if (snapSettings != null)
  1222. {
  1223. FieldInfo snapInitialized = snapSettings.GetField("s_Initialized", BindingFlags.NonPublic | BindingFlags.Static);
  1224. if (snapInitialized != null)
  1225. {
  1226. snapInitialized.SetValue(null, (object)false);
  1227. EditorWindow win = Resources.FindObjectsOfTypeAll<EditorWindow>().FirstOrDefault(x => x.ToString().Contains("SnapSettings"));
  1228. if (win != null)
  1229. win.Repaint();
  1230. }
  1231. }
  1232. }
  1233. gridRepaint = true;
  1234. }
  1235. public void SetRenderPlane(Axis axis)
  1236. {
  1237. offset = 0f;
  1238. fullGrid = false;
  1239. renderPlane = axis;
  1240. EditorPrefs.SetBool(pg_Constant.PerspGrid, fullGrid);
  1241. EditorPrefs.SetInt(pg_Constant.GridAxis, (int)renderPlane);
  1242. gridRepaint = true;
  1243. RepaintSceneView();
  1244. }
  1245. public void SetGridEnabled(bool enable)
  1246. {
  1247. drawGrid = enable;
  1248. if (!drawGrid)
  1249. pg_GridRenderer.Destroy();
  1250. else
  1251. pg_Util.SetUnityGridEnabled(false);
  1252. EditorPrefs.SetBool("showgrid", enable);
  1253. gridRepaint = true;
  1254. RepaintSceneView();
  1255. }
  1256. public void SetDrawAngles(bool enable)
  1257. {
  1258. drawAngles = enable;
  1259. gridRepaint = true;
  1260. RepaintSceneView();
  1261. }
  1262. private void SnapToGrid(Transform[] transforms)
  1263. {
  1264. Undo.RecordObjects(transforms as UnityEngine.Object[], "Snap to Grid");
  1265. foreach (Transform t in transforms)
  1266. t.position = pg_Util.SnapValue(t.position, snapValue);
  1267. gridRepaint = true;
  1268. PushToGrid(snapValue);
  1269. }
  1270. #endregion
  1271. #region GLOBAL SETTING
  1272. internal bool GetUseAxisConstraints() { return toggleAxisConstraint ? !useAxisConstraints : useAxisConstraints; }
  1273. internal float GetSnapValue() { return snapValue; }
  1274. internal bool GetSnapEnabled() { return (toggleTempSnap ? !snapEnabled : snapEnabled); }
  1275. /**
  1276. * Returns the value of useAxisConstraints, accounting for the shortcut key toggle.
  1277. */
  1278. public static bool UseAxisConstraints()
  1279. {
  1280. return instance != null ? instance.GetUseAxisConstraints() : false;
  1281. }
  1282. /**
  1283. * Return the current snap value.
  1284. */
  1285. public static float SnapValue()
  1286. {
  1287. return instance != null ? instance.GetSnapValue() : 0f;
  1288. }
  1289. /**
  1290. * Return true if snapping is enabled, false otherwise.
  1291. */
  1292. public static bool SnapEnabled()
  1293. {
  1294. return instance == null ? false : instance.GetSnapEnabled();
  1295. }
  1296. public static void AddPushToGridListener(System.Action<float> listener)
  1297. {
  1298. pushToGridListeners.Add(listener);
  1299. }
  1300. public static void RemovePushToGridListener(System.Action<float> listener)
  1301. {
  1302. pushToGridListeners.Remove(listener);
  1303. }
  1304. public static void AddToolbarEventSubscriber(System.Action<bool> listener)
  1305. {
  1306. toolbarEventSubscribers.Add(listener);
  1307. }
  1308. public static void RemoveToolbarEventSubscriber(System.Action<bool> listener)
  1309. {
  1310. toolbarEventSubscribers.Remove(listener);
  1311. }
  1312. public static bool SceneToolbarActive()
  1313. {
  1314. return instance != null;
  1315. }
  1316. [SerializeField]
  1317. static List<System.Action<float>> pushToGridListeners = new List<System.Action<float>>();
  1318. [SerializeField]
  1319. static List<System.Action<bool>> toolbarEventSubscribers = new List<System.Action<bool>>();
  1320. private void PushToGrid(float snapValue)
  1321. {
  1322. foreach (System.Action<float> listener in pushToGridListeners)
  1323. listener(snapValue);
  1324. }
  1325. public static void OnHandleMove(Vector3 worldDirection)
  1326. {
  1327. if (instance != null)
  1328. instance.OnHandleMove_Internal(worldDirection);
  1329. }
  1330. private void OnHandleMove_Internal(Vector3 worldDirection)
  1331. {
  1332. if (predictiveGrid && firstMove && !fullGrid)
  1333. {
  1334. firstMove = false;
  1335. Axis dragAxis = pg_Util.CalcDragAxis(worldDirection, SceneView.lastActiveSceneView.camera);
  1336. if (dragAxis != Axis.None && dragAxis != renderPlane)
  1337. SetRenderPlane(dragAxis);
  1338. }
  1339. }
  1340. #endregion
  1341. }
  1342. }