using Godot; using System.Reflection; using System.Collections.Generic; using System.Linq; namespace Rokojori { [Tool] [GlobalClass] public abstract partial class SpatialOverlayLayer:ShaderGenerationModule { [Export] public SpatialMask[] masks; [Export] public SpatialMaskFormulaType maskFormulaType = SpatialMaskFormulaType.Multiply; [Export] public string customMaskFormula; public enum OverlayMode { Mix, Blend_Alpha } [Export] public OverlayMode overlayMode; public enum ChannelType { RGBA, RGB, RG, R, G, B, A, Float } public ChannelType channelType = ChannelType.RGB; public string GetDataType() { if ( ChannelType.RGBA == channelType ) { return "vec4"; } if ( ChannelType.RGB == channelType ) { return "vec3"; } if ( ChannelType.RG == channelType ) { return "vec2"; } return "float"; } public bool IsColorBlendMode() { List modes = [ OverlayMode.Blend_Alpha ]; return modes.IndexOf( overlayMode ) != -1; } public List GetOverlayCode( ShaderGenerationContext context, string name, string oldValue, string targetValue ) { var list = new List(); var currentValueName = $"{name}Value"; if ( context.isFragmentPhase ) { var dataType = GetDataType(); var initData = $"{dataType} {currentValueName};\n"; list.Add( ToCode( initData.Indent( " " ) ) ); var valueCode = GetLayerCode( context, name, currentValueName ); list.Add( valueCode ); var maskName = $"{name}CombinedMask"; var maskCode = SpatialMaskFormulaTypeUtility.GetFragmentMaskCode( context, maskFormulaType, customMaskFormula, masks, name, maskName ); list.Add( maskCode ); if ( OverlayMode.Mix == overlayMode ) { var blendCode = @$" {targetValue} = mix( {oldValue}, {currentValueName}, {maskName} ); "; list.Add( ToCode( blendCode.Indent( " " ) ) ); } else if ( IsColorBlendMode() ) { var blendModeFunction = ( overlayMode + "" ).Replace( "Blend_", "" ).ToLower(); var blendCode = @$" {targetValue} = blend_{blendModeFunction}( {oldValue}, fade( {currentValueName} * {maskName} ) ); "; list.Add( ToCode( blendCode.Indent( " " ) ) ); } } else { var maskIndex = 0; masks.ForEach( ( m )=> { var maskName = $"{name}Mask{maskIndex}"; var maskCode = m.GetMaskCode( context, name, maskName ); if ( maskCode != null ) { list.Add( maskCode ); } maskIndex++; } ); var layerCode = GetLayerCode( context, name, currentValueName ); if ( layerCode != null ) { list.Add( layerCode ); } } return list; } public abstract List GetLayerCode( ShaderGenerationContext context, string name, string currentValueName ); } }