Skip to content

Commit b39c278

Browse files
authored
Merge pull request #1185 from FoundationGames/export-import-opts
Bug Fixes and Improvements to the Shader Pack Option GUI
2 parents d020b33 + 290eba9 commit b39c278

File tree

14 files changed

+712
-159
lines changed

14 files changed

+712
-159
lines changed

src/main/java/net/coderbot/iris/Iris.java

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.coderbot.iris;
22

33
import java.io.IOException;
4+
import java.io.OutputStream;
45
import java.nio.file.FileSystem;
56
import java.nio.file.FileSystemNotFoundException;
67
import java.nio.file.FileSystems;
@@ -21,10 +22,14 @@
2122
import net.coderbot.iris.gui.screen.ShaderPackScreen;
2223
import net.coderbot.iris.pipeline.*;
2324
import net.coderbot.iris.shaderpack.DimensionId;
25+
import net.coderbot.iris.shaderpack.OptionalBoolean;
2426
import net.coderbot.iris.shaderpack.ProgramSet;
2527
import net.coderbot.iris.shaderpack.ShaderPack;
28+
import net.coderbot.iris.shaderpack.option.OptionSet;
2629
import net.coderbot.iris.shaderpack.option.Profile;
2730
import net.coderbot.iris.shaderpack.discovery.ShaderpackDirectoryManager;
31+
import net.coderbot.iris.shaderpack.option.values.MutableOptionValues;
32+
import net.coderbot.iris.shaderpack.option.values.OptionValues;
2833
import net.fabricmc.loader.api.ModContainer;
2934
import net.irisshaders.iris.api.v0.IrisApi;
3035
import net.minecraft.ChatFormatting;
@@ -68,6 +73,9 @@ public class Iris implements ClientModInitializer {
6873
private static KeyMapping shaderpackScreenKeybind;
6974

7075
private static final Map<String, String> shaderPackOptionQueue = new HashMap<>();
76+
// Flag variable used when reloading
77+
// Used in favor of queueDefaultShaderPackOptionValues() for resetting as the
78+
// behavior is more concrete and therefore is more likely to repair a user's issues
7179
private static boolean resetShaderPackOptions = false;
7280

7381
private static String IRIS_VERSION;
@@ -276,7 +284,7 @@ private static boolean loadExternalShaderpack(String name) {
276284
return false;
277285
}
278286

279-
Map<String, String> changedConfigs = loadConfigProperties(shaderPackConfigTxt)
287+
Map<String, String> changedConfigs = tryReadConfigProperties(shaderPackConfigTxt)
280288
.map(properties -> (Map<String, String>) (Map) properties)
281289
.orElse(new HashMap<>());
282290

@@ -288,12 +296,17 @@ private static boolean loadExternalShaderpack(String name) {
288296
}
289297
resetShaderPackOptions = false;
290298

291-
Properties configsToSave = new Properties();
292-
configsToSave.putAll(changedConfigs);
293-
saveConfigProperties(shaderPackConfigTxt, configsToSave);
294-
295299
try {
296300
currentPack = new ShaderPack(shaderPackPath, changedConfigs);
301+
302+
MutableOptionValues changedConfigsValues = currentPack.getShaderPackOptions().getOptionValues().mutableCopy();
303+
304+
// Store changed values from those currently in use by the shader pack
305+
Properties configsToSave = new Properties();
306+
changedConfigsValues.getBooleanValues().forEach((k, v) -> configsToSave.setProperty(k, Boolean.toString(v)));
307+
changedConfigsValues.getStringValues().forEach(configsToSave::setProperty);
308+
309+
tryUpdateConfigPropertiesFile(shaderPackConfigTxt, configsToSave);
297310
} catch (Exception e) {
298311
logger.error("Failed to load the shaderpack \"{}\"!", name);
299312
logger.catching(e);
@@ -358,24 +371,37 @@ private static void setShadersDisabled() {
358371
logger.info("Shaders are disabled");
359372
}
360373

361-
private static Optional<Properties> loadConfigProperties(Path path) {
374+
private static Optional<Properties> tryReadConfigProperties(Path path) {
362375
Properties properties = new Properties();
363376

364-
try {
365-
// NB: config properties are specified to be encoded with ISO-8859-1 by OptiFine,
366-
// so we don't need to do the UTF-8 workaround here.
367-
properties.load(Files.newInputStream(path));
368-
} catch (IOException e) {
369-
// TODO: Better error handling
370-
return Optional.empty();
377+
if (Files.exists(path)) {
378+
try {
379+
// NB: config properties are specified to be encoded with ISO-8859-1 by OptiFine,
380+
// so we don't need to do the UTF-8 workaround here.
381+
properties.load(Files.newInputStream(path));
382+
} catch (IOException e) {
383+
// TODO: Better error handling
384+
return Optional.empty();
385+
}
371386
}
372387

373388
return Optional.of(properties);
374389
}
375390

376-
private static void saveConfigProperties(Path path, Properties properties) {
391+
private static void tryUpdateConfigPropertiesFile(Path path, Properties properties) {
377392
try {
378-
properties.store(Files.newOutputStream(path), null);
393+
if (properties.isEmpty()) {
394+
// Delete the file or don't create it if there are no changed configs
395+
if (Files.exists(path)) {
396+
Files.delete(path);
397+
}
398+
399+
return;
400+
}
401+
402+
try (OutputStream out = Files.newOutputStream(path)) {
403+
properties.store(out, null);
404+
}
379405
} catch (IOException e) {
380406
// TODO: Better error handling
381407
}
@@ -425,6 +451,34 @@ public static void queueShaderPackOptionsFromProfile(Profile profile) {
425451
getShaderPackOptionQueue().putAll(profile.optionValues);
426452
}
427453

454+
public static void queueShaderPackOptionsFromProperties(Properties properties) {
455+
queueDefaultShaderPackOptionValues();
456+
457+
properties.stringPropertyNames().forEach(key ->
458+
getShaderPackOptionQueue().put(key, properties.getProperty(key)));
459+
}
460+
461+
// Used in favor of resetShaderPackOptions as the aforementioned requires the pack to be reloaded
462+
public static void queueDefaultShaderPackOptionValues() {
463+
clearShaderPackOptionQueue();
464+
465+
getCurrentPack().ifPresent(pack -> {
466+
OptionSet options = pack.getShaderPackOptions().getOptionSet();
467+
OptionValues values = pack.getShaderPackOptions().getOptionValues();
468+
469+
options.getStringOptions().forEach((key, mOpt) -> {
470+
if (values.getStringValue(key).isPresent()) {
471+
getShaderPackOptionQueue().put(key, mOpt.getOption().getDefaultValue());
472+
}
473+
});
474+
options.getBooleanOptions().forEach((key, mOpt) -> {
475+
if (values.getBooleanValue(key) != OptionalBoolean.DEFAULT) {
476+
getShaderPackOptionQueue().put(key, Boolean.toString(mOpt.getOption().getDefaultValue()));
477+
}
478+
});
479+
});
480+
}
481+
428482
public static void clearShaderPackOptionQueue() {
429483
getShaderPackOptionQueue().clear();
430484
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package net.coderbot.iris.gui;
2+
3+
import org.jetbrains.annotations.Nullable;
4+
import org.lwjgl.PointerBuffer;
5+
import org.lwjgl.system.MemoryStack;
6+
import org.lwjgl.util.tinyfd.TinyFileDialogs;
7+
8+
import java.nio.file.Path;
9+
import java.nio.file.Paths;
10+
import java.util.Optional;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.concurrent.ExecutorService;
13+
import java.util.concurrent.Executors;
14+
15+
/**
16+
* Class used to make interfacing with {@link TinyFileDialogs} easier and asynchronous.
17+
*/
18+
public final class FileDialogUtil {
19+
private static final ExecutorService FILE_DIALOG_EXECUTOR = Executors.newSingleThreadExecutor();
20+
21+
private FileDialogUtil() {}
22+
23+
/**
24+
* Opens an asynchronous file select dialog window.
25+
*
26+
* @param dialog Whether to open a "save" dialog or an "open" dialog
27+
* @param title The title of the dialog window
28+
* @param origin The path that the window should start at
29+
* @param filterLabel A label used to describe what file extensions are allowed and their purpose
30+
* @param filters The file extension filters used by the dialog, each formatted as {@code "*.extension"}
31+
* @return a {@link CompletableFuture} which is completed once a file is selected or the dialog is cancelled.
32+
*/
33+
public static CompletableFuture<Optional<Path>> fileSelectDialog(DialogType dialog, String title, @Nullable Path origin, @Nullable String filterLabel, String ... filters) {
34+
CompletableFuture<Optional<Path>> future = new CompletableFuture<>();
35+
36+
FILE_DIALOG_EXECUTOR.submit(() -> {
37+
String result = null;
38+
39+
try (MemoryStack stack = MemoryStack.stackPush()) {
40+
PointerBuffer filterBuffer = stack.mallocPointer(filters.length);
41+
42+
for (String filter : filters) {
43+
filterBuffer.put(stack.UTF8(filter));
44+
}
45+
filterBuffer.flip();
46+
47+
String path = origin != null ? origin.toAbsolutePath().toString() : null;
48+
49+
if (dialog == DialogType.SAVE) {
50+
result = TinyFileDialogs.tinyfd_saveFileDialog(title, path, filterBuffer, filterLabel);
51+
} else if (dialog == DialogType.OPEN) {
52+
result = TinyFileDialogs.tinyfd_openFileDialog(title, path, filterBuffer, filterLabel, false);
53+
}
54+
}
55+
56+
future.complete(Optional.ofNullable(result).map(Paths::get));
57+
});
58+
59+
return future;
60+
}
61+
62+
public enum DialogType {
63+
SAVE, OPEN
64+
}
65+
}

src/main/java/net/coderbot/iris/gui/GuiUtil.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,11 @@ public static void playButtonClickSound() {
169169
public static class Icon {
170170
public static final Icon SEARCH = new Icon(0, 0, 7, 8);
171171
public static final Icon CLOSE = new Icon(7, 0, 5, 6);
172-
public static final Icon REFRESH = new Icon(12, 0, 11, 11);
172+
public static final Icon REFRESH = new Icon(12, 0, 10, 10);
173+
public static final Icon EXPORT = new Icon(22, 0, 7, 8);
174+
public static final Icon EXPORT_COLORED = new Icon(29, 0, 7, 8);
175+
public static final Icon IMPORT = new Icon(22, 8, 7, 8);
176+
public static final Icon IMPORT_COLORED = new Icon(29, 8, 7, 8);
173177

174178
private final int u;
175179
private final int v;
@@ -200,5 +204,13 @@ public void draw(PoseStack poseStack, int x, int y) {
200204
// Draw the texture to the screen
201205
GuiComponent.blit(poseStack, x, y, u, v, width, height, 256, 256);
202206
}
207+
208+
public int getWidth() {
209+
return width;
210+
}
211+
212+
public int getHeight() {
213+
return height;
214+
}
203215
}
204216
}

src/main/java/net/coderbot/iris/gui/NavigationController.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public void refresh() {
5252
}
5353
}
5454

55+
public boolean hasHistory() {
56+
return this.history.size() > 0;
57+
}
58+
5559
public void setActiveOptionList(ShaderPackOptionList optionList) {
5660
this.optionList = optionList;
5761
}

0 commit comments

Comments
 (0)