├── Docs.meta ├── Docs ├── QuickToggle-Options.png └── QuickToggle-Options.png.meta ├── Editor.meta ├── Editor ├── QuickToggle.cs └── QuickToggle.cs.meta ├── LICENSE ├── LICENSE.meta ├── README.md └── README.md.meta /Docs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b64cf2375bca5ea46926249756dca60c 3 | folderAsset: yes 4 | timeCreated: 1497243946 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Docs/QuickToggle-Options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SubjectNerd-Unity/QuickToggle/74261ec59b479880c9f73c6aa74cbe27b5a16b63/Docs/QuickToggle-Options.png -------------------------------------------------------------------------------- /Docs/QuickToggle-Options.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b5679d7447d4b88429639d07ffae9caa 3 | timeCreated: 1497243946 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 4 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | sRGBTexture: 1 12 | linearTexture: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 6 25 | cubemapConvolution: 0 26 | seamlessCubemap: 0 27 | textureFormat: 1 28 | maxTextureSize: 2048 29 | textureSettings: 30 | filterMode: -1 31 | aniso: 16 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 0 35 | lightmap: 0 36 | compressionQuality: 50 37 | spriteMode: 0 38 | spriteExtrude: 1 39 | spriteMeshType: 1 40 | alignment: 0 41 | spritePivot: {x: 0.5, y: 0.5} 42 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 43 | spritePixelsToUnits: 100 44 | alphaUsage: 1 45 | alphaIsTransparency: 0 46 | spriteTessellationDetail: -1 47 | textureType: 8 48 | textureShape: 1 49 | maxTextureSizeSet: 0 50 | compressionQualitySet: 0 51 | textureFormatSet: 0 52 | platformSettings: 53 | - buildTarget: DefaultTexturePlatform 54 | maxTextureSize: 2048 55 | textureFormat: -1 56 | textureCompression: 1 57 | compressionQuality: 50 58 | crunchedCompression: 0 59 | allowsAlphaSplitting: 0 60 | overridden: 0 61 | - buildTarget: Standalone 62 | maxTextureSize: 2048 63 | textureFormat: -1 64 | textureCompression: 1 65 | compressionQuality: 50 66 | crunchedCompression: 0 67 | allowsAlphaSplitting: 0 68 | overridden: 0 69 | - buildTarget: iPhone 70 | maxTextureSize: 2048 71 | textureFormat: -1 72 | textureCompression: 1 73 | compressionQuality: 50 74 | crunchedCompression: 0 75 | allowsAlphaSplitting: 0 76 | overridden: 0 77 | - buildTarget: Android 78 | maxTextureSize: 2048 79 | textureFormat: -1 80 | textureCompression: 1 81 | compressionQuality: 50 82 | crunchedCompression: 0 83 | allowsAlphaSplitting: 0 84 | overridden: 0 85 | - buildTarget: WebGL 86 | maxTextureSize: 2048 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | spriteSheet: 94 | serializedVersion: 2 95 | sprites: [] 96 | outline: [] 97 | spritePackingTag: 98 | userData: 99 | assetBundleName: 100 | assetBundleVariant: 101 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b48a1bdc6397c4379b3e28a4e25ab0b0 3 | folderAsset: yes 4 | timeCreated: 1447732428 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Editor/QuickToggle.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017, Jeiel Aranal 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 5 | and associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial 11 | portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 14 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 15 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 16 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 17 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | */ 19 | 20 | using System; 21 | using System.Collections.Generic; 22 | using System.Reflection; 23 | using UnityEditor; 24 | using UnityEngine; 25 | using Object = UnityEngine.Object; 26 | 27 | namespace SubjectNerd.QuickToggle 28 | { 29 | [InitializeOnLoad] 30 | public class QuickToggle 31 | { 32 | #region Constants 33 | private const string PrefKeyShowToggle = "UnityToolbag.QuickToggle.Visible"; 34 | private const string PrefKeyShowDividers = "UnityToolbag.QuickToggle.Dividers"; 35 | private const string PrefKeyShowIcons = "UnityToolbag.QuickToggle.Icons"; 36 | private const string PrefKeyGutterLevel = "UnityToolbag.QuickToggle.Gutter"; 37 | private const string PrefKeyShowVisIcon = "UnityToolbag.QuickToggle.VisIcon"; 38 | 39 | private const string MENU_NAME = "Window/Hierarchy Quick Toggle/Show Toggles"; 40 | private const string MENU_DIVIDER = "Window/Hierarchy Quick Toggle/Dividers"; 41 | private const string MENU_ICONS = "Window/Hierarchy Quick Toggle/Object Icons"; 42 | private const string MENU_VIS_ICONS = "Window/Hierarchy Quick Toggle/Show Visibility Icon"; 43 | private const string MENU_GUTTER_0 = "Window/Hierarchy Quick Toggle/Right Gutter/0"; 44 | private const string MENU_GUTTER_1 = "Window/Hierarchy Quick Toggle/Right Gutter/1"; 45 | private const string MENU_GUTTER_2 = "Window/Hierarchy Quick Toggle/Right Gutter/2"; 46 | #endregion 47 | 48 | private static readonly Type HierarchyWindowType; 49 | private static readonly MethodInfo getObjectIcon; 50 | 51 | private static bool stylesBuilt; 52 | private static GUIStyle styleLock, styleUnlocked, 53 | styleVisOn, styleVisOff, 54 | styleDivider; 55 | 56 | private static bool showDivider, showIcons, showVisIcon; 57 | 58 | #region Menu stuff 59 | [MenuItem(MENU_NAME, false, 1)] 60 | private static void QuickToggleMenu() 61 | { 62 | bool toggle = EditorPrefs.GetBool(PrefKeyShowToggle); 63 | ShowQuickToggle(!toggle); 64 | Menu.SetChecked(MENU_NAME, !toggle); 65 | } 66 | 67 | [MenuItem(MENU_NAME, true)] 68 | private static bool SetupMenuCheckMarks() 69 | { 70 | Menu.SetChecked(MENU_NAME, EditorPrefs.GetBool(PrefKeyShowToggle)); 71 | Menu.SetChecked(MENU_VIS_ICONS, EditorPrefs.GetBool(PrefKeyShowVisIcon)); 72 | Menu.SetChecked(MENU_DIVIDER, EditorPrefs.GetBool(PrefKeyShowDividers)); 73 | Menu.SetChecked(MENU_ICONS, EditorPrefs.GetBool(PrefKeyShowIcons)); 74 | 75 | int gutterLevel = EditorPrefs.GetInt(PrefKeyGutterLevel, 0); 76 | gutterCount = gutterLevel; 77 | UpdateGutterMenu(gutterCount); 78 | return true; 79 | } 80 | 81 | [MenuItem(MENU_VIS_ICONS, false, 20)] 82 | private static void ToggleVisIcons() 83 | { 84 | ToggleSettings(PrefKeyShowVisIcon, MENU_VIS_ICONS, out showVisIcon); 85 | } 86 | 87 | [MenuItem(MENU_DIVIDER, false, 21)] 88 | private static void ToggleDivider() 89 | { 90 | ToggleSettings(PrefKeyShowDividers, MENU_DIVIDER, out showDivider); 91 | } 92 | 93 | [MenuItem(MENU_ICONS, false, 22)] 94 | private static void ToggleIcons() 95 | { 96 | ToggleSettings(PrefKeyShowIcons, MENU_ICONS, out showIcons); 97 | } 98 | 99 | private static void ToggleSettings(string prefKey, string menuString, out bool valueBool) 100 | { 101 | valueBool = !EditorPrefs.GetBool(prefKey); 102 | EditorPrefs.SetBool(prefKey, valueBool); 103 | Menu.SetChecked(menuString, valueBool); 104 | EditorApplication.RepaintHierarchyWindow(); 105 | } 106 | 107 | [MenuItem(MENU_GUTTER_0, false, 40)] 108 | private static void SetGutter0() { SetGutterLevel(0); } 109 | [MenuItem(MENU_GUTTER_1, false, 41)] 110 | private static void SetGutter1() { SetGutterLevel(1); } 111 | [MenuItem(MENU_GUTTER_2, false, 42)] 112 | private static void SetGutter2() { SetGutterLevel(2); } 113 | 114 | private static void SetGutterLevel(int gutterLevel) 115 | { 116 | gutterLevel = Mathf.Clamp(gutterLevel, 0, 2); 117 | EditorPrefs.SetInt(PrefKeyGutterLevel, gutterLevel); 118 | gutterCount = gutterLevel; 119 | UpdateGutterMenu(gutterCount); 120 | EditorApplication.RepaintHierarchyWindow(); 121 | } 122 | 123 | private static void UpdateGutterMenu(int gutterLevel) 124 | { 125 | string[] gutterKeys = new[] { MENU_GUTTER_0, MENU_GUTTER_1, MENU_GUTTER_2 }; 126 | bool[] gutterValues = null; 127 | switch (gutterLevel) 128 | { 129 | case 1: 130 | gutterValues = new[] { false, true, false }; 131 | break; 132 | case 2: 133 | gutterValues = new[] { false, false, true }; 134 | break; 135 | default: 136 | gutterValues = new[] { true, false, false }; 137 | break; 138 | } 139 | for (int i = 0; i < gutterKeys.Length; i++) 140 | { 141 | string key = gutterKeys[i]; 142 | bool isChecked = gutterValues[i]; 143 | Menu.SetChecked(key, isChecked); 144 | } 145 | } 146 | #endregion 147 | 148 | static QuickToggle() 149 | { 150 | // Setup initial state of editor prefs if there are no prefs keys yet 151 | string[] resetPrefs = new string[] {PrefKeyShowToggle, PrefKeyShowDividers, 152 | PrefKeyShowIcons, PrefKeyShowVisIcon}; 153 | foreach (string prefKey in resetPrefs) 154 | { 155 | if (EditorPrefs.HasKey(prefKey) == false) 156 | EditorPrefs.SetBool(prefKey, false); 157 | } 158 | 159 | // Fetch some reflection/type stuff for use later on 160 | Assembly editorAssembly = typeof(EditorWindow).Assembly; 161 | HierarchyWindowType = editorAssembly.GetType("UnityEditor.SceneHierarchyWindow"); 162 | 163 | var flags = BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic; 164 | Type editorGuiUtil = typeof (EditorGUIUtility); 165 | getObjectIcon = editorGuiUtil.GetMethod("GetIconForObject", flags, null, new Type[] { typeof(UnityEngine.Object) }, null); 166 | 167 | // Not calling BuildStyles() in constructor because script gets loaded 168 | // on Unity initialization, styles might not be loaded yet 169 | 170 | // Reset mouse state 171 | ResetVars(); 172 | // Setup quick toggle 173 | ShowQuickToggle(EditorPrefs.GetBool(PrefKeyShowToggle)); 174 | } 175 | 176 | private static void ShowQuickToggle(bool show) 177 | { 178 | EditorPrefs.SetBool(PrefKeyShowToggle, show); 179 | showDivider = EditorPrefs.GetBool(PrefKeyShowDividers, false); 180 | showIcons = EditorPrefs.GetBool(PrefKeyShowIcons, false); 181 | showVisIcon = EditorPrefs.GetBool(PrefKeyShowVisIcon, false); 182 | gutterCount = EditorPrefs.GetInt(PrefKeyGutterLevel); 183 | 184 | if (show) 185 | { 186 | ResetVars(); 187 | EditorApplication.update += HandleEditorUpdate; 188 | EditorApplication.hierarchyWindowItemOnGUI += DrawHierarchyItem; 189 | } 190 | else 191 | { 192 | EditorApplication.update -= HandleEditorUpdate; 193 | EditorApplication.hierarchyWindowItemOnGUI -= DrawHierarchyItem; 194 | } 195 | EditorApplication.RepaintHierarchyWindow(); 196 | } 197 | 198 | private struct PropagateState 199 | { 200 | public bool isVisibility; 201 | public bool propagateValue; 202 | 203 | public PropagateState(bool isVisibility, bool propagateValue) 204 | { 205 | this.isVisibility = isVisibility; 206 | this.propagateValue = propagateValue; 207 | } 208 | } 209 | 210 | private static PropagateState propagateState; 211 | 212 | // Because we can't hook into OnGUI of HierarchyWindow, doing a hack 213 | // button that involves the editor update loop and the hierarchy item draw event 214 | private static bool isFrameFresh; 215 | private static bool isMousePressed; 216 | 217 | private static int gutterCount = 0; 218 | 219 | private static void ResetVars() 220 | { 221 | isFrameFresh = false; 222 | isMousePressed = false; 223 | } 224 | 225 | private static void HandleEditorUpdate() 226 | { 227 | EditorWindow window = EditorWindow.mouseOverWindow; 228 | if (window == null) 229 | { 230 | ResetVars(); 231 | return; 232 | } 233 | 234 | if (window.GetType() == HierarchyWindowType) 235 | { 236 | if (window.wantsMouseMove == false) 237 | window.wantsMouseMove = true; 238 | 239 | isFrameFresh = true; 240 | } 241 | } 242 | 243 | private static void DrawHierarchyItem(int instanceId, Rect selectionRect) 244 | { 245 | BuildStyles(); 246 | 247 | GameObject target = EditorUtility.InstanceIDToObject(instanceId) as GameObject; 248 | if (target == null) 249 | return; 250 | 251 | // Get states 252 | bool isVisible = target.activeSelf; 253 | bool isLocked = (target.hideFlags & HideFlags.NotEditable) > 0; 254 | 255 | // Check if mouse is over hierarchy item, to act like Unity vis toggle 256 | Event evt = Event.current; 257 | if (isLocked == false && selectionRect.Contains(evt.mousePosition) == false) 258 | return; 259 | 260 | // Reserve the draw rects 261 | float gutterX = selectionRect.height*gutterCount; 262 | if (gutterX > 0) 263 | gutterX += selectionRect.height*0.1f; 264 | float xMax = selectionRect.xMax - gutterX; 265 | 266 | Rect visRect = new Rect(selectionRect) 267 | { 268 | xMin = xMax - (selectionRect.height * 2.1f), 269 | xMax = xMax - selectionRect.height 270 | }; 271 | Rect lockRect = new Rect(selectionRect) 272 | { 273 | xMin = xMax - (selectionRect.height * 1.05f), 274 | xMax = xMax - (selectionRect.height * 0.05f) 275 | }; 276 | 277 | if (showVisIcon) 278 | { 279 | // Draw the visibility toggle 280 | GUIStyle visStyle = (isVisible) ? styleVisOn : styleVisOff; 281 | GUI.Label(visRect, GUIContent.none, visStyle); 282 | } 283 | 284 | // Draw lock toggle 285 | GUIStyle lockStyle = (isLocked) ? styleLock : styleUnlocked; 286 | GUI.Label(lockRect, GUIContent.none, lockStyle); 287 | 288 | // Draw optional divider 289 | if (showDivider) 290 | { 291 | Rect lineRect = new Rect(selectionRect) 292 | { 293 | yMin = selectionRect.yMax - 1f, 294 | yMax = selectionRect.yMax + 2f 295 | }; 296 | GUI.Label(lineRect, GUIContent.none, styleDivider); 297 | } 298 | // Draw optional object icons 299 | if (showIcons && getObjectIcon != null) 300 | { 301 | Texture2D iconImg = getObjectIcon.Invoke(null, new object[] { target }) as Texture2D; 302 | if (iconImg != null) 303 | { 304 | Rect iconRect = new Rect(selectionRect) 305 | { 306 | xMin = visRect.xMin - 30, 307 | xMax = visRect.xMin - 5 308 | }; 309 | GUI.DrawTexture(iconRect, iconImg, ScaleMode.ScaleToFit); 310 | } 311 | } 312 | 313 | if (Event.current == null) 314 | return; 315 | 316 | HandleMouse(target, isVisible, isLocked, visRect, lockRect); 317 | } 318 | 319 | private static void HandleMouse(GameObject target, bool isVisible, bool isLocked, Rect visRect, Rect lockRect) 320 | { 321 | Event evt = Event.current; 322 | 323 | bool toggleActive = visRect.Contains(evt.mousePosition); 324 | bool toggleLock = lockRect.Contains(evt.mousePosition); 325 | bool stateChanged = (toggleActive || toggleLock); 326 | 327 | bool doMouse = false; 328 | switch (evt.type) 329 | { 330 | case EventType.MouseDown: 331 | // Checking is frame fresh so mouse state is only tested once per frame 332 | // instead of every time a hierarchy item is drawn 333 | bool isMouseDown = false; 334 | if (isFrameFresh && stateChanged) 335 | { 336 | isMouseDown = !isMousePressed; 337 | isMousePressed = true; 338 | isFrameFresh = false; 339 | } 340 | 341 | if (stateChanged && isMouseDown) 342 | { 343 | doMouse = true; 344 | if (toggleActive) isVisible = !isVisible; 345 | if (toggleLock) isLocked = !isLocked; 346 | 347 | propagateState = new PropagateState(toggleActive, (toggleActive) ? isVisible : isLocked); 348 | evt.Use(); 349 | } 350 | break; 351 | case EventType.MouseDrag: 352 | doMouse = isMousePressed; 353 | break; 354 | case EventType.DragPerform: 355 | case EventType.DragExited: 356 | case EventType.DragUpdated: 357 | case EventType.MouseUp: 358 | ResetVars(); 359 | break; 360 | } 361 | 362 | if (doMouse && stateChanged) 363 | { 364 | if (propagateState.isVisibility) 365 | SetVisible(target, propagateState.propagateValue); 366 | else 367 | SetLockObject(target, propagateState.propagateValue); 368 | 369 | EditorApplication.RepaintHierarchyWindow(); 370 | } 371 | } 372 | 373 | private static Object[] GatherObjects(GameObject root) 374 | { 375 | List objects = new List(); 376 | Stack recurseStack = new Stack(new GameObject[] { root }); 377 | 378 | while (recurseStack.Count > 0) 379 | { 380 | GameObject obj = recurseStack.Pop(); 381 | objects.Add(obj); 382 | 383 | foreach (Transform childT in obj.transform) 384 | recurseStack.Push(childT.gameObject); 385 | } 386 | return objects.ToArray(); 387 | } 388 | 389 | private static void SetLockObject(GameObject target, bool isLocked) 390 | { 391 | bool objectLockState = (target.hideFlags & HideFlags.NotEditable) > 0; 392 | if (objectLockState == isLocked) 393 | return; 394 | 395 | List setGameObjects = new List() { target }; 396 | 397 | // If target object is part of selection, logical thing is to set state of selection 398 | List selectionList = new List(Selection.gameObjects); 399 | if (selectionList.Contains(target)) 400 | setGameObjects = selectionList; 401 | 402 | List gatheredObjects = new List(); 403 | foreach (GameObject setGameObject in setGameObjects) 404 | { 405 | gatheredObjects.AddRange(GatherObjects(setGameObject)); 406 | } 407 | 408 | foreach (Object obj in gatheredObjects) 409 | { 410 | GameObject go = (GameObject)obj; 411 | string undoString = string.Format("{0} {1}", isLocked ? "Lock" : "Unlock", go.name); 412 | Undo.RecordObject(go, undoString); 413 | 414 | // Set state according to isLocked 415 | if (isLocked) 416 | { 417 | go.hideFlags |= HideFlags.NotEditable; 418 | } 419 | else 420 | { 421 | go.hideFlags &= ~HideFlags.NotEditable; 422 | } 423 | 424 | // Set hideflags of components 425 | foreach (Component comp in go.GetComponents()) 426 | { 427 | if (comp is Transform) 428 | continue; 429 | if (isLocked) 430 | { 431 | comp.hideFlags |= HideFlags.NotEditable; 432 | comp.hideFlags |= HideFlags.HideInHierarchy; 433 | } 434 | else 435 | { 436 | comp.hideFlags &= ~HideFlags.NotEditable; 437 | comp.hideFlags &= ~HideFlags.HideInHierarchy; 438 | } 439 | EditorUtility.SetDirty(comp); 440 | } 441 | EditorUtility.SetDirty(go); 442 | } 443 | Undo.IncrementCurrentGroup(); 444 | } 445 | 446 | private static void SetVisible(GameObject target, bool isActive) 447 | { 448 | if (target.activeSelf == isActive) return; 449 | 450 | string undoString = string.Format("{0} {1}", 451 | isActive ? "Show" : "Hide", 452 | target.name); 453 | Undo.RecordObject(target, undoString); 454 | 455 | target.SetActive(isActive); 456 | EditorUtility.SetDirty(target); 457 | } 458 | 459 | private static void BuildStyles() 460 | { 461 | // All of the styles have been built, don't do anything 462 | if (stylesBuilt) 463 | return; 464 | 465 | // Now build the GUI styles 466 | // Using icons different from regular lock button so that 467 | // it would look darker 468 | var tempStyle = GUI.skin.FindStyle("IN LockButton"); 469 | styleLock = new GUIStyle(tempStyle) 470 | { 471 | normal = tempStyle.onNormal, 472 | active = tempStyle.onActive, 473 | hover = tempStyle.onHover, 474 | focused = tempStyle.onFocused, 475 | }; 476 | 477 | // Unselected just makes the normal states have no lock images 478 | tempStyle = GUI.skin.FindStyle("OL Toggle"); 479 | styleUnlocked = new GUIStyle(tempStyle); 480 | #if UNITY_2018_3_OR_NEWER 481 | tempStyle = new GUIStyle() 482 | { 483 | normal = new GUIStyleState() { background = EditorGUIUtility.Load("Icons/d_VisibilityOff.png") as Texture2D }, 484 | onNormal = new GUIStyleState() { background = EditorGUIUtility.Load("Icons/d_VisibilityOn.png") as Texture2D }, 485 | fixedHeight = 16, 486 | fixedWidth = 16, 487 | border = new RectOffset(2, 2, 2, 2), 488 | overflow = new RectOffset(-1, 1, -2, 2), 489 | padding = new RectOffset(3, 3, 3, 3), 490 | richText = false, 491 | stretchHeight = false, 492 | stretchWidth = false, 493 | }; 494 | #else 495 | tempStyle = GUI.skin.FindStyle("VisibilityToggle"); 496 | #endif 497 | 498 | 499 | styleVisOff = new GUIStyle(tempStyle); 500 | styleVisOn = new GUIStyle(tempStyle) 501 | { 502 | normal = new GUIStyleState() { background = tempStyle.onNormal.background } 503 | }; 504 | 505 | styleDivider = GUI.skin.FindStyle("EyeDropperHorizontalLine"); 506 | 507 | stylesBuilt = (styleLock != null && styleUnlocked != null && 508 | styleVisOn != null && styleVisOff != null && 509 | styleDivider != null); 510 | } 511 | } 512 | } -------------------------------------------------------------------------------- /Editor/QuickToggle.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 122638ede509d4054b67b6d7676df6b9 3 | timeCreated: 1447732429 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 SubjectNerd-Unity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a1d6aaf72778a2469126737c26d6cd0 3 | timeCreated: 1497243829 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hierarchy Quick Toggle 2 | 3 | Hierarchy Quick Toggle adds icons in the Hierarchy view to quickly hide or lock objects in the scene, similar to Photoshop's layer view. 4 | 5 | ![Quick Toggle](https://thumbs.gfycat.com/CheerySandyCanine-size_restricted.gif) 6 | 7 | ## Installation 8 | 9 | Get the latest UnityPackage from [GitHub releases](https://github.com/SubjectNerd-Unity/QuickToggle/releases). The `QuickToggle` directory can be moved to another directory after importing. 10 | 11 | ## Usage 12 | 13 | The toggles can be turned on and off by going to `Window>Hierarchy Quick Toggle>Show Toggles` 14 | 15 | ![Hide/Show Quick Toggle](./Docs/QuickToggle-Options.png) 16 | 17 | ### Options 18 | 19 | **Dividers** — A horizontal line is drawn between each hierarchy item. 20 | 21 | **Object Icons** — If an [icon is assigned to an object](https://docs.unity3d.com/Manual/AssigningIcons.html), draw the icon in the hierarchy. 22 | 23 | **Right Gutter** — If other plugins draw on the right of the hierarchy window, use this setting to add spacing. 24 | 25 | ## Buy me a coffee! 26 | 27 | If this useful to you, it would be great if you could [buy me a coffee](https://ko-fi.com/subjectnerd)! 28 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 301e5b8bad4e1d342b15461b75731c48 3 | timeCreated: 1497243946 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | --------------------------------------------------------------------------------