using Godot; using System.Reflection; using System.Collections.Generic; using System.IO; namespace Rokojori { [Tool] [GlobalClass] public partial class ShaderGenerator:Node { [ExportToolButton( "Create" )] public Callable CreateButton => Callable.From( ()=> { UpdateShader(); } ); [Export] public string path; [Export] public string shaderName; [Export] public Shader shader; [Export] public bool sendGodotUpdateMessage = false; public virtual List GetPhases() { return new List(); } public virtual List GetShaderGenerationModules( ShaderPhase phase ) { return new List(); } public virtual ShaderGenerationContext GenerateShaderVariants() { var context = new ShaderGenerationContext(); var phases = GetPhases(); this.LogInfo( context.variants ); phases.ForEach( ( phase )=> { context.phase = phase; var modules = GetShaderGenerationModules( phase ); this.LogInfo( "PHASE", phase, ">>", context.variants, "MODS:", modules == null ? "-" : ( modules.Map( m => m.GetType().Name ) )); if ( modules == null ) { return; } modules.ForEach( ( m )=> { var code = m.GetCode( context ); this.LogInfo( phase, m.GetType().Name, code ); if ( code == null ) { return; } context.Add( code ); } ); } ); return context; } public void UpdateShader() { var context = GenerateShaderVariants(); this.LogInfo( "Created variants:", context.variants ); var first = true; foreach ( var variant in context.variants ) { var shaderCode = variant.GetCode( context ); var absolutePath = path; if ( absolutePath.StartsWith( "res://" ) || absolutePath.StartsWith( "user://" ) ) { absolutePath = ProjectSettings.GlobalizePath( path ); } this.LogInfo( shaderCode ); var filePath = FilePath.Join( absolutePath, shaderName + variant.variantName + ".gdshader" ); FilesSync.SaveUTF8( filePath, shaderCode ); if ( sendGodotUpdateMessage ) { GodotEditorHelper.UpdateFile( filePath ); } if ( first ) { shader = ResourceLoader.Load( filePath ); } first =false; } } } }