GlslPreprocessor.java

com.mojang.blaze3d.preprocessor.GlslPreprocessor

信息

  • 全限定名:com.mojang.blaze3d.preprocessor.GlslPreprocessor
  • 类型:public abstract class
  • 包:com.mojang.blaze3d.preprocessor
  • 源码路径:src/main/java/com/mojang/blaze3d/preprocessor/GlslPreprocessor.java
  • 起始行号:L17
  • 职责:

    TODO

字段/常量

  • C_COMMENT

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L18
    • 说明:

      TODO

  • LINE_COMMENT

    • 类型: String
    • 修饰符: private static final
    • 源码定位: L19
    • 说明:

      TODO

  • REGEX_MOJ_IMPORT

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L20
    • 说明:

      TODO

  • REGEX_VERSION

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L23
    • 说明:

      TODO

  • REGEX_ENDS_WITH_WHITESPACE

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L26
    • 说明:

      TODO

内部类/嵌套类型

  • com.mojang.blaze3d.preprocessor.GlslPreprocessor.Context
    • 类型: class
    • 修饰符: private static final
    • 源码定位: L141
    • 说明:

      TODO

构造器

方法

下面的方法块按源码顺序生成。

public List<String> process(String source) @ L28

  • 方法名:process
  • 源码定位:L28
  • 返回类型:List
  • 修饰符:public

参数:

  • source: String

说明:

TODO

private List<String> processImports(String source, GlslPreprocessor.Context context, String parentPath) @ L35

  • 方法名:processImports
  • 源码定位:L35
  • 返回类型:List
  • 修饰符:private

参数:

  • source: String
  • context: GlslPreprocessor.Context
  • parentPath: String

说明:

TODO

private String processVersions(String source, GlslPreprocessor.Context context) @ L92

  • 方法名:processVersions
  • 源码定位:L92
  • 返回类型:String
  • 修饰符:private

参数:

  • source: String
  • context: GlslPreprocessor.Context

说明:

TODO

private String setVersion(String source, int version) @ L102

  • 方法名:setVersion
  • 源码定位:L102
  • 返回类型:String
  • 修饰符:private

参数:

  • source: String
  • version: int

说明:

TODO

private static boolean isDirectiveEnabled(String source, Matcher matcher) @ L109

  • 方法名:isDirectiveEnabled
  • 源码定位:L109
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • source: String
  • matcher: Matcher

说明:

TODO

private static boolean isDirectiveDisabled(String source, Matcher matcher, int start) @ L113

  • 方法名:isDirectiveDisabled
  • 源码定位:L113
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • source: String
  • matcher: Matcher
  • start: int

说明:

TODO

public abstract String applyImport(boolean isRelative, String path) @ L128

  • 方法名:applyImport
  • 源码定位:L128
  • 返回类型:String
  • 修饰符:public abstract

参数:

  • isRelative: boolean
  • path: String

说明:

TODO

public static String injectDefines(String source, ShaderDefines defines) @ L130

  • 方法名:injectDefines
  • 源码定位:L130
  • 返回类型:String
  • 修饰符:public static

参数:

  • source: String
  • defines: ShaderDefines

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public abstract class GlslPreprocessor {
    private static final String C_COMMENT = "/\\*(?:[^*]|\\*+[^*/])*\\*+/";
    private static final String LINE_COMMENT = "//[^\\v]*";
    private static final Pattern REGEX_MOJ_IMPORT = Pattern.compile(
        "(#(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*moj_import(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*(?:\"(.*)\"|<(.*)>))"
    );
    private static final Pattern REGEX_VERSION = Pattern.compile(
        "(#(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*version(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*(\\d+))\\b"
    );
    private static final Pattern REGEX_ENDS_WITH_WHITESPACE = Pattern.compile("(?:^|\\v)(?:\\s|/\\*(?:[^*]|\\*+[^*/])*\\*+/|(//[^\\v]*))*\\z");
 
    public List<String> process(String source) {
        GlslPreprocessor.Context context = new GlslPreprocessor.Context();
        List<String> sourceList = this.processImports(source, context, "");
        sourceList.set(0, this.setVersion(sourceList.get(0), context.glslVersion));
        return sourceList;
    }
 
    private List<String> processImports(String source, GlslPreprocessor.Context context, String parentPath) {
        int thisSourceId = context.sourceId;
        int previousMatchEnd = 0;
        String lineMacro = "";
        List<String> sourceList = Lists.newArrayList();
        Matcher matcher = REGEX_MOJ_IMPORT.matcher(source);
 
        while (matcher.find()) {
            if (!isDirectiveDisabled(source, matcher, previousMatchEnd)) {
                String path = matcher.group(2);
                boolean isRelative = path != null;
                if (!isRelative) {
                    path = matcher.group(3);
                }
 
                if (path != null) {
                    String sourceBeforeImport = source.substring(previousMatchEnd, matcher.start(1));
                    String importPath = parentPath + path;
                    String contents = this.applyImport(isRelative, importPath);
                    if (!Strings.isNullOrEmpty(contents)) {
                        if (!StringUtil.endsWithNewLine(contents)) {
                            contents = contents + System.lineSeparator();
                        }
 
                        context.sourceId++;
                        int importSourceId = context.sourceId;
                        List<String> importedSources = this.processImports(contents, context, isRelative ? FileUtil.getFullResourcePath(importPath) : "");
                        importedSources.set(
                            0, String.format(Locale.ROOT, "#line %d %d\n%s", 0, importSourceId, this.processVersions(importedSources.get(0), context))
                        );
                        if (!StringUtil.isBlank(sourceBeforeImport)) {
                            sourceList.add(sourceBeforeImport);
                        }
 
                        sourceList.addAll(importedSources);
                    } else {
                        String disabledImport = isRelative
                            ? String.format(Locale.ROOT, "/*#moj_import \"%s\"*/", path)
                            : String.format(Locale.ROOT, "/*#moj_import <%s>*/", path);
                        sourceList.add(lineMacro + sourceBeforeImport + disabledImport);
                    }
 
                    int lineCount = StringUtil.lineCount(source.substring(0, matcher.end(1)));
                    lineMacro = String.format(Locale.ROOT, "#line %d %d", lineCount, thisSourceId);
                    previousMatchEnd = matcher.end(1);
                }
            }
        }
 
        String remaining = source.substring(previousMatchEnd);
        if (!StringUtil.isBlank(remaining)) {
            sourceList.add(lineMacro + remaining);
        }
 
        return sourceList;
    }
 
    private String processVersions(String source, GlslPreprocessor.Context context) {
        Matcher matcher = REGEX_VERSION.matcher(source);
        if (matcher.find() && isDirectiveEnabled(source, matcher)) {
            context.glslVersion = Math.max(context.glslVersion, Integer.parseInt(matcher.group(2)));
            return source.substring(0, matcher.start(1)) + "/*" + source.substring(matcher.start(1), matcher.end(1)) + "*/" + source.substring(matcher.end(1));
        } else {
            return source;
        }
    }
 
    private String setVersion(String source, int version) {
        Matcher matcher = REGEX_VERSION.matcher(source);
        return matcher.find() && isDirectiveEnabled(source, matcher)
            ? source.substring(0, matcher.start(2)) + Math.max(version, Integer.parseInt(matcher.group(2))) + source.substring(matcher.end(2))
            : source;
    }
 
    private static boolean isDirectiveEnabled(String source, Matcher matcher) {
        return !isDirectiveDisabled(source, matcher, 0);
    }
 
    private static boolean isDirectiveDisabled(String source, Matcher matcher, int start) {
        int checkLength = matcher.start() - start;
        if (checkLength == 0) {
            return false;
        } else {
            Matcher preceedingWhiteSpace = REGEX_ENDS_WITH_WHITESPACE.matcher(source.substring(start, matcher.start()));
            if (!preceedingWhiteSpace.find()) {
                return true;
            } else {
                int lineCommentEnd = preceedingWhiteSpace.end(1);
                return lineCommentEnd == matcher.start();
            }
        }
    }
 
    public abstract @Nullable String applyImport(boolean isRelative, String path);
 
    public static String injectDefines(String source, ShaderDefines defines) {
        if (defines.isEmpty()) {
            return source;
        } else {
            int versionLineEnd = source.indexOf(10);
            int injectIndex = versionLineEnd + 1;
            return source.substring(0, injectIndex) + defines.asSourceDirectives() + "#line 1 0\n" + source.substring(injectIndex);
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    private static final class Context {
        private int glslVersion;
        private int sourceId;
    }
}

引用的其他类

  • LoggedChatMessage

    • 引用位置: 方法调用
    • 关联成员: System.lineSeparator()
  • ShaderDefines

    • 引用位置: 参数
  • FileUtil

    • 引用位置: 方法调用
    • 关联成员: FileUtil.getFullResourcePath()
  • StringUtil

    • 引用位置: 方法调用
    • 关联成员: StringUtil.endsWithNewLine(), StringUtil.isBlank(), StringUtil.lineCount()
  • TropicalFish

    • 引用位置: 字段/方法调用
    • 关联成员: Pattern.compile()