Skip to content

Instantly share code, notes, and snippets.

@codeimpossible
Last active May 6, 2021 12:22
Show Gist options
  • Save codeimpossible/3f30c44e1a10c3e197d71818683f4e30 to your computer and use it in GitHub Desktop.
Save codeimpossible/3f30c44e1a10c3e197d71818683f4e30 to your computer and use it in GitHub Desktop.
Tags, Layers and Scene Builder - Auto Generate Tags, Layers and Scenes classes containing consts for all variables for code completion

Tags, Layers and Scene Builder - Auto Generate Tags, Layers and Scenes classes containing consts for all variables for code completion

This script should be placed in your Editor code directory in your unity project. It will add a new menu option under Tools -> TroubleCat Studios -> Rebuild Tags, Layers and Scenes Classes. This will create code files for all your Tags, Layers, Scenes and SortingLayers within the Assets/Scripts/AutoGenerated/ folder.

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace TroubleCat.Editor.BuildTools {
// Tags, Layers and Scene Builder - Auto Generate Tags, Layers and Scenes classes containing consts for all variables for code completion
// released under MIT License
// http://www.opensource.org/licenses/mit-license.php
//
// bug fixes, sorting layers and other improvements:
//@author Jared Barboza
//@website http://jaredbarboza.me
//
// Original code by:
//@author Devin Reimer - AlmostLogical Software / Owlchemy Labs
//@website http://blog.almostlogical.com, http://owlchemylabs.com
/*
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
//Note: This class uses UnityEditorInternal which is an undocumented internal feature
public class TagsLayersScenesBuilder {
private const string NAMESPACE = "Game";
private const string FOLDER_LOCATION = "Scripts/AutoGenerated/";
private const string TAGS_FILE_NAME = "Tags";
private const string LAYERS_FILE_NAME = "Layers";
private const string SCENES_FILE_NAME = "Scenes";
private const string SORTING_LAYERS_FILE_NAME = "SortingLayers";
private const string SCRIPT_EXTENSION = ".cs";
[MenuItem("Tools/TroubleCat Studios/Rebuild Tags, Layers and Scenes Classes")]
public static void RebuildTagsAndLayersClasses() {
string folderPath = Application.dataPath + "/" + FOLDER_LOCATION;
if (!Directory.Exists(folderPath)) {
Directory.CreateDirectory(folderPath);
}
File.WriteAllText(folderPath + TAGS_FILE_NAME + SCRIPT_EXTENSION, GetClassContent(TAGS_FILE_NAME, UnityEditorInternal.InternalEditorUtility.tags));
File.WriteAllText(folderPath + LAYERS_FILE_NAME + SCRIPT_EXTENSION, GetLayerClassContent(LAYERS_FILE_NAME, UnityEditorInternal.InternalEditorUtility.layers));
File.WriteAllText(folderPath + SCENES_FILE_NAME + SCRIPT_EXTENSION, GetClassContent(SCENES_FILE_NAME, EditorBuildSettingsScenesToNameStrings(EditorBuildSettings.scenes)));
var labels = GetSortingLayerNames();
var values = GetSortingLayerUniqueIDs();
File.WriteAllText(folderPath + SORTING_LAYERS_FILE_NAME + SCRIPT_EXTENSION, GetSortingLayerClassContent(SORTING_LAYERS_FILE_NAME, labels, values));
AssetDatabase.ImportAsset("Assets/" + FOLDER_LOCATION + TAGS_FILE_NAME + SCRIPT_EXTENSION, ImportAssetOptions.ForceUpdate);
AssetDatabase.ImportAsset("Assets/" + FOLDER_LOCATION + LAYERS_FILE_NAME + SCRIPT_EXTENSION, ImportAssetOptions.ForceUpdate);
AssetDatabase.ImportAsset("Assets/" + FOLDER_LOCATION + SCENES_FILE_NAME + SCRIPT_EXTENSION, ImportAssetOptions.ForceUpdate);
AssetDatabase.ImportAsset("Assets/" + FOLDER_LOCATION + SORTING_LAYERS_FILE_NAME + SCRIPT_EXTENSION, ImportAssetOptions.ForceUpdate);
Debug.Log("Rebuild Complete");
}
// Get the sorting layer names
private static string[] GetSortingLayerNames() {
Type internalEditorUtilityType = typeof(UnityEditorInternal.InternalEditorUtility);
PropertyInfo sortingLayersProperty = internalEditorUtilityType.GetProperty("sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic);
return (string[])sortingLayersProperty.GetValue(null, new object[0]);
}
// Get the unique sorting layer IDs -- tossed this in for good measure
private static int[] GetSortingLayerUniqueIDs() {
Type internalEditorUtilityType = typeof(UnityEditorInternal.InternalEditorUtility);
PropertyInfo sortingLayerUniqueIDsProperty = internalEditorUtilityType.GetProperty("sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic);
return (int[])sortingLayerUniqueIDsProperty.GetValue(null, new object[0]);
}
private static string[] EditorBuildSettingsScenesToNameStrings(EditorBuildSettingsScene[] scenes) {
return scenes
.Select(s => System.IO.Path.GetFileNameWithoutExtension(s.path))
.TakeWhile(s => !string.IsNullOrWhiteSpace(s))
.ToArray();
}
private static string GetClassWrapper(string className, string contents) {
string output = $"namespace {NAMESPACE} {{";
output += " using System.Collections.Generic;\n";
output += " //This class is auto-generated do not modify (TagsLayersScenesBuilder.cs) - blog.almostlogical.com\n";
output += " public class " + className + "{\n";
output += contents;
output += "\n }\n";
output += "}";
return output;
}
private static string GetClassContent(string className, string[] labelsArray) {
string output = "";
var list = new StringBuilder();
list.AppendLine($"\t\tpublic static List<string> All{className} = new List<string>() {{");
foreach (string label in labelsArray) {
output += "\t\t" + BuildConstVariable(label) + "\n";
list.AppendLine($"\t\t\t\"{label}\",");
}
list.AppendLine($"\t\t}};");
output += list.ToString();
return GetClassWrapper(className, output);
}
private static string GetSortingLayerClassContent(string className, string[] labelsArray, int[] valuesArray) {
string output = "";
foreach (string label in labelsArray) {
output += "\t\t" + BuildConstVariable(label) + "\n";
}
output += "\n";
var dictionary = new StringBuilder();
dictionary.AppendLine($"\t\tpublic static Dictionary<int, string> All{className} = new Dictionary<int, string>() {{");
int idx = 0;
foreach (string label in labelsArray) {
output += "\t\t" + "public const int " + ToUpperCaseWithUnderscores(label) + "_INT" + " = " + valuesArray[idx] + ";\n";
dictionary.AppendLine($"\t\t\t{{ {valuesArray[idx]} ,\"{label}\" }},");
idx++;
}
dictionary.AppendLine($"\t\t}};");
output += dictionary.ToString();
return GetClassWrapper(className, output);
}
private static string GetLayerClassContent(string className, string[] labelsArray) {
string output = "";
foreach (string label in labelsArray) {
output += "\t\t" + BuildConstVariable(label) + "\n";
}
output += "\n";
var dictionary = new StringBuilder();
dictionary.AppendLine($"\t\tpublic static Dictionary<int, string> All{className} = new Dictionary<int, string>() {{");
foreach (string label in labelsArray) {
output += "\t\t" + "public const int " + ToUpperCaseWithUnderscores(label) + "_INT" + " = " + LayerMask.NameToLayer(label) + ";\n";
dictionary.AppendLine($"\t\t\t{{ {LayerMask.NameToLayer(label)} ,\"{label}\" }},");
}
dictionary.AppendLine($"\t\t}};");
output += dictionary.ToString();
return GetClassWrapper(className, output);
}
private static string BuildConstVariable(string varName) {
return "public const string " + ToUpperCaseWithUnderscores(varName) + " = " + '"' + varName + '"' + ";";
}
private static string ToUpperCaseWithUnderscores(string input) {
input = Regex.Replace(input, @"^[\d]", string.Empty);
return Regex.Replace(input, @"[^\w\d]", string.Empty).ToUpper();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment