diff --git a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java index 273ff05..dccda4f 100644 --- a/src/main/java/org/saturnclient/saturnclient/SaturnClient.java +++ b/src/main/java/org/saturnclient/saturnclient/SaturnClient.java @@ -7,6 +7,7 @@ import net.minecraft.client.gui.screen.TitleScreen; import org.saturnclient.saturnclient.auth.Auth; import org.saturnclient.saturnclient.config.ConfigManager; +import org.saturnclient.saturnclient.config.ThemeManager; import org.saturnclient.saturnclient.cosmetics.Hats; import org.saturnclient.saturnclient.cosmetics.cloaks.Cloaks; import org.saturnclient.saturnclient.event.KeyInputHandler; @@ -31,8 +32,9 @@ public class SaturnClient implements ModInitializer { LOGGER.info("Initializing " + MOD_ID); ModManager.init(); ConfigManager.load(); + ThemeManager.load(); - ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> ConfigManager.save()); + ClientLifecycleEvents.CLIENT_STOPPING.register(_o -> {ConfigManager.save(); ThemeManager.save();}); ScreenEvents.BEFORE_INIT.register((client, screen, scaledWidth, scaledHeight) -> { if (SaturnClientConfig.saturnTitleScreen.value && screen instanceof TitleScreen && !(screen instanceof SaturnMenu)) { diff --git a/src/main/java/org/saturnclient/saturnclient/config/Property.java b/src/main/java/org/saturnclient/saturnclient/config/Property.java index e4a82fe..22ba2ab 100644 --- a/src/main/java/org/saturnclient/saturnclient/config/Property.java +++ b/src/main/java/org/saturnclient/saturnclient/config/Property.java @@ -139,4 +139,15 @@ public class Property { public static boolean valueIsNamespace(Object obj) { return obj instanceof Map; } + + @SuppressWarnings("unchecked") + public void setValue(Object value) { + this.value = (T) value; + } + + @SuppressWarnings("unchecked") + public void setValue(Object value, Object defaultValue) { + this.value = (T) value; + this.defaultValue = (T) defaultValue; + } } diff --git a/src/main/java/org/saturnclient/saturnclient/config/Theme.java b/src/main/java/org/saturnclient/saturnclient/config/Theme.java new file mode 100644 index 0000000..5e46c99 --- /dev/null +++ b/src/main/java/org/saturnclient/saturnclient/config/Theme.java @@ -0,0 +1,31 @@ +package org.saturnclient.saturnclient.config; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.saturnclient.saturnclient.SaturnClient; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; + +import net.minecraft.client.MinecraftClient; + +public class Theme { + private Map> currentMap; + + public void setProperty(String name, Property value) { + currentMap.put(name, value); + } + + public Property getProperty(String name) { + return currentMap.get(name); + } +} diff --git a/src/main/java/org/saturnclient/saturnclient/config/ThemeManager.java b/src/main/java/org/saturnclient/saturnclient/config/ThemeManager.java new file mode 100644 index 0000000..64074e5 --- /dev/null +++ b/src/main/java/org/saturnclient/saturnclient/config/ThemeManager.java @@ -0,0 +1,226 @@ +package org.saturnclient.saturnclient.config; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.saturnclient.saturnclient.SaturnClient; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; + +import net.minecraft.client.MinecraftClient; + +public class ThemeManager { + + private static File themeFile = new File( + MinecraftClient.getInstance().runDirectory, + "saturn.theme.json"); + private static Map>> properties = new HashMap<>(); + + // private Map>> states; + private Map> currentStyling; + private String state; + private String[] states; + private String namespace; + + public ThemeManager(String namespace, String... states) { + // this.states = new LinkedHashMap<>(); + this.namespace = namespace; + this.states = states; + currentStyling = new LinkedHashMap<>(); + + properties.put(namespace, new LinkedHashMap<>()); + + for (String s : states) { + properties.put(namespace+"@"+s, new LinkedHashMap<>()); + } + } + + public void setState(String state) { + this.state = state; + + if (this.state != null) { + for (Map.Entry> tProp : properties.get(namespace+"@"+state).entrySet()) { + currentStyling.get(tProp.getKey()).setValue(tProp.getValue().value); + } + } else { + for (Map.Entry> tProp : properties.get(namespace).entrySet()) { + currentStyling.get(tProp.getKey()).setValue(tProp.getValue().value); + } + } + } + + // Generic method to store any type of property + public Property property(String name, Property prop) { + for (String state : states) { + properties.get(namespace+"@"+state).put(name, new Property(prop.value)); + } + + properties.get(namespace).put(name, new Property(prop.value)); + currentStyling.put(name, prop); + + return prop; + } + + public void propertyStateDefault(String state, String name, T value) { + properties.get(namespace+"@"+state).get(name).setValue(value, value); // sets the current and default value + } + + public static void load() { + try { + SaturnClient.LOGGER.info("Starting to load theme..."); + if (!themeFile.exists()) { + themeFile.createNewFile(); + Files.write(themeFile.toPath(), "{}".getBytes()); + } + + JsonObject jsonObject = JsonParser.parseString( + new String(Files.readAllBytes(themeFile.toPath()))).getAsJsonObject(); + + for (String namespace : properties.keySet()) { + JsonElement themeElement = jsonObject.get(namespace); + + if (themeElement == null) + continue; + + JsonObject theme = jsonObject.get(namespace).getAsJsonObject(); + + if (theme == null) { + continue; + } + + Map> propertyMap = properties.get(namespace); + loadProperties(theme, propertyMap); + } + } catch (IOException e) { + SaturnClient.LOGGER.error("Error reading the theme file", e); + } + } + + @SuppressWarnings("unchecked") + private static void loadProperties(JsonObject theme, Map> propertyMap) { + for (String propertyName : propertyMap.keySet()) { + JsonElement c = theme.get(propertyName); + + if (c == null) { + continue; + } + + Property p = propertyMap.get(propertyName); + if (p.matchesJson(c)) { + if (p.getType() == Property.PropertyType.NAMESPACE) { + // Handle nested namespace + JsonObject nestedTheme = c.getAsJsonObject(); + Map> nestedProperties = p.getNamespaceValue(); + loadProperties(nestedTheme, nestedProperties); + } else { + // Handle regular properties + switch (p.getType()) { + case BOOLEAN: + ((Property) p).value = c.getAsBoolean(); + break; + case INTEGER: + ((Property) p).value = c.getAsInt(); + break; + case FLOAT: + ((Property) p).value = c.getAsFloat(); + break; + case STRING: + ((Property) p).value = c.getAsString(); + break; + case HEX: + ((Property) p).value = c.getAsInt(); + break; + default: + break; + } + } + } else { + SaturnClient.LOGGER.warn( + "Property does not match JSON: " + propertyName); + } + } + } + + public static void save() { + try { + SaturnClient.LOGGER.info("Starting to save theme..."); + + JsonObject jsonObject = new JsonObject(); + + // Iterate through all namespaces and their properties + for (String namespace : properties.keySet()) { + JsonObject namespaceTheme = new JsonObject(); + Map> propertyMap = properties.get(namespace); + + // Save properties for this namespace + saveProperties(namespaceTheme, propertyMap); + + // Add the namespace theme to the main JSON object + jsonObject.add(namespace, namespaceTheme); + } + + // Format the json so it can easily be edited + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String formattedJson = gson.toJson(jsonObject); + + // Write the JSON object to the theme file + Files.write(themeFile.toPath(), formattedJson.getBytes()); + SaturnClient.LOGGER.info("Theme saved successfully."); + } catch (IOException e) { + SaturnClient.LOGGER.error("Error saving the theme file", e); + } + } + + @SuppressWarnings("unchecked") + private static void saveProperties(JsonObject theme, Map> propertyMap) { + // Iterate through each property in the namespace + for (String propertyName : propertyMap.keySet()) { + Property property = propertyMap.get(propertyName); + JsonElement propertyValue = null; + + if (property.getType() == Property.PropertyType.NAMESPACE) { + // Handle nested namespace + JsonObject nestedTheme = new JsonObject(); + Map> nestedProperties = (Map>) property.value; + saveProperties(nestedTheme, nestedProperties); + propertyValue = nestedTheme; + } else { + // Convert the property value based on its type + switch (property.getType()) { + case BOOLEAN: + propertyValue = new JsonPrimitive((Boolean) property.value); + break; + case INTEGER: + propertyValue = new JsonPrimitive((Integer) property.value); + break; + case FLOAT: + propertyValue = new JsonPrimitive((Float) property.value); + break; + case STRING: + propertyValue = new JsonPrimitive((String) property.value); + break; + case HEX: + propertyValue = new JsonPrimitive((Integer) property.value); + break; + default: + SaturnClient.LOGGER.warn( + "Unknown property type for: " + propertyName); + break; + } + } + + if (propertyValue != null) { + theme.add(propertyName, propertyValue); + } + } + } +} diff --git a/src/main/java/org/saturnclient/saturnclient/menus/SaturnMenu.java b/src/main/java/org/saturnclient/saturnclient/menus/SaturnMenu.java index 3d3de03..d6ce73f 100644 --- a/src/main/java/org/saturnclient/saturnclient/menus/SaturnMenu.java +++ b/src/main/java/org/saturnclient/saturnclient/menus/SaturnMenu.java @@ -10,6 +10,6 @@ public class SaturnMenu extends SaturnScreen { @Override public void ui() { - draw(new Button("Settings", false).center(width, height)); + draw(new Button("Settings").center(width, height)); } } diff --git a/src/main/java/org/saturnclient/ui2/Element.java b/src/main/java/org/saturnclient/ui2/Element.java index b2cfba8..cabd299 100644 --- a/src/main/java/org/saturnclient/ui2/Element.java +++ b/src/main/java/org/saturnclient/ui2/Element.java @@ -5,9 +5,8 @@ public class Element { protected int y; protected int width; protected int height; - protected int color; - public void render(RenderScope renderScope) { + public void render(RenderScope renderScope, boolean hovering) { } public final void dimensions(int width, int height) { diff --git a/src/main/java/org/saturnclient/ui2/SaturnScreen.java b/src/main/java/org/saturnclient/ui2/SaturnScreen.java index 6c7ee53..796a476 100644 --- a/src/main/java/org/saturnclient/ui2/SaturnScreen.java +++ b/src/main/java/org/saturnclient/ui2/SaturnScreen.java @@ -3,6 +3,7 @@ package org.saturnclient.ui2; import java.util.ArrayList; import java.util.List; +import org.saturnclient.saturnclient.config.ThemeManager; import org.saturnclient.saturnclient.mixin.DrawContextAccessor; import net.minecraft.client.gui.DrawContext; @@ -11,9 +12,11 @@ import net.minecraft.text.Text; public class SaturnScreen extends Screen { protected List elements = new ArrayList<>(); + private int hoveringIndex; public SaturnScreen(String title) { super(Text.literal(title)); + ThemeManager.load(); } public void draw(Element element) { @@ -41,14 +44,22 @@ public class SaturnScreen extends Screen { renderScope.matrices.push(); - for (Element element : elements) { - renderScope.setOpacity(0.5f); + for (int i = 0; i < elements.size(); i++) { + Element element = elements.get(i); + renderScope.matrices.push(); renderScope.matrices.translate(element.x, element.y, 0); - element.render(renderScope); + element.render(renderScope, isMouseInside(mouseX, mouseY, element)); renderScope.matrices.pop(); } renderScope.matrices.pop(); } + + public static boolean isMouseInside(int mouseX, int mouseY, Element element) { + return mouseX >= element.x && + mouseX <= (element.x + element.width) && + mouseY >= element.y && + mouseY <= (element.y + element.height); + } } diff --git a/src/main/java/org/saturnclient/ui2/elements/Button.java b/src/main/java/org/saturnclient/ui2/elements/Button.java index 150c401..42e8b9f 100644 --- a/src/main/java/org/saturnclient/ui2/elements/Button.java +++ b/src/main/java/org/saturnclient/ui2/elements/Button.java @@ -1,5 +1,7 @@ package org.saturnclient.ui2.elements; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.saturnclient.config.ThemeManager; import org.saturnclient.ui2.Element; import org.saturnclient.ui2.RenderScope; import org.saturnclient.ui2.resources.Fonts; @@ -7,22 +9,33 @@ import org.saturnclient.ui2.resources.Fonts; import net.minecraft.util.Identifier; public class Button extends Element { + private static ThemeManager theme = new ThemeManager("Button", "testing"); + private static Property bgColor = theme.property("bg-color", new Property(0xFF000000)); + private static Property fgColor = theme.property("fg-color", new Property(0xFFFFFFFF)); + private static Property bold = theme.property("fg-bold", new Property(false)); + + static { + theme.propertyStateDefault("hovering", "fg-color", 0xFFFF0000); + } + private String text; - private boolean bold; private Identifier font; - public Button(String text, boolean bold) { + public Button(String text) { this.text = text; - this.bold = bold; - this.font = Fonts.getFont(bold); + this.font = Fonts.getFont(bold.value); this.dimensions(Fonts.getWidth(text, font)+ 25 , Fonts.getHeight() + 10); - this.color = 0xFFFFFFFF; } @Override - public void render(RenderScope renderScope) { - renderScope.drawRoundedRectangle(0, 0, width, height, 10, 0xFF000000); + public void render(RenderScope renderScope, boolean hovering) { + if (hovering) { + theme.setState("hovering"); + } else { + theme.setState(null); + } + renderScope.drawRoundedRectangle(0, 0, width, height, 10, bgColor.value); - renderScope.drawText(text, width / 2 - Fonts.getWidth(text, font) / 2, height / 2 - Fonts.getHeight() / 2, bold, color); + renderScope.drawText(text, width / 2 - Fonts.getWidth(text, font) / 2, height / 2 - Fonts.getHeight() / 2, bold.value, fgColor.value); } } diff --git a/src/main/java/org/saturnclient/ui2/elements/Text.java b/src/main/java/org/saturnclient/ui2/elements/Text.java index 2996d41..e80ed57 100644 --- a/src/main/java/org/saturnclient/ui2/elements/Text.java +++ b/src/main/java/org/saturnclient/ui2/elements/Text.java @@ -8,11 +8,10 @@ public class Text extends Element { public Text(String text) { this.text = text; - this.color = 0xFFFFFFFF; } @Override - public void render(RenderScope renderScope) { - renderScope.drawText(this.text, this.x, this.y, false, this.color); + public void render(RenderScope renderScope, boolean hovering) { + renderScope.drawText(this.text, this.x, this.y, false, 0xFFFFFFFF); } }