using Godot; using System.Reflection; using System.Collections.Generic; using System.Linq; namespace Rokojori { public class ShaderCode { public string variantName = ""; public ShaderPhase phase; public bool sortableCode = false; public List variableOccurances = new List(); protected virtual string _GetCode( ShaderGenerationContext context ) { return ""; } public string GetCode( ShaderGenerationContext context ) { return _GetCode( context ); } public void ResolveVariableOccurances( ShaderGenerationContext context ) { var code = GetCode( context ); var lexed = GDShaderLexer.Lex( code ); var index = lexed.CreateIndex(); var relevantVariables = ShaderCodeVariable.DefaultVariables.Map( v => v.variableName ).CreateSet(); var foundVariables = lexed.Filter( le => le.Is( LexerMatcherLibrary.CwordMatcher ) && relevantVariables.Contains( le.match ) ); var mapped = new Dictionary(); foundVariables.ForEach( ( w )=> { var nextTokenResult = LexerEvent.Find( lexed, index[ w ], ( le ) => { if ( le.Is( LexerMatcherLibrary.OperatorMatcher ) ) { return LexerEvent.FindResultType.Found; } if ( le.IsAnyOf( LexerMatcherLibrary.Ignore ) ) { return LexerEvent.FindResultType.KeepSearching; } return LexerEvent.FindResultType.NotFound; } ); if ( LexerEvent.FindResultType.NotFound == nextTokenResult.type ) { variableOccurances.Add( ShaderCodeVariableOccurance.Read( w.match ) ); } else { var token = lexed[ nextTokenResult.index ]; if ( token.match == "=" ) { variableOccurances.Add( ShaderCodeVariableOccurance.Assignment( w.match ) ); } else if ( token.MatchIsAny( "++", "--", "+=", "-=", "*=", "/=" ) ) { variableOccurances.Add( ShaderCodeVariableOccurance.Modification( w.match ) ); } else { variableOccurances.Add( ShaderCodeVariableOccurance.Read( w.match ) ); } } mapped[ variableOccurances.Last() ] = w; } ); variableOccurances.ForEach( ( vo )=> { var lineInfo = mapped[ vo ].GetLineInfo( code ); RJLog.Log( vo.type, ":", vo.variable.variableName, " >> ", lineInfo ); } ); } } public class StringShaderCode:ShaderCode { public string code = ""; public StringShaderCode( string code ) { this.code = code; } protected override string _GetCode( ShaderGenerationContext context ) { return code; } public static StringShaderCode FromLines( List code, bool addBreaks = true ) { return new StringShaderCode( code.Join( addBreaks ? "\n" : "" ) ); } } public class BuiltInTextureShaderCode:ShaderCode { public enum TextureType { Screen, Depth, NormalRoughness } public TextureType textureType => _textureType; TextureType _textureType; public static BuiltInTextureShaderCode Screen { get { var sc = new BuiltInTextureShaderCode(); sc._textureType = TextureType.Screen; return sc; } } public static BuiltInTextureShaderCode Depth { get { var sc = new BuiltInTextureShaderCode(); sc._textureType = TextureType.Depth; return sc; } } public static BuiltInTextureShaderCode NormalRoughness { get { var sc = new BuiltInTextureShaderCode(); sc._textureType = TextureType.NormalRoughness; return sc; } } public ShaderCode GetBuiltInCode() { if ( _textureType == TextureType.Screen ) { return new StringShaderCode( ShaderGenerationModule.ScreenTextureUniform().LineBreak() ); } if ( _textureType == TextureType.Depth ) { return new StringShaderCode( ShaderGenerationModule.DepthTextureUniform().LineBreak() ); } if ( _textureType == TextureType.NormalRoughness ) { return new StringShaderCode( ShaderGenerationModule.NormalRoughnessTextureUniform().LineBreak() ); } return null; } } }