Skip to content

Instantly share code, notes, and snippets.

@arkms
Created June 7, 2017 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arkms/1d8177fdb8957265bc2bb986555e8aab to your computer and use it in GitHub Desktop.
Save arkms/1d8177fdb8957265bc2bb986555e8aab to your computer and use it in GitHub Desktop.
Script que automáticamente genera otros scripts que tiene los Tags, Layers y Sorting Layers del proyecto para trabajar con ellos en un script de manera sencilla, simplemente se debe actualizar llamando 'Edit/Generate Constants Classes'
using UnityEngine;
using UnityEditor;
using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
using System.Reflection;
//Basado en codigo de Prime31Editor
//Poner siempre este script dentro de una carpeta llamado 'Editor'
public class ConstantsGeneratorKit : MonoBehaviour
{
private const string FOLDER_LOCATION = "Scripts/Keys/";
private const string NAMESPACE = "k";
private static ConstantNamingStyle CONSTANT_NAMING_STYLE = ConstantNamingStyle.UppercaseWithUnderscores;
private const string DIGIT_PREFIX = "k";
private static bool SHOW_SUCCESS_MESSAGE = false;
private const string TAGS_FILE_NAME = "Tags.cs";
private const string LAYERS_FILE_NAME = "Layers.cs";
private const string SORTING_LAYERS_FILE_NAME = "SortingLayers.cs";
[MenuItem( "Edit/Generate Constants Classes..." )]
static void rebuildConstantsClassesMenuItem()
{
rebuildConstantsClasses();
}
public static void rebuildConstantsClasses( bool buildResources = true, bool buildScenes = true, bool buildTagsAndLayers = true, bool buildSortingLayers = true )
{
var folderPath = Application.dataPath + "/" + FOLDER_LOCATION;
if( !Directory.Exists(folderPath ) )
Directory.CreateDirectory( folderPath );
if( buildTagsAndLayers )
{
File.WriteAllText( folderPath + TAGS_FILE_NAME, getClassContent( TAGS_FILE_NAME.Replace( ".cs", string.Empty ), UnityEditorInternal.InternalEditorUtility.tags ) );
File.WriteAllText( folderPath + LAYERS_FILE_NAME, getLayerClassContent( LAYERS_FILE_NAME.Replace( ".cs", string.Empty ), UnityEditorInternal.InternalEditorUtility.layers ) );
AssetDatabase.ImportAsset( "Assets/" + FOLDER_LOCATION + TAGS_FILE_NAME, ImportAssetOptions.ForceUpdate );
AssetDatabase.ImportAsset( "Assets/" + FOLDER_LOCATION + LAYERS_FILE_NAME, ImportAssetOptions.ForceUpdate );
}
if( buildSortingLayers )
{
var sortingLayers = getSortingLayers();
var layerIds = getSortingLayerIds( sortingLayers.Length );
File.WriteAllText( folderPath + SORTING_LAYERS_FILE_NAME, getSortingLayerClassContent( SORTING_LAYERS_FILE_NAME.Replace( ".cs", string.Empty ), sortingLayers, layerIds ) );
AssetDatabase.ImportAsset( "Assets/" + FOLDER_LOCATION + SORTING_LAYERS_FILE_NAME, ImportAssetOptions.ForceUpdate );
}
if( SHOW_SUCCESS_MESSAGE && buildResources && buildScenes && buildTagsAndLayers )
Debug.Log( "ConstantsGeneratorKit complete. Constants classes built to " + FOLDER_LOCATION );
}
private static string[] editorBuildSettingsScenesToNameStrings( EditorBuildSettingsScene[] scenes )
{
var sceneNames = new string[scenes.Length];
for( var n = 0; n < sceneNames.Length; n++ )
sceneNames[n] = Path.GetFileNameWithoutExtension( scenes[n].path );
return sceneNames;
}
private static string[] getSortingLayers()
{
var type = typeof( UnityEditorInternal.InternalEditorUtility );
var prop = type.GetProperty( "sortingLayerNames", BindingFlags.Static | BindingFlags.NonPublic );
return prop.GetValue( null, null ) as string[];
}
private static int[] getSortingLayerIds( int totalSortingLayers )
{
var type = typeof( UnityEditorInternal.InternalEditorUtility );
var layerIds = type.GetProperty( "sortingLayerUniqueIDs", BindingFlags.Static | BindingFlags.NonPublic ).GetValue( null, null ) as int[];
return layerIds;
}
private static string getClassContent( string className, string[] labelsArray )
{
var output = "";
output += "//This class is auto-generated do not modify\n";
output += "namespace " + NAMESPACE + "\n";
output += "{\n";
output += "\tpublic static class " + className + "\n";
output += "\t{\n";
foreach( var label in labelsArray )
output += "\t\t" + buildConstVariable( label ) + "\n";
output += "\t}\n";
output += "}";
return output;
}
private static string getLayerClassContent( string className, string[] labelsArray )
{
var output = "";
output += "// This class is auto-generated do not modify\n";
output += "namespace " + NAMESPACE + "\n";
output += "{\n";
output += "\tpublic static class " + className + "\n";
output += "\t{\n";
foreach( var label in labelsArray )
output += "\t\t" + "public const int " + formatConstVariableName( label ) + " = " + LayerMask.NameToLayer( label ) + ";\n";
output += "\n\n";
output += @" public static int onlyIncluding( params int[] layers )
{
int mask = 0;
for( var i = 0; i < layers.Length; i++ )
mask |= ( 1 << layers[i] );
return mask;
}
public static int everythingBut( params int[] layers )
{
return ~onlyIncluding( layers );
}";
output += "\n";
output += "\t}\n";
output += "}";
return output;
}
private static string getSortingLayerClassContent( string className, string[] sortingLayers, int[] layerIds )
{
var output = "";
output += "// This class is auto-generated do not modify\n";
output += "namespace " + NAMESPACE + "\n";
output += "{\n";
output += "\tpublic static class " + className + "\n";
output += "\t{\n";
for( var i = 0; i < sortingLayers.Length; i++ )
output += "\t\t" + "public const int " + formatConstVariableName( sortingLayers[i] ) + " = " + layerIds[i] + ";\n";
output += "\n";
output += "\t}\n";
output += "}";
return output;
}
private static string buildConstVariable( string varName, string suffix = "", string value = null )
{
value = value ?? varName;
return "public const string " + formatConstVariableName( varName ) + suffix + " = " + '"' + value + '"' + ";";
}
private static string formatConstVariableName( string input )
{
switch ( CONSTANT_NAMING_STYLE ) {
case ConstantNamingStyle.UppercaseWithUnderscores:
return toUpperCaseWithUnderscores( input );
case ConstantNamingStyle.CamelCase:
return toCamelCase( input );
default:
return toUpperCaseWithUnderscores( input );
}
}
private static string toCamelCase( string input )
{
input = input.Replace( " ", "" );
if ( char.IsLower(input[0]) )
input = char.ToUpper( input[0] ) + input.Substring( 1 );
// uppercase letters before dash or underline
Func<char,int,string> func = ( x, i ) =>{
if ( x == '-' || x == '_' )
return "";
if( i > 0 && (input[i - 1] == '-' || input[i - 1] == '_') )
return x.ToString().ToUpper();
return x.ToString();
};
input = string.Concat( input.Select( func ).ToArray() );
// digits are a no-no so stick prefix in front
if( char.IsDigit( input[0] ) )
return DIGIT_PREFIX + input;
return input;
}
private static string toUpperCaseWithUnderscores( string input )
{
input = input.Replace( "-", "_" );
input = Regex.Replace( input, @"\s+", "_" );
// make camel-case have an underscore between letters
Func<char,int,string> func = ( x, i ) =>
{
if( i > 0 && char.IsUpper( x ) && char.IsLower( input[i - 1] ) )
return "_" + x.ToString();
return x.ToString();
};
input = string.Concat( input.Select( func ).ToArray() );
// digits are a no-no so stick prefix in front
if( char.IsDigit( input[0] ) )
return DIGIT_PREFIX + input.ToUpper();
return input.ToUpper();
}
private enum ConstantNamingStyle {
UppercaseWithUnderscores,
CamelCase
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment