144 lines
5 KiB
Java
144 lines
5 KiB
Java
package com.mojang.blaze3d.preprocessor;
|
|
|
|
import com.google.common.base.Strings;
|
|
import com.google.common.collect.Lists;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.FileUtil;
|
|
import net.minecraft.client.renderer.ShaderDefines;
|
|
import net.minecraft.util.StringUtil;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.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 shaderData) {
|
|
GlslPreprocessor.Context context = new GlslPreprocessor.Context();
|
|
List<String> list = this.processImports(shaderData, context, "");
|
|
list.set(0, this.setVersion((String)list.get(0), context.glslVersion));
|
|
return list;
|
|
}
|
|
|
|
private List<String> processImports(String shaderData, GlslPreprocessor.Context context, String includeDirectory) {
|
|
int i = context.sourceId;
|
|
int j = 0;
|
|
String string = "";
|
|
List<String> list = Lists.<String>newArrayList();
|
|
Matcher matcher = REGEX_MOJ_IMPORT.matcher(shaderData);
|
|
|
|
while (matcher.find()) {
|
|
if (!isDirectiveDisabled(shaderData, matcher, j)) {
|
|
String string2 = matcher.group(2);
|
|
boolean bl = string2 != null;
|
|
if (!bl) {
|
|
string2 = matcher.group(3);
|
|
}
|
|
|
|
if (string2 != null) {
|
|
String string3 = shaderData.substring(j, matcher.start(1));
|
|
String string4 = includeDirectory + string2;
|
|
String string5 = this.applyImport(bl, string4);
|
|
if (!Strings.isNullOrEmpty(string5)) {
|
|
if (!StringUtil.endsWithNewLine(string5)) {
|
|
string5 = string5 + System.lineSeparator();
|
|
}
|
|
|
|
context.sourceId++;
|
|
int k = context.sourceId;
|
|
List<String> list2 = this.processImports(string5, context, bl ? FileUtil.getFullResourcePath(string4) : "");
|
|
list2.set(0, String.format(Locale.ROOT, "#line %d %d\n%s", 0, k, this.processVersions((String)list2.get(0), context)));
|
|
if (!StringUtil.isBlank(string3)) {
|
|
list.add(string3);
|
|
}
|
|
|
|
list.addAll(list2);
|
|
} else {
|
|
String string6 = bl ? String.format(Locale.ROOT, "/*#moj_import \"%s\"*/", string2) : String.format(Locale.ROOT, "/*#moj_import <%s>*/", string2);
|
|
list.add(string + string3 + string6);
|
|
}
|
|
|
|
int k = StringUtil.lineCount(shaderData.substring(0, matcher.end(1)));
|
|
string = String.format(Locale.ROOT, "#line %d %d", k, i);
|
|
j = matcher.end(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
String string2x = shaderData.substring(j);
|
|
if (!StringUtil.isBlank(string2x)) {
|
|
list.add(string + string2x);
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
private String processVersions(String versionData, GlslPreprocessor.Context context) {
|
|
Matcher matcher = REGEX_VERSION.matcher(versionData);
|
|
if (matcher.find() && isDirectiveEnabled(versionData, matcher)) {
|
|
context.glslVersion = Math.max(context.glslVersion, Integer.parseInt(matcher.group(2)));
|
|
return versionData.substring(0, matcher.start(1))
|
|
+ "/*"
|
|
+ versionData.substring(matcher.start(1), matcher.end(1))
|
|
+ "*/"
|
|
+ versionData.substring(matcher.end(1));
|
|
} else {
|
|
return versionData;
|
|
}
|
|
}
|
|
|
|
private String setVersion(String versionData, int glslVersion) {
|
|
Matcher matcher = REGEX_VERSION.matcher(versionData);
|
|
return matcher.find() && isDirectiveEnabled(versionData, matcher)
|
|
? versionData.substring(0, matcher.start(2)) + Math.max(glslVersion, Integer.parseInt(matcher.group(2))) + versionData.substring(matcher.end(2))
|
|
: versionData;
|
|
}
|
|
|
|
private static boolean isDirectiveEnabled(String shaderData, Matcher matcher) {
|
|
return !isDirectiveDisabled(shaderData, matcher, 0);
|
|
}
|
|
|
|
private static boolean isDirectiveDisabled(String shaderData, Matcher matcher, int offset) {
|
|
int i = matcher.start() - offset;
|
|
if (i == 0) {
|
|
return false;
|
|
} else {
|
|
Matcher matcher2 = REGEX_ENDS_WITH_WHITESPACE.matcher(shaderData.substring(offset, matcher.start()));
|
|
if (!matcher2.find()) {
|
|
return true;
|
|
} else {
|
|
int j = matcher2.end(1);
|
|
return j == matcher.start();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
public abstract String applyImport(boolean useFullPath, String directory);
|
|
|
|
public static String injectDefines(String shaderSource, ShaderDefines defines) {
|
|
if (defines.isEmpty()) {
|
|
return shaderSource;
|
|
} else {
|
|
int i = shaderSource.indexOf(10);
|
|
int j = i + 1;
|
|
return shaderSource.substring(0, j) + defines.asSourceDirectives() + "#line 1 0\n" + shaderSource.substring(j);
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static final class Context {
|
|
int glslVersion;
|
|
int sourceId;
|
|
}
|
|
}
|