Last active
September 3, 2018 20:53
-
-
Save jonHuffman/e8d61c154806bc3398447e6e928073b8 to your computer and use it in GitHub Desktop.
A utility script for Unity that generates a constants file for the scenes listed in the build settings. Can be accessed under Tools/Code Generation/Create Scene Constants
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ------------------------------------------------------------------------------ | |
// <auto-generated> | |
// This code was generated by a tool. | |
// Runtime Version: 15.0.0.0 | |
// | |
// Changes to this file may cause incorrect behavior and will be lost if | |
// the code is regenerated. | |
// </auto-generated> | |
// ------------------------------------------------------------------------------ | |
namespace CodeGeneration.Constants | |
{ | |
using System; | |
/// <summary> | |
/// Class to produce the template output | |
/// </summary> | |
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")] | |
public partial class SceneConstantsGenerator : SceneConstantsGeneratorBase | |
{ | |
/// <summary> | |
/// Create the template output | |
/// </summary> | |
public virtual string TransformText() | |
{ | |
// The output generated by this file is automatically copied into the Core project via a post-build step in the project file. | |
// The namespace of the generated code is custom defined in the properties of this file. | |
this.Write("namespace Utils.Constants\r\n{\r\n\tpublic static class "); | |
this.Write(this.ToStringHelper.ToStringWithCulture(className)); | |
this.Write("\r\n\t{\r\n"); | |
for(int i = 0; i < scenes.Length; i++) | |
{ | |
this.Write("\t\tpublic const int "); | |
this.Write(this.ToStringHelper.ToStringWithCulture(scenes[i])); | |
this.Write(" = "); | |
this.Write(this.ToStringHelper.ToStringWithCulture(i)); | |
this.Write(";\r\n"); | |
} | |
this.Write("\t}\r\n}"); | |
return this.GenerationEnvironment.ToString(); | |
} | |
private string _classNameField; | |
/// <summary> | |
/// Access the className parameter of the template. | |
/// </summary> | |
private string className | |
{ | |
get | |
{ | |
return this._classNameField; | |
} | |
} | |
private string[] _scenesField; | |
/// <summary> | |
/// Access the scenes parameter of the template. | |
/// </summary> | |
private string[] scenes | |
{ | |
get | |
{ | |
return this._scenesField; | |
} | |
} | |
/// <summary> | |
/// Initialize the template | |
/// </summary> | |
public virtual void Initialize() | |
{ | |
if ((this.Errors.HasErrors == false)) | |
{ | |
bool classNameValueAcquired = false; | |
if (this.Session.ContainsKey("className")) | |
{ | |
this._classNameField = ((string)(this.Session["className"])); | |
classNameValueAcquired = true; | |
} | |
if ((classNameValueAcquired == false)) | |
{ | |
object data = global::System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("className"); | |
if ((data != null)) | |
{ | |
this._classNameField = ((string)(data)); | |
} | |
} | |
bool scenesValueAcquired = false; | |
if (this.Session.ContainsKey("scenes")) | |
{ | |
this._scenesField = ((string[])(this.Session["scenes"])); | |
scenesValueAcquired = true; | |
} | |
if ((scenesValueAcquired == false)) | |
{ | |
object data = global::System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("scenes"); | |
if ((data != null)) | |
{ | |
this._scenesField = ((string[])(data)); | |
} | |
} | |
} | |
} | |
} | |
#region Base class | |
/// <summary> | |
/// Base class for this transformation | |
/// </summary> | |
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")] | |
public class SceneConstantsGeneratorBase | |
{ | |
#region Fields | |
private global::System.Text.StringBuilder generationEnvironmentField; | |
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; | |
private global::System.Collections.Generic.List<int> indentLengthsField; | |
private string currentIndentField = ""; | |
private bool endsWithNewline; | |
private global::System.Collections.Generic.IDictionary<string, object> sessionField; | |
#endregion | |
#region Properties | |
/// <summary> | |
/// The string builder that generation-time code is using to assemble generated output | |
/// </summary> | |
protected System.Text.StringBuilder GenerationEnvironment | |
{ | |
get | |
{ | |
if ((this.generationEnvironmentField == null)) | |
{ | |
this.generationEnvironmentField = new global::System.Text.StringBuilder(); | |
} | |
return this.generationEnvironmentField; | |
} | |
set | |
{ | |
this.generationEnvironmentField = value; | |
} | |
} | |
/// <summary> | |
/// The error collection for the generation process | |
/// </summary> | |
public System.CodeDom.Compiler.CompilerErrorCollection Errors | |
{ | |
get | |
{ | |
if ((this.errorsField == null)) | |
{ | |
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); | |
} | |
return this.errorsField; | |
} | |
} | |
/// <summary> | |
/// A list of the lengths of each indent that was added with PushIndent | |
/// </summary> | |
private System.Collections.Generic.List<int> indentLengths | |
{ | |
get | |
{ | |
if ((this.indentLengthsField == null)) | |
{ | |
this.indentLengthsField = new global::System.Collections.Generic.List<int>(); | |
} | |
return this.indentLengthsField; | |
} | |
} | |
/// <summary> | |
/// Gets the current indent we use when adding lines to the output | |
/// </summary> | |
public string CurrentIndent | |
{ | |
get | |
{ | |
return this.currentIndentField; | |
} | |
} | |
/// <summary> | |
/// Current transformation session | |
/// </summary> | |
public virtual global::System.Collections.Generic.IDictionary<string, object> Session | |
{ | |
get | |
{ | |
return this.sessionField; | |
} | |
set | |
{ | |
this.sessionField = value; | |
} | |
} | |
#endregion | |
#region Transform-time helpers | |
/// <summary> | |
/// Write text directly into the generated output | |
/// </summary> | |
public void Write(string textToAppend) | |
{ | |
if (string.IsNullOrEmpty(textToAppend)) | |
{ | |
return; | |
} | |
// If we're starting off, or if the previous text ended with a newline, | |
// we have to append the current indent first. | |
if (((this.GenerationEnvironment.Length == 0) | |
|| this.endsWithNewline)) | |
{ | |
this.GenerationEnvironment.Append(this.currentIndentField); | |
this.endsWithNewline = false; | |
} | |
// Check if the current text ends with a newline | |
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) | |
{ | |
this.endsWithNewline = true; | |
} | |
// This is an optimization. If the current indent is "", then we don't have to do any | |
// of the more complex stuff further down. | |
if ((this.currentIndentField.Length == 0)) | |
{ | |
this.GenerationEnvironment.Append(textToAppend); | |
return; | |
} | |
// Everywhere there is a newline in the text, add an indent after it | |
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); | |
// If the text ends with a newline, then we should strip off the indent added at the very end | |
// because the appropriate indent will be added when the next time Write() is called | |
if (this.endsWithNewline) | |
{ | |
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); | |
} | |
else | |
{ | |
this.GenerationEnvironment.Append(textToAppend); | |
} | |
} | |
/// <summary> | |
/// Write text directly into the generated output | |
/// </summary> | |
public void WriteLine(string textToAppend) | |
{ | |
this.Write(textToAppend); | |
this.GenerationEnvironment.AppendLine(); | |
this.endsWithNewline = true; | |
} | |
/// <summary> | |
/// Write formatted text directly into the generated output | |
/// </summary> | |
public void Write(string format, params object[] args) | |
{ | |
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); | |
} | |
/// <summary> | |
/// Write formatted text directly into the generated output | |
/// </summary> | |
public void WriteLine(string format, params object[] args) | |
{ | |
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); | |
} | |
/// <summary> | |
/// Raise an error | |
/// </summary> | |
public void Error(string message) | |
{ | |
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); | |
error.ErrorText = message; | |
this.Errors.Add(error); | |
} | |
/// <summary> | |
/// Raise a warning | |
/// </summary> | |
public void Warning(string message) | |
{ | |
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); | |
error.ErrorText = message; | |
error.IsWarning = true; | |
this.Errors.Add(error); | |
} | |
/// <summary> | |
/// Increase the indent | |
/// </summary> | |
public void PushIndent(string indent) | |
{ | |
if ((indent == null)) | |
{ | |
throw new global::System.ArgumentNullException("indent"); | |
} | |
this.currentIndentField = (this.currentIndentField + indent); | |
this.indentLengths.Add(indent.Length); | |
} | |
/// <summary> | |
/// Remove the last indent that was added with PushIndent | |
/// </summary> | |
public string PopIndent() | |
{ | |
string returnValue = ""; | |
if ((this.indentLengths.Count > 0)) | |
{ | |
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; | |
this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); | |
if ((indentLength > 0)) | |
{ | |
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); | |
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); | |
} | |
} | |
return returnValue; | |
} | |
/// <summary> | |
/// Remove any indentation | |
/// </summary> | |
public void ClearIndent() | |
{ | |
this.indentLengths.Clear(); | |
this.currentIndentField = ""; | |
} | |
#endregion | |
#region ToString Helpers | |
/// <summary> | |
/// Utility class to produce culture-oriented representation of an object as a string. | |
/// </summary> | |
public class ToStringInstanceHelper | |
{ | |
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; | |
/// <summary> | |
/// Gets or sets format provider to be used by ToStringWithCulture method. | |
/// </summary> | |
public System.IFormatProvider FormatProvider | |
{ | |
get | |
{ | |
return this.formatProviderField ; | |
} | |
set | |
{ | |
if ((value != null)) | |
{ | |
this.formatProviderField = value; | |
} | |
} | |
} | |
/// <summary> | |
/// This is called from the compile/run appdomain to convert objects within an expression block to a string | |
/// </summary> | |
public string ToStringWithCulture(object objectToConvert) | |
{ | |
if ((objectToConvert == null)) | |
{ | |
throw new global::System.ArgumentNullException("objectToConvert"); | |
} | |
System.Type t = objectToConvert.GetType(); | |
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { | |
typeof(System.IFormatProvider)}); | |
if ((method == null)) | |
{ | |
return objectToConvert.ToString(); | |
} | |
else | |
{ | |
return ((string)(method.Invoke(objectToConvert, new object[] { | |
this.formatProviderField }))); | |
} | |
} | |
} | |
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); | |
/// <summary> | |
/// Helper to produce culture-oriented representation of an object as a string | |
/// </summary> | |
public ToStringInstanceHelper ToStringHelper | |
{ | |
get | |
{ | |
return this.toStringHelperField; | |
} | |
} | |
#endregion | |
} | |
#endregion | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.IO; | |
using UnityEditor; | |
using UnityEngine; | |
namespace CodeGeneration.Constants | |
{ | |
public partial class SceneConstantsGenerator | |
{ | |
private static string title = "Save Location"; | |
private static string filename = "GameScene"; | |
private static string extension = "cs"; | |
private static string message = "Where do you want to save this constants file?"; | |
private static string path = string.Format("{0}", Application.dataPath); | |
[MenuItem("Tools/Code Generation/Create Scene Constants")] | |
public static void GenerateStatics() | |
{ | |
string outputPath = RequestOutputPathWithFilename(); | |
SceneConstantsGenerator generator = new SceneConstantsGenerator(); | |
generator.Session = BuildSessionParameters(); | |
generator.Initialize(); | |
string generatedClassContents = generator.TransformText(); | |
File.WriteAllText(outputPath, generatedClassContents); | |
AssetDatabase.Refresh(); | |
} | |
private static string RequestOutputPathWithFilename() | |
{ | |
return EditorUtility.SaveFilePanelInProject(title, filename, extension, message, path); | |
} | |
private static Dictionary<string, object> BuildSessionParameters() | |
{ | |
Dictionary<string, object> sessionParameters = new Dictionary<string, object>(); | |
sessionParameters["className"] = filename; | |
sessionParameters = SetSceneParameter(sessionParameters); | |
return sessionParameters; | |
} | |
private static Dictionary<string, object> SetSceneParameter(Dictionary<string, object> sessionParameters) | |
{ | |
List<string> sceneData = new List<string>(); | |
EditorBuildSettingsScene[] scenes = EditorBuildSettings.scenes; | |
foreach(EditorBuildSettingsScene scene in scenes) | |
{ | |
string sceneName = Path.GetFileNameWithoutExtension(scene.path); | |
sceneData.Add(sceneName); | |
} | |
sessionParameters["scenes"] = sceneData.ToArray(); | |
return sessionParameters; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment