├── .gitignore ├── About.meta ├── About ├── Editor.meta ├── Editor │ ├── groups_AboutWindow.cs │ └── groups_AboutWindow.cs.meta ├── Images.meta ├── Images │ ├── Banner.png │ ├── Banner.png.meta │ ├── ProBuilder_AssetStore_Icon_96px.png │ ├── ProBuilder_AssetStore_Icon_96px.png.meta │ ├── ProGrids_AssetStore_Icon_96px.png │ ├── ProGrids_AssetStore_Icon_96px.png.meta │ ├── ProGroups_AssetStore_Icon_96px.png │ ├── ProGroups_AssetStore_Icon_96px.png.meta │ ├── Prototype_AssetStore_Icon_96px.png │ ├── Prototype_AssetStore_Icon_96px.png.meta │ ├── QuickBrush_AssetStore_Icon_96px.png │ ├── QuickBrush_AssetStore_Icon_96px.png.meta │ ├── QuickDecals_AssetStore_Icon_96px.png │ ├── QuickDecals_AssetStore_Icon_96px.png.meta │ ├── QuickEdit_AssetStore_Icon_96px.png │ └── QuickEdit_AssetStore_Icon_96px.png.meta ├── changelog.txt ├── changelog.txt.meta ├── pc_AboutEntry_ProGroups.txt └── pc_AboutEntry_ProGroups.txt.meta ├── GUI.meta ├── GUI ├── ProGroupsIcons_Add.png ├── ProGroupsIcons_Add.png.meta ├── ProGroupsIcons_Delete.png ├── ProGroupsIcons_Delete.png.meta ├── ProGroupsIcons_Drag.png ├── ProGroupsIcons_Drag.png.meta ├── ProGroupsIcons_Eye.png ├── ProGroupsIcons_Eye.png.meta ├── ProGroupsIcons_Gear.png ├── ProGroupsIcons_Gear.png.meta ├── ProGroupsIcons_MoveUp.png ├── ProGroupsIcons_MoveUp.png.meta ├── ProGroupsIcons_MultiPlus.png ├── ProGroupsIcons_MultiPlus.png.meta ├── ProGroupsIcons_Rect.png ├── ProGroupsIcons_Rect.png.meta ├── ProGroupsIcons_Select.png ├── ProGroupsIcons_Select.png.meta ├── ProGroupsIcons_SnowFlake.png ├── ProGroupsIcons_SnowFlake.png.meta ├── ProGroupsIcons_UpdateGroup.png └── ProGroupsIcons_UpdateGroup.png.meta ├── LICENSE ├── ProGroups_Manual.pdf ├── ProGroups_Manual.pdf.meta ├── README.md ├── Scripts.meta └── Scripts ├── Editor.meta ├── Editor ├── ProGroups_About.cs ├── ProGroups_About.cs.meta ├── ProGroups_Window.cs └── ProGroups_Window.cs.meta ├── InScene.meta └── InScene ├── GroupContainer.cs ├── GroupContainer.cs.meta ├── ProGroups_Util.cs └── ProGroups_Util.cs.meta /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Visual Studio 2015 cache directory 9 | /.vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | 26 | # Unity3D generated meta files 27 | *.pidb.meta 28 | 29 | # Unity3D Generated File On Crash Reports 30 | sysinfo.txt 31 | 32 | # Builds 33 | *.apk 34 | *.unitypackage 35 | -------------------------------------------------------------------------------- /About.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 028d1e3cb1430364e88fd1f24ad49ca7 3 | -------------------------------------------------------------------------------- /About/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5436d8f7366972c4680dc719ed509d03 3 | -------------------------------------------------------------------------------- /About/Editor/groups_AboutWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | 7 | /** 8 | * INSTRUCTIONS 9 | * 10 | * - Only modify properties in the USER SETTINGS region. 11 | * - All content is loaded from external files (pc_AboutEntry_YourProduct. Use the templates! 12 | */ 13 | 14 | /** 15 | * Used to pop up the window on import. 16 | */ 17 | public class groups_AboutWindowSetup : AssetPostprocessor 18 | { 19 | #region Initialization 20 | 21 | static void OnPostprocessAllAssets ( 22 | string[] importedAssets, 23 | string[] deletedAssets, 24 | string[] movedAssets, 25 | string[] movedFromAssetPaths) 26 | { 27 | 28 | string[] entries = System.Array.FindAll(importedAssets, name => name.Contains("pc_AboutEntry") && !name.EndsWith(".meta")); 29 | 30 | foreach(string str in entries) 31 | if( groups_AboutWindow.Init(str, false) ) 32 | break; 33 | } 34 | 35 | // [MenuItem("Edit/Preferences/Clear About Version: " + groups_AboutWindow.PRODUCT_IDENTIFIER)] 36 | // public static void MenuClearVersionPref() 37 | // { 38 | // EditorPrefs.DeleteKey(groups_AboutWindow.PRODUCT_IDENTIFIER); 39 | // } 40 | #endregion 41 | } 42 | 43 | /* Change 'groups_AboutWindow' to your own class name */ 44 | public class groups_AboutWindow : EditorWindow 45 | { 46 | 47 | /** 48 | * Modify these constants to customize about screen. 49 | */ 50 | #region User Settings 51 | 52 | /* Path to the root folder */ 53 | const string ABOUT_ROOT = "Assets/ProCore/ProGroups/About"; 54 | 55 | /** 56 | * Changelog.txt file should follow this format: 57 | * 58 | * | -- Product Name 2.1.0 - 59 | * | 60 | * | # Features 61 | * | - All kinds of awesome stuff 62 | * | - New flux capacitor design achieves time travel at lower velocities. 63 | * | - Dark matter reactor recalibrated. 64 | * | 65 | * | # Bug Fixes 66 | * | - No longer explodes when spacebar is pressed. 67 | * | - Fix rolling issue in Rickmeter. 68 | * | 69 | * | # Changes 70 | * | - Changed Blue to Red. 71 | * | - Enter key now causes explosions. 72 | * 73 | * This path is relative to the PRODUCT_ROOT path. 74 | * 75 | * Note that your changelog may contain multiple entries. Only the top-most 76 | * entry will be displayed. 77 | */ 78 | 79 | /** 80 | * Advertisement thumb constructor is: 81 | * new AdvertisementThumb( PathToAdImage : string, URLToPurchase : string, ProductDescription : string ) 82 | * Provide as many or few (or none) as desired. 83 | * 84 | * Notes - The http:// part is required. Partial URLs do not work on Mac. 85 | */ 86 | [SerializeField] 87 | public static AdvertisementThumb[] advertisements = new AdvertisementThumb[] { 88 | new AdvertisementThumb( ABOUT_ROOT + "/Images/ProBuilder_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/probuilder/", "Build and Texture Geometry In-Editor"), 89 | new AdvertisementThumb( ABOUT_ROOT + "/Images/ProGrids_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/progrids/", "True Grids and Grid-Snapping"), 90 | new AdvertisementThumb( ABOUT_ROOT + "/Images/ProGroups_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/progroups/", "Hide, Freeze, Group, & Organize"), 91 | new AdvertisementThumb( ABOUT_ROOT + "/Images/Prototype_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/prototype/", "Design and Build With Zero Lag"), 92 | new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickBrush_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickbrush/", "Quickly Add Detail Geometry"), 93 | new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickDecals_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickdecals/", "Add Dirt, Splatters, Posters, etc"), 94 | new AdvertisementThumb( ABOUT_ROOT + "/Images/QuickEdit_AssetStore_Icon_96px.png", "http://www.protoolsforunity3d.com/quickedit/", "Edit Imported Meshes!"), 95 | }; 96 | #endregion 97 | 98 | /* Recommend you do not modify these. */ 99 | #region Private Fields (automatically populated) 100 | 101 | private string AboutEntryPath = ""; 102 | 103 | private string ProductName = ""; 104 | // private string ProductIdentifer = ""; 105 | private string ProductVersion = ""; 106 | private string ProductRevision = ""; 107 | private string ChangelogPath = ""; 108 | private string BannerPath = ABOUT_ROOT + "/Images/Banner.png"; 109 | 110 | 111 | const int AD_HEIGHT = 96; 112 | 113 | /** 114 | * Struct containing data for use in Advertisement shelf. 115 | */ 116 | [System.Serializable] 117 | public struct AdvertisementThumb 118 | { 119 | public Texture2D image; 120 | public string url; 121 | public string about; 122 | public GUIContent guiContent; 123 | 124 | public AdvertisementThumb(string imagePath, string url, string about) 125 | { 126 | guiContent = new GUIContent("", about); 127 | this.image = (Texture2D) AssetDatabase.LoadAssetAtPath(imagePath, typeof(Texture2D)); 128 | guiContent.image = this.image; 129 | this.url = url; 130 | this.about = about; 131 | } 132 | } 133 | 134 | Texture2D banner; 135 | 136 | // populated by first entry in changelog 137 | string changelog = ""; 138 | #endregion 139 | 140 | #region Init 141 | 142 | // [MenuItem("Tools/Test Search About Window", false, 0)] 143 | // public static void MenuInit() 144 | // { 145 | // // this could be slow in large projects? 146 | // string[] allFiles = System.IO.Directory.GetFiles("Assets/", "*.*", System.IO.SearchOption.AllDirectories); 147 | // string[] entries = System.Array.FindAll(allFiles, name => name.Contains("pc_AboutEntry")); 148 | 149 | // if(entries.Length > 0) 150 | // groups_AboutWindow.Init(entries[0], true); 151 | // } 152 | 153 | /** 154 | * Return true if Init took place, false if not. 155 | */ 156 | public static bool Init (string aboutEntryPath, bool fromMenu) 157 | { 158 | string identifier, version; 159 | 160 | if( !GetField(aboutEntryPath, "version: ", out version) || !GetField(aboutEntryPath, "identifier: ", out identifier)) 161 | return false; 162 | 163 | if(fromMenu || EditorPrefs.GetString(identifier) != version) 164 | { 165 | string tname; 166 | groups_AboutWindow win; 167 | 168 | if(!GetField(aboutEntryPath, "name: ", out tname) || !tname.Contains("ProGroups")) 169 | return false; 170 | 171 | win = (groups_AboutWindow)EditorWindow.GetWindow(typeof(groups_AboutWindow), true, tname, true); 172 | win.SetAboutEntryPath(aboutEntryPath); 173 | win.ShowUtility(); 174 | 175 | EditorPrefs.SetString(identifier, version); 176 | 177 | return true; 178 | } 179 | else 180 | { 181 | return false; 182 | } 183 | } 184 | 185 | public void OnEnable() 186 | { 187 | banner = (Texture2D)AssetDatabase.LoadAssetAtPath(BannerPath, typeof(Texture2D)); 188 | 189 | // With Unity 4 (on PC) if you have different values for minSize and maxSize, 190 | // they do not apply restrictions to window size. 191 | #if UNITY_4 192 | this.minSize = new Vector2(banner.width + 12, banner.height * 7); 193 | this.maxSize = new Vector2(banner.width + 12, banner.height * 7); 194 | #else 195 | this.minSize = new Vector2(banner.width + 12, banner.height * 6); 196 | this.maxSize = new Vector2(banner.width + 12, 1440); 197 | #endif 198 | } 199 | 200 | public void SetAboutEntryPath(string path) 201 | { 202 | AboutEntryPath = path; 203 | PopulateDataFields(AboutEntryPath); 204 | } 205 | #endregion 206 | 207 | #region GUI 208 | 209 | Color LinkColor = new Color(0f, .682f, .937f, 1f); 210 | 211 | GUIStyle boldTextStyle, 212 | headerTextStyle, 213 | linkTextStyle; 214 | 215 | GUIStyle advertisementStyle; 216 | Vector2 scroll = Vector2.zero, adScroll = Vector2.zero; 217 | // int mm = 32; 218 | void OnGUI() 219 | { 220 | headerTextStyle = headerTextStyle ?? new GUIStyle( EditorStyles.boldLabel );//GUI.skin.label); 221 | headerTextStyle.fontSize = 16; 222 | 223 | linkTextStyle = linkTextStyle ?? new GUIStyle( GUI.skin.label );//GUI.skin.label); 224 | linkTextStyle.normal.textColor = LinkColor; 225 | linkTextStyle.alignment = TextAnchor.MiddleLeft; 226 | 227 | boldTextStyle = boldTextStyle ?? new GUIStyle( GUI.skin.label );//GUI.skin.label); 228 | boldTextStyle.fontStyle = FontStyle.Bold; 229 | boldTextStyle.alignment = TextAnchor.MiddleLeft; 230 | 231 | // #if UNITY_4 232 | // richTextLabel.richText = true; 233 | // #endif 234 | 235 | advertisementStyle = advertisementStyle ?? new GUIStyle(GUI.skin.button); 236 | advertisementStyle.normal.background = null; 237 | 238 | if(banner != null) 239 | GUILayout.Label(banner); 240 | 241 | // mm = EditorGUI.IntField(new Rect(Screen.width - 200, 100, 200, 18), "W: ", mm); 242 | 243 | // grr stupid rich text faiiilluuure 244 | { 245 | GUILayout.Label("Thank you for purchasing " + ProductName + ". Your support allows us to keep developing this and future tools for everyone.", EditorStyles.wordWrappedLabel); 246 | GUILayout.Space(2); 247 | GUILayout.Label("Read these quick \"ProTips\" before starting:", headerTextStyle); 248 | 249 | GUILayout.BeginHorizontal(); 250 | GUILayout.Label("1) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16)); 251 | GUILayout.Label("Register", boldTextStyle, GUILayout.MinWidth(58), GUILayout.MaxWidth(58)); 252 | GUILayout.Label("for instant email updates, send your invoice # to", GUILayout.MinWidth(284), GUILayout.MaxWidth(284)); 253 | if( GUILayout.Button("contact@procore3d.com", linkTextStyle, GUILayout.MinWidth(142), GUILayout.MaxWidth(142)) ) 254 | Application.OpenURL("mailto:contact@procore3d.com?subject=Sign me up for the Beta!"); 255 | GUILayout.EndHorizontal(); 256 | 257 | GUILayout.BeginHorizontal(); 258 | GUILayout.Label("2) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16)); 259 | GUILayout.Label("Report bugs", boldTextStyle, GUILayout.MinWidth(82), GUILayout.MaxWidth(82)); 260 | GUILayout.Label("to the ProCore Forum at", GUILayout.MinWidth(144), GUILayout.MaxWidth(144)); 261 | if( GUILayout.Button("www.procore3d.com/forum", linkTextStyle, GUILayout.MinWidth(162), GUILayout.MaxWidth(162)) ) 262 | Application.OpenURL("http://www.procore3d.com/forum"); 263 | GUILayout.EndHorizontal(); 264 | 265 | GUILayout.BeginHorizontal(); 266 | GUILayout.Label("3) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16)); 267 | GUILayout.Label("Customize!", boldTextStyle, GUILayout.MinWidth(74), GUILayout.MaxWidth(74)); 268 | GUILayout.Label("Click on \"Edit > Preferences\" then \"" + ProductName + "\"", GUILayout.MinWidth(276), GUILayout.MaxWidth(276)); 269 | GUILayout.EndHorizontal(); 270 | 271 | GUILayout.BeginHorizontal(); 272 | GUILayout.Label("4) ", GUILayout.MinWidth(16), GUILayout.MaxWidth(16)); 273 | GUILayout.Label("Documentation", boldTextStyle, GUILayout.MinWidth(102), GUILayout.MaxWidth(102)); 274 | GUILayout.Label("Tutorials, & more info:", GUILayout.MinWidth(132), GUILayout.MaxWidth(132)); 275 | if( GUILayout.Button("www.procore3d.com/" + ProductName.ToLower(), linkTextStyle, GUILayout.MinWidth(190), GUILayout.MaxWidth(190)) ) 276 | Application.OpenURL("http://www.procore3d.com/" + ProductName.ToLower()); 277 | GUILayout.EndHorizontal(); 278 | 279 | GUILayout.Space(4); 280 | 281 | GUILayout.BeginHorizontal(GUILayout.MaxWidth(50)); 282 | 283 | GUILayout.Label("Links:", boldTextStyle); 284 | 285 | linkTextStyle.fontStyle = FontStyle.Italic; 286 | linkTextStyle.alignment = TextAnchor.MiddleCenter; 287 | 288 | if( GUILayout.Button("procore3d.com", linkTextStyle)) 289 | Application.OpenURL("http://www.procore3d.com"); 290 | 291 | if( GUILayout.Button("facebook", linkTextStyle)) 292 | Application.OpenURL("http://www.facebook.com/probuilder3d"); 293 | 294 | if( GUILayout.Button("twitter", linkTextStyle)) 295 | Application.OpenURL("http://www.twitter.com/probuilder3d"); 296 | 297 | linkTextStyle.fontStyle = FontStyle.Normal; 298 | GUILayout.EndHorizontal(); 299 | 300 | GUILayout.Space(4); 301 | } 302 | 303 | HorizontalLine(); 304 | 305 | // always bold the first line (cause it's the version info stuff) 306 | scroll = EditorGUILayout.BeginScrollView(scroll); 307 | GUILayout.Label(ProductName + " | version: " + ProductVersion + " | revision: " + ProductRevision, EditorStyles.boldLabel); 308 | GUILayout.Label("\n" + changelog); 309 | EditorGUILayout.EndScrollView(); 310 | 311 | HorizontalLine(); 312 | 313 | GUILayout.Label("More ProCore Products", EditorStyles.boldLabel); 314 | 315 | int pad = advertisements.Length * AD_HEIGHT > Screen.width ? 22 : 6; 316 | adScroll = EditorGUILayout.BeginScrollView(adScroll, false, false, GUILayout.MinHeight(AD_HEIGHT + pad), GUILayout.MaxHeight(AD_HEIGHT + pad)); 317 | GUILayout.BeginHorizontal(); 318 | 319 | foreach(AdvertisementThumb ad in advertisements) 320 | { 321 | if(ad.url.ToLower().Contains(ProductName.ToLower())) 322 | continue; 323 | 324 | if(GUILayout.Button(ad.guiContent, advertisementStyle, 325 | GUILayout.MinWidth(AD_HEIGHT), GUILayout.MaxWidth(AD_HEIGHT), 326 | GUILayout.MinHeight(AD_HEIGHT), GUILayout.MaxHeight(AD_HEIGHT))) 327 | { 328 | Application.OpenURL(ad.url); 329 | } 330 | } 331 | GUILayout.EndHorizontal(); 332 | EditorGUILayout.EndScrollView(); 333 | /* shill other products */ 334 | } 335 | 336 | /** 337 | * Draw a horizontal line across the screen and update the guilayout. 338 | */ 339 | void HorizontalLine() 340 | { 341 | Rect r = GUILayoutUtility.GetLastRect(); 342 | Color og = GUI.backgroundColor; 343 | GUI.backgroundColor = Color.black; 344 | GUI.Box(new Rect(0f, r.y + r.height + 2, Screen.width, 2f), ""); 345 | GUI.backgroundColor = og; 346 | 347 | GUILayout.Space(6); 348 | } 349 | #endregion 350 | 351 | #region Data Parsing 352 | 353 | /* rich text ain't wuurkin' in unity 3.5 */ 354 | const string RemoveBraketsRegex = "(\\<.*?\\>)"; 355 | 356 | /** 357 | * Open VersionInfo and Changelog and pull out text to populate vars for OnGUI to display. 358 | */ 359 | void PopulateDataFields(string entryPath) 360 | { 361 | /* Get data from VersionInfo.txt */ 362 | TextAsset versionInfo = (TextAsset)AssetDatabase.LoadAssetAtPath( entryPath, typeof(TextAsset)); 363 | 364 | ProductName = ""; 365 | // ProductIdentifer = ""; 366 | ProductVersion = ""; 367 | ProductRevision = ""; 368 | ChangelogPath = ""; 369 | 370 | if(versionInfo != null) 371 | { 372 | string[] txt = versionInfo.text.Split('\n'); 373 | foreach(string cheese in txt) 374 | { 375 | if(cheese.StartsWith("name:")) 376 | ProductName = cheese.Replace("name: ", "").Trim(); 377 | else 378 | if(cheese.StartsWith("version:")) 379 | ProductVersion = cheese.Replace("version: ", "").Trim(); 380 | else 381 | if(cheese.StartsWith("revision:")) 382 | ProductRevision = cheese.Replace("revision: ", "").Trim(); 383 | else 384 | if(cheese.StartsWith("changelog:")) 385 | ChangelogPath = cheese.Replace("changelog: ", "").Trim(); 386 | } 387 | } 388 | 389 | // notes = notes.Trim(); 390 | 391 | /* Get first entry in changelog.txt */ 392 | TextAsset changelogText = (TextAsset)AssetDatabase.LoadAssetAtPath( ChangelogPath, typeof(TextAsset)); 393 | 394 | if(changelogText) 395 | { 396 | string[] split = changelogText.text.Split( new string[] {"--"}, System.StringSplitOptions.RemoveEmptyEntries ); 397 | StringBuilder sb = new StringBuilder(); 398 | string[] newLineSplit = split[0].Trim().Split('\n'); 399 | for(int i = 2; i < newLineSplit.Length; i++) 400 | sb.AppendLine(newLineSplit[i]); 401 | 402 | changelog = sb.ToString(); 403 | } 404 | } 405 | 406 | private static bool GetField(string path, string field, out string value) 407 | { 408 | TextAsset entry = (TextAsset)AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset)); 409 | value = ""; 410 | 411 | if(!entry) return false; 412 | 413 | foreach(string str in entry.text.Split('\n')) 414 | { 415 | if(str.Contains(field)) 416 | { 417 | value = str.Replace(field, "").Trim(); 418 | return true; 419 | } 420 | } 421 | 422 | return false; 423 | } 424 | #endregion 425 | } 426 | -------------------------------------------------------------------------------- /About/Editor/groups_AboutWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84f9e739ca00ea345a8cdbf7bb526a60 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | -------------------------------------------------------------------------------- /About/Images.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1cfa7e713a573d341b8eb0fb28abb7dc 3 | -------------------------------------------------------------------------------- /About/Images/Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/Banner.png -------------------------------------------------------------------------------- /About/Images/Banner.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 596e0ecfffb5081489f2685f6bccc078 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 0 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | cubemapConvolution: 0 24 | cubemapConvolutionSteps: 8 25 | cubemapConvolutionExponent: 1.5 26 | seamlessCubemap: 0 27 | textureFormat: 5 28 | maxTextureSize: 1024 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: 1 34 | nPOTScale: 0 35 | lightmap: 0 36 | rGBM: 0 37 | compressionQuality: 50 38 | spriteMode: 0 39 | spriteExtrude: 1 40 | spriteMeshType: 1 41 | alignment: 0 42 | spritePivot: {x: .5, y: .5} 43 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 44 | spritePixelsToUnits: 100 45 | alphaIsTransparency: 0 46 | textureType: 5 47 | buildTargetSettings: [] 48 | spriteSheet: 49 | sprites: [] 50 | spritePackingTag: 51 | userData: 52 | assetBundleName: 53 | assetBundleVariant: 54 | -------------------------------------------------------------------------------- /About/Images/ProBuilder_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/ProBuilder_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/ProBuilder_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dfd287a1b4a4a0c4f854fd7ebadf2da0 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/ProGrids_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/ProGrids_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/ProGrids_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4edf0bc18be476e44a6b6d09dca3342b 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/ProGroups_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/ProGroups_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/ProGroups_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb0c7613c2adcfc41a41a57a04563df5 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/Prototype_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/Prototype_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/Prototype_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c3fcad1c8cf29064da31da1e92653c4e 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/QuickBrush_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/QuickBrush_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/QuickBrush_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7c21b03319db30a48832a90258cf87f4 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/QuickDecals_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/QuickDecals_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/QuickDecals_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7f33c7410f26eb47ba0b5e14e4a92ac 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/Images/QuickEdit_AssetStore_Icon_96px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/About/Images/QuickEdit_AssetStore_Icon_96px.png -------------------------------------------------------------------------------- /About/Images/QuickEdit_AssetStore_Icon_96px.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 92b2287fb1ecbbd429323818c4effa51 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 5 23 | maxTextureSize: 512 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /About/changelog.txt: -------------------------------------------------------------------------------- 1 | -- ProGroups 1.2.7f1 2 | 3 | # Features 4 | 5 | - Click list items to select individual objects. 6 | 7 | # Bug Fixes 8 | 9 | - When adding new objects to a group, apply Freeze and Hide states to objects. 10 | - Fix icons not loading when ProGroups folder is moved. 11 | - Fix About window opening changelogs that do not belong to ProGroups. 12 | 13 | -- ProGroups 1.2.6 14 | 15 | # Bug Fixes 16 | 17 | - Fix GUI rendering on macOS Retina displays. 18 | 19 | -- ProGroups 1.2.5 20 | 21 | # Features 22 | 23 | - Add ability to collapse and expand groups individually 24 | - Improve visibility of groups by alternating row color 25 | 26 | -- ProGroups 1.2.4 27 | 28 | # Features 29 | 30 | - When a group is selected, show all it's children with a delete button to remove it from the group. 31 | 32 | -- ProGroups 1.2.3 - 33 | 34 | # Bug Fixes 35 | 36 | - Fix occasional null reference exception caused by deleting all groups in a scene. 37 | - Add menu item to clear all groups in a scene. 38 | 39 | -- ProGroups 1.2.2 - 40 | 41 | # Features 42 | 43 | - Unity 5.1 compatibility. 44 | 45 | -- ProGroups 1.2.1 - 46 | 47 | # Bug Fixes 48 | 49 | - Fix issue where deleting an object belonging to a group would lead to null-ref errors. 50 | - Enable objects to belong to more than one group simultaneously. 51 | 52 | -- ProGroups 1.2.0 - 53 | 54 | # Features 55 | 56 | - Show a highlight behind groups that contain a selected gameobject. 57 | - Enable clicking anywhere on a group entry to select all contained objects. 58 | - Add "Move Down" button when sorting groups. 59 | - Add ability to drag and drop Hierarchy objects into groups, and create new groups by dragging anywhere onto the window. 60 | - Show a tooltip when hovering a group name with a list of objects it contains. 61 | - Add ability to double-click a group name to edit it's text. 62 | - Add context-click menu to switch between a dockable and floating window. 63 | - Use name of first selected object when creating new groups instead of always defaulting to "New Group." 64 | 65 | # Bug Fixes 66 | - Fix issue in Unity 5 where groups would be erased on entering playmode. 67 | - Wrap code in ProGroups namespace to avoid conflicts. 68 | - Remove circular references to EditorWindow. 69 | - Add Undo support for creating, deleting, and modifying groups. 70 | - Fix inconsistent formatting on text and button fields. 71 | - Prompt user to remove or ignore objects when creating new groups from objects already belonging to a group. 72 | - Remove null or empty groups automatically. 73 | 74 | -- ProGroups 1.1.2 - 75 | 76 | # Bug Fixes 77 | 78 | - Fix crash when docking ProGroups window in Unity 5. 79 | 80 | 81 | -- ProGroups 1.1.1 - 82 | 83 | # Bug Fixes 84 | 85 | - Fix namespace conflicts with Bundle packages in Unity 5. 86 | - Fix deprecated API warnings in Unity 5. 87 | -------------------------------------------------------------------------------- /About/changelog.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7c187b1e6be88f4e93d404408bdcf9b 3 | -------------------------------------------------------------------------------- /About/pc_AboutEntry_ProGroups.txt: -------------------------------------------------------------------------------- 1 | name: ProGroups 2 | identifier: ProGroups_AboutWindowIdentifier 3 | version: 1.2.7f1 4 | date: 04-03-2017 5 | changelog: Assets/ProCore/ProGroups/About/changelog.txt 6 | -------------------------------------------------------------------------------- /About/pc_AboutEntry_ProGroups.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 98b37287d64c39a4c92d05df6ade3819 3 | -------------------------------------------------------------------------------- /GUI.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 713f4b655174e47458c92a3c4a398e11 3 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Add.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Add.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 662dac47ffa9567408c5e0840640f1b8 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Delete.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Delete.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a8d0f575c528b0343b7f22dd6bf70dfc 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Drag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Drag.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Drag.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 73f819efafcc0b84fa6f513ca5fc3b19 3 | timeCreated: 1428588244 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: .25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 8 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: -1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | spriteMode: 0 41 | spriteExtrude: 1 42 | spriteMeshType: 1 43 | alignment: 0 44 | spritePivot: {x: .5, y: .5} 45 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 46 | spritePixelsToUnits: 100 47 | alphaIsTransparency: 0 48 | textureType: -1 49 | buildTargetSettings: [] 50 | spriteSheet: 51 | sprites: [] 52 | spritePackingTag: 53 | userData: 54 | assetBundleName: 55 | assetBundleVariant: 56 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Eye.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Eye.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 907430644fbb62d4d85844426a625877 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Gear.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Gear.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0794634d871dcc74f9ed9f336d608d58 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_MoveUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_MoveUp.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_MoveUp.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f2e9401b42920634ea696f4cfffd5114 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_MultiPlus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_MultiPlus.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_MultiPlus.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3bb8d59b5f8ffbb4aba26f8ee88babcf 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Rect.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Rect.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4c92531e415e98940a65cd2c10e4693e 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_Select.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_Select.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7d542293fe4d33438661815a7a1885c 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 1 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: -1 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: -1 29 | nPOTScale: 1 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: -1 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_SnowFlake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_SnowFlake.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_SnowFlake.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e37b38c9a7dd444792de34040f969e3 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 0 8 | linearTexture: 1 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: 4 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: 1 27 | mipBias: -1 28 | wrapMode: 1 29 | nPOTScale: 0 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: 5 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_UpdateGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/GUI/ProGroupsIcons_UpdateGroup.png -------------------------------------------------------------------------------- /GUI/ProGroupsIcons_UpdateGroup.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 32e796ff088171d4aa7b5908f1338757 3 | TextureImporter: 4 | serializedVersion: 2 5 | mipmaps: 6 | mipMapMode: 0 7 | enableMipMap: 1 8 | linearTexture: 0 9 | correctGamma: 0 10 | fadeOut: 0 11 | borderMipMap: 0 12 | mipMapFadeDistanceStart: 1 13 | mipMapFadeDistanceEnd: 3 14 | bumpmap: 15 | convertToNormalMap: 0 16 | externalNormalMap: 0 17 | heightScale: .25 18 | normalMapFilter: 0 19 | isReadable: 0 20 | grayScaleToAlpha: 0 21 | generateCubemap: 0 22 | textureFormat: -1 23 | maxTextureSize: 1024 24 | textureSettings: 25 | filterMode: -1 26 | aniso: -1 27 | mipBias: -1 28 | wrapMode: -1 29 | nPOTScale: 1 30 | lightmap: 0 31 | compressionQuality: 50 32 | textureType: -1 33 | buildTargetSettings: [] 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unity Companion License (“License”) 2 | Software Copyright © 2017 Unity Technologies ApS 3 | 4 | Unity Technologies ApS (“Unity”) grants to you a worldwide, non-exclusive, 5 | no-charge, and royalty-free copyright license to reproduce, prepare derivative 6 | works of, publicly display, publicly perform, sublicense, and distribute the 7 | software that is made available under this License (“Software”), subject to the 8 | following terms and conditions: 9 | 10 | 1. Unity Companion Use Only. Exercise of the license granted herein is limited 11 | to exercise for the creation, use, and/or distribution of applications, 12 | software, or other content pursuant to a valid Unity content authoring and 13 | rendering engine software license (“Engine License”). That means while use of 14 | the Software is not limited to use in the software licensed under the Engine 15 | License, the Software may not be used for any purpose other than the creation, 16 | use, and/or distribution of Engine License-dependent applications, software, or 17 | other content. No other exercise of the license granted herein is permitted, 18 | and in no event may the Software be used for competitive analysis or to develop 19 | a competing product or service. 20 | 21 | 2. No Modification of Engine License. Neither this License nor any exercise of 22 | the license granted herein modifies the Engine License in any way. 23 | 24 | 3. Ownership & Grant Back to You. 25 | 26 | 3.1 You own your content. In this License, “derivative works” means derivatives 27 | of the Software itself--works derived only from the Software by you under this 28 | License (for example, modifying the code of the Software itself to improve its 29 | efficacy); “derivative works” of the Software do not include, for example, 30 | games, apps, or content that you create using the Software. You keep all right, 31 | title, and interest to your own content. 32 | 33 | 3.2 Unity owns its content. While you keep all right, title, and interest to 34 | your own content per the above, as between Unity and you, Unity will own all 35 | right, title, and interest to all intellectual property rights (including 36 | patent, trademark, and copyright) in the Software and derivative works of the 37 | Software, and you hereby assign and agree to assign all such rights in those 38 | derivative works to Unity. 39 | 40 | 3.3 You have a license to those derivative works. Subject to this License, 41 | Unity grants to you the same worldwide, non-exclusive, no-charge, and 42 | royalty-free copyright license to derivative works of the Software you create 43 | as is granted to you for the Software under this License. 44 | 45 | 4. Trademarks. You are not granted any right or license under this License to 46 | use any trademarks, service marks, trade names, products names, or branding of 47 | Unity or its affiliates (“Trademarks”). Descriptive uses of Trademarks are 48 | permitted; see, for example, Unity’s Branding Usage Guidelines at 49 | https://unity3d.com/public-relations/brand. 50 | 51 | 5. Notices & Third-Party Rights. This License, including the copyright notice 52 | associated with the Software, must be provided in all substantial portions of 53 | the Software and derivative works thereof (or, if that is impracticable, in any 54 | other location where such notices are customarily placed). Further, if the 55 | Software is accompanied by a Unity “third-party notices” or similar file, you 56 | acknowledge and agree that software identified in that file is governed by 57 | those separate license terms. 58 | 59 | 6. DISCLAIMER, LIMITATION OF LIABILITY. THE SOFTWARE AND ANY DERIVATIVE WORKS 60 | THEREOF IS PROVIDED ON AN "AS IS" BASIS, AND IS PROVIDED WITHOUT WARRANTY OF 61 | ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY WARRANTIES OF 62 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT. IN 63 | NO EVENT SHALL ANY COPYRIGHT HOLDER OR AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES 64 | (WHETHER DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL, 65 | INCLUDING PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR 66 | PROFITS, AND BUSINESS INTERRUPTION), OR OTHER LIABILITY WHATSOEVER, WHETHER IN 67 | AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM OR OUT OF, OR IN 68 | CONNECTION WITH, THE SOFTWARE OR ANY DERIVATIVE WORKS THEREOF OR THE USE OF OR 69 | OTHER DEALINGS IN SAME, EVEN WHERE ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 70 | 71 | 7. USE IS ACCEPTANCE and License Versions. Your receipt and use of the Software 72 | constitutes your acceptance of this License and its terms and conditions. 73 | Software released by Unity under this License may be modified or updated and 74 | the License with it; upon any such modification or update, you will comply with 75 | the terms of the updated License for any use of any of the Software under the 76 | updated License. 77 | 78 | 8. Use in Compliance with Law and Termination. Your exercise of the license 79 | granted herein will at all times be in compliance with applicable law and will 80 | not infringe any proprietary rights (including intellectual property rights); 81 | this License will terminate immediately on any breach by you of this License. 82 | 83 | 9. Severability. If any provision of this License is held to be unenforceable 84 | or invalid, that provision will be enforced to the maximum extent possible and 85 | the other provisions will remain in full force and effect. 86 | 87 | 10. Governing Law and Venue. This License is governed by and construed in 88 | accordance with the laws of Denmark, except for its conflict of laws rules; the 89 | United Nations Convention on Contracts for the International Sale of Goods will 90 | not apply. If you reside (or your principal place of business is) within the 91 | United States, you and Unity agree to submit to the personal and exclusive 92 | jurisdiction of and venue in the state and federal courts located in San 93 | Francisco County, California concerning any dispute arising out of this License 94 | (“Dispute”). If you reside (or your principal place of business is) outside the 95 | United States, you and Unity agree to submit to the personal and exclusive 96 | jurisdiction of and venue in the courts located in Copenhagen, Denmark 97 | concerning any Dispute. 98 | -------------------------------------------------------------------------------- /ProGroups_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Unity-Technologies/progroups/5d2ce7eb6fc26cf4baa1f79b39b7a6d02f736705/ProGroups_Manual.pdf -------------------------------------------------------------------------------- /ProGroups_Manual.pdf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6e4bf934a9cd9c9478a614091c898825 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ** IMPORTANT ** 2 | 3 | ProGroups is deprecated and no longer under development- use at your own risk! These files are made available as-is with zero guarantees or promises of support. 4 | 5 | In time, we (World Building team) do hope to re-create similar functionality in Unity, scene organization is important to us! 6 | 7 | --- 8 | 9 | # Overview 10 | 11 | ProGroups allows you to organize objects in your scene into “selection sets”, **without modifying the objects or hierarchy**. Then, use the interface to **hide, freeze, and select** entire groups at once. 12 | 13 | These features help keep your large, complex scenes nicely organized and easy to work with. 14 | 15 | # Installation and Setup 16 | 17 | 1. Open Unity 18 | 1. Download ProGroups (Click the green "Clone or Download" button or use this [Direct Link](https://github.com/Unity-Technologies/progroups/archive/master.zip)) 19 | 1. Unzip and place the ProGroups files into Assets folder of your Unity project 20 | 21 | **Or, via command line:** 22 | ``` 23 | cd YourProject/Assets 24 | git clone https://github.com/Unity-Technologies/progroups.git ProGroups 25 | ``` 26 | 27 | # Getting Started with ProGroups 28 | 29 | ProGroups works differently than simple hierarchy organization. ProGroups does not alter or modify your objects or hierarchy in any way. This allows you to have any object in multiple Groups, and to keep your hierarchy clean and efficient. 30 | 31 | 1. From the top menu, choose `Tools > ProGroups > ProGroups Window` 32 | 1. The ProGroups window will now appear as a dock-able panel. You can change this by right clicking (Option Click on Mac) anywhere in the ProGroups window and selecting the Window menu. 33 | 1. The ProGroups window has two modes: **Normal** and **Modify**. Normal mode is where you will typically stay. You can create new groups, view and edit group names, toggle visibility and frozen status, and select all objects in each group. 34 | 1. Modify mode lets you change group names, remove groups, and re-order your groups. 35 | 36 | # The ProGroups GUI 37 | 38 | ## Normal Mode 39 | 40 | ![normal mode](http://www.procore3d.com/docs/progroups/progroups_MainPanel.jpg) 41 | 42 | 1. Before creating a new group, you can specify a group name here. 43 | 1. Click the plus icon to create a new group from the current selection. 44 | 1. Click the gear icon to modify the order or delete groups. 45 | 1. Click the pointer icon to select all items in this group. 46 | 1. Click the eye icon to hide or show objects in this group. Hold `Alt` to hide all other groups (isolate). 47 | 1. Click the snowflake icon to freeze or un-freeze the current selection. 48 | - Freezing a group means that the objects may not be edited in any way. 49 | 1. Toggle the drop-down of child items in this group. 50 | 1. The group name. Double-click to edit this value, or single click to select objects in this group. The number of items currently in this group will be displayed to the far right. 51 | 52 | When in **Normal** mode, you may drag objects from the Hierarchy window to create new groups. Dragging objects over existing group entries will add those objects to that group. Dragging objects into an empty space of the window will create a new group. 53 | 54 | As you're working ProGroups will highlight groups that contain objects that are in your current selection. 55 | 56 | ## Modify Mode 57 | 58 | ![modify mode](http://www.procore3d.com/docs/progroups/progroups_ModifyPanel.jpg) 59 | 60 | **Modify** mode makes it easy to edit many groups simultaneously. 61 | 62 | 1. Exit Modify mode 63 | 1. Move the group up one level in the list. 64 | 1. Move the group down one in the list. 65 | 1. Remove the Group 66 | - All objects will be un-hidden and un-frozen. 67 | - No objects will be deleted! 68 | 1. Text field for renaming the Group 69 | 70 | --- 71 | 72 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a2790c10eedbb864fa2212e382259133 3 | -------------------------------------------------------------------------------- /Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7d0d369b924ef8b4ab7efd9a075bbc5b 3 | -------------------------------------------------------------------------------- /Scripts/Editor/ProGroups_About.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | 5 | /** 6 | * JS compiled in Editor pass doesn't know about CS compiled in Editor pass. 7 | */ 8 | public class ProGroups_About : Editor 9 | { 10 | [MenuItem("Tools/ProGroups/About", false, 0)] 11 | public static void MenuAbout () 12 | { 13 | groups_AboutWindow.Init("Assets/ProCore/ProGroups/About/pc_AboutEntry_ProGroups.txt", true); 14 | } 15 | } -------------------------------------------------------------------------------- /Scripts/Editor/ProGroups_About.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6a672a5247d53914eb7b2dc993c54b1d 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | -------------------------------------------------------------------------------- /Scripts/Editor/ProGroups_Window.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.IO; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace ProGroups 9 | { 10 | 11 | /** 12 | * Editor interface for ProGroups. 13 | */ 14 | public class ProGroups_Window : EditorWindow 15 | { 16 | #region Class Variables 17 | 18 | const string GROUPS_GAMEOBJECT_NAME = "Progroups2_Groups_Container_Object"; 19 | 20 | static readonly Color EVEN_ROW_COLOR = new Color(.1f, .1f, .1f, .2f); 21 | static readonly Color ODD_ROW_COLOR = new Color(.35f, .35f, .35f, .2f); 22 | 23 | // A reference to the scene's current groupContainer component. 24 | static GroupContainer _groupContainer; 25 | 26 | private Group nextRepaintSetGroup = null; 27 | private Dictionary groupExpandos = new Dictionary(); 28 | 29 | static GUIStyle _backgroundColorStyle = null; 30 | 31 | public static GUIStyle backgroundColorStyle 32 | { 33 | get 34 | { 35 | if(_backgroundColorStyle == null) 36 | { 37 | _backgroundColorStyle = new GUIStyle(); 38 | _backgroundColorStyle.margin = new RectOffset(4,4,4,4); 39 | _backgroundColorStyle.padding = new RectOffset(4,4,4,4); 40 | _backgroundColorStyle.normal.background = EditorGUIUtility.whiteTexture; 41 | } 42 | 43 | return _backgroundColorStyle; 44 | } 45 | } 46 | 47 | static GroupContainer groupContainer 48 | { 49 | get 50 | { 51 | if(_groupContainer == null) 52 | { 53 | GameObject go = GameObject.Find(GROUPS_GAMEOBJECT_NAME); 54 | 55 | if(go == null) 56 | { 57 | go = new GameObject(); 58 | go.name = GROUPS_GAMEOBJECT_NAME; 59 | go.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; 60 | _groupContainer = go.AddComponent(); 61 | } 62 | else 63 | { 64 | _groupContainer = go.GetComponent(); 65 | } 66 | } 67 | 68 | return _groupContainer; 69 | } 70 | 71 | set 72 | { 73 | _groupContainer = value; 74 | } 75 | } 76 | 77 | // Indices of groups that contains items in the current selection 78 | List selectedGroupIndices = new List(); 79 | 80 | // Path to the icons used in the editor. 81 | string guiPath = "Assets/ProCore/ProGroups/GUI/"; 82 | 83 | // Default name for new groups. 84 | public static string newGroupName = "New Group"; 85 | 86 | // Icons 87 | Texture2D icon_Rect, 88 | icon_SnowFlake, 89 | icon_Eye, 90 | icon_Select, 91 | // icon_UpdateGroup, 92 | icon_MoveUp, 93 | icon_Delete, 94 | icon_Gear, 95 | icon_Add, 96 | icon_freeze, 97 | icon_vis, 98 | icon_Drag; 99 | // icon_MultiPlus; 100 | 101 | // Scrollbar position. 102 | Vector2 scrollPos; 103 | 104 | // If the editor is in 'modification' mode - meaning editing the group position / deleting / renaming groups. 105 | bool modMode = false; 106 | readonly Color LightGray = new Color(1f, 1f, 1f, .2f); 107 | 108 | static ProGroups_Window instance; 109 | #endregion 110 | 111 | #region Menu 112 | 113 | [MenuItem("Tools/ProGroups/ProGroups Window")] 114 | static void MenuInitProGroupsWindow() 115 | { 116 | bool floating = EditorPrefs.HasKey("groups_floatingWindow") ? EditorPrefs.GetBool("groups_floatingWindow") : false; 117 | EditorWindow.GetWindow(floating, "ProGroups", false); 118 | } 119 | 120 | [MenuItem("Tools/ProGroups/New Group From Selection %g")] 121 | static void NewGroupFromSelection() 122 | { 123 | ProGroups_Window.NewGroupWithObjects( Selection.gameObjects, Selection.gameObjects.Length > 0 ? Selection.gameObjects[0].name : "New Group" ); 124 | 125 | if(ProGroups_Window.instance != null) 126 | { 127 | ProGroups_Window.instance.Repaint(); 128 | ProGroups_Window.instance.OnSelectionChange(); 129 | } 130 | } 131 | 132 | [MenuItem("Tools/ProGroups/Clear All Groups in Scene")] 133 | static void ClearAll() 134 | { 135 | GameObject go = GameObject.Find(GROUPS_GAMEOBJECT_NAME); 136 | int count = 0; 137 | 138 | if( !EditorUtility.DisplayDialog("Remove All Groups", "This will remove all groups in this scene. It is not undo-able. Continue?", "Yes", "No") ) 139 | return; 140 | 141 | while(go != null) 142 | { 143 | count ++; 144 | GameObject.DestroyImmediate(go); 145 | go = GameObject.Find(GROUPS_GAMEOBJECT_NAME); 146 | } 147 | 148 | SceneView.lastActiveSceneView.ShowNotification(new GUIContent("Removed " + count + " Group Container" + (count == 1 ? "" : "s"), "")); 149 | } 150 | 151 | void OpenContextMenu() 152 | { 153 | GenericMenu menu = new GenericMenu(); 154 | 155 | menu.AddItem (new GUIContent("Window/Open as Floating Window", ""), EditorPrefs.GetBool("groups_floatingWindow", false), ContextMenu_OpenFloatingWindow); 156 | menu.AddItem (new GUIContent("Window/Open as Dockable Window", ""), !EditorPrefs.GetBool("groups_floatingWindow", false), ContextMenu_OpenDockableWindow); 157 | 158 | menu.AddSeparator(""); 159 | 160 | menu.AddItem( new GUIContent("Collapse Selected Groups"), false, () => 161 | { 162 | instance.CollapseSelectedGroups(); 163 | }); 164 | 165 | menu.ShowAsContext(); 166 | } 167 | 168 | void CollapseSelectedGroups() 169 | { 170 | if(selectedGroupIndices.Count < 1) 171 | return; 172 | 173 | IEnumerable selectedGroups = groupContainer.sceneGroups.Where((x,i) => selectedGroupIndices.Contains(i)); 174 | GameObject[] all = selectedGroups.SelectMany(x => x.objects).ToArray(); 175 | groupContainer.RemoveGroups(selectedGroupIndices); 176 | NewGroupWithObjects(all, string.Join("+", selectedGroups.Select(x => x.name).ToArray())); 177 | } 178 | 179 | static void ContextMenu_OpenFloatingWindow() 180 | { 181 | EditorPrefs.SetBool("groups_floatingWindow", true); 182 | 183 | EditorWindow.GetWindow().Close(); 184 | EditorWindow.GetWindow(true, "ProGroups", true); 185 | } 186 | 187 | static void ContextMenu_OpenDockableWindow() 188 | { 189 | EditorPrefs.SetBool("groups_floatingWindow", false); 190 | 191 | EditorWindow.GetWindow().Close(); 192 | EditorWindow.GetWindow(false, "ProGroups", true); 193 | } 194 | #endregion 195 | 196 | #region Initialization 197 | 198 | /** 199 | * Find a directory in the Assets folder by searching for a partial path. 200 | */ 201 | static string FindFolder(string folder, bool exactMatch = false) 202 | { 203 | string single = folder.Replace("\\", "/").Substring(folder.LastIndexOf('/') + 1); 204 | 205 | string[] matches = Directory.GetDirectories("Assets/", single, SearchOption.AllDirectories); 206 | 207 | foreach(string str in matches) 208 | { 209 | string path = str.Replace("\\", "/"); 210 | 211 | if( path.Contains(folder) ) 212 | { 213 | if(exactMatch) 214 | { 215 | string found = path.Substring(str.LastIndexOf('/') + 1); 216 | 217 | if(!found.Equals(single)) 218 | continue; 219 | } 220 | 221 | if(!path.EndsWith("/")) 222 | path += "/"; 223 | 224 | return path; 225 | } 226 | } 227 | 228 | return null; 229 | } 230 | 231 | void OnEnable() 232 | { 233 | this.autoRepaintOnSceneChange = true; 234 | this.wantsMouseMove = true; 235 | instance = this; 236 | 237 | guiPath = FindFolder("ProGroups/GUI"); 238 | 239 | icon_Rect = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Rect.png", typeof(Texture2D)); 240 | icon_SnowFlake = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_SnowFlake.png", typeof(Texture2D)); 241 | icon_Eye = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Eye.png", typeof(Texture2D)); 242 | icon_Select = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Select.png", typeof(Texture2D)); 243 | // icon_UpdateGroup = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_UpdateGroup.png", typeof(Texture2D)); 244 | icon_MoveUp = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_MoveUp.png", typeof(Texture2D)); 245 | icon_Delete = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Delete.png", typeof(Texture2D)); 246 | icon_Gear = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Gear.png", typeof(Texture2D)); 247 | icon_Drag = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Drag.png", typeof(Texture2D)); 248 | icon_Add = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_Add.png", typeof(Texture2D)); 249 | // icon_MultiPlus = (Texture2D) AssetDatabase.LoadAssetAtPath(guiPath + "ProGroupsIcons_MultiPlus.png", typeof(Texture2D)); 250 | } 251 | #endregion 252 | 253 | /** 254 | * On a selection change, update the currently selected display. 255 | */ 256 | public void OnSelectionChange() 257 | { 258 | selectedGroupIndices.Clear(); 259 | 260 | for(int i = 0; i < groupContainer.sceneGroups.Length; i++) 261 | { 262 | if( groupContainer.sceneGroups[i].objects.Intersect(Selection.gameObjects).Any() ) 263 | selectedGroupIndices.Add(i); 264 | } 265 | 266 | Repaint(); 267 | } 268 | 269 | void OnLostFocus() 270 | { 271 | editingTitle = -1; 272 | } 273 | 274 | private int dragIndex = -1; 275 | private int editingTitle = -1; 276 | private bool wantsRepaint = false; 277 | private bool guiInitialied = false; 278 | private bool dragInProgress = false; 279 | private bool dragImageReady = false; 280 | private GUIStyle iconButtonStyle, labelStyle, textFieldStyle; 281 | private GUIContent groupTooltip = new GUIContent(); 282 | 283 | void OnGUI() 284 | { 285 | Event curEvent = Event.current; 286 | 287 | if(curEvent.type == EventType.ContextClick) 288 | OpenContextMenu(); 289 | 290 | if(!guiInitialied) 291 | { 292 | iconButtonStyle = new GUIStyle(GUI.skin.button); 293 | iconButtonStyle.stretchWidth = false; 294 | iconButtonStyle.margin = new RectOffset(2,2,2,2); 295 | iconButtonStyle.padding.left = 2; 296 | iconButtonStyle.padding.right = 2; 297 | iconButtonStyle.normal.background = null; 298 | iconButtonStyle.hover.background = null; 299 | iconButtonStyle.active.background = null; 300 | iconButtonStyle.focused.background = null; 301 | iconButtonStyle.onNormal.background = null; 302 | iconButtonStyle.onHover.background = null; 303 | iconButtonStyle.onActive.background = null; 304 | iconButtonStyle.onFocused.background = null; 305 | 306 | labelStyle = new GUIStyle(GUI.skin.label); 307 | labelStyle.padding.top = 3; 308 | guiInitialied = true; 309 | 310 | textFieldStyle = new GUIStyle(EditorStyles.textField); 311 | textFieldStyle.margin.top = 4; 312 | textFieldStyle.padding.top = 1; 313 | } 314 | 315 | GUILayout.Label(modMode ? "Edit Groups" : "Create New", EditorStyles.boldLabel); 316 | 317 | EditorGUILayout.BeginHorizontal(); 318 | 319 | if(!modMode) 320 | { 321 | newGroupName = EditorGUI.TextField(new Rect(3, 27, this.position.width-50, 17), newGroupName); 322 | 323 | GUILayout.FlexibleSpace(); 324 | 325 | if(newGroupName == "") 326 | newGroupName = "New Group"; 327 | 328 | if(GUILayout.Button(new GUIContent(icon_Add, "Create New Group from Selected Objects"), iconButtonStyle)) 329 | { 330 | GUIUtility.keyboardControl = 0; 331 | 332 | NewGroupWithObjects( Selection.gameObjects, newGroupName ); 333 | } 334 | 335 | if(GUILayout.Button (new GUIContent(icon_Gear, "Modify Groups"), iconButtonStyle)) 336 | { 337 | modMode = true; 338 | } 339 | 340 | } 341 | else 342 | { 343 | if(GUILayout.Button("Done")) 344 | { 345 | modMode = false; 346 | } 347 | } 348 | 349 | EditorGUILayout.EndHorizontal(); 350 | 351 | GUILayout.Label("Groups", EditorStyles.boldLabel); 352 | 353 | groupContainer.Clean(); 354 | 355 | GameObject[] dragItems; 356 | bool dragging = ListenForDragAndDrop(curEvent, out dragItems); 357 | 358 | if(dragging && !dragInProgress) 359 | dragInProgress = true; 360 | 361 | if(groupContainer.sceneGroups != null) 362 | { 363 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos); 364 | EditorGUILayout.BeginVertical(); 365 | 366 | for(int i = 0; i < groupContainer.sceneGroups.Length; i++) 367 | { 368 | Group group = groupContainer.sceneGroups[i]; 369 | 370 | if(group.frozen) 371 | icon_freeze = icon_SnowFlake; 372 | else 373 | icon_freeze = icon_Rect; 374 | 375 | if(group.hidden) 376 | icon_vis = icon_Rect; 377 | else 378 | icon_vis = icon_Eye; 379 | 380 | Rect r = i > 0 ? GUILayoutUtility.GetLastRect() : new Rect(2, 0, 0, 0); 381 | Rect rowRect = new Rect(r.x, r.y + r.height + 2, this.position.width-8, 32); 382 | bool doExpandGroups = false; 383 | 384 | GUI.backgroundColor = i % 2 == 0 ? EVEN_ROW_COLOR : ODD_ROW_COLOR; 385 | GUILayout.BeginVertical(backgroundColorStyle); 386 | GUI.backgroundColor = Color.white; 387 | 388 | GUILayout.BeginHorizontal(); 389 | 390 | if(modMode) 391 | { 392 | //move up 393 | GUI.enabled = i != 0; 394 | if(GUILayout.Button(new GUIContent(icon_MoveUp, "Move Group Up"), iconButtonStyle)) 395 | { 396 | GUIUtility.keyboardControl = 0; 397 | groupContainer.MoveGroupUp(i); 398 | Repaint(); 399 | } 400 | 401 | // would it have been easier to just create another icon? probably. would it have 402 | // been as much fun? probably not. 403 | Rect mbr = GUILayoutUtility.GetLastRect(); 404 | Vector2 pivot = new Vector2(mbr.x + mbr.width + mbr.width/2f + 2, mbr.y + mbr.height/2f - 1); 405 | GUIUtility.RotateAroundPivot(180f, pivot); 406 | GUI.enabled = i != groupContainer.sceneGroups.Length-1; 407 | if(GUILayout.Button(new GUIContent(icon_MoveUp, "Move Group Down"), iconButtonStyle)) 408 | { 409 | GUIUtility.keyboardControl = 0; 410 | groupContainer.MoveGroupDown(i); 411 | Repaint(); 412 | } 413 | GUIUtility.RotateAroundPivot(-180f, pivot); 414 | GUI.enabled = true; 415 | 416 | //delete 417 | if(GUILayout.Button(new GUIContent(icon_Delete, "Remove Group (does not delete objects)"), iconButtonStyle)) 418 | { 419 | if(EditorUtility.DisplayDialog("Remove This Group?", "All objects from the group will become visible and un-frozen. No objects will be deleted.", "Confirm","Cancel")) 420 | { 421 | GUIUtility.keyboardControl = 0; 422 | Undo.RecordObject(groupContainer, "Remove Group"); 423 | groupContainer.RemoveGroup(i); 424 | Repaint(); 425 | } 426 | } 427 | 428 | // //add selected to group 429 | // if(GUILayout.Button(new GUIContent(icon_MultiPlus, "Add Selected Objects to this Group"), iconButtonStyle)) 430 | // { 431 | // GUIUtility.keyboardControl = 0; 432 | // AddToGroup(Selection.gameObjects, group); 433 | // Repaint(); 434 | // } 435 | 436 | // //update 437 | // if(GUILayout.Button(new GUIContent(icon_UpdateGroup, "Rebuild Group from Selection"), iconButtonStyle)) 438 | // { 439 | // if(EditorUtility.DisplayDialog("Replace Objects in the Group With Selected Objects", "Note: all objects from the old group will become visible and un-frozen.", "Confirm", "Cancel")) 440 | // { 441 | // GUIUtility.keyboardControl = 0; 442 | 443 | // groupContainer.UpdateGroup(group, Selection.gameObjects); 444 | 445 | // Repaint(); 446 | // } 447 | // } 448 | 449 | //group name 450 | group.name = EditorGUILayout.TextField(group.name); 451 | } 452 | else 453 | { 454 | if( selectedGroupIndices.Contains(i) || dragIndex == i ) 455 | { 456 | GUI.backgroundColor = i == dragIndex ? Color.green : Color.white; 457 | GUI.Box(rowRect, ""); 458 | GUI.backgroundColor = Color.white; 459 | } 460 | 461 | if(!groupExpandos.TryGetValue(group, out doExpandGroups)) 462 | groupExpandos.Add(group, doExpandGroups); 463 | 464 | EditorGUI.BeginChangeCheck(); 465 | 466 | doExpandGroups = EditorGUILayout.Toggle(doExpandGroups, EditorStyles.foldout, GUILayout.MaxWidth(14)); 467 | 468 | if(EditorGUI.EndChangeCheck()) 469 | groupExpandos[group] = doExpandGroups; 470 | 471 | //select 472 | if(GUILayout.Button(new GUIContent(icon_Select, "Select Group Objects"), iconButtonStyle)) 473 | { 474 | GUIUtility.keyboardControl = 0; 475 | nextRepaintSetGroup = group; 476 | } 477 | 478 | //vis toggle 479 | if(GUILayout.Button(icon_vis, iconButtonStyle)) 480 | { 481 | if(Event.current.alt) 482 | { 483 | groupContainer.Isolate(i); 484 | } 485 | else 486 | { 487 | groupContainer.ToggleVis(group); 488 | } 489 | 490 | GUIUtility.keyboardControl = 0; 491 | } 492 | 493 | //freeze toggle 494 | if(GUILayout.Button(icon_freeze, iconButtonStyle)) 495 | { 496 | GUIUtility.keyboardControl = 0; 497 | groupContainer.ToggleFreeze(group); 498 | SceneView.RepaintAll(); 499 | } 500 | 501 | //group name 502 | if( editingTitle == i ) 503 | { 504 | group.name = EditorGUILayout.TextField(group.name, textFieldStyle); 505 | } 506 | else 507 | { 508 | groupTooltip.text = group.name; 509 | groupTooltip.tooltip = ConcatString(group.objects); 510 | GUILayout.Label(groupTooltip, labelStyle); 511 | } 512 | 513 | GUILayout.FlexibleSpace(); 514 | 515 | Color c = GUI.color; 516 | GUI.color = EditorGUIUtility.isProSkin ? Color.gray : LightGray; 517 | GUILayout.Label(string.Format("({0})", group.objects.Length),labelStyle); 518 | GUI.color = c; 519 | } 520 | 521 | EditorGUILayout.EndHorizontal(); 522 | 523 | if( !modMode && doExpandGroups && group.objects.Length > 0 ) 524 | { 525 | GUILayout.BeginVertical(); 526 | 527 | GUILayout.Label("Objects in Group", EditorStyles.boldLabel); 528 | 529 | foreach(GameObject go in group.objects) 530 | { 531 | GUILayout.BeginHorizontal(); 532 | if(GUILayout.Button(icon_Delete, iconButtonStyle)) 533 | { 534 | Undo.RecordObject(groupContainer, "Remove from Group"); 535 | group.RemoveObject(go); 536 | break; 537 | } 538 | 539 | GUILayout.Label(go.name); 540 | 541 | if(curEvent.type == EventType.MouseDown && GUILayoutUtility.GetLastRect().Contains(curEvent.mousePosition)) 542 | { 543 | Selection.objects = new UnityEngine.Object[] { go }; 544 | curEvent.Use(); 545 | } 546 | 547 | GUILayout.EndHorizontal(); 548 | } 549 | 550 | GUILayout.EndVertical(); 551 | } 552 | 553 | GUILayout.EndVertical(); 554 | 555 | Rect groupRect = GUILayoutUtility.GetLastRect(); 556 | 557 | // GUILayoutUtility.GetLastRect() 558 | if( groupRect.Contains(curEvent.mousePosition) ) 559 | { 560 | if(dragging) 561 | { 562 | dragIndex = i; 563 | wantsRepaint = true; 564 | } 565 | 566 | switch(curEvent.type) 567 | { 568 | case EventType.DragPerform: 569 | if(dragging) 570 | { 571 | AddToGroup(dragItems, group); 572 | curEvent.Use(); 573 | dragIndex = -1; 574 | dragInProgress = false; 575 | dragImageReady = false; 576 | } 577 | break; 578 | 579 | case EventType.MouseDown: 580 | 581 | nextRepaintSetGroup = group; 582 | 583 | editingTitle = -1; 584 | 585 | if( curEvent.clickCount > 1 ) 586 | { 587 | editingTitle = i; 588 | curEvent.Use(); 589 | } 590 | break; 591 | } 592 | } 593 | } 594 | 595 | EditorGUILayout.EndVertical(); 596 | EditorGUILayout.EndScrollView(); 597 | } 598 | 599 | if(dragInProgress) 600 | { 601 | if(!dragImageReady && curEvent.type == EventType.Layout) 602 | dragImageReady = true; 603 | 604 | if(dragImageReady) 605 | { 606 | GUILayout.FlexibleSpace(); 607 | GUILayout.BeginHorizontal(); 608 | GUILayout.FlexibleSpace(); 609 | GUILayout.Label(icon_Drag); 610 | GUILayout.FlexibleSpace(); 611 | GUILayout.EndHorizontal(); 612 | GUILayout.FlexibleSpace(); 613 | } 614 | } 615 | else if(groupContainer.sceneGroups == null || groupContainer.sceneGroups.Length < 1) 616 | { 617 | GUILayout.FlexibleSpace(); 618 | GUILayout.BeginHorizontal(); 619 | GUILayout.FlexibleSpace(); 620 | GUILayout.Label("Drag GameObjects Here!", EditorStyles.largeLabel); 621 | GUILayout.FlexibleSpace(); 622 | GUILayout.EndHorizontal(); 623 | GUILayout.FlexibleSpace(); 624 | } 625 | 626 | // if( curEvent.type != EventType.Repaint && 627 | // curEvent.type != EventType.Layout && 628 | // curEvent.type != EventType.MouseMove ) 629 | // Debug.Log(curEvent.type + " " + curEvent.clickCount); 630 | 631 | if( curEvent.type == EventType.MouseDown || 632 | (curEvent.type == EventType.KeyDown && 633 | (curEvent.keyCode == KeyCode.Return || 634 | curEvent.keyCode == KeyCode.KeypadEnter || 635 | curEvent.keyCode == KeyCode.Clear || 636 | curEvent.keyCode == KeyCode.Escape || 637 | curEvent.keyCode == KeyCode.Tab) 638 | ) 639 | ) 640 | { 641 | editingTitle = -1; 642 | wantsRepaint = true; 643 | } 644 | 645 | if( curEvent.type == EventType.Ignore || 646 | curEvent.type == EventType.DragPerform || 647 | curEvent.type == EventType.DragExited || 648 | curEvent.type == EventType.Repaint) 649 | { 650 | // Dragged into the void. Create a new group. 651 | if( dragIndex < 0 && curEvent.type == EventType.DragPerform ) 652 | { 653 | NewGroupWithObjects( dragItems, dragItems[0].name ); 654 | wantsRepaint = true; 655 | } 656 | 657 | if(curEvent.type != EventType.Repaint) 658 | { 659 | dragInProgress = false; 660 | dragImageReady = false; 661 | } 662 | 663 | if(curEvent.type != EventType.Repaint) 664 | dragIndex = -1; 665 | } 666 | 667 | if( nextRepaintSetGroup != null && curEvent.type == EventType.Repaint ) 668 | SelectGroup(nextRepaintSetGroup); 669 | 670 | if(wantsRepaint) 671 | Repaint(); 672 | } 673 | 674 | string ConcatString(GameObject[] array) 675 | { 676 | System.Text.StringBuilder sb = new System.Text.StringBuilder(); 677 | 678 | for(int i = 0; i < array.Length - 1; i++) 679 | { 680 | if(array[i] != null) 681 | sb.AppendLine(array[i].name); 682 | } 683 | 684 | if(array.Length > 0 && array[array.Length-1] != null) 685 | sb.Append( array[array.Length-1].name ); 686 | 687 | return sb.ToString(); 688 | } 689 | 690 | bool ListenForDragAndDrop(Event curEvent, out GameObject[] dragItems) 691 | { 692 | dragItems = null; 693 | 694 | if( (curEvent.type == EventType.DragUpdated || curEvent.type == EventType.DragPerform) && DragAndDrop.objectReferences.Length > 0) 695 | { 696 | dragItems = (GameObject[]) DragAndDrop.objectReferences.Where(x => x is GameObject).Cast().ToArray(); 697 | 698 | if(dragItems != null && dragItems.Length > 0) 699 | DragAndDrop.visualMode = DragAndDropVisualMode.Copy; 700 | } 701 | 702 | return dragItems != null && dragItems.Length > 0; 703 | } 704 | 705 | /** 706 | * Set Selection.gameObjects to match @InGroup gameObjects. 707 | */ 708 | void SelectGroup(Group InGroup) 709 | { 710 | nextRepaintSetGroup = null; 711 | Selection.objects = InGroup.objects; 712 | } 713 | 714 | /** 715 | * Create a new group with @InObjects and @name. 716 | */ 717 | public static void NewGroupWithObjects(GameObject[] InObjects, string name) 718 | { 719 | Undo.RecordObject(groupContainer, "New Group from Selection"); 720 | 721 | // Uncomment to restrict objects to a single group. 722 | // GameObject[] cleanObjects = DuplicateCheckObjects(InObjects); 723 | GameObject[] cleanObjects = InObjects; 724 | 725 | groupContainer.NewGroup(name, cleanObjects); 726 | 727 | // groupContainer.RemoveNullOrEmpty(); 728 | 729 | if( ProGroups_Window.instance != null ) 730 | ProGroups_Window.instance.OnSelectionChange(); 731 | } 732 | 733 | /** 734 | * Add @InObjectsToAdd to @InGroup, checking for existing entries 735 | * in other groups. 736 | */ 737 | void AddToGroup(GameObject[] InObjectsToAdd, Group InGroup) 738 | { 739 | Undo.RecordObject(groupContainer, "Add objects to group"); 740 | 741 | InGroup.AddObjects( InObjectsToAdd ); 742 | 743 | foreach(GameObject go in InObjectsToAdd) 744 | { 745 | if(InGroup.frozen) 746 | go.Freeze(); 747 | else 748 | go.Thaw(); 749 | 750 | if(InGroup.hidden) 751 | go.Hide(); 752 | else 753 | go.Show(); 754 | } 755 | 756 | // Uncomment to restrict objects to a single group. 757 | // InGroup.AddObjects( DuplicateCheckObjects(InObjectsToAdd, InGroup) ); 758 | // groupContainer.RemoveNullOrEmpty(); 759 | 760 | OnSelectionChange(); 761 | } 762 | 763 | /** 764 | * Checks for existing entries in the GroupContainer arrays, and prompts user 765 | * to either remove them from the existing group or removes them from the 766 | * current selection. 767 | * @GroupMask is an optional parameter that tells the duplicate check to ignore 768 | * that particular group. 769 | */ 770 | static GameObject[] DuplicateCheckObjects(GameObject[] InObjects) 771 | { 772 | return DuplicateCheckObjects(InObjects, null); 773 | } 774 | 775 | static GameObject[] DuplicateCheckObjects(GameObject[] InObjects, Group InGroupMask) 776 | { 777 | List appendObjects = new List(InObjects); 778 | 779 | // check for entries in existing groups 780 | int removeFromExistingGroup = -1; 781 | 782 | for(int i = 0; i < groupContainer.sceneGroups.Length; i++) 783 | { 784 | Group group = groupContainer.sceneGroups[i]; 785 | 786 | if( group == InGroupMask ) 787 | continue; 788 | 789 | GameObject[] dup = group.objects.Intersect(appendObjects).ToArray(); 790 | 791 | if( dup != null && dup.Length > 0 ) 792 | { 793 | foreach(GameObject duplicate in dup) 794 | { 795 | if( removeFromExistingGroup != 2 ) 796 | removeFromExistingGroup = EditorUtility.DisplayDialogComplex("Remove from current group?", duplicate.name + " already belongs to a group. Would you like to remove it from it's current groups and place it in the new one?", "Yes", "No", "Yes to All"); 797 | 798 | switch(removeFromExistingGroup) 799 | { 800 | case 0: // yes 801 | case 2: // yes to all 802 | group.RemoveObject(duplicate); 803 | break; 804 | 805 | case 1: // no 806 | appendObjects.Remove(duplicate); 807 | break; 808 | 809 | default: 810 | // ehu? 811 | break; 812 | } 813 | } 814 | } 815 | } 816 | 817 | return appendObjects.ToArray(); 818 | } 819 | } 820 | } 821 | -------------------------------------------------------------------------------- /Scripts/Editor/ProGroups_Window.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c10930b8241cb4dda81c90c5cbc3c82b 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Scripts/InScene.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 62325bc89d8cda345b08d22cfcf018d5 3 | -------------------------------------------------------------------------------- /Scripts/InScene/GroupContainer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace ProGroups 7 | { 8 | /** 9 | * Container class for a group. Consists of name, objects in group, and frozen / hidden status. 10 | */ 11 | [System.Serializable] 12 | public class Group 13 | { 14 | public string name; 15 | public GameObject[] objects; 16 | public bool frozen; 17 | public bool hidden; 18 | 19 | public Group(string InName, GameObject[] InObjects, bool InFrozen, bool InHidden) 20 | { 21 | this.name = InName; 22 | this.objects = InObjects.Distinct().ToArray(); 23 | this.frozen = InFrozen; 24 | this.hidden = InHidden; 25 | } 26 | 27 | /** 28 | * Remove null or missing objects from this group. 29 | */ 30 | public void RemoveNullOrEmpty() 31 | { 32 | if( objects == null ) 33 | { 34 | objects = new GameObject[0]; 35 | } 36 | else 37 | { 38 | IEnumerable valid = objects.Where(x => x != null); 39 | objects = valid == null ? new GameObject[0] : valid.ToArray(); 40 | } 41 | } 42 | 43 | /** 44 | * Add @InGameObjects to the list of objects in this group. 45 | */ 46 | public void AddObjects(GameObject[] InObjects) 47 | { 48 | ArrayExt.AddRange(ref objects, InObjects); 49 | objects = objects.Distinct().ToArray(); 50 | } 51 | 52 | /** 53 | * Remove @InObject from objects. 54 | */ 55 | public void RemoveObject(GameObject InObject) 56 | { 57 | ArrayExt.Remove(ref objects, InObject); 58 | 59 | } 60 | 61 | /** 62 | * Remove @InObjects from objects. 63 | */ 64 | public void RemoveObjects(GameObject[] InObjects) 65 | { 66 | ArrayExt.Remove(ref objects, InObjects); 67 | } 68 | } 69 | 70 | /** 71 | * Extension methods for working with arrays. 72 | */ 73 | static class ArrayExt 74 | { 75 | public static void Add(ref T[] array, T val) 76 | { 77 | T[] tmp = new T[array.Length + 1]; 78 | System.Array.Copy(array, tmp, array.Length); 79 | tmp[array.Length] = val; 80 | array = tmp; 81 | } 82 | 83 | /** 84 | * Concatenate @values with @array. 85 | */ 86 | public static void AddRange(ref T[] array, T[] values) 87 | { 88 | T[] tmp = new T[array.Length + values.Length]; 89 | System.Array.Copy(array, tmp, array.Length); 90 | System.Array.Copy(values, 0, tmp, array.Length, values.Length); 91 | array = tmp; 92 | } 93 | 94 | /** 95 | * Remove all instances of @value from @array. 96 | */ 97 | public static void Remove(ref T[] array, T value) 98 | { 99 | array = array.Where(x => !value.Equals(x)).ToArray(); 100 | } 101 | 102 | public static void Remove(ref T[] array, T[] values) 103 | { 104 | array = array.Where(x => !values.Contains(x)).ToArray(); 105 | } 106 | 107 | public static void RemoveAt(ref T[] array, int index) 108 | { 109 | T[] tmp = new T[array.Length-1]; 110 | for(int i = 0; i < array.Length; i++) 111 | if(i != index) 112 | tmp[i > index ? i-1 : i] = array[i]; 113 | array = tmp; 114 | } 115 | } 116 | 117 | /** 118 | * Component that holds array of user groups. 119 | */ 120 | public class GroupContainer : MonoBehaviour 121 | { 122 | public Group[] sceneGroups = new Group[0] {}; 123 | 124 | /** 125 | * Add a new group. 126 | */ 127 | public void NewGroup(string InName, GameObject[] InObjects) 128 | { 129 | Group newGroup = new Group(InName, InObjects, false, false); 130 | 131 | if(sceneGroups != null) 132 | { 133 | ArrayExt.Add(ref sceneGroups, newGroup); 134 | } 135 | else 136 | { 137 | sceneGroups = new Group[] { newGroup }; 138 | } 139 | } 140 | 141 | /** 142 | * Freeze all objects in @InGroup. 143 | */ 144 | public void ToggleFreeze(Group InGroup) 145 | { 146 | InGroup.RemoveNullOrEmpty(); 147 | 148 | InGroup.frozen = !InGroup.frozen; 149 | 150 | foreach(GameObject obj in InGroup.objects) 151 | { 152 | if(InGroup.frozen) 153 | obj.Freeze(); 154 | else 155 | obj.Thaw(); 156 | } 157 | } 158 | 159 | /** 160 | * Hide or show all items in @InGroup. 161 | */ 162 | public void ToggleVis(Group InGroup) 163 | { 164 | if(InGroup.hidden) 165 | ShowGroup(InGroup); 166 | else 167 | HideGroup(InGroup); 168 | } 169 | 170 | /** 171 | * Hide all items in @InGroup. 172 | */ 173 | public void HideGroup(Group InGroup) 174 | { 175 | InGroup.RemoveNullOrEmpty(); 176 | 177 | foreach(GameObject obj in InGroup.objects) 178 | obj.Hide(); 179 | 180 | InGroup.hidden = true; 181 | } 182 | 183 | /** 184 | * Show all items in @InGroup. 185 | */ 186 | public void ShowGroup(Group InGroup) 187 | { 188 | InGroup.RemoveNullOrEmpty(); 189 | 190 | foreach(GameObject obj in InGroup.objects) 191 | obj.Show(); 192 | 193 | InGroup.hidden = false; 194 | } 195 | 196 | /** 197 | * Hide all groups save for group at index @i. 198 | */ 199 | public void Isolate(int i ) 200 | { 201 | for(int j = 0; j < sceneGroups.Length; j++) 202 | { 203 | if(j != i) 204 | { 205 | HideGroup(sceneGroups[j]); 206 | } 207 | } 208 | 209 | ShowGroup(sceneGroups[i]); 210 | } 211 | 212 | public void RemoveGroups(IEnumerable indices) 213 | { 214 | List sorted = new List(indices); 215 | sorted.Sort(); 216 | 217 | int offset = 0; 218 | 219 | for(int i = 0; i < sorted.Count; i++) 220 | { 221 | int ind = sorted[i] - offset++; 222 | RemoveGroup(ind); 223 | } 224 | } 225 | 226 | /** 227 | * Remove group at index @i from the container list. 228 | */ 229 | public void RemoveGroup(int i ) 230 | { 231 | sceneGroups[i].RemoveNullOrEmpty(); 232 | 233 | foreach(GameObject obj in sceneGroups[i].objects) 234 | { 235 | #if UNITY_3_5 236 | obj.active = true; 237 | #else 238 | obj.SetActive(true); 239 | #endif 240 | obj.hideFlags = 0; 241 | } 242 | 243 | ArrayExt.RemoveAt(ref sceneGroups, i); 244 | } 245 | 246 | /** 247 | * Rebuild @InGroup with @InObjects, and reset hidden and frozen flags. 248 | */ 249 | public void UpdateGroup(Group InGroup, GameObject[] InObjects) 250 | { 251 | InGroup.RemoveNullOrEmpty(); 252 | 253 | foreach(GameObject obj in InGroup.objects) 254 | { 255 | #if UNITY_3_5 256 | obj.active = true; 257 | #else 258 | obj.SetActive(true); 259 | #endif 260 | obj.hideFlags = 0; 261 | } 262 | 263 | InGroup.objects = InObjects; 264 | 265 | InGroup.hidden = false; 266 | InGroup.frozen = false; 267 | } 268 | 269 | /** 270 | * Move group at @InShiftIndex up one index. 271 | */ 272 | public void MoveGroupUp(int InShiftIndex) 273 | { 274 | if( InShiftIndex < 1 || InShiftIndex > sceneGroups.Length-1) 275 | return; 276 | 277 | Group tmp = sceneGroups[InShiftIndex-1]; 278 | sceneGroups[InShiftIndex-1] = sceneGroups[InShiftIndex]; 279 | sceneGroups[InShiftIndex] = tmp; 280 | } 281 | 282 | /** 283 | * Move group at @InShiftIndex down one index. 284 | */ 285 | public void MoveGroupDown(int InShiftIndex) 286 | { 287 | if( InShiftIndex < 0 || InShiftIndex > sceneGroups.Length-2) 288 | return; 289 | 290 | Group tmp = sceneGroups[InShiftIndex+1]; 291 | sceneGroups[InShiftIndex+1] = sceneGroups[InShiftIndex]; 292 | sceneGroups[InShiftIndex] = tmp; 293 | } 294 | 295 | /** 296 | * Remove null or empty groups. 297 | */ 298 | public void RemoveNullOrEmpty() 299 | { 300 | sceneGroups = sceneGroups.Where(x => x != null && x.objects.Length > 0).ToArray(); 301 | } 302 | 303 | /** 304 | * Make sure there aren't any null objects in groups. 305 | */ 306 | public void Clean() 307 | { 308 | for(int i = 0; i < sceneGroups.Length; i++) { 309 | sceneGroups[i].RemoveNullOrEmpty(); 310 | } 311 | } 312 | } 313 | } 314 | -------------------------------------------------------------------------------- /Scripts/InScene/GroupContainer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 34619e0f20e4a43fa8120864b07d987d 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | -------------------------------------------------------------------------------- /Scripts/InScene/ProGroups_Util.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace ProGroups 4 | { 5 | /** 6 | * Utility functions for ProGroups. 7 | */ 8 | public static class ProGroups_Util 9 | { 10 | /** 11 | * Set hide flags for "Frozen" state (NotEditable, but visibility doesn't change). 12 | */ 13 | public static void Freeze(this GameObject go) 14 | { 15 | HideFlags flags = go.hideFlags; 16 | go.hideFlags = flags | HideFlags.NotEditable; 17 | } 18 | 19 | /** 20 | * Set hide flags for not "Frozen" state (clear NotEditable flag; visibility doesn't change). 21 | */ 22 | public static void Thaw(this GameObject go) 23 | { 24 | HideFlags flags = go.hideFlags; 25 | go.hideFlags = flags & (~HideFlags.NotEditable); 26 | } 27 | 28 | /** 29 | * Freeze and set to inactive. 30 | */ 31 | public static void Hide(this GameObject go) 32 | { 33 | go.SetActive(false); 34 | } 35 | 36 | /** 37 | * Thaw and set to active. 38 | */ 39 | public static void Show(this GameObject go) 40 | { 41 | go.SetActive(true); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Scripts/InScene/ProGroups_Util.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1c85209daad2484ca13b9fec941b840 3 | timeCreated: 1491234569 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | --------------------------------------------------------------------------------