rj-action-library/Runtime/Shading/Tools/CSShaderClassGenerator/CSShaderClassGenerator.cs

149 lines
4.8 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class CSShaderClassGenerator:Node
{
[Export]
public string resourcePath;
[Export]
public bool generate;
public override void _Process( double delta )
{
if ( generate )
{
generate = false;
Generate();
}
}
public static readonly string ShaderName = "${ShaderName}";
public static readonly string ShaderResourcePath = "${ShaderResourcePath}";
public static readonly string ShaderStaticPropertyNames = "${ShaderStaticPropertyNames}";
public static readonly string ShaderInstancePropertiesDeclarations = "${ShaderInstancePropertiesDeclarations}";
public static readonly string ShaderInstancePropertiesInitializers = "${ShaderInstancePropertiesInitializers}";
public static readonly string MaterialPresets = "${MaterialPresets}";
public void Generate()
{
var shader = ResourceLoader.Load<Shader>( resourcePath );
var resourceParentPath = RegexUtility.ParentPath( resourcePath );
var absoluteFilePath = FilePath.Absolute( ProjectSettings.GlobalizePath( resourcePath ) );
var absoluteParentPath = absoluteFilePath.CreateAbsoluteParent();
RJLog.Log( resourceParentPath );
var shaderName = absoluteFilePath.fileName;
var members = Shaders.GetUniformMembers( shader );
var templatePath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime/Shading/Tools/CSShaderClassGenerator/CSShaderClassTemplate.txt" );
var template = FilesSync.LoadUTF8( templatePath );
var staticProps = new List<string>();
var instanceProps = new List<string>();
var instanceInitializers = new List<string>();
members.ForEach(
( m )=>
{
var type = m.GetPropertyNameType();
var name = m.name;
var csName = name.ToCamelCase();
var declaration = "public static readonly ${type}PropertyName ${csName} = ${type}PropertyName.Create( \"${name}\" );";
var instance = "public readonly CustomMaterialProperty<${csType}> ${csName};";
var init = "${csName} = new CustomMaterialProperty<${csType}>( this, ${ShaderName}.${csName} );";
var csType = type;
if ( csType == "Float" )
{
csType = "float";
}
else if ( csType == "Int" )
{
csType = "float";
}
var map = new StringMap();
map[ "${type}" ] = type;
map[ "${csType}"] = csType;
map[ "${name}" ] = name;
map[ "${csName}" ] = csName;
map[ "${ShaderName}"] = shaderName;
staticProps.Add( map.ReplaceAll( declaration ) );
instanceProps.Add( map.ReplaceAll( instance ) );
instanceInitializers.Add( map.ReplaceAll( init ) );
}
);
var materials = FilesSync.GetFiles( absoluteParentPath.fullPath,
( f ) =>
{
return f.hasFileExtension( "material" );
}
);
var presets = new List<string>();
materials.ForEach( m =>
{
var materialName = m.fileName;
var shortName = materialName;
if ( materialName.ToLower().StartsWith( shaderName.ToLower() ) )
{
shortName = shortName.Substring( shaderName.Length );
}
var declaration =
"public static readonly CachedResource<${ShaderName}Material> ${csName} = CustomMaterial.Cached<${ShaderName}Material>(\n" +
" \"${materialPath}\"\n" +
" );";
var mMap = new StringMap();
mMap[ "${materialPath}" ] = resourceParentPath + "/" + materialName + ".material";
mMap[ "${ShaderName}" ] = shaderName;
mMap[ "${csName}" ] = RegexUtility.ToValidCSName( shortName ).ToPascalCase();
presets.Add( mMap.ReplaceAll( declaration ) );
}
);
var variables = new StringMap();
variables[ CSShaderClassGenerator.ShaderName ] = shaderName;
variables[ CSShaderClassGenerator.ShaderResourcePath ] = resourcePath;
variables[ CSShaderClassGenerator.ShaderStaticPropertyNames ] = Lists.Join( staticProps, "\n " );
variables[ CSShaderClassGenerator.ShaderInstancePropertiesDeclarations ] = Lists.Join( instanceProps, "\n " );
variables[ CSShaderClassGenerator.ShaderInstancePropertiesInitializers ] = Lists.Join( instanceInitializers, "\n " );
variables[ CSShaderClassGenerator.MaterialPresets ] = Lists.Join( presets, "\n " );
var shaderClass = variables.ReplaceAll( template );
var outputPath = absoluteFilePath.WithExtension( "cs" );
FilesSync.SaveUTF8( outputPath.fullPath, shaderClass );
this.LogInfo( "\nGenerated >> ", outputPath.fullPath, "\n" + shaderClass );
}
}
}