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; [Export] public int numVariants = -1; public virtual List GetPhases() { return new List(); } public virtual List GetShaderGenerationModules( ShaderPhase phase ) { return new List(); } public virtual ShaderGenerationContext GenerateShaderVariants() { numVariants = 0; 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 variants = m.GetVariants( context ); if ( variants == null ) { return; } variants.ForEach( c => { c.shaderCode.ForEach( cs => { cs.phase = phase; cs.sortableCode = m.CodeIsSortable( phase ); } ); } ); this.LogInfo( phase, m.GetType().Name, ">>", variants.Count ); context.AddVariants( variants ); } ); } ); return context; } public void UpdateShader() { numVariants = 0; var context = GenerateShaderVariants(); numVariants = context.variants.Count; // 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; } } } }