using Godot; using System.Reflection; using System.Collections.Generic; namespace Rokojori { [Tool] [GlobalClass] public partial class SpatialShaderGenerator:ShaderGenerator { [Export] public SpatialShaderData data = new SpatialShaderData(); public override List GetPhases() { return new List() { ShaderPhase.Header, ShaderPhase.RenderMode, ShaderPhase.Includes, ShaderPhase.Variables, ShaderPhase.Functions, ShaderPhase.Vertex, ShaderPhase.Fragment, ShaderPhase.Light }; } public string RokojoriInfo() { var allModules = GetAllModules(); var hashValues = allModules.Map( a => a.GetShaderCacheHash() ); hashValues.Sort(); var hash = hashValues.Join( "-" ); var allInfos = allModules.Map( a => a.GetShaderCacheData() ); return $"// Rokojori Shader @{hash}: \n/*\n" + allInfos.Join( "\n" ) + "\n*/\n"; } List GetAllModules() { return GetHeaderModules().Concat( GetMainModules() ); } List GetHeaderModules() { List list = [ data.transparency, data.shading, data.stencil ]; return list.FilterNulls(); } List GetMainModules() { List list = [ data.geometry, data.uv, data.albedo, data.alpha, data.fading, data.normalMap, data.occlusion, data.roughness, data.metallic, data.specular, data.emission, data.backlight, data.subsurfaceScattering ]; return list.FilterNulls(); } public override List GetShaderGenerationModules( ShaderPhase phase ) { if ( ShaderPhase.Header == phase ) { var info = RokojoriInfo(); return [ new ShaderRawModule( "\n\nshader_type spatial;\n" ), new ShaderRawModule( $"\n{info}\n") ]; } if ( ShaderPhase.RenderMode == phase ) { List modules = [ new ShaderRawModule( "render_mode " ), data.transparency, new ShaderRawModule( ", " ), data.shading, new ShaderRawModule( ";\n" ), ]; if ( data.stencil != null ) { modules.Add( new ShaderRawModule( data.stencil.ToShaderCode() + "\n" ) ); } modules.Add( new ShaderRawModule( "\n" ) ); return modules; } var mainModules = GetMainModules(); if ( ShaderPhase.Includes == phase || ShaderPhase.Variables == phase || ShaderPhase.Functions == phase ) { List preModules = [ data.transparency, data.shading ] ; return preModules.Concat( mainModules ); } if ( ShaderPhase.Vertex == phase ) { return new List() { new ShaderRawModule( "\nvoid vertex()\n{\n\n" ) } .Concat( mainModules ) .Concat ( new ShaderRawModule( "\n}\n" ) ); } if ( ShaderPhase.Fragment == phase ) { return new List() { new ShaderRawModule( "\nvoid fragment()\n{\n\n" ) } .Concat( mainModules ) .Concat ( new ShaderRawModule( "\n}\n" ) ); } return null; } } }