From 58a9c6ef38ec1a5409467b9033d069d4d4f3d168 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:16:32 +0530 Subject: [PATCH 01/40] So many changes. ContextMenu skins, fixed many bugs, and more comprehensive stuff. --- .../dynamichud/DynamicHUD.java | 10 +- .../dynamichud/DynamicHudTest.java | 4 +- .../screens/AbstractMoveableScreen.java | 21 +- .../utils/contextmenu/ContextMenu.java | 146 ++++-- .../utils/contextmenu/ContextMenuManager.java | 91 ++++ .../contextmenu/ContextMenuProperties.java | 181 ++++++++ .../contextmenu/ContextMenuProvider.java | 6 + .../dynamichud/utils/contextmenu/Option.java | 60 ++- .../contextmenuscreen/ContextMenuScreen.java | 87 ++++ .../ContextMenuScreenFactory.java | 14 + .../DefaultContextMenuScreenFactory.java | 15 + .../contextmenu/options/BooleanOption.java | 54 ++- .../contextmenu/options/ColorOption.java | 24 +- .../contextmenu/options/DoubleOption.java | 25 +- .../utils/contextmenu/options/EnumOption.java | 19 +- .../utils/contextmenu/options/ListOption.java | 18 +- .../contextmenu/options/RunnableOption.java | 18 +- .../contextmenu/options/SubMenuOption.java | 39 +- .../coloroption/ColorGradientPicker.java | 108 +++-- .../coloroption/ColorPickerButton.java | 4 +- .../contextmenu/skinsystem/ClassicSkin.java | 264 +++++++++++ .../contextmenu/skinsystem/MinecraftSkin.java | 419 ++++++++++++++++++ .../utils/contextmenu/skinsystem/Skin.java | 55 +++ .../contextmenu/skinsystem/SkinRenderer.java | 26 ++ .../dynamichud/widget/Widget.java | 63 ++- .../dynamichud/widget/WidgetManager.java | 27 +- .../dynamichud/widget/WidgetRenderer.java | 4 +- .../dynamichud/widgets/TextWidget.java | 42 +- src/main/resources/dynamichud.mixins.json | 5 +- 29 files changed, 1643 insertions(+), 206 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 2f2f4be..5d43b98 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -6,6 +6,7 @@ import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.widgets.ItemWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; @@ -73,7 +74,8 @@ public void onInitializeClient() { // Add WidgetData of included widgets WidgetManager.registerCustomWidgets( - TextWidget.DATA + TextWidget.DATA, + ItemWidget.DATA ); //YACL load @@ -112,7 +114,7 @@ public void onInitializeClient() { DHIntegration.initAfter(); // Get the instance of AbstractMoveableScreen - screen = Objects.requireNonNull( DHIntegration.getMovableScreen()); + screen = Objects.requireNonNull(DHIntegration.getMovableScreen()); // Get the keybind to open the screen instance binding = DHIntegration.getKeyBind(); @@ -155,11 +157,11 @@ public void onInitializeClient() { if (e instanceof IOException) { logger.warn("An error has occurred while loading widgets of mod {}", modId, e); } else { - logger.warn("Mod {} has improper implementation of DynamicHUD", modId, e); + logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); } } }); - printInfo("(DynamicHUD) Integration of mods found was successful"); + printInfo("(DynamicHUD) Integration of supported mods was successful"); //Global config saving (YACL) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java index 0883606..bc68bca 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java @@ -51,8 +51,8 @@ public void init() { .build(); DynamicHUDWidget = new TextWidget.Builder() - .setX(5) - .setY(5) + .setX(0) + .setY(0) .setDraggable(false) .rainbow(true) .setDRKey("DynamicHUD") diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 7b62fdc..58bf8dd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.screens; import com.tanishisherewith.dynamichud.config.GlobalConfig; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.minecraft.client.gui.DrawContext; @@ -27,6 +28,7 @@ public void onDisplayed() { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { widgetRenderer.mouseDragged(mouseX, mouseY, button, snapSize); + ContextMenuManager.getInstance().handleMouseDragged(mouseX,mouseY,button,deltaX,deltaY); return false; } @@ -35,30 +37,35 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if(widgetRenderer.mouseClicked(mouseX, mouseY, button)){ handleClickOnWidget(widgetRenderer.selectedWidget,mouseX,mouseY,button); } + ContextMenuManager.getInstance().handleMouseClicked(mouseX,mouseY,button); return false; } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { widgetRenderer.mouseReleased(mouseX, mouseY, button); + ContextMenuManager.getInstance().handleMouseReleased(mouseX,mouseY,button); return false; } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyPressed(keyCode); + ContextMenuManager.getInstance().handleKeyPressed(keyCode, scanCode, modifiers); return super.keyPressed(keyCode, scanCode, modifiers); } @Override public boolean keyReleased(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyReleased(keyCode); + ContextMenuManager.getInstance().handleKeyReleased(keyCode, scanCode, modifiers); return super.keyReleased(keyCode, scanCode, modifiers); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { widgetRenderer.mouseScrolled(mouseX, mouseY, verticalAmount, horizontalAmount); + ContextMenuManager.getInstance().handleMouseScrolled(mouseX, mouseY, horizontalAmount,verticalAmount); return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @@ -81,8 +88,17 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) // Draw each widget widgetRenderer.renderWidgets(drawContext, mouseX, mouseY); - if(widgetRenderer.selectedWidget != null && GlobalConfig.get().shouldDisplayDescriptions() && widgetRenderer.selectedWidget.DATA.description() != null){ - drawContext.drawTooltip(client.textRenderer,Text.of(widgetRenderer.selectedWidget.DATA.description()),mouseX,mouseY); + ContextMenuManager.getInstance().renderAll(drawContext,mouseX,mouseY); + + if(GlobalConfig.get().shouldDisplayDescriptions()) { + for (Widget widget : widgetRenderer.getWidgets()) { + if (widget == null || widget.shiftDown) continue; + + if (widget.getWidgetBox().isMouseOver(mouseX, mouseY)) { + drawContext.drawTooltip(client.textRenderer, Text.of(widget.DATA.description()), mouseX, mouseY); + break; + } + } } } public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button){ @@ -93,6 +109,7 @@ public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int public void close() { widgetRenderer.isInEditor = false; widgetRenderer.onCloseScreen(); + ContextMenuManager.getInstance().onClose(); super.close(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 688d7b8..4297b69 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -1,67 +1,101 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; +import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreen; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.util.math.MathHelper; import java.awt.*; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class ContextMenu { + + //The properties of a context menu + protected final ContextMenuProperties properties; + private final List> options = new ArrayList<>(); // The list of options in the context menu public int x, y; // Width is counted while the options are being rendered. // FinalWidth is the width at the end of the count. private int width = 0; public int finalWidth = 0; - public int height = 0; - public Color backgroundColor = new Color(107, 112, 126, 124); - private final Color darkerBorderColor = backgroundColor.darker().darker().darker().darker().darker().darker(); + public int height = 0, widgetHeight = 0; //Todo: Add padding around the rectangle instead of just one side. - public int padding = 5; // The amount of padding around the rectangle - public int heightOffset = 4; // Height offset from the widget public boolean shouldDisplay = false; - public static boolean drawBorder = true; - protected float scale = 0.0f; + public float scale = 0.0f; + public final Color darkerBackgroundColor; + public boolean newScreenFlag = false; + public Screen parentScreen = null; + private final ContextMenuScreenFactory screenFactory; - public ContextMenu(int x, int y) { + public ContextMenu(int x, int y, ContextMenuProperties properties) { + this(x, y, properties, new DefaultContextMenuScreenFactory()); + } + + public ContextMenu(int x, int y, ContextMenuProperties properties, ContextMenuScreenFactory screenFactory) { this.x = x; - this.y = y + heightOffset; + this.y = y + properties.getHeightOffset(); + this.properties = properties; + this.screenFactory = screenFactory; + darkerBackgroundColor = properties.getBackgroundColor().darker().darker().darker().darker().darker().darker(); } public void addOption(Option option) { + option.updateProperties(this.getProperties()); options.add(option); } - public void render(DrawContext drawContext, int x, int y, int height, int mouseX, int mouseY) { - this.x = x; - this.y = y + heightOffset + height; - if (!shouldDisplay) return; + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { + if(newScreenFlag && screenFactory != null) { + DynamicHUD.MC.setScreen(screenFactory.create(this,properties)); + return; + } + this.x = x; + this.y = y + properties.getHeightOffset() + widgetHeight; update(); + if (scale <= 0.0f || newScreenFlag) return; + DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, scale); + properties.getSkin().setContextMenu(this); + properties.getSkin().renderContextMenu(drawContext,this,mouseX,mouseY); + + /* // Draw the background - DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1, this.y, this.width, this.height, 2,backgroundColor.getRGB()); - if(drawBorder){ - DrawHelper.drawOutlineRoundedBox(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1,this.y,this.width,this.height,2,0.7f,darkerBorderColor.getRGB()); + DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1, this.y, this.width, this.height, 2,properties.getBackgroundColor().getRGB()); + if(properties.shouldDrawBorder()){ + DrawHelper.drawOutlineRoundedBox(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1,this.y,this.width,this.height,2, properties.getBorderWidth(), darkerBorderColor.getRGB()); } int yOffset = this.y + 3; this.width = 10; for (Option option : options) { if (!option.shouldRender()) continue; - if(isMouseOver(mouseX,mouseY, this.x +1,yOffset-1,this.finalWidth - 2,option.height)){ - DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x,yOffset - 1.24f,this.finalWidth - 2,option.height + 0.48f,2,backgroundColor.darker().darker().getRGB()); + + // Adjust mouse coordinates based on the scale + int adjustedMouseX = (int) (mouseX / GlobalConfig.get().getScale()); + int adjustedMouseY = (int) (mouseY / GlobalConfig.get().getScale()); + + if (isMouseOver(adjustedMouseX, adjustedMouseY, this.x + 1, yOffset - 1, this.finalWidth - 2, option.height)) { + DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x, yOffset - 1.24f, this.finalWidth - 2, option.height + 0.48f, 2,properties.getBackgroundColor().darker().darker().getRGB()); } option.render(drawContext, x + 2, yOffset,mouseX,mouseY); this.width = Math.max(this.width, option.width); yOffset += option.height + 1; } - this.width = this.width + padding; + this.width = this.width + properties.getPadding(); this.finalWidth = this.width; this.height = (yOffset - this.y); + */ + DrawHelper.stopScaling(drawContext.getMatrices()); } public boolean isMouseOver(int mouseX, int mouseY, int x, int y, int width, int height){ @@ -69,22 +103,38 @@ public boolean isMouseOver(int mouseX, int mouseY, int x, int y, int width, int } public void update() { - // Update the scale - float scaleSpeed = 0.1f; - scale += scaleSpeed; - if (scale > 1.0f) { + if(!properties.enableAnimations()){ scale = 1.0f; + return; } + + // Update the scale + if(shouldDisplay){ + scale += 0.1f; + } else{ + scale -= 0.1f; + } + + scale = MathHelper.clamp(scale,0,1.0f); } public void close() { + if(newScreenFlag && scale <= 0 && parentScreen != null){ + shouldDisplay = false; + newScreenFlag = false; + DynamicHUD.MC.setScreen(parentScreen); + } + for(Option option: options){ + option.onClose(); + } shouldDisplay = false; - scale = 0.0f; + newScreenFlag = false; } public void open() { shouldDisplay = true; update(); + parentScreen = DynamicHUD.MC.currentScreen; } public void toggleDisplay() { @@ -100,6 +150,7 @@ public void mouseClicked(double mouseX, double mouseY, int button) { for (Option option : options) { option.mouseClicked(mouseX, mouseY, button); } + properties.getSkin().mouseClicked(this,mouseX,mouseY,button); } public void mouseReleased(double mouseX, double mouseY, int button) { @@ -107,27 +158,47 @@ public void mouseReleased(double mouseX, double mouseY, int button) { for (Option option : options) { option.mouseReleased(mouseX, mouseY, button); } + properties.getSkin().mouseReleased(this,mouseX,mouseY,button); } - public void mouseDragged(double mouseX, double mouseY, int button) { + public void mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { if (!shouldDisplay) return; for (Option option : options) { - option.mouseDragged(mouseX, mouseY, button); + option.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); } + properties.getSkin().mouseDragged(this,mouseX,mouseY,button,deltaX,deltaY); } - public void keyPressed(int key) { + public void keyPressed(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; for (Option option : options) { option.keyPressed(key); } + + properties.getSkin().keyPressed(this,key,scanCode,modifiers); + } - public void keyReleased(int key) { + public void keyReleased(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; for (Option option : options) { option.keyReleased(key); } + properties.getSkin().keyReleased(this,key,scanCode,modifiers); + + } + + public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + for(Option option: options){ + option.mouseScrolled(mouseX,mouseY,horizontalAmount,verticalAmount); + } + properties.getSkin().mouseScrolled(this,mouseX,mouseY,horizontalAmount,verticalAmount); + } + + public void set(int x,int y, int widgetHeight){ + this.x = x; + this.y = y; + this.widgetHeight = widgetHeight; } public int getX() { @@ -138,14 +209,29 @@ public int getY() { return y; } public List> getOptions() { - return options; + return Collections.unmodifiableList(options); } public int getHeight() { return height; } - public int getWidth() { + public int getFinalWidth() { return finalWidth; } + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setFinalWidth(int finalWidth) { + this.finalWidth = finalWidth; + } + + public ContextMenuProperties getProperties() { + return properties; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java new file mode 100644 index 0000000..29b5773 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java @@ -0,0 +1,91 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu; + +import net.minecraft.client.gui.DrawContext; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class ContextMenuManager { + private static final ContextMenuManager INSTANCE = new ContextMenuManager(); + private final List providers = new ArrayList<>(); + + private ContextMenuManager() {} + + public static ContextMenuManager getInstance() { + return INSTANCE; + } + + public void registerProvider(ContextMenuProvider provider) { + providers.add(provider); + } + + public void renderAll(DrawContext drawContext, int mouseX, int mouseY) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.render(drawContext, contextMenu.getX(), contextMenu.getY(), mouseX, mouseY); + } + } + } + + public void handleMouseClicked(double mouseX, double mouseY, int button) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.mouseClicked(mouseX, mouseY, button); + } + } + } + + public void handleMouseReleased(double mouseX, double mouseY, int button) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.mouseReleased(mouseX, mouseY, button); + } + } + } + + public void handleMouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + } + } + + public void handleKeyPressed(int key, int scanCode, int modifiers) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.keyPressed(key, scanCode, modifiers); + } + } + } + + public void handleKeyReleased(int key, int scanCode, int modifiers) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.keyReleased(key, scanCode, modifiers); + } + } + } + + public void handleMouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + } + } + } + public void onClose(){ + for(ContextMenuProvider provider: providers){ + provider.getContextMenu().close(); + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java new file mode 100644 index 0000000..330f561 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -0,0 +1,181 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu; + +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ClassicSkin; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin; + +import java.awt.*; + +public class ContextMenuProperties { + private Color backgroundColor = new Color(107, 112, 126, 124); + private Color borderColor = Color.BLACK; + private float borderWidth = 1f; + private int padding = 5; // The amount of padding around the rectangle + private int heightOffset = 4; // Height offset from the widget + private boolean drawBorder = true; + private boolean shadow = false; + private boolean roundedCorners = true; + private int cornerRadius = 3; + private boolean hoverEffect = true; + private Color hoverColor = new Color(42, 42, 42, 150); + private boolean enableAnimations = true; + private Skin skin = new ClassicSkin(); + + private ContextMenuProperties() {} + + public static Builder builder() { + return new ContextMenuProperties().new Builder(); + } + + public static ContextMenuProperties createGenericSimplified() { + return new ContextMenuProperties().new Builder().build(); + } + + public class Builder { + private Builder() {} + + public Builder backgroundColor(Color backgroundColor) { + ContextMenuProperties.this.backgroundColor = backgroundColor; + return this; + } + + public Builder borderColor(Color borderColor) { + ContextMenuProperties.this.borderColor = borderColor; + return this; + } + + public Builder skin(Skin skin) { + ContextMenuProperties.this.skin = skin; + return this; + } + + public Builder borderWidth(float borderWidth) { + ContextMenuProperties.this.borderWidth = borderWidth; + return this; + } + + public Builder padding(int padding) { + ContextMenuProperties.this.padding = padding; + return this; + } + + public Builder heightOffset(int heightOffset) { + ContextMenuProperties.this.heightOffset = heightOffset; + return this; + } + + public Builder drawBorder(boolean drawBorder) { + ContextMenuProperties.this.drawBorder = drawBorder; + return this; + } + + public Builder shadow(boolean shadow) { + ContextMenuProperties.this.shadow = shadow; + return this; + } + + public Builder roundedCorners(boolean roundedCorners) { + ContextMenuProperties.this.roundedCorners = roundedCorners; + return this; + } + + public Builder cornerRadius(int cornerRadius) { + ContextMenuProperties.this.cornerRadius = cornerRadius; + return this; + } + + public Builder hoverEffect(boolean hoverEffect) { + ContextMenuProperties.this.hoverEffect = hoverEffect; + return this; + } + + public Builder hoverColor(Color hoverColor) { + ContextMenuProperties.this.hoverColor = hoverColor; + return this; + } + + public Builder enableAnimations(boolean enableAnimations) { + ContextMenuProperties.this.enableAnimations = enableAnimations; + return this; + } + + public ContextMenuProperties build() { + return ContextMenuProperties.this; + } + } + + // Getters for all properties + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getBorderColor() { + return borderColor; + } + + public float getBorderWidth() { + return borderWidth; + } + + public int getPadding() { + return padding; + } + + public int getHeightOffset() { + return heightOffset; + } + + public boolean shouldDrawBorder() { + return drawBorder; + } + + public boolean shadow() { + return shadow; + } + + public boolean roundedCorners() { + return roundedCorners; + } + + public int getCornerRadius() { + return cornerRadius; + } + + public boolean hoverEffect() { + return hoverEffect; + } + + public Color getHoverColor() { + return hoverColor; + } + + public boolean enableAnimations() { + return enableAnimations; + } + + public Skin getSkin() { + return skin; + } + + public void setHeightOffset(int heightOffset) { + this.heightOffset = heightOffset; + } + + public ContextMenuProperties copy(){ + return ContextMenuProperties.builder() + .backgroundColor(backgroundColor) + .borderColor(borderColor) + .borderWidth(borderWidth) + .padding(padding) + .heightOffset(heightOffset) + .drawBorder(drawBorder) + .shadow(shadow) + .roundedCorners(roundedCorners) + .cornerRadius(cornerRadius) + .hoverEffect(hoverEffect) + .hoverColor(hoverColor) + .skin(skin) + .enableAnimations(enableAnimations) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java new file mode 100644 index 0000000..0541de5 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java @@ -0,0 +1,6 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu; + +public interface ContextMenuProvider { + ContextMenu getContextMenu(); +} + diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java index dfea08c..e56a2d9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.SkinRenderer; import com.tanishisherewith.dynamichud.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -18,59 +19,78 @@ public abstract class Option { protected Consumer setter; protected T defaultValue = null; protected MinecraftClient mc = MinecraftClient.getInstance(); + protected ContextMenuProperties properties; + protected SkinRenderer> renderer; public Option(Supplier getter, Consumer setter) { - this.getter = getter; - this.setter = setter; - value = get(); - defaultValue = get(); + this(getter,setter,()->true); } - public Option(Supplier getter, Consumer setter, Supplier shouldRender) { + public Option(Supplier getter, Consumer setter, Supplier shouldRender,ContextMenuProperties properties) { this.getter = getter; this.setter = setter; this.shouldRender = shouldRender; value = get(); defaultValue = get(); + updateProperties(properties); } - protected T get() { + public Option(Supplier getter, Consumer setter, Supplier shouldRender) { + this(getter,setter,shouldRender,ContextMenuProperties.createGenericSimplified()); + } + + public T get() { return getter.get(); } - protected void set(T value) { + public void set(T value) { this.value = value; setter.accept(value); } - public void render(DrawContext drawContext, int x, int y) { - this.x = x; - this.y = y; + public void updateProperties(ContextMenuProperties properties){ + this.properties = properties; + this.renderer = properties.getSkin().getRenderer((Class>) this.getClass()); + if (renderer == null) { + System.err.println("Renderer not found for class: " + this.getClass().getName()); + throw new RuntimeException(); + } } + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { - this.render(drawContext, x, y); + this.x = x; + this.y = y; + + // Retrieve the renderer and ensure it is not null + renderer.render(drawContext, this, x, y, mouseX, mouseY); } public boolean mouseClicked(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY); + return isMouseOver(mouseX, mouseY) || renderer.mouseClicked(this,mouseX,mouseY,button); + } public boolean mouseReleased(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY); + return isMouseOver(mouseX, mouseY) || renderer.mouseReleased(this,mouseX,mouseY,button); } - public boolean mouseDragged(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY); + public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { + return isMouseOver(mouseX, mouseY) || renderer.mouseDragged(this,mouseX,mouseY,button,deltaX,deltaY); } public void keyPressed(int key) { - + renderer.keyPressed(this,key); } - public void keyReleased(int key) { - + renderer.keyReleased(this,key); + } + public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + renderer.mouseScrolled(this,mouseX,mouseY,horizontalAmount,verticalAmount); } + //Called when the context menu closes + public void onClose(){} + public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } @@ -83,4 +103,8 @@ public Option setShouldRender(Supplier shouldRender) { public boolean shouldRender() { return shouldRender.get(); } + + public ContextMenuProperties getProperties() { + return properties; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java new file mode 100644 index 0000000..4bcedee --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java @@ -0,0 +1,87 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen; + +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; + +public class ContextMenuScreen extends Screen { + ContextMenu contextMenu; + ContextMenuProperties properties; + + protected ContextMenuScreen(ContextMenu menu,ContextMenuProperties properties) { + super(Text.of("ContextMenu screen")); + this.contextMenu = menu; + this.properties = properties; + } + + @Override + public void onDisplayed() { + super.onDisplayed(); + contextMenu.shouldDisplay = true; + } + + @Override + public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { + contextMenu.update(); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width /2, (float) height /2,contextMenu.scale); + + properties.getSkin().setContextMenu(contextMenu); + properties.getSkin().renderContextMenu(drawContext,contextMenu,mouseX,mouseY); + + DrawHelper.stopScaling(drawContext.getMatrices()); + + if(contextMenu.scale <= 0 && !contextMenu.shouldDisplay){ + contextMenu.close(); + } + } + + @Override + protected void renderDarkening(DrawContext context) { + + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + contextMenu.mouseClicked(mouseX,mouseY,button); + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + contextMenu.mouseDragged(mouseX,mouseY,button,deltaX,deltaY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + contextMenu.mouseScrolled(mouseX,mouseY,horizontalAmount,verticalAmount); + return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + contextMenu.mouseReleased(mouseX,mouseY,button); + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean keyReleased(int keyCode, int scanCode, int modifiers) { + contextMenu.keyReleased(keyCode,scanCode,modifiers); + return super.keyReleased(keyCode, scanCode, modifiers); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + contextMenu.keyPressed(keyCode,scanCode,modifiers); + return super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public void close() { + contextMenu.close(); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java new file mode 100644 index 0000000..9475b76 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java @@ -0,0 +1,14 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen; + +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import net.minecraft.client.gui.screen.Screen; + +/** + * We will use this interface to provide the context menu with the screen required by its skins. + * Some skins like {@link com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin} require a separate screen to render its contents. + * This can also be used for developers to provide a new custom screen by them or for a custom skin. + */ +public interface ContextMenuScreenFactory { + Screen create(ContextMenu contextMenu, ContextMenuProperties properties); +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java new file mode 100644 index 0000000..90bd220 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java @@ -0,0 +1,15 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen; + +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import net.minecraft.client.gui.screen.Screen; + +/** + * Default implementation of the {@link ContextMenuScreenFactory} providing a {@link ContextMenuScreen} + */ +public class DefaultContextMenuScreenFactory implements ContextMenuScreenFactory { + @Override + public Screen create(ContextMenu contextMenu, ContextMenuProperties properties) { + return new ContextMenuScreen(contextMenu, properties); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index d5ec0e4..c2366c8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -3,43 +3,79 @@ import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; +import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; -import java.awt.*; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; public class BooleanOption extends Option { public String name = "Empty"; + private BooleanType booleanType; - public BooleanOption(String name, Supplier getter, Consumer setter) { + public BooleanOption(String name, Supplier getter, Consumer setter, BooleanType booleanType) { super(getter, setter); this.name = name; + this.booleanType = booleanType; + this.renderer.init(this); + } + public BooleanOption(String name, Supplier getter, Consumer setter) { + this(name,getter,setter,BooleanType.TRUE_FALSE); } public BooleanOption(String name, boolean defaultValue) { - this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value)); + this(name,defaultValue,BooleanType.TRUE_FALSE); + } + + public BooleanOption(String name, boolean defaultValue,BooleanType type) { + this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),type); BooleanPool.put(name, defaultValue); } @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); - + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { value = get(); + super.render(drawContext, x, y,mouseX,mouseY); + + // properties.getSkin().getRenderer(BooleanOption.class).render(drawContext,this,x,y,mouseX,mouseY); + /* int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name) + 1; + + */ } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - if (isMouseOver(mouseX, mouseY)) { + if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { value = !value; set(value); + return true; + } + return super.mouseClicked(mouseX,mouseY,button); + } + + public BooleanType getBooleanType() { + return booleanType; + } + + public enum BooleanType{ + ON_OFF(ScreenTexts::onOrOff), + TRUE_FALSE(aBoolean -> aBoolean ? Text.of("True") : Text.of("False")), + YES_NO(aBoolean -> aBoolean ? ScreenTexts.YES: ScreenTexts.NO); + + private final Function function; + + BooleanType(Function function){ + this.function = function; + } + + public Text getText(boolean val){ + return function.apply(val); } - return true; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 6ad4d49..f6dc41d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -22,12 +22,16 @@ public ColorOption(String name, ContextMenu parentMenu, Supplier getter, this.name = name; this.parentMenu = parentMenu; colorPicker = new ColorGradientPicker(x + this.parentMenu.finalWidth, y - 10, get(), this::set, 50, 100); + this.renderer.init(this); } @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + super.render(drawContext, x, y,mouseX,mouseY); + // properties.getSkin().getRenderer(ColorOption.class).render(drawContext,this,x,y,mouseX,mouseY); + + /* int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name) + 8; @@ -46,6 +50,8 @@ public void render(DrawContext drawContext, int x, int y) { 1); colorPicker.render(drawContext, this.x + parentMenu.finalWidth + 7, y - 10); + + */ } @Override @@ -70,8 +76,18 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button) { + public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { colorPicker.mouseDragged(mouseX, mouseY, button); - return super.mouseDragged(mouseX, mouseY, button); + return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); + } + + public ColorGradientPicker getColorPicker() { + return colorPicker; + } + + @Override + public void onClose() { + isVisible = false; + colorPicker.close(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 90123ee..59316eb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -6,6 +6,7 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import org.apache.commons.lang3.Validate; +import org.lwjgl.glfw.GLFW; import java.awt.*; import java.util.function.Consumer; @@ -15,7 +16,8 @@ public class DoubleOption extends Option { public String name = "Empty"; float step = 0.1f; private boolean isDragging = false; - private double minValue = 0.0, maxValue = 0.0; + public double minValue = 0.0; + public double maxValue = 0.0; ContextMenu parentMenu; public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { @@ -29,13 +31,17 @@ public DoubleOption(String name, double minValue, double maxValue, float step, S this.step = step; this.parentMenu = parentMenu; Validate.isTrue(this.step > 0.0f, "Step cannot be less than or equal to 0 (zero)"); + this.renderer.init(this); } @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { value = get(); + super.render(drawContext, x, y,mouseX,mouseY); + //properties.getSkin().getRenderer(DoubleOption.class).render(drawContext,this,x,y,mouseX,mouseY); + + /* this.width = 35; this.height = 16; @@ -68,9 +74,11 @@ public void render(DrawContext drawContext, int x, int y) { 90, 0.6f, 0.6f); + + */ } - private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) { + public void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) { DrawHelper.drawRectangle(drawContext.getMatrices().peek().getPositionMatrix(), sliderX, sliderY, sliderWidth, 2, 0xFFFFFFFF); if (handleX - sliderX > 0) { DrawHelper.drawRectangle(drawContext.getMatrices().peek().getPositionMatrix(), (float) sliderX, (float) sliderY, (float) ((value - minValue) / (maxValue - minValue) * (width - 3)), 2, Color.ORANGE.getRGB()); @@ -79,8 +87,7 @@ private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int s @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - if (isMouseOver(mouseX, mouseY)) { + if (super.mouseClicked(mouseX, mouseY, button) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { step(mouseX); isDragging = true; } @@ -93,7 +100,7 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { return super.mouseReleased(mouseX, mouseY, button); } - private void step(double mouseX) { + public void step(double mouseX) { double newValue = minValue + (float) (mouseX - x) / width * (maxValue - minValue); // Round the new value to the nearest step newValue = Math.round(newValue / step) * step; @@ -101,10 +108,10 @@ private void step(double mouseX) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button) { + public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { if (isMouseOver(mouseX, mouseY) && isDragging) { step(mouseX); } - return super.mouseDragged(mouseX, mouseY, button); + return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index 1351d17..ceace21 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -24,24 +24,29 @@ public EnumOption(String name, Supplier getter, Consumer setter, E[] value break; } } + this.renderer.init(this); } @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); - + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { value = get(); + super.render(drawContext, x, y,mouseX,mouseY); + + // properties.getSkin().getRenderer(EnumOption.class).render(drawContext,this,x,y,mouseX,mouseY); + + /* this.height = mc.textRenderer.fontHeight + 1; this.width = mc.textRenderer.getWidth(name + ": " + value.name()) + 1; drawContext.drawText(mc.textRenderer, Text.of(name + ": "), x, y, Color.WHITE.getRGB(), false); drawContext.drawText(mc.textRenderer, Text.of(value.name()), x + mc.textRenderer.getWidth(name + ": ") + 1, y, Color.CYAN.getRGB(), false); + + */ } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - if (isMouseOver(mouseX, mouseY)) { + if (super.mouseClicked(mouseX,mouseY,button)) { if (button == 0) { currentIndex = (currentIndex + 1) % values.length; if (currentIndex > values.length - 1) { @@ -59,4 +64,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } return true; } + + public E[] getValues() { + return values; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index a7aef94..382973f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -25,25 +25,27 @@ public ListOption(String name, Supplier getter, Consumer setter, List v break; } } + this.renderer.init(this); } @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); - + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { value = get(); + super.render(drawContext, x, y,mouseX,mouseY); + + // properties.getSkin().getRenderer(ListOption.class).render(drawContext,this,x,y,mouseX,mouseY); +/* this.height = mc.textRenderer.fontHeight + 1; this.width = mc.textRenderer.getWidth(name + ": " + value.toString()) + 1; drawContext.drawText(mc.textRenderer, Text.of(name + ": "), x, y, Color.WHITE.getRGB(), false); drawContext.drawText(mc.textRenderer, Text.of(value.toString()), x + mc.textRenderer.getWidth(name + ": ") + 1, y, Color.CYAN.getRGB(), false); - +*/ } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - if (isMouseOver(mouseX, mouseY)) { + if (super.mouseClicked(mouseX, mouseY, button)) { if (button == 0) { currentIndex = (currentIndex + 1) % values.size(); if (currentIndex > values.size() - 1) { @@ -61,4 +63,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } return true; } + + public List getValues() { + return values; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index c797189..dae637d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -25,6 +25,7 @@ public RunnableOption(String name, Supplier getter, Consumer s super(getter, setter); this.name = "Run: " + name; // prepend the "run" symbol to the name this.task = task; + this.renderer.init(this); } public RunnableOption(String name, boolean defaultValue,Runnable task) { @@ -32,24 +33,25 @@ public RunnableOption(String name, boolean defaultValue,Runnable task) { BooleanPool.put(name, defaultValue); } - Color DARK_RED = new Color(116, 0, 0); - Color DARK_GREEN = new Color(24, 132, 0, 226); - @Override - public void render(DrawContext drawContext, int x, int y) { - super.render(drawContext, x, y); - + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { value = get(); + super.render(drawContext, x, y,mouseX,mouseY); + + //properties.getSkin().getRenderer(RunnableOption.class).render(drawContext,this,x,y,mouseX,mouseY); + + /* this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth("Run: " + name); int color = value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(); drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); + + */ } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); - if (isMouseOver(mouseX, mouseY)) { + if (super.mouseClicked(mouseX, mouseY, button)) { value = !value; set(value); if (value) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 07a7b0b..1496581 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -2,12 +2,14 @@ import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import java.awt.*; import java.util.Objects; +import java.util.Properties; import java.util.function.Consumer; import java.util.function.Supplier; @@ -23,31 +25,30 @@ public class SubMenuOption extends Option { private final ContextMenu parentMenu; public String name = "Empty"; - - public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter, ContextMenuProperties properties) { super(getter, setter); Objects.requireNonNull(parentMenu, "Parent Menu cannot be null"); this.name = name; this.parentMenu = parentMenu; - this.subMenu = new ContextMenu(parentMenu.x + parentMenu.finalWidth, this.y); - this.subMenu.heightOffset = 0; + this.subMenu = new ContextMenu(parentMenu.x + parentMenu.finalWidth, this.y,properties); + this.subMenu.getProperties().setHeightOffset(0); this.subMenu.shouldDisplay = get(); + this.renderer.init(this); + } + public SubMenuOption(String name, ContextMenu parentMenu, ContextMenuProperties properties) { + this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),properties); + } + public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + this(name,parentMenu,getter,setter,parentMenu.getProperties().copy()); } public SubMenuOption(String name, ContextMenu parentMenu) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value)); + this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),parentMenu.getProperties().copy()); } @Override public void render(DrawContext drawContext, int x, int y,int mouseX,int mouseY) { - this.x = x; - this.y = y; - - int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(name), x, y + 1, color, false); - this.height = mc.textRenderer.fontHeight + 2; - this.width = mc.textRenderer.getWidth(name) + 1; - - subMenu.render(drawContext, this.x + parentMenu.finalWidth, this.y, 0,mouseX, mouseY); + super.render(drawContext,x,y,mouseX,mouseY); + // properties.getSkin().getRenderer(SubMenuOption.class).render(drawContext,this,x,y,mouseX,mouseY); } @Override @@ -68,9 +69,9 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button) { - subMenu.mouseDragged(mouseX, mouseY, button); - return super.mouseDragged(mouseX, mouseY, button); + public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { + subMenu.mouseDragged(mouseX, mouseY, button,deltaX, deltaY); + return super.mouseDragged(mouseX, mouseY, button,deltaX, deltaY); } public SubMenuOption getOption() { @@ -80,4 +81,8 @@ public SubMenuOption getOption() { public ContextMenu getSubMenu() { return subMenu; } + + public ContextMenu getParentMenu() { + return parentMenu; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 65a15c9..9d1ed11 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -5,6 +5,7 @@ import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.gui.DrawContext; import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; import java.awt.*; import java.nio.ByteBuffer; @@ -68,27 +69,40 @@ public void render(DrawContext drawContext, int x1, int y1) { if (colorPickerButton.isPicking() && GlobalConfig.get().showColorPickerPreview()) { // Draw the preview box near cursor - - //Translate cursor screen position to minecraft's scaled window - double mouseX = client.mouse.getX() * client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); - double mouseY = client.mouse.getY() * client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); - Framebuffer framebuffer = client.getFramebuffer(); - int x = (int) (mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth()); - int y = (int) ((client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight()); - - //Read the pixel color at x,y pos to buffer - ByteBuffer buffer = ByteBuffer.allocate(4); - GL11.glReadPixels(x, y, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); - int red = buffer.get(0) & 0xFF; - int green = buffer.get(1) & 0xFF; - int blue = buffer.get(2) & 0xFF; - - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0, 0, 500); - drawContext.fill((int) mouseX + 10, (int) mouseY, (int) mouseX + 26, (int) mouseY + 16, -1); - drawContext.fill((int) mouseX + 11, (int) mouseY + 1, (int) mouseX + 25, (int) mouseY + 15, (red << 16) | (green << 8) | blue | 0xFF000000); - drawContext.getMatrices().pop(); + if (framebuffer != null) { + //Translate cursor screen position to minecraft's scaled window + double mouseX = client.mouse.getX() * client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); + double mouseY = client.mouse.getY() * client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); + + int x = (int) (mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth()); + int y = (int) ((client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight()); + + try { + int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; + + ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); + GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); + + int index = (x + y * framebuffer.textureWidth) * 4; + if (index >= 0 && index + 3 < bufferSize) { + int blue = buffer.get(index) & 0xFF; + int green = buffer.get(index + 1) & 0xFF; + int red = buffer.get(index + 2) & 0xFF; + + drawContext.getMatrices().push(); + drawContext.getMatrices().translate(0, 0, 500); + drawContext.fill((int) mouseX + 10, (int) mouseY, (int) mouseX + 26, (int) mouseY + 16, -1); + drawContext.fill((int) mouseX + 11, (int) mouseY + 1, (int) mouseX + 25, (int) mouseY + 15, (red << 16) | (green << 8) | blue | 0xFF000000); + drawContext.getMatrices().pop(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + System.err.println("Framebuffer is null"); + } } } @@ -105,26 +119,48 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { gradientBox.onClick(mouseX, mouseY, button); } else if (colorPickerButton.isPicking()) { Framebuffer framebuffer = client.getFramebuffer(); - int x = (int) (mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth()); - int y = (int) ((client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight()); - - ByteBuffer buffer = ByteBuffer.allocate(4); - GL11.glReadPixels(x, y, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); - int red = buffer.get(0) & 0xFF; - int green = buffer.get(1) & 0xFF; - int blue = buffer.get(2) & 0xFF; - - float[] hsv = Color.RGBtoHSB(red, green, blue, null); - gradientSlider.setHue(hsv[0]); - gradientBox.setHue(hsv[0]); - gradientBox.setSaturation(hsv[1]); - gradientBox.setValue(hsv[2]); - - colorPickerButton.setPicking(false); + if (framebuffer != null) { + int x = (int) (mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth()); + int y = (int) ((client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight()); + + try { + // Calculate the size of the buffer needed to store the texture data + int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; + + ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); + // Bind the texture from the framebuffer + GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); + // Read the texture data into the buffer + GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); + + // Calculate the index of the pixel in the buffer + int index = (x + y * framebuffer.textureWidth) * 4; + + // Check if the index is within the bounds of the buffer + if (index >= 0 && index + 3 < bufferSize) { + int blue = buffer.get(index) & 0xFF; + int green = buffer.get(index + 1) & 0xFF; + int red = buffer.get(index + 2) & 0xFF; + + float[] hsv = Color.RGBtoHSB(red, green, blue, null); + gradientSlider.setHue(hsv[0]); + gradientBox.setHue(hsv[0]); + gradientBox.setSaturation(hsv[1]); + gradientBox.setValue(hsv[2]); + + colorPickerButton.setPicking(false); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + System.err.println("Framebuffer is null"); + } } alphaSlider.setColor(new Color(gradientBox.getColor())); alphaSlider.onClick(mouseX, mouseY, button); onColorSelected.accept(alphaSlider.getColor()); + return true; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java index fa2b8f1..3afa00e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -3,6 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import java.awt.*; + public class ColorPickerButton { private final int width; private final int height; @@ -23,7 +25,7 @@ public void render(DrawContext drawContext, int x, int y) { drawContext.getMatrices().push(); drawContext.getMatrices().translate(0, 0, 404); // Draw the button - drawContext.fill(x + 2, y + 2, x + width - 2, y + height - 2, 0xFFAAAAAA); + drawContext.fill(x + 2, y + 2, x + width - 2, y + height - 2, isPicking() ? Color.GREEN.getRGB() : 0xFFAAAAAA); drawContext.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, "Pick", x + width / 2, y + (height - 8) / 2, 0xFFFFFFFF); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java new file mode 100644 index 0000000..2810c33 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -0,0 +1,264 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; + +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; + +import java.awt.*; + +/** + * This is one of the Skins provided by DynamicHUD featuring the classic rendering, + * which should be used when you have a low amount of settings and want quicker way of changing the settings. + */ +public class ClassicSkin extends Skin { + public static MinecraftClient mc = MinecraftClient.getInstance(); + + public ClassicSkin() { + super(); + + addRenderer(BooleanOption.class, new ClassicBooleanRenderer()); + addRenderer(DoubleOption.class, new ClassicDoubleRenderer()); + addRenderer(EnumOption.class, new ClassicEnumRenderer()); + addRenderer(ListOption.class, new ClassicListRenderer()); + addRenderer(SubMenuOption.class, new ClassicSubMenuRenderer()); + addRenderer(RunnableOption.class, new ClassicRunnableRenderer()); + addRenderer(ColorOption.class, new ClassicColorOptionRenderer()); + } + + @Override + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + this.contextMenu = contextMenu; + this.contextMenu.newScreenFlag = false; + + MatrixStack matrices = drawContext.getMatrices(); + ContextMenuProperties properties = contextMenu.getProperties(); + + // Draw the background + drawBackground(matrices, contextMenu, properties); + + int yOffset = contextMenu.y + 3; + contextMenu.setWidth(10); + for (Option option : contextMenu.getOptions()) { + if (!option.shouldRender()) continue; + + // Adjust mouse coordinates based on the scale + if (contextMenu.getProperties().hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, contextMenu.x + 1, yOffset - 1, contextMenu.getFinalWidth() - 2, option.height)) { + drawBackground(matrices, contextMenu, properties, yOffset - 1,contextMenu.getFinalWidth(), option.height + 1, contextMenu.getProperties().getHoverColor().getRGB(),false); + } + + option.render(drawContext, contextMenu.x + 4, yOffset, mouseX, mouseY); + contextMenu.setWidth(Math.max(contextMenu.getWidth(), option.width)); + yOffset += option.height + 1; + } + contextMenu.setWidth(contextMenu.getWidth() + properties.getPadding()); + contextMenu.setFinalWidth(contextMenu.getWidth()); + contextMenu.height = (yOffset - contextMenu.y); + + // Draw the border if needed + if (properties.shouldDrawBorder()) { + drawBorder(matrices, contextMenu, properties); + } + } + + private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { + drawBackground(matrices, contextMenu, properties, contextMenu.y,contextMenu.getWidth(), contextMenu.height, properties.getBackgroundColor().getRGB(),properties.shadow()); + } + + private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset,int width, int height, int color,boolean shadow) { + // Wow so good code. + if (properties.roundedCorners()) { + if(shadow){ + DrawHelper.drawRoundedRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), + contextMenu.x, + yOffset, + width, + height, + properties.getCornerRadius(), + color, + 150, + 1, + 1 + ); + }else { + DrawHelper.drawRoundedRectangle(matrices.peek().getPositionMatrix(), + contextMenu.x, + yOffset, + width, + height, + properties.getCornerRadius(), + color + ); + } + } else { + if(shadow){ + DrawHelper.drawRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), + contextMenu.x, + yOffset, + width, + height, + color, + 150, + 1, + 1 + ); + }else { + DrawHelper.drawRectangle(matrices.peek().getPositionMatrix(), + contextMenu.x, + yOffset, + width, + height, + color + ); + } + } + } + + private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { + if (properties.roundedCorners()) { + DrawHelper.drawOutlineRoundedBox(matrices.peek().getPositionMatrix(), + contextMenu.x, + contextMenu.y, + contextMenu.getWidth(), + contextMenu.height, + properties.getCornerRadius(), + properties.getBorderWidth(), + properties.getBorderColor().getRGB() + ); + } else { + DrawHelper.drawOutlineBox(matrices.peek().getPositionMatrix(), + contextMenu.x, + contextMenu.y, + contextMenu.getWidth(), + contextMenu.height, + properties.getBorderWidth(), + properties.getBorderColor().getRGB() + ); + } + } + + public static class ClassicBooleanRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { + int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + option.height = mc.textRenderer.fontHeight; + option.width = mc.textRenderer.getWidth(option.name) + 1; + } + } + + public static class ClassicColorOptionRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, ColorOption option, int x, int y, int mouseX, int mouseY) { + int color = option.isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + option.height = mc.textRenderer.fontHeight; + option.width = mc.textRenderer.getWidth(option.name) + 1; + + int shadowOpacity = Math.min(option.value.getAlpha(),90); + DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), + x + option.width, + y - 1, + 8, + 8, + 2, + option.value.getRGB(), + shadowOpacity, + 1, + 1); + + option.getColorPicker().render(drawContext, x + option.parentMenu.getFinalWidth() + 7, y - 10); + } + } + + public class ClassicDoubleRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { + option.width = Math.max(35, contextMenu != null ? contextMenu.getFinalWidth() - option.getProperties().getPadding() - 2 : 0); + option.height = 16; + + // Draw the label + TextRenderer textRenderer = mc.textRenderer; + DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, 0.7f); + String labelText = option.name + ": " + String.format("%.1f", option.value); + int labelWidth = textRenderer.getWidth(labelText); + option.width = Math.max(option.width, labelWidth); + drawContext.drawTextWithShadow(textRenderer, labelText, x, y + 1, 0xFFFFFFFF); + DrawHelper.stopScaling(drawContext.getMatrices()); + + float handleWidth = 3; + float handleHeight = 8; + double handleX = x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.width - handleWidth); + double handleY = y + textRenderer.fontHeight + 1 + ((2 - handleHeight) / 2); + + // Draw the slider + option.drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, option.width, handleX); + + // Draw the handle + + DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), + (float) handleX, + (float) handleY, + handleWidth, + handleHeight, + 1, + 0xFFFFFFFF, + 90, + 0.6f, + 0.6f); + } + } + + public static class ClassicEnumRenderer> implements SkinRenderer> { + @Override + public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { + option.height = mc.textRenderer.fontHeight + 1; + option.width = mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1; + + drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y, Color.WHITE.getRGB(), false); + drawContext.drawText(mc.textRenderer, Text.of(option.value.name()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); + } + } + + public class ClassicListRenderer implements SkinRenderer> { + @Override + public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { + option.height = mc.textRenderer.fontHeight + 1; + option.width = mc.textRenderer.getWidth(option.name + ": " + option.value.toString()) + 1; + + drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y + 1, Color.WHITE.getRGB(), false); + drawContext.drawText(mc.textRenderer, Text.of(option.value.toString()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false); + } + } + + public static class ClassicSubMenuRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, SubMenuOption option, int x, int y, int mouseX, int mouseY) { + int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + option.height = mc.textRenderer.fontHeight; + option.width = mc.textRenderer.getWidth(option.name) + 1; + + option.getSubMenu().render(drawContext, x + option.getParentMenu().finalWidth, y, mouseX, mouseY); + } + } + + public static class ClassicRunnableRenderer implements SkinRenderer { + Color DARK_RED = new Color(116, 0, 0); + Color DARK_GREEN = new Color(24, 132, 0, 226); + + @Override + public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) { + option.height = mc.textRenderer.fontHeight; + option.width = mc.textRenderer.getWidth("Run: " + option.name); + int color = option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java new file mode 100644 index 0000000..6eb2874 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -0,0 +1,419 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ButtonTextures; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; + +import java.awt.*; + +/** + * This is one of the Skins provided by DynamicHUD featuring the minecraft-like style rendering. + * It runs on a separate screen and provides more complex features like scrolling and larger dimension. + * It tries to imitate the minecraft look and provides various form of panel shades {@link PanelColor} + */ +public class MinecraftSkin extends Skin { + public static MinecraftClient mc = MinecraftClient.getInstance(); + public Identifier BACKGROUND_PANEL; + private int scrollOffset = 0; + private int maxScrollOffset = 0; + private final int panelWidth; + private final int panelHeight; + private final PanelColor panelColor; + public static final ButtonTextures TEXTURES = new ButtonTextures(Identifier.ofVanilla("widget/button"), Identifier.ofVanilla("widget/button_disabled"), Identifier.ofVanilla("widget/button_highlighted")); + private double scrollVelocity = 0; + + public enum PanelColor { + DARK_PANEL(0.2f, 0.2f, 0.2f, 0.9f), + CREAMY(1.0f, 0.9f, 0.8f, 0.9f), + LIGHT_BLUE(0.6f, 0.8f, 1.0f, 0.9f), + SOFT_GREEN(0.6f, 1.0f, 0.6f, 0.9f), + WARM_YELLOW(1.0f, 1.0f, 0.6f, 0.9f), + SUNSET_ORANGE(1.0f, 0.5f, 0.0f, 0.9f), + OCEAN_BLUE(0.0f, 0.5f, 1.0f, 0.9f), + FOREST_GREEN(0.0f, 0.6f, 0.2f, 0.9f), + MIDNIGHT_PURPLE(0.3f, 0.0f, 0.5f, 0.9f), + GOLDEN_YELLOW(1.0f, 0.8f, 0.0f, 0.9f), + ROSE_PINK(1.0f, 0.4f, 0.6f, 0.9f), + SKY_BLUE(0.5f, 0.8f, 1.0f, 0.9f), + LIME_GREEN(0.7f, 1.0f, 0.3f, 0.9f), + COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f), + LAVENDER(0.8f, 0.6f, 1.0f, 0.9f), + CUSTOM(0.0f, 0.0f, 0.0f, 0.0f); // Placeholder for custom colors + + private float red; + private float green; + private float blue; + private float alpha; + + PanelColor(float red, float green, float blue, float alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + } + + public void applyColor() { + RenderSystem.setShaderColor(red, green, blue, alpha); + } + + public static PanelColor custom(float red, float green, float blue, float alpha) { + PanelColor custom = CUSTOM; + custom.red = red; + custom.green = green; + custom.blue = blue; + custom.alpha = alpha; + return custom; + } + } + + public MinecraftSkin(PanelColor color, Identifier backgroundPanel, int panelWidth, int panelHeight) { + super(); + this.panelColor = color; + addRenderer(BooleanOption.class, new MinecraftBooleanRenderer()); + addRenderer(DoubleOption.class, new MinecraftDoubleRenderer()); + addRenderer(EnumOption.class, new MinecraftEnumRenderer()); + addRenderer(ListOption.class, new MinecraftListRenderer()); + addRenderer(SubMenuOption.class, new MinecraftSubMenuRenderer()); + addRenderer(RunnableOption.class, new MinecraftRunnableRenderer()); + addRenderer(ColorOption.class, new MinecraftColorOptionRenderer()); + + this.panelHeight = panelHeight; + this.panelWidth = panelWidth; + this.BACKGROUND_PANEL = backgroundPanel; + + if(contextMenu != null){ + contextMenu.newScreenFlag = true; + } + } + public MinecraftSkin(PanelColor color) { + this(color,Identifier.of("minecraft","textures/gui/demo_background.png"),248,165); + } + + @Override + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + this.contextMenu = contextMenu; + if (!contextMenu.newScreenFlag) { + contextMenu.newScreenFlag = true; + return; + } + + int screenWidth = mc.getWindow().getScaledWidth(); + int screenHeight = mc.getWindow().getScaledHeight(); + + int centerX = screenWidth / 2; + int centerY = screenHeight / 2; + + contextMenu.set(centerX,centerY,0); + + // Calculate the top-left corner of the image + int imageX = centerX - panelWidth / 2; + int imageY = centerY - panelHeight / 2; + + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + panelColor.applyColor(); + drawContext.drawTexture(BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight); + RenderSystem.setShaderColor(1.0f,1.0f,1.0f,1.0f); + drawContext.drawGuiTexture(TEXTURES.get(true, isMouseOver(mouseX,mouseY,imageX + 3,imageY + 3,14,14)), imageX + 3,imageY + 3,14,14); + drawContext.drawText(mc.textRenderer,"X",imageX + 10 - mc.textRenderer.getWidth("X")/2 ,imageY + 6,-1,true); + + DrawHelper.enableScissor(imageX,imageY + 2,screenWidth,panelHeight - 4); + int yOffset = imageY + 10 - scrollOffset; + contextMenu.setWidth(panelWidth - 4); + contextMenu.setFinalWidth(panelWidth - 4); + contextMenu.y = imageY; + int maxYOffset = imageY + panelHeight - 4; + + for (Option option : contextMenu.getOptions()) { + if (!option.shouldRender()) continue; + + if (yOffset >= imageY && yOffset <= maxYOffset - option.height + 4) { + option.render(drawContext, imageX + 4, yOffset, mouseX, mouseY); + } + + yOffset += option.height + 1; + } + + contextMenu.height = (yOffset - imageY) + 25; + + applyMomentum(); + + // Calculate max scroll offset + maxScrollOffset = Math.max(0, contextMenu.height - panelHeight + 10); + scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); + + // Disable scissor after rendering + DrawHelper.disableScissor(); + } + private boolean isMouseOver(double mouseX, double mouseY, double x, double y,double width, double height){ + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + private void applyMomentum() { + if (scrollVelocity != 0) { + scrollOffset += (int) scrollVelocity; + scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); + scrollVelocity *= 0.9; //Friction + + // Stop the scrolling if the velocity is very low + if (Math.abs(scrollVelocity) < 0.12) { + scrollVelocity = 0; + } + } + } + + @Override + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + scrollVelocity += verticalAmount; + super.mouseScrolled(menu, mouseX, mouseY, horizontalAmount, verticalAmount); + } + + @Override + public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { + int screenWidth = mc.getWindow().getScaledWidth(); + int screenHeight = mc.getWindow().getScaledHeight(); + + // Calculate the top-left corner of the image + int imageX = (screenWidth - panelWidth) / 2; + int imageY = (screenHeight - panelHeight) / 2; + + if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX,mouseY,imageX + 3,imageY + 3,14,14)){ + contextMenu.close(); + } + + return super.mouseClicked(menu, mouseX, mouseY, button); + } + + public class MinecraftBooleanRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - 75; + option.y = y; + + int width = 50; + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,width,20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + Text text = option.getBooleanType().getText(option.value); + int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer,text,(int) (option.x + (width/2.0f) -(mc.textRenderer.getWidth(text)/2.0f)) ,y + 5,color,true); + //drawContext.drawTexture(BOOLEAN_TEXTURE); + + option.height = 25; + + //Widths dont matter in this skin. + option.width = width; + } + + @Override + public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, int button) { + if(mouseX >= option.x && mouseX <= option.x + 50 && mouseY >= option.y && mouseY <= option.y + option.height){ + option.set(!option.get()); + } + return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button); + } + } + + public class MinecraftColorOptionRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, ColorOption option, int x, int y, int mouseX, int mouseY) { + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - 75; + option.y = y; + + int width = 20; + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX,mouseY)), option.x,y,width,20); + int shadowOpacity = Math.min(option.value.getAlpha(),45); + DrawHelper.drawRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), + option.x + 4, + y + 4, + width - 8, + 20 - 8, + option.value.getRGB(), + shadowOpacity, + 1, + 1); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + + option.height = 25; + option.width = width; + + option.getColorPicker().render(drawContext, x + panelWidth + 10, y - 10); + } + } + + public class MinecraftDoubleRenderer implements SkinRenderer { + private static final Identifier TEXTURE = Identifier.ofVanilla("widget/slider"); + private static final Identifier HIGHLIGHTED_TEXTURE = Identifier.ofVanilla("widget/slider_highlighted"); + private static final Identifier HANDLE_TEXTURE = Identifier.ofVanilla("widget/slider_handle"); + private static final Identifier HANDLE_HIGHLIGHTED_TEXTURE = Identifier.ofVanilla("widget/slider_handle_highlighted"); + + @Override + public void init(DoubleOption option) { + SkinRenderer.super.init(option); + } + + @Override + public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + + option.width = panelWidth - 150; + option.height = 25; + + option.x = x + panelWidth - 122; + option.y = y; + double sliderX = option.x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.width - 8); + boolean isMouseOverHandle = isMouseOver(mouseX,mouseY, sliderX, y); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.enableDepthTest(); + + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawGuiTexture(option.isMouseOver(mouseX,mouseY)? HIGHLIGHTED_TEXTURE : TEXTURE, option.x, y, option.width, 20); + drawContext.drawGuiTexture(isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE , (int) Math.round(sliderX), y, 8, 20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + drawContext.drawText(mc.textRenderer, String.valueOf(option.value),option.x + option.width/2 - mc.textRenderer.getWidth(option.value.toString())/2 ,y + 5,16777215,false); + } + private boolean isMouseOver(double mouseX, double mouseY, double x, double y){ + return mouseX >= x && mouseX <= x + 10 && mouseY >= y && mouseY <= y + 20; + } + + @Override + public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) { + return isMouseOver(mouseX,mouseY,option.x,option.y); + } + } + + public class MinecraftEnumRenderer> implements SkinRenderer> { + private int maxWidth = 50; + + private void calculateMaxWidth(EnumOption option) { + for (E enumConstant : option.getValues()) { + int width = mc.textRenderer.getWidth(enumConstant.name()) + 5; + if (width > maxWidth) { + maxWidth = width; + } + } + } + + @Override + public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { + calculateMaxWidth(option); + option.height = 25; + option.width = maxWidth; + + drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - maxWidth - 25; + option.y = y; + + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,maxWidth,20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + String text = option.get().toString(); + drawContext.drawText(mc.textRenderer,text,option.x + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + } + } + + public class MinecraftListRenderer implements SkinRenderer> { + private int maxWidth = 50; + + private void calculateMaxWidth(ListOption option) { + for (E listValues : option.getValues()) { + int width = mc.textRenderer.getWidth(listValues.toString()) + 5; + if (width > maxWidth) { + maxWidth = width; + } + } + } + + @Override + public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { + calculateMaxWidth(option); + option.height = 25; + option.width = maxWidth; + + drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - maxWidth - 25; + option.y = y; + + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,maxWidth,20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + String text = option.get().toString(); + drawContext.drawText(mc.textRenderer,text,option.x + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + } + } + + public class MinecraftSubMenuRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, SubMenuOption option, int x, int y, int mouseX, int mouseY) { + option.height = 20; + option.width = 30; + + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - 75; + option.y = y; + + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y, option.width,20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + String text = "Open"; + drawContext.drawText(mc.textRenderer,text,option.x + option.width/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.YELLOW.getRGB(),true); + + option.getSubMenu().render(drawContext, x + option.getParentMenu().finalWidth, y, mouseX, mouseY); + } + } + + public class MinecraftRunnableRenderer implements SkinRenderer { + Color DARK_RED = new Color(116, 0, 0); + Color DARK_GREEN = new Color(24, 132, 0, 226); + + @Override + public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) { + option.height = 25; + option.width = 26; + + drawContext.drawText(mc.textRenderer, option.name.replaceFirst("Run: ","") + ": ", x + 15, y + 25/2 - 5, -1, true); + + option.x = x + panelWidth - 75; + option.y = y; + + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX,mouseY)), option.x,y, option.width,20); + drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawText(mc.textRenderer,"Run",option.x + option.width/2 - mc.textRenderer.getWidth("Run")/2 ,y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(),true); + } + } + + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java new file mode 100644 index 0000000..4533af1 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java @@ -0,0 +1,55 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; + +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import net.minecraft.client.gui.DrawContext; + +import java.util.HashMap; +import java.util.Map; + +public abstract class Skin { + protected ContextMenu contextMenu; + protected Map>, SkinRenderer>> renderers = new HashMap<>(); + + public > void addRenderer(Class optionClass, SkinRenderer renderer) { + renderers.put(optionClass, renderer); + } + + public Skin(ContextMenu menu){ + this.contextMenu = menu; + } + public Skin(){ + } + + @SuppressWarnings("unchecked") + public > SkinRenderer getRenderer(Class optionClass) { + return (SkinRenderer) renderers.get(optionClass); + } + + public void setContextMenu(ContextMenu contextMenu) { + this.contextMenu = contextMenu; + } + + public void setRenderers(Map>, SkinRenderer>> renderers) { + this.renderers = renderers; + } + + public abstract void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY); + + public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { + return false; + } + + public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { + return false; + } + + public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return false; + } + + public void keyPressed(ContextMenu menu, int key,int scanCode, int modifiers) {} + public void keyReleased(ContextMenu menu, int key,int scanCode, int modifiers) {} + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount){} +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java new file mode 100644 index 0000000..fc498de --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java @@ -0,0 +1,26 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; + +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import net.minecraft.client.gui.DrawContext; + +public interface SkinRenderer> { + void render(DrawContext drawContext, T option, int x, int y, int mouseX, int mouseY); + + default boolean mouseClicked(T option, double mouseX, double mouseY, int button) { + return option.isMouseOver(mouseX, mouseY); + } + + default boolean mouseReleased(T option, double mouseX, double mouseY, int button) { + return option.isMouseOver(mouseX, mouseY); + } + + default boolean mouseDragged(T option, double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return option.isMouseOver(mouseX, mouseY); + } + + default void keyPressed(T option, int key) {} + + default void keyReleased(T option, int key) {} + default void mouseScrolled(T option, double mouseX, double mouseY, double horizontalAmount, double verticalAmount){} + default void init(T option){} +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 3898d1f..b80175b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -10,11 +10,12 @@ import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; +import java.util.Properties; import java.util.Set; public abstract class Widget { - public static WidgetData DATA; + public WidgetData DATA; /** * This is the UID of the widget used to identify during loading and saving. *

@@ -23,7 +24,8 @@ public abstract class Widget { * @see #modId */ public UID uid = UID.generate(); - public boolean isInEditor = false; + protected boolean isInEditor = false; + // Whether the widget is enabled and should be displayed. public boolean display = true; public boolean isDraggable = true; @@ -33,9 +35,10 @@ public abstract class Widget { //To enable/disable snapping public boolean shiftDown = false; + // Absolute position of the widget on screen in pixels. - public int x, y; - public boolean shouldScale = true; + protected int x, y; + protected boolean shouldScale = true; /** * An identifier for widgets to group them under one ID. *

@@ -61,7 +64,7 @@ public abstract class Widget { int startX, startY; public Widget(WidgetData DATA, String modId) { - Widget.DATA = DATA; + this.DATA = DATA; widgetBox = new WidgetBox(0, 0, 0, 0); this.modId = modId; init(); @@ -71,7 +74,6 @@ public Widget(WidgetData DATA, String modId) { * This method is called at the end of the {@link Widget#Widget(WidgetData, String)} constructor. */ public void init() { - } /** @@ -100,25 +102,33 @@ public float getHeight() { return widgetBox.getHeight(); } + private void updatePercentages() { + int screenWidth = mc.getWindow().getScaledWidth(); + int screenHeight = mc.getWindow().getScaledHeight(); + this.xPercent = (float) (this.x + this.getWidth() / 2) / screenWidth; + this.yPercent = (float) (this.y + this.getHeight() / 2) / screenHeight; + } + + void updatePositionFromPercentages(int screenWidth, int screenHeight) { + this.x = (int) (this.xPercent * screenWidth - this.getWidth() / 2); + this.y = (int) (this.yPercent * screenHeight - this.getHeight() / 2); + + this.x = (int) MathHelper.clamp(x, 0, mc.getWindow().getScaledWidth() - getWidth()); + this.y = (int) MathHelper.clamp(y, 0, mc.getWindow().getScaledHeight() - getHeight()); + } + public void setPosition(int x, int y) { this.x = x; this.y = y; + if(mc.getWindow() != null) { + updatePercentages(); + } } public void setDraggable(boolean draggable) { isDraggable = draggable; } - public boolean isOverlapping(Set other) { - for (Widget widgetBox : other) { - if ((this.getX() < widgetBox.getX() + widgetBox.getWidgetBox().getWidth() && this.getX() + this.getWidgetBox().getWidth() > widgetBox.getX() && - this.getY() < widgetBox.getY() + widgetBox.getWidgetBox().getHeight() && this.getY() + this.getWidgetBox().getHeight() > widgetBox.getY())) { - return true; - } - } - return false; - } - public boolean isOverlapping(Widget other) { return this.getX() < other.getX() + other.getWidgetBox().getWidth() && this.getX() + this.getWidgetBox().getWidth() > other.getX() && this.getY() < other.getY() + other.getWidgetBox().getHeight() && this.getY() + this.getWidgetBox().getHeight() > other.getY(); @@ -223,8 +233,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi this.x = (int) MathHelper.clamp(newX, 0, mc.getWindow().getScaledWidth() - getWidth()); this.y = (int) MathHelper.clamp(newY, 0, mc.getWindow().getScaledHeight() - getHeight()); - this.xPercent = (float) this.x / mc.getWindow().getScaledWidth(); - this.yPercent = (float) this.y / mc.getWindow().getScaledHeight(); + updatePercentages(); return true; } @@ -269,7 +278,6 @@ protected void displayBg(DrawContext context) { backgroundColor); } - public void readFromTag(NbtCompound tag) { modId = tag.getString("modId"); uid = new UID(tag.getString("UID")); @@ -278,6 +286,19 @@ public void readFromTag(NbtCompound tag) { display = tag.getBoolean("Display"); isDraggable = tag.getBoolean("isDraggable"); shouldScale = tag.getBoolean("shouldScale"); + xPercent = tag.getFloat("xPercent"); + yPercent = tag.getFloat("yPercent"); + + if(mc.getWindow() != null) { + mc.execute(()->{ + if (x != mc.getWindow().getScaledWidth() * xPercent) { + x = (int) MathHelper.clamp(mc.getWindow().getScaledWidth() * xPercent, 0, mc.getWindow().getScaledWidth() - getWidth()); + } + if (y != mc.getWindow().getScaledHeight() * yPercent) { + y = (int) MathHelper.clamp(mc.getWindow().getScaledHeight() * yPercent, 0, mc.getWindow().getScaledHeight() - getHeight()); + } + }); + } } /** @@ -293,6 +314,8 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("shouldScale", shouldScale); tag.putInt("x", x); tag.putInt("y", y); + tag.putFloat("xPercent", xPercent); + tag.putFloat("yPercent", yPercent); tag.putBoolean("Display", display); } @@ -326,7 +349,7 @@ public String getModId() { @Override public String toString() { - return "Widget{" + + return this.getClass().getName() + "{" + "uniqueId='" + uid.getUniqueID() + '\'' + ", x=" + x + ", y=" + y + diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index 978feac..fbde8cb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -108,20 +108,10 @@ public static void onScreenResized(int newWidth, int newHeight, int previousWidt widget.yPercent = (float) widget.getY() / previousHeight; } - // Use the stored percentages to calculate the new position - float newX = widget.xPercent * newWidth; - float newY = widget.yPercent * newHeight; + widget.updatePositionFromPercentages(newWidth, newHeight); - // Ensure the widget is within the screen bounds - newX = MathHelper.clamp(newX, 0, newWidth - widget.getWidth()); - newY = MathHelper.clamp(newY, 0, newHeight - widget.getHeight()); - - // Update the widget's position - widget.setPosition((int) newX, (int) newY); - - // Update the stored percentages with the new screen size (after resize). - widget.xPercent = (float) widget.getX() / newWidth; - widget.yPercent = (float) widget.getY() / newHeight; + widget.xPercent = (widget.getX() + widget.getWidth() / 2) / newWidth; + widget.yPercent = (widget.getY() + widget.getHeight() / 2) / newHeight; } } @@ -184,19 +174,23 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti public static void loadWidgets(File file) throws IOException { widgets.clear(); - if (file.exists()) { + if (file.exists() || (file = new File(file.getAbsolutePath() + ".backup")).exists()) { + if(!file.exists()){ + printWarn("Main file " + file.getAbsolutePath() + " was not found... Loading from a found backup file"); + } + NbtCompound rootTag = NbtIo.read(file.toPath()); NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); if (widgetList == null) { - printWarn("RootTag is null. File is either empty or corrupted," + file); + printWarn("RootTag or WidgetList is null. File is either empty or corrupted: " + file); return; } for (int i = 0; i < widgetList.size(); i++) { NbtCompound widgetTag = widgetList.getCompound(i); WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); Widget widget = widgetData.createWidget(); - printInfo("Loading Widget: " + widget); widget.readFromTag(widgetTag); + printInfo("Loaded Widget: " + widget); widgets.add(widget); } } else { @@ -204,6 +198,7 @@ public static void loadWidgets(File file) throws IOException { } } + /** * Returns the list of managed widgets. * diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index 4c734c1..c3eac55 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreen; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.Screen; @@ -27,6 +28,7 @@ public class WidgetRenderer { public WidgetRenderer(List widgets) { this.widgets = widgets; addScreen(GameMenuScreen.class); + addScreen(ContextMenuScreen.class); } public void addWidget(Widget widget) { @@ -64,7 +66,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { return; } //Render in any other screen - if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass()) && !this.isInEditor) { + if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass())) { for (Widget widget : widgets) { widget.isInEditor = false; widget.render(context, 0, 0); diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 9e6fa6a..374e12b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -4,7 +4,11 @@ import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -18,7 +22,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; -public class TextWidget extends Widget { +public class TextWidget extends Widget implements ContextMenuProvider { public Color textColor; protected boolean shadow; // Whether to draw a shadow behind the text public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); @@ -28,10 +32,10 @@ public class TextWidget extends Widget { String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; private ContextMenu menu; + public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); } - /** * Searches for the supplier within the {@link DynamicValueRegistry#globalRegistry} using the given registryKey * @@ -47,6 +51,7 @@ public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow, Co this.rainbow = rainbow; this.textColor = color; createMenu(); + ContextMenuManager.getInstance().registerProvider(this); } /** @@ -67,29 +72,34 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis this.shadow = shadow; this.rainbow = rainbow; createMenu(); + ContextMenuManager.getInstance().registerProvider(this); } public void createMenu() { - menu = new ContextMenu(getX(), getY()); - menu.addOption(new BooleanOption("Shadow", () -> this.shadow, value -> this.shadow = value)); - menu.addOption(new BooleanOption("Rainbow", () -> this.rainbow, value -> this.rainbow = value)); + ContextMenuProperties properties = ContextMenuProperties.builder() + .skin(new MinecraftSkin(MinecraftSkin.PanelColor.CREAMY)) + .build(); + + menu = new ContextMenu(getX(), getY(), properties); + menu.getProperties().getSkin().setContextMenu(menu); + menu.addOption(new BooleanOption("Shadow", () -> this.shadow, value -> this.shadow = value, BooleanOption.BooleanType.ON_OFF)); + menu.addOption(new BooleanOption("Rainbow", () -> this.rainbow, value -> this.rainbow = value, BooleanOption.BooleanType.ON_OFF)); menu.addOption(new ColorOption("TextColor", menu, () -> this.textColor, value -> this.textColor = value)); - menu.addOption(new DoubleOption("RainbowSpeed", 1, 4, 1.0f, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(),menu)); + menu.addOption(new DoubleOption("RainbowSpeed", 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(),menu)); - /* TEST - AtomicReference enums = new AtomicReference<>(Enum.Enum1); + /* AtomicReference option = new AtomicReference<>("Enum1"); - List options = Arrays.asList("List1", "List2", "List3"); + List options = Arrays.asList("List1", "LONGER LIST 2", "List3"); AtomicBoolean running = new AtomicBoolean(false); AtomicBoolean subMenu = new AtomicBoolean(false); - menu.addOption(new EnumOption<>("Enum", enums::get, enums::set, Enum.values())); menu.addOption(new ListOption<>("List", option::get, option::set, options)); - menu.addOption(new RunnableOption("Runnable Test",running::get,running::set, this::printStuff)); + menu.addOption(new RunnableOption("Runnable Test",running::get,running::set, ()-> System.out.println("Runnable ran"))); SubMenuOption subMenuOption = new SubMenuOption("SubMenu",menu,subMenu::get,subMenu::set); subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows2", () -> this.shadow, value -> this.shadow = value)); subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows3", () -> this.shadow, value -> this.shadow = value)); subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows4", () -> this.shadow, value -> this.shadow = value)); menu.addOption(subMenuOption); + */ } @@ -101,7 +111,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow); widgetBox.setSizeAndPosition(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale()); } - menu.render(drawContext, getX(), getY(), (int) Math.ceil(getHeight()),mouseX,mouseY); + menu.set(getX(),getY(),(int) Math.ceil(getHeight())); } @Override @@ -109,19 +119,16 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) { menu.toggleDisplay(); } - menu.mouseClicked(mouseX, mouseY, button); return super.mouseClicked(mouseX, mouseY, button); } @Override public void mouseReleased(double mouseX, double mouseY, int button) { - menu.mouseReleased(mouseX, mouseY, button); super.mouseReleased(mouseX, mouseY, button); } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { - menu.mouseDragged(mouseX, mouseY, button); return super.mouseDragged(mouseX, mouseY, button, snapSize); } @@ -169,6 +176,11 @@ public void readFromTag(NbtCompound tag) { createMenu(); } + @Override + public ContextMenu getContextMenu() { + return menu; + } + public static class Builder extends WidgetBuilder { protected boolean shadow = false; protected boolean rainbow = false; diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json index 2cff290..6d7d318 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -4,11 +4,10 @@ "package": "com.tanishisherewith.dynamichud.mixins", "compatibilityLevel": "JAVA_17", "mixins": [ + "ScreenMixin" ], "injectors": { "defaultRequire": 1 }, - "client": [ - "ScreenMixin" - ] + "client": [] } From a73a79a349bc0e1eb7c88ec4e2de74493022beb1 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:02:44 +0530 Subject: [PATCH 02/40] Changes and better code structure. --- .../utils/contextmenu/ContextMenu.java | 70 +++++----- .../dynamichud/utils/contextmenu/Option.java | 45 +++++- .../contextmenuscreen/ContextMenuScreen.java | 6 +- .../contextmenu/options/ColorOption.java | 4 +- .../contextmenu/options/SubMenuOption.java | 6 +- .../contextmenu/skinsystem/ClassicSkin.java | 59 ++++---- .../contextmenu/skinsystem/MinecraftSkin.java | 129 ++++++++---------- .../utils/contextmenu/skinsystem/Skin.java | 9 ++ .../dynamichud/widgets/TextWidget.java | 4 - 9 files changed, 176 insertions(+), 156 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 4297b69..1dac53f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -24,15 +24,15 @@ public class ContextMenu { // Width is counted while the options are being rendered. // FinalWidth is the width at the end of the count. private int width = 0; - public int finalWidth = 0; - public int height = 0, widgetHeight = 0; + private int finalWidth = 0; + private int height = 0, widgetHeight = 0; //Todo: Add padding around the rectangle instead of just one side. - public boolean shouldDisplay = false; - public float scale = 0.0f; + private boolean shouldDisplay = false; + private float scale = 0.0f; public final Color darkerBackgroundColor; - public boolean newScreenFlag = false; - public Screen parentScreen = null; + private Screen parentScreen = null; private final ContextMenuScreenFactory screenFactory; + private boolean newScreenFlag = false; public ContextMenu(int x, int y, ContextMenuProperties properties) { this(x, y, properties, new DefaultContextMenuScreenFactory()); @@ -52,8 +52,8 @@ public void addOption(Option option) { } public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - if(newScreenFlag && screenFactory != null) { - DynamicHUD.MC.setScreen(screenFactory.create(this,properties)); + if (newScreenFlag && screenFactory != null) { + DynamicHUD.MC.setScreen(screenFactory.create(this, properties)); return; } @@ -67,35 +67,6 @@ public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY properties.getSkin().setContextMenu(this); properties.getSkin().renderContextMenu(drawContext,this,mouseX,mouseY); - /* - // Draw the background - DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1, this.y, this.width, this.height, 2,properties.getBackgroundColor().getRGB()); - if(properties.shouldDrawBorder()){ - DrawHelper.drawOutlineRoundedBox(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1,this.y,this.width,this.height,2, properties.getBorderWidth(), darkerBorderColor.getRGB()); - } - - int yOffset = this.y + 3; - this.width = 10; - for (Option option : options) { - if (!option.shouldRender()) continue; - - // Adjust mouse coordinates based on the scale - int adjustedMouseX = (int) (mouseX / GlobalConfig.get().getScale()); - int adjustedMouseY = (int) (mouseY / GlobalConfig.get().getScale()); - - if (isMouseOver(adjustedMouseX, adjustedMouseY, this.x + 1, yOffset - 1, this.finalWidth - 2, option.height)) { - DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x, yOffset - 1.24f, this.finalWidth - 2, option.height + 0.48f, 2,properties.getBackgroundColor().darker().darker().getRGB()); - } - option.render(drawContext, x + 2, yOffset,mouseX,mouseY); - this.width = Math.max(this.width, option.width); - yOffset += option.height + 1; - } - this.width = this.width + properties.getPadding(); - this.finalWidth = this.width; - this.height = (yOffset - this.y); - - */ - DrawHelper.stopScaling(drawContext.getMatrices()); } public boolean isMouseOver(int mouseX, int mouseY, int x, int y, int width, int height){ @@ -119,7 +90,7 @@ public void update() { } public void close() { - if(newScreenFlag && scale <= 0 && parentScreen != null){ + if(properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null){ shouldDisplay = false; newScreenFlag = false; DynamicHUD.MC.setScreen(parentScreen); @@ -135,6 +106,9 @@ public void open() { shouldDisplay = true; update(); parentScreen = DynamicHUD.MC.currentScreen; + if (properties.getSkin().shouldCreateNewScreen()) { + newScreenFlag = true; + } } public void toggleDisplay() { @@ -176,7 +150,6 @@ public void keyPressed(int key, int scanCode, int modifiers) { } properties.getSkin().keyPressed(this,key,scanCode,modifiers); - } public void keyReleased(int key, int scanCode, int modifiers) { @@ -234,4 +207,23 @@ public void setFinalWidth(int finalWidth) { public ContextMenuProperties getProperties() { return properties; } + public void setWidgetHeight(int widgetHeight) { + this.widgetHeight = widgetHeight; + } + + public void setHeight(int height) { + this.height = height; + } + + public float getScale() { + return scale; + } + + public void setVisible(boolean shouldDisplay) { + this.shouldDisplay = shouldDisplay; + } + + public boolean isVisible() { + return shouldDisplay; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java index e56a2d9..08bd0ae 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -9,12 +9,11 @@ import java.util.function.Supplier; public abstract class Option { - public int x, y; - public int width = 0; - public int height = 0; + protected int x, y; + protected int width = 0; + protected int height = 0; public T value = null; - public Supplier shouldRender = () -> true; - protected float scale = 0.0f; + protected Supplier shouldRender = () -> true; protected Supplier getter; protected Consumer setter; protected T defaultValue = null; @@ -107,4 +106,40 @@ public boolean shouldRender() { public ContextMenuProperties getProperties() { return properties; } + + public void setY(int y) { + this.y = y; + } + + public void setX(int x) { + this.x = x; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public int getY() { + return y; + } + + public int getX() { + return x; + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + public void set(int x, int y){ + this.x = x; + this.y = y; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java index 4bcedee..9584622 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java @@ -21,20 +21,20 @@ protected ContextMenuScreen(ContextMenu menu,ContextMenuProperties properties) { @Override public void onDisplayed() { super.onDisplayed(); - contextMenu.shouldDisplay = true; + contextMenu.setVisible(true); } @Override public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { contextMenu.update(); - DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width /2, (float) height /2,contextMenu.scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width /2, (float) height /2,contextMenu.getScale()); properties.getSkin().setContextMenu(contextMenu); properties.getSkin().renderContextMenu(drawContext,contextMenu,mouseX,mouseY); DrawHelper.stopScaling(drawContext.getMatrices()); - if(contextMenu.scale <= 0 && !contextMenu.shouldDisplay){ + if(contextMenu.getScale() <= 0 && !contextMenu.isVisible()){ contextMenu.close(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index f6dc41d..fc52ce5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -21,7 +21,7 @@ public ColorOption(String name, ContextMenu parentMenu, Supplier getter, super(getter, setter); this.name = name; this.parentMenu = parentMenu; - colorPicker = new ColorGradientPicker(x + this.parentMenu.finalWidth, y - 10, get(), this::set, 50, 100); + colorPicker = new ColorGradientPicker(x + this.parentMenu.getFinalWidth(), y - 10, get(), this::set, 50, 100); this.renderer.init(this); } @@ -59,7 +59,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY)) { isVisible = !isVisible; if (isVisible) { - colorPicker.setPos(this.x + parentMenu.finalWidth + 7, y - 10); + colorPicker.setPos(this.x + parentMenu.getFinalWidth() + 7, y - 10); colorPicker.display(); } else { colorPicker.close(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 1496581..737f815 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -30,9 +30,9 @@ public SubMenuOption(String name, ContextMenu parentMenu, Supplier gett Objects.requireNonNull(parentMenu, "Parent Menu cannot be null"); this.name = name; this.parentMenu = parentMenu; - this.subMenu = new ContextMenu(parentMenu.x + parentMenu.finalWidth, this.y,properties); + this.subMenu = new ContextMenu(parentMenu.x + parentMenu.getFinalWidth(), this.y,properties); this.subMenu.getProperties().setHeightOffset(0); - this.subMenu.shouldDisplay = get(); + this.subMenu.setVisible(get()); this.renderer.init(this); } public SubMenuOption(String name, ContextMenu parentMenu, ContextMenuProperties properties) { @@ -55,7 +55,7 @@ public void render(DrawContext drawContext, int x, int y,int mouseX,int mouseY) public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { subMenu.toggleDisplay(); - set(subMenu.shouldDisplay); + set(subMenu.isVisible()); return true; } subMenu.mouseClicked(mouseX, mouseY, button); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 2810c33..1328571 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -30,12 +30,13 @@ public ClassicSkin() { addRenderer(SubMenuOption.class, new ClassicSubMenuRenderer()); addRenderer(RunnableOption.class, new ClassicRunnableRenderer()); addRenderer(ColorOption.class, new ClassicColorOptionRenderer()); + + setCreateNewScreen(false); } @Override public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { this.contextMenu = contextMenu; - this.contextMenu.newScreenFlag = false; MatrixStack matrices = drawContext.getMatrices(); ContextMenuProperties properties = contextMenu.getProperties(); @@ -49,17 +50,17 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, if (!option.shouldRender()) continue; // Adjust mouse coordinates based on the scale - if (contextMenu.getProperties().hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, contextMenu.x + 1, yOffset - 1, contextMenu.getFinalWidth() - 2, option.height)) { - drawBackground(matrices, contextMenu, properties, yOffset - 1,contextMenu.getFinalWidth(), option.height + 1, contextMenu.getProperties().getHoverColor().getRGB(),false); + if (contextMenu.getProperties().hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, contextMenu.x + 1, yOffset - 1, contextMenu.getFinalWidth() - 2, option.getHeight())) { + drawBackground(matrices, contextMenu, properties, yOffset - 1,contextMenu.getFinalWidth(), option.getHeight() + 1, contextMenu.getProperties().getHoverColor().getRGB(),false); } option.render(drawContext, contextMenu.x + 4, yOffset, mouseX, mouseY); - contextMenu.setWidth(Math.max(contextMenu.getWidth(), option.width)); - yOffset += option.height + 1; + contextMenu.setWidth(Math.max(contextMenu.getWidth(), option.getWidth())); + yOffset += option.getHeight() + 1; } contextMenu.setWidth(contextMenu.getWidth() + properties.getPadding()); contextMenu.setFinalWidth(contextMenu.getWidth()); - contextMenu.height = (yOffset - contextMenu.y); + contextMenu.setHeight(yOffset - contextMenu.y); // Draw the border if needed if (properties.shouldDrawBorder()) { @@ -68,7 +69,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, } private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { - drawBackground(matrices, contextMenu, properties, contextMenu.y,contextMenu.getWidth(), contextMenu.height, properties.getBackgroundColor().getRGB(),properties.shadow()); + drawBackground(matrices, contextMenu, properties, contextMenu.y,contextMenu.getWidth(), contextMenu.getHeight(), properties.getBackgroundColor().getRGB(),properties.shadow()); } private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset,int width, int height, int color,boolean shadow) { @@ -126,7 +127,7 @@ private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, ContextMe contextMenu.x, contextMenu.y, contextMenu.getWidth(), - contextMenu.height, + contextMenu.getHeight(), properties.getCornerRadius(), properties.getBorderWidth(), properties.getBorderColor().getRGB() @@ -136,7 +137,7 @@ private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, ContextMe contextMenu.x, contextMenu.y, contextMenu.getWidth(), - contextMenu.height, + contextMenu.getHeight(), properties.getBorderWidth(), properties.getBorderColor().getRGB() ); @@ -148,8 +149,8 @@ public static class ClassicBooleanRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { - option.width = Math.max(35, contextMenu != null ? contextMenu.getFinalWidth() - option.getProperties().getPadding() - 2 : 0); - option.height = 16; + option.setWidth(Math.max(35, contextMenu != null ? contextMenu.getFinalWidth() - option.getProperties().getPadding() - 2 : 0)); + option.setHeight(16); // Draw the label TextRenderer textRenderer = mc.textRenderer; DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, 0.7f); String labelText = option.name + ": " + String.format("%.1f", option.value); int labelWidth = textRenderer.getWidth(labelText); - option.width = Math.max(option.width, labelWidth); + + option.setWidth(Math.max(option.getWidth(), labelWidth)); + drawContext.drawTextWithShadow(textRenderer, labelText, x, y + 1, 0xFFFFFFFF); DrawHelper.stopScaling(drawContext.getMatrices()); float handleWidth = 3; float handleHeight = 8; - double handleX = x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.width - handleWidth); + double handleX = x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.getWidth() - handleWidth); double handleY = y + textRenderer.fontHeight + 1 + ((2 - handleHeight) / 2); // Draw the slider - option.drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, option.width, handleX); + option.drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, option.getWidth(), handleX); // Draw the handle @@ -218,8 +221,8 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i public static class ClassicEnumRenderer> implements SkinRenderer> { @Override public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { - option.height = mc.textRenderer.fontHeight + 1; - option.width = mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1; + option.setHeight(mc.textRenderer.fontHeight + 1); + option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1); drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y, Color.WHITE.getRGB(), false); drawContext.drawText(mc.textRenderer, Text.of(option.value.name()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); @@ -229,8 +232,8 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y, public class ClassicListRenderer implements SkinRenderer> { @Override public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { - option.height = mc.textRenderer.fontHeight + 1; - option.width = mc.textRenderer.getWidth(option.name + ": " + option.value.toString()) + 1; + option.setHeight(mc.textRenderer.fontHeight + 1); + option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.toString()) + 1); drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y + 1, Color.WHITE.getRGB(), false); drawContext.drawText(mc.textRenderer, Text.of(option.value.toString()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false); @@ -242,10 +245,10 @@ public static class ClassicSubMenuRenderer implements SkinRenderer option : contextMenu.getOptions()) { if (!option.shouldRender()) continue; - if (yOffset >= imageY && yOffset <= maxYOffset - option.height + 4) { + if (yOffset >= imageY && yOffset <= maxYOffset - option.getHeight() + 4) { option.render(drawContext, imageX + 4, yOffset, mouseX, mouseY); } - yOffset += option.height + 1; + yOffset += option.getHeight() + 1; } - contextMenu.height = (yOffset - imageY) + 25; + contextMenu.setHeight(yOffset - imageY + 25); applyMomentum(); // Calculate max scroll offset - maxScrollOffset = Math.max(0, contextMenu.height - panelHeight + 10); + maxScrollOffset = Math.max(0, contextMenu.getHeight() - panelHeight + 10); scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); // Disable scissor after rendering @@ -197,29 +191,28 @@ public class MinecraftBooleanRenderer implements SkinRenderer { public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - 75; - option.y = y; + option.set(x + panelWidth - 75, y); int width = 50; drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,width,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,width,20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); Text text = option.getBooleanType().getText(option.value); int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer,text,(int) (option.x + (width/2.0f) -(mc.textRenderer.getWidth(text)/2.0f)) ,y + 5,color,true); + drawContext.drawText(mc.textRenderer,text,(int) (option.getX() + (width/2.0f) -(mc.textRenderer.getWidth(text)/2.0f)) ,y + 5,color,true); //drawContext.drawTexture(BOOLEAN_TEXTURE); - option.height = 25; + option.setHeight(25); - //Widths dont matter in this skin. - option.width = width; + //Widths dont matter in this skin + option.setWidth(width); } @Override public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, int button) { - if(mouseX >= option.x && mouseX <= option.x + 50 && mouseY >= option.y && mouseY <= option.y + option.height){ + if(mouseX >= option.getX() && mouseX <= option.getX() + 50 && mouseY >= option.getY() && mouseY <= option.getY() + option.getHeight()){ option.set(!option.get()); } return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button); @@ -231,17 +224,16 @@ public class MinecraftColorOptionRenderer implements SkinRenderer { public void render(DrawContext drawContext, ColorOption option, int x, int y, int mouseX, int mouseY) { drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - 75; - option.y = y; + option.set(x + panelWidth - 75 , y); int width = 20; drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX,mouseY)), option.x,y,width,20); + drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX,mouseY)), option.getX(),y,width,20); int shadowOpacity = Math.min(option.value.getAlpha(),45); DrawHelper.drawRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), - option.x + 4, + option.getX() + 4, y + 4, width - 8, 20 - 8, @@ -252,8 +244,8 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - option.height = 25; - option.width = width; + option.setHeight(25); + option.setWidth(width); option.getColorPicker().render(drawContext, x + panelWidth + 10, y - 10); } @@ -274,12 +266,11 @@ public void init(DoubleOption option) { public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); - option.width = panelWidth - 150; - option.height = 25; + option.setWidth(panelWidth - 150); + option.setHeight(25); - option.x = x + panelWidth - 122; - option.y = y; - double sliderX = option.x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.width - 8); + option.set(x + panelWidth - 122,y); + double sliderX = option.getX() + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.getWidth() - 8); boolean isMouseOverHandle = isMouseOver(mouseX,mouseY, sliderX, y); RenderSystem.enableBlend(); @@ -287,11 +278,11 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i RenderSystem.enableDepthTest(); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawGuiTexture(option.isMouseOver(mouseX,mouseY)? HIGHLIGHTED_TEXTURE : TEXTURE, option.x, y, option.width, 20); + drawContext.drawGuiTexture(option.isMouseOver(mouseX,mouseY)? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20); drawContext.drawGuiTexture(isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE , (int) Math.round(sliderX), y, 8, 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawText(mc.textRenderer, String.valueOf(option.value),option.x + option.width/2 - mc.textRenderer.getWidth(option.value.toString())/2 ,y + 5,16777215,false); + drawContext.drawText(mc.textRenderer, String.valueOf(option.value),option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth(option.value.toString())/2 ,y + 5,16777215,false); } private boolean isMouseOver(double mouseX, double mouseY, double x, double y){ return mouseX >= x && mouseX <= x + 10 && mouseY >= y && mouseY <= y + 20; @@ -299,7 +290,7 @@ private boolean isMouseOver(double mouseX, double mouseY, double x, double y){ @Override public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) { - return isMouseOver(mouseX,mouseY,option.x,option.y); + return isMouseOver(mouseX,mouseY,option.getX(),option.getY()); } } @@ -318,21 +309,20 @@ private void calculateMaxWidth(EnumOption option) { @Override public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { calculateMaxWidth(option); - option.height = 25; - option.width = maxWidth; + option.setHeight(25); + option.setWidth(maxWidth); drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - maxWidth - 25; - option.y = y; + option.set(x + panelWidth - maxWidth - 25, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,maxWidth,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,maxWidth,20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); - drawContext.drawText(mc.textRenderer,text,option.x + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + drawContext.drawText(mc.textRenderer,text,option.getX() + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); } } @@ -351,44 +341,42 @@ private void calculateMaxWidth(ListOption option) { @Override public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { calculateMaxWidth(option); - option.height = 25; - option.width = maxWidth; + option.setHeight(25); + option.setWidth(maxWidth); drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - maxWidth - 25; - option.y = y; + option.set(x + panelWidth - maxWidth - 25, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y,maxWidth,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,maxWidth,20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); - drawContext.drawText(mc.textRenderer,text,option.x + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + drawContext.drawText(mc.textRenderer,text,option.getX() + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); } } public class MinecraftSubMenuRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, SubMenuOption option, int x, int y, int mouseX, int mouseY) { - option.height = 20; - option.width = 30; + option.setHeight(20); + option.setWidth(30); drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - 75; - option.y = y; + option.set(x + panelWidth - 75, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.x,y, option.width,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y, option.getWidth(),20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = "Open"; - drawContext.drawText(mc.textRenderer,text,option.x + option.width/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.YELLOW.getRGB(),true); + drawContext.drawText(mc.textRenderer,text,option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.YELLOW.getRGB(),true); - option.getSubMenu().render(drawContext, x + option.getParentMenu().finalWidth, y, mouseX, mouseY); + option.getSubMenu().render(drawContext, x + option.getParentMenu().getFinalWidth(), y, mouseX, mouseY); } } @@ -398,22 +386,19 @@ public class MinecraftRunnableRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) { - option.height = 25; - option.width = 26; + option.setHeight(25); + option.setWidth(26); drawContext.drawText(mc.textRenderer, option.name.replaceFirst("Run: ","") + ": ", x + 15, y + 25/2 - 5, -1, true); - option.x = x + panelWidth - 75; - option.y = y; + option.set(x + panelWidth - 75, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX,mouseY)), option.x,y, option.width,20); + drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX,mouseY)), option.getX(),y, option.getWidth(),20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawText(mc.textRenderer,"Run",option.x + option.width/2 - mc.textRenderer.getWidth("Run")/2 ,y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(),true); + drawContext.drawText(mc.textRenderer,"Run",option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth("Run")/2 ,y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(),true); } } - - -} +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java index 4533af1..b2007a3 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java @@ -11,6 +11,7 @@ public abstract class Skin { protected ContextMenu contextMenu; protected Map>, SkinRenderer>> renderers = new HashMap<>(); + private boolean createNewScreen; public > void addRenderer(Class optionClass, SkinRenderer renderer) { renderers.put(optionClass, renderer); @@ -52,4 +53,12 @@ public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int public void keyPressed(ContextMenu menu, int key,int scanCode, int modifiers) {} public void keyReleased(ContextMenu menu, int key,int scanCode, int modifiers) {} public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount){} + + public boolean shouldCreateNewScreen() { + return createNewScreen; + } + + public void setCreateNewScreen(boolean createNewScreen) { + this.createNewScreen = createNewScreen; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 374e12b..0dfdd08 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -232,8 +232,4 @@ public TextWidget build() { return widget; } } - - - - } From 5ea697bae94d417d6804dc21761a874e8d14ba25 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 1 Oct 2024 22:33:25 +0530 Subject: [PATCH 03/40] Bump to 1.21.1 --- build.gradle | 2 +- gradle.properties | 13 +++++++------ .../tanishisherewith/dynamichud/widget/Widget.java | 8 ++++---- .../dynamichud/widgets/TextWidget.java | 2 +- src/main/resources/dynamichud.mixins.json | 2 +- src/main/resources/fabric.mod.json | 6 +++++- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 782b183..9f94dfe 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ dependencies { modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}" - modApi "com.terraformersmc:modmenu:11.0.1" + modApi "com.terraformersmc:modmenu:${project.modmenu_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index da95953..e2dee65 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,15 +4,16 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21 -yarn_mappings=1.21+build.2 -loader_version=0.15.11 +minecraft_version=1.21.1 +yarn_mappings=1.21.1+build.3 +loader_version=0.16.2 # Mod Properties -mod_version = 2.1.0 +mod_version = 2.2.0 maven_group = com.tanishisherewith archives_base_name = dynamichud # Dependencies -fabric_version=0.100.3+1.21 -yacl_version=3.5.0+1.21-fabric \ No newline at end of file +fabric_version=0.102.1+1.21.1 +yacl_version=3.5.0+1.21-fabric +modmenu_version = 11.0.2 \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index b80175b..cd9f980 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -105,13 +105,13 @@ public float getHeight() { private void updatePercentages() { int screenWidth = mc.getWindow().getScaledWidth(); int screenHeight = mc.getWindow().getScaledHeight(); - this.xPercent = (float) (this.x + this.getWidth() / 2) / screenWidth; - this.yPercent = (float) (this.y + this.getHeight() / 2) / screenHeight; + this.xPercent = (float) (this.x) / screenWidth; + this.yPercent = (float) (this.y) / screenHeight; } void updatePositionFromPercentages(int screenWidth, int screenHeight) { - this.x = (int) (this.xPercent * screenWidth - this.getWidth() / 2); - this.y = (int) (this.yPercent * screenHeight - this.getHeight() / 2); + this.x = (int) (this.xPercent * screenWidth); + this.y = (int) (this.yPercent * screenHeight); this.x = (int) MathHelper.clamp(x, 0, mc.getWindow().getScaledWidth() - getWidth()); this.y = (int) MathHelper.clamp(y, 0, mc.getWindow().getScaledHeight() - getHeight()); diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 0dfdd08..120aaab 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -77,7 +77,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis public void createMenu() { ContextMenuProperties properties = ContextMenuProperties.builder() - .skin(new MinecraftSkin(MinecraftSkin.PanelColor.CREAMY)) + .skin(new MinecraftSkin(MinecraftSkin.PanelColor.DARK_PANEL)) .build(); menu = new ContextMenu(getX(), getY(), properties); diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json index 6d7d318..f40333e 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.tanishisherewith.dynamichud.mixins", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "ScreenMixin" ], diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6b684b8..33a2089 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -15,7 +15,7 @@ "repo": "https://github.com/V-Fast/DynamicHUD", "issues": "https://github.com/V-Fast/DynamicHUD/issues" }, - "license": "All-Rights-Reserved", + "license": "MIT", "environment": "client", "entrypoints": { "client": [ @@ -31,11 +31,15 @@ "depends": { "fabricloader": ">=${loader_version}", "fabric": "*", + "java": ">=21", "minecraft": "~${minecraft_version}" }, "custom": { "modmenu": { "badges": ["library"] } + }, + "suggests": { + "yet_another_config_lib_v3": "3.5.0+1.21-fabric" } } From 1cd3569ae6631f6f4a86fe2378b0e50635e688e0 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:33:32 +0530 Subject: [PATCH 04/40] Scroll-Bar, and a new widget anchoring system for resizing. As well as some more stuff. --- .../dynamichud/DynamicHUD.java | 2 +- .../contextmenu/skinsystem/MinecraftSkin.java | 67 ++++++++++--- .../dynamichud/widget/Widget.java | 96 +++++++++++-------- .../dynamichud/widget/WidgetManager.java | 12 ++- .../dynamichud/widgets/TextWidget.java | 2 +- 5 files changed, 122 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 5d43b98..80800da 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -104,7 +104,7 @@ public void onInitializeClient() { widgetsFile = DHIntegration.getWidgetsFile(); // Adds / loads widgets from file - if (widgetsFile.exists()) { + if (WidgetManager.doesWidgetFileExist(widgetsFile)) { WidgetManager.loadWidgets(widgetsFile); } else { DHIntegration.addWidgets(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index c61a860..874c268 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -8,6 +8,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ButtonTextures; +import net.minecraft.client.texture.Sprite; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -29,7 +30,12 @@ public class MinecraftSkin extends Skin { private final int panelHeight; private final PanelColor panelColor; public static final ButtonTextures TEXTURES = new ButtonTextures(Identifier.ofVanilla("widget/button"), Identifier.ofVanilla("widget/button_disabled"), Identifier.ofVanilla("widget/button_highlighted")); + private static final Identifier SCROLLER = Identifier.ofVanilla("widget/scroller"); + private static final Identifier SCROLL_BAR_BACKGROUND = Identifier.ofVanilla("widget/scroller_background"); private double scrollVelocity = 0; + public static int SCROLLBAR_WIDTH = 10; + + int imageX, imageY; public enum PanelColor { COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f), @@ -109,8 +115,9 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, contextMenu.set(centerX,centerY,0); // Calculate the top-left corner of the image - int imageX = centerX - panelWidth / 2; - int imageY = centerY - panelHeight / 2; + imageX = (screenWidth - panelWidth) / 2; + imageY = (screenHeight - panelHeight) / 2; + RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); @@ -139,6 +146,8 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, contextMenu.setHeight(yOffset - imageY + 25); + drawScrollbar(drawContext); + applyMomentum(); // Calculate max scroll offset @@ -148,22 +157,47 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, // Disable scissor after rendering DrawHelper.disableScissor(); } + + private void drawScrollbar(DrawContext context) { + int scrollbarX = imageX + panelWidth + 5; + int scrollbarY = imageY; + + // Draw scrollbar background + context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + context.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, SCROLLBAR_WIDTH, panelHeight); + context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + + if (maxScrollOffset > 0) { + float scrollPercentage = (float) scrollOffset / maxScrollOffset; + int handleHeight = Math.max(15, (int) ((float) panelHeight * (panelHeight / (float) contextMenu.getHeight()))); + int handleY = scrollbarY + (int) ((panelHeight - handleHeight) * scrollPercentage); + + // Draw scrollbar handle + context.drawGuiTexture(SCROLLER, scrollbarX, handleY, SCROLLBAR_WIDTH, handleHeight); + } + } + private boolean isMouseOver(double mouseX, double mouseY, double x, double y,double width, double height){ return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } + private void applyMomentum() { if (scrollVelocity != 0) { scrollOffset += (int) scrollVelocity; scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); - scrollVelocity *= 0.9; //Friction - // Stop the scrolling if the velocity is very low - if (Math.abs(scrollVelocity) < 0.12) { + // Stop the scrolling if the velocity is very low or if we've reached the limits + if (Math.abs(scrollVelocity) < 0.12 || scrollOffset == 0 || scrollOffset-maxScrollOffset <= 3) { scrollVelocity = 0; + } else { + scrollVelocity *= 0.89; // Apply friction } } } + @Override public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { scrollVelocity += verticalAmount; @@ -172,13 +206,6 @@ public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double @Override public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { - int screenWidth = mc.getWindow().getScaledWidth(); - int screenHeight = mc.getWindow().getScaledHeight(); - - // Calculate the top-left corner of the image - int imageX = (screenWidth - panelWidth) / 2; - int imageY = (screenHeight - panelHeight) / 2; - if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX,mouseY,imageX + 3,imageY + 3,14,14)){ contextMenu.close(); } @@ -186,6 +213,22 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int return super.mouseClicked(menu, mouseX, mouseY, button); } + @Override + public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (button == 0 && mouseX >= imageX + panelWidth + 5 && mouseX <= imageX + panelWidth + 20) { + if (mouseY >= imageY && mouseY <= imageY + panelHeight) { + float scrollPercentage = (float) (mouseY - imageY) / panelHeight; + int handleY = imageY + (int) ((panelHeight - 15) * scrollPercentage); + + // Draw scrollbar handle + scrollOffset = (int) (maxScrollOffset * scrollPercentage); + scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); + return true; + } + } + return super.mouseDragged(menu, mouseX, mouseY, button, deltaX, deltaY); + } + public class MinecraftBooleanRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index cd9f980..2e34341 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -6,6 +6,7 @@ import com.tanishisherewith.dynamichud.utils.UID; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.option.VideoOptionsScreen; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; @@ -14,6 +15,7 @@ import java.util.Set; public abstract class Widget { + public enum Anchor { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER } public WidgetData DATA; /** @@ -30,6 +32,8 @@ public abstract class Widget { public boolean display = true; public boolean isDraggable = true; + private int offsetX, offsetY; // Offset from the anchor point + //Boolean to check if the widget is being dragged public boolean dragging; @@ -49,10 +53,6 @@ public abstract class Widget { */ public String modId = "unknown"; protected MinecraftClient mc = MinecraftClient.getInstance(); - // The x position of the widget as a percentage of the screen width, i.e. the relative x position of the widget for resizing and scaling - protected float xPercent; - // The y position of the widget as a percentage of the screen height, i.e. the relative y position of the widget for resizing and scaling - protected float yPercent; /** * Scale of the current widget. * @@ -62,14 +62,20 @@ public abstract class Widget { //Dimensions of the widget protected WidgetBox widgetBox; int startX, startY; + private final Anchor anchor; // The chosen anchor point public Widget(WidgetData DATA, String modId) { + this(DATA,modId,Anchor.CENTER); + } + public Widget(WidgetData DATA, String modId,Anchor anchor) { this.DATA = DATA; widgetBox = new WidgetBox(0, 0, 0, 0); this.modId = modId; + this.anchor = anchor; init(); } + /** * This method is called at the end of the {@link Widget#Widget(WidgetData, String)} constructor. */ @@ -102,26 +108,50 @@ public float getHeight() { return widgetBox.getHeight(); } - private void updatePercentages() { - int screenWidth = mc.getWindow().getScaledWidth(); - int screenHeight = mc.getWindow().getScaledHeight(); - this.xPercent = (float) (this.x) / screenWidth; - this.yPercent = (float) (this.y) / screenHeight; + private void calculateOffset(int initialX, int initialY, int screenWidth, int screenHeight) { + int anchorX = getAnchorX(screenWidth); + int anchorY = getAnchorY(screenHeight); + this.offsetX = initialX - anchorX; + this.offsetY = initialY - anchorY; } - void updatePositionFromPercentages(int screenWidth, int screenHeight) { - this.x = (int) (this.xPercent * screenWidth); - this.y = (int) (this.yPercent * screenHeight); + private int getAnchorX(int screenWidth) { + return switch (anchor) { + case TOP_RIGHT, BOTTOM_RIGHT -> screenWidth; + case CENTER -> screenWidth / 2; + default -> 0; // TOP_LEFT and BOTTOM_LEFT + }; + } - this.x = (int) MathHelper.clamp(x, 0, mc.getWindow().getScaledWidth() - getWidth()); - this.y = (int) MathHelper.clamp(y, 0, mc.getWindow().getScaledHeight() - getHeight()); + private int getAnchorY(int screenHeight) { + return switch (anchor) { + case BOTTOM_LEFT, BOTTOM_RIGHT -> screenHeight; + case CENTER -> screenHeight / 2; + default -> 0; // TOP_LEFT and TOP_RIGHT + }; + } + + // Update position based on anchor and offset + void updatePosition(int screenWidth, int screenHeight) { + if(offsetX == 0 || offsetY == 0){ + calculateOffset(x,y,screenWidth,screenHeight); + } + + int anchorX = getAnchorX(screenWidth); + int anchorY = getAnchorY(screenHeight); + this.x = anchorX + offsetX; + this.y = anchorY + offsetY; + + clampPosition(); } public void setPosition(int x, int y) { this.x = x; this.y = y; - if(mc.getWindow() != null) { - updatePercentages(); + if(mc.getWindow() != null){ + //updatePercentages(); + calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Set initial offset + updatePosition( mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Initial placement } } @@ -148,7 +178,7 @@ public final void render(DrawContext drawContext, int mouseX, int mouseY) { if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } - + clampPosition(); } /** @@ -167,6 +197,7 @@ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } + clampPosition(); } @@ -188,7 +219,6 @@ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY * Override this method without super call to remove the background. * Could also be used to display placeholder values. * - * @param context */ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { //displayBg(context); @@ -210,6 +240,10 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } return false; } + public void clampPosition(){ + this.x = (int) MathHelper.clamp(this.x, 0, mc.getWindow().getScaledWidth() - getWidth()); + this.y = (int) MathHelper.clamp(this.y, 0, mc.getWindow().getScaledHeight() - getHeight()); + } public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { if(!isDraggable) return false; @@ -233,7 +267,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi this.x = (int) MathHelper.clamp(newX, 0, mc.getWindow().getScaledWidth() - getWidth()); this.y = (int) MathHelper.clamp(newY, 0, mc.getWindow().getScaledHeight() - getHeight()); - updatePercentages(); + calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Set initial offset return true; } @@ -286,19 +320,6 @@ public void readFromTag(NbtCompound tag) { display = tag.getBoolean("Display"); isDraggable = tag.getBoolean("isDraggable"); shouldScale = tag.getBoolean("shouldScale"); - xPercent = tag.getFloat("xPercent"); - yPercent = tag.getFloat("yPercent"); - - if(mc.getWindow() != null) { - mc.execute(()->{ - if (x != mc.getWindow().getScaledWidth() * xPercent) { - x = (int) MathHelper.clamp(mc.getWindow().getScaledWidth() * xPercent, 0, mc.getWindow().getScaledWidth() - getWidth()); - } - if (y != mc.getWindow().getScaledHeight() * yPercent) { - y = (int) MathHelper.clamp(mc.getWindow().getScaledHeight() * yPercent, 0, mc.getWindow().getScaledHeight() - getHeight()); - } - }); - } } /** @@ -314,9 +335,8 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("shouldScale", shouldScale); tag.putInt("x", x); tag.putInt("y", y); - tag.putFloat("xPercent", xPercent); - tag.putFloat("yPercent", yPercent); tag.putBoolean("Display", display); + } public boolean shouldDisplay() { @@ -327,14 +347,6 @@ public WidgetBox getWidgetBox() { return widgetBox; } - public void setxPercent(float xPercent) { - this.xPercent = xPercent; - } - - public void setyPercent(float yPercent) { - this.yPercent = yPercent; - } - public void setUid(UID uid) { this.uid = uid; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index fbde8cb..d3afbcc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.widget; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.mixins.ScreenMixin; import net.fabricmc.fabric.api.util.NbtType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; @@ -89,7 +90,7 @@ public static void removeWidget(Widget widget) { * Larger the GUI scale, more accurate is the position on any resolution. *

*

- * Called in {@link com.tanishisherewith.dynamichud.mixins.ScreenMixin} + * Called in {@link ScreenMixin} *

*

* @@ -101,6 +102,10 @@ public static void removeWidget(Widget widget) { public static void onScreenResized(int newWidth, int newHeight, int previousWidth, int previousHeight) { for (Widget widget : widgets) { // To ensure that infinite coordinates is not returned for the first time its resized. + + widget.updatePosition(newWidth, newHeight); + + /* if (widget.xPercent <= 0.0f) { widget.xPercent = (float) widget.getX() / previousWidth; } @@ -112,6 +117,8 @@ public static void onScreenResized(int newWidth, int newHeight, int previousWidt widget.xPercent = (widget.getX() + widget.getWidth() / 2) / newWidth; widget.yPercent = (widget.getY() + widget.getHeight() / 2) / newHeight; + + */ } } @@ -198,6 +205,9 @@ public static void loadWidgets(File file) throws IOException { } } + public static boolean doesWidgetFileExist(File file){ + return file.exists() || new File(file.getAbsolutePath() + ".backup").exists(); + } /** * Returns the list of managed widgets. diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 120aaab..4db69cb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -87,7 +87,7 @@ public void createMenu() { menu.addOption(new ColorOption("TextColor", menu, () -> this.textColor, value -> this.textColor = value)); menu.addOption(new DoubleOption("RainbowSpeed", 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(),menu)); - /* + /* TEST AtomicReference option = new AtomicReference<>("Enum1"); List options = Arrays.asList("List1", "LONGER LIST 2", "List3"); AtomicBoolean running = new AtomicBoolean(false); From 25c4c4be902ff2a202ffbe4671f549bc523d7e07 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 3 Oct 2024 22:27:47 +0530 Subject: [PATCH 05/40] Some YACL changes and a few changes. --- .../dynamichud/DynamicHUD.java | 10 ------ .../dynamichud/ModMenuIntegration.java | 4 +-- .../dynamichud/config/GlobalConfig.java | 16 +++++++++ .../screens/AbstractMoveableScreen.java | 8 ++--- .../utils/contextmenu/ContextMenu.java | 1 - .../contextmenu/skinsystem/MinecraftSkin.java | 36 ++++++++++++------- 6 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 80800da..a75631f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -163,16 +163,6 @@ public void onInitializeClient() { }); printInfo("(DynamicHUD) Integration of supported mods was successful"); - - //Global config saving (YACL) - ServerLifecycleEvents.SERVER_STOPPING.register(server -> GlobalConfig.HANDLER.save()); - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> GlobalConfig.HANDLER.save()); - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> GlobalConfig.HANDLER.save()); - ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> { - GlobalConfig.HANDLER.save(); - }); - - //In game screen render. HudRenderCallback.EVENT.register(new HudRender()); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java index 30fffb4..7cab250 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java @@ -7,10 +7,8 @@ public class ModMenuIntegration implements ModMenuApi { - public static Screen YACL_CONFIG_SCREEN = GlobalConfig.get().createYACLGUI(); - @Override public ConfigScreenFactory getModConfigScreenFactory() { - return parent -> YACL_CONFIG_SCREEN; + return parent -> GlobalConfig.get().createYACLGUI(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index d8b5690..8621b99 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -3,6 +3,7 @@ import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; +import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; import dev.isxander.yacl3.config.v2.api.SerialEntry; import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; @@ -19,6 +20,7 @@ public final class GlobalConfig { .setJson5(true) .build()) .build(); + private static final GlobalConfig INSTANCE = new GlobalConfig(); /** * Common scale for all widgets. Set by the user using YACL. @@ -32,6 +34,9 @@ public final class GlobalConfig { @SerialEntry private boolean showColorPickerPreview = true; + @SerialEntry + private int snapSize = 100; + public static GlobalConfig get() { return INSTANCE; } @@ -63,8 +68,15 @@ public final Screen createYACLGUI() { .binding(true, () -> this.displayDescriptions, newVal -> this.displayDescriptions = newVal) .controller(booleanOption -> BooleanControllerBuilder.create(booleanOption).yesNoFormatter()) .build()) + .option(Option.createBuilder() + .name(Text.literal("Snap Size")) + .description(OptionDescription.of(Text.literal("Grid size for snapping widgets"))) + .binding( 100, () -> this.snapSize, newVal -> this.snapSize = newVal) + .controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10,500)) + .build()) .build()) .build()) + .save(HANDLER::save) .build() .generateScreen(null); } @@ -79,4 +91,8 @@ public boolean showColorPickerPreview() { public boolean shouldDisplayDescriptions() { return displayDescriptions; } + + public int getSnapSize() { + return snapSize; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 58bf8dd..95c4801 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -10,7 +10,7 @@ public abstract class AbstractMoveableScreen extends Screen { public final WidgetRenderer widgetRenderer; - public int snapSize = 100; + /** * Constructs a AbstractMoveableScreen object. */ @@ -27,7 +27,7 @@ public void onDisplayed() { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - widgetRenderer.mouseDragged(mouseX, mouseY, button, snapSize); + widgetRenderer.mouseDragged(mouseX, mouseY, button, GlobalConfig.get().getSnapSize()); ContextMenuManager.getInstance().handleMouseDragged(mouseX,mouseY,button,deltaX,deltaY); return false; } @@ -117,9 +117,5 @@ public void close() { public boolean shouldPause() { return false; } - - public void setSnapSize(int size) { - this.snapSize = size; - } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 1dac53f..8736a93 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -26,7 +26,6 @@ public class ContextMenu { private int width = 0; private int finalWidth = 0; private int height = 0, widgetHeight = 0; - //Todo: Add padding around the rectangle instead of just one side. private boolean shouldDisplay = false; private float scale = 0.0f; public final Color darkerBackgroundColor; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index 874c268..082c0a1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -22,20 +22,30 @@ * It tries to imitate the minecraft look and provides various form of panel shades {@link PanelColor} */ public class MinecraftSkin extends Skin { - public static MinecraftClient mc = MinecraftClient.getInstance(); - public Identifier BACKGROUND_PANEL; - private int scrollOffset = 0; - private int maxScrollOffset = 0; + private static final MinecraftClient mc = MinecraftClient.getInstance(); + private static final int DEFAULT_SCROLLBAR_WIDTH = 10; + private static final int DEFAULT_PANEL_WIDTH = 248; + private static final int DEFAULT_PANEL_HEIGHT = 165; + private static final Identifier DEFAULT_BACKGROUND_PANEL = Identifier.of("minecraft", "textures/gui/demo_background.png"); + + public static final ButtonTextures TEXTURES = new ButtonTextures( + Identifier.ofVanilla("widget/button"), + Identifier.ofVanilla("widget/button_disabled"), + Identifier.ofVanilla("widget/button_highlighted") + ); + + private static final Identifier SCROLLER_TEXTURE = Identifier.ofVanilla("widget/scroller"); + private static final Identifier SCROLL_BAR_BACKGROUND = Identifier.ofVanilla("widget/scroller_background"); + + private final Identifier BACKGROUND_PANEL; private final int panelWidth; private final int panelHeight; private final PanelColor panelColor; - public static final ButtonTextures TEXTURES = new ButtonTextures(Identifier.ofVanilla("widget/button"), Identifier.ofVanilla("widget/button_disabled"), Identifier.ofVanilla("widget/button_highlighted")); - private static final Identifier SCROLLER = Identifier.ofVanilla("widget/scroller"); - private static final Identifier SCROLL_BAR_BACKGROUND = Identifier.ofVanilla("widget/scroller_background"); - private double scrollVelocity = 0; - public static int SCROLLBAR_WIDTH = 10; - int imageX, imageY; + private int scrollOffset = 0; + private int maxScrollOffset = 0; + private double scrollVelocity = 0; + private int imageX, imageY; public enum PanelColor { COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f), @@ -99,7 +109,7 @@ public MinecraftSkin(PanelColor color, Identifier backgroundPanel, int panelWidt setCreateNewScreen(true); } public MinecraftSkin(PanelColor color) { - this(color,Identifier.of("minecraft","textures/gui/demo_background.png"),248,165); + this(color,DEFAULT_BACKGROUND_PANEL,DEFAULT_PANEL_WIDTH,DEFAULT_PANEL_HEIGHT); } @Override @@ -166,7 +176,7 @@ private void drawScrollbar(DrawContext context) { context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - context.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, SCROLLBAR_WIDTH, panelHeight); + context.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, DEFAULT_SCROLLBAR_WIDTH, panelHeight); context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); if (maxScrollOffset > 0) { @@ -175,7 +185,7 @@ private void drawScrollbar(DrawContext context) { int handleY = scrollbarY + (int) ((panelHeight - handleHeight) * scrollPercentage); // Draw scrollbar handle - context.drawGuiTexture(SCROLLER, scrollbarX, handleY, SCROLLBAR_WIDTH, handleHeight); + context.drawGuiTexture(SCROLLER_TEXTURE, scrollbarX, handleY, DEFAULT_SCROLLBAR_WIDTH, handleHeight); } } From 8ace820a1f69193310ae5f5afddbc169ec38b034 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 8 Oct 2024 23:53:33 +0530 Subject: [PATCH 06/40] New Test System --- .../dynamichud/DynamicHUD.java | 81 +++++++++++++++++-- 1 file changed, 73 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index a75631f..3062df2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -9,25 +9,33 @@ import com.tanishisherewith.dynamichud.widgets.ItemWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.entrypoint.EntrypointContainer; +import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; import net.fabricmc.loader.api.metadata.ModMetadata; +import net.fabricmc.loader.api.metadata.ModOrigin; +import net.fabricmc.loader.language.JavaLanguageAdapter; +import net.fabricmc.loader.language.LanguageAdapter; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.main.Main; import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; +import java.nio.file.Path; +import java.util.*; +@Environment(EnvType.CLIENT) public class DynamicHUD implements ClientModInitializer { /** * This is a map to store the list of widgets for each widget file to be saved. @@ -39,6 +47,7 @@ public class DynamicHUD implements ClientModInitializer { private static final List widgetRenderers = new ArrayList<>(); public static MinecraftClient MC = MinecraftClient.getInstance(); public static String MOD_ID = "dynamichud"; + private static boolean enableTestIntegration = false; public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { widgetRenderers.add(widgetRenderer); @@ -81,10 +90,26 @@ public void onInitializeClient() { //YACL load GlobalConfig.HANDLER.load(); + String[] args = FabricLoader.getInstance().getLaunchArguments(true); + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { + enableTestIntegration = Boolean.parseBoolean(args[i + 1]); + break; + } + } + printInfo("Integrating mods..."); - FabricLoader.getInstance() - .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class) - .forEach(entrypoint -> { + List> integrations = new ArrayList<>(getRegisteredIntegrations()); + + if (enableTestIntegration) { + EntrypointContainer testIntegration = getTestIntegration(); + if (testIntegration != null) { + integrations.add(testIntegration); + printInfo("Test integration enabled and loaded successfully."); + } + } + + for (EntrypointContainer entrypoint : integrations) { ModMetadata metadata = entrypoint.getProvider().getMetadata(); String modId = metadata.getId(); @@ -160,7 +185,7 @@ public void onInitializeClient() { logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); } } - }); + } printInfo("(DynamicHUD) Integration of supported mods was successful"); //In game screen render. @@ -176,4 +201,44 @@ private void saveWidgetsSafely(File widgetsFile, List widgets) { } } + private List> getRegisteredIntegrations() { + return new ArrayList<>(FabricLoader.getInstance() + .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class)); + } + + /** + * This makes it so that if minecraft is launched with the program arguments + *

+ * {@code --dynamicHudTest true} + *

+ * then it will + * load the {@link DynamicHudTest} class as an entrypoint, eliminating any errors due to human incapacity of + * adding/removing a single line from the `fabric.mod.json` + */ + private EntrypointContainer getTestIntegration() { + DynamicHudIntegration testIntegration; + try { + Class testClass = Class.forName("com.tanishisherewith.dynamichud.DynamicHudTest"); + testIntegration = (DynamicHudIntegration) testClass.getDeclaredConstructor().newInstance(); + } catch (ClassNotFoundException e) { + logger.info("DynamicHudTest class not found. Skipping test integration."); + return null; + } catch (Exception e) { + logger.error("Error instantiating DynamicHudTest", e); + return null; + } + + return new EntrypointContainer<>() { + @Override + public DynamicHudIntegration getEntrypoint() { + return testIntegration; + } + + @Override + public ModContainer getProvider() { + return FabricLoader.getInstance().getModContainer("dynamichud").orElseThrow(); + } + }; + } + } From 25af2e00ff6199fbdfe9dc994df246900617c9e9 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:08:20 +0530 Subject: [PATCH 07/40] Error fixing --- .../dynamichud/DynamicHUD.java | 148 +++++++------- .../dynamichud/DynamicHudIntegration.java | 7 +- .../dynamichud/HudRender.java | 2 +- .../dynamichud/ModMenuIntegration.java | 1 - .../dynamichud/config/GlobalConfig.java | 9 +- .../dynamichud/helpers/DrawHelper.java | 4 +- .../dynamichud/helpers/TextureHelper.java | 55 ++--- .../screens/AbstractMoveableScreen.java | 31 +-- .../dynamichud/utils/BooleanPool.java | 1 + .../dynamichud/utils/Input.java | 22 ++ .../utils/contextmenu/ContextMenu.java | 104 +++++----- .../utils/contextmenu/ContextMenuManager.java | 46 +++-- .../contextmenu/ContextMenuProperties.java | 157 +++++++------- .../dynamichud/utils/contextmenu/Option.java | 87 ++++---- .../contextmenuscreen/ContextMenuScreen.java | 21 +- .../contextmenu/options/BooleanOption.java | 29 +-- .../contextmenu/options/ColorOption.java | 12 +- .../contextmenu/options/DoubleOption.java | 13 +- .../utils/contextmenu/options/EnumOption.java | 8 +- .../utils/contextmenu/options/ListOption.java | 6 +- .../contextmenu/options/RunnableOption.java | 10 +- .../contextmenu/options/SubMenuOption.java | 26 +-- .../coloroption/ColorGradientPicker.java | 2 +- .../coloroption/ColorPickerButton.java | 2 +- .../contextmenu/skinsystem/ClassicSkin.java | 88 ++++---- .../contextmenu/skinsystem/MinecraftSkin.java | 193 +++++++++--------- .../utils/contextmenu/skinsystem/Skin.java | 23 ++- .../contextmenu/skinsystem/SkinRenderer.java | 14 +- .../dynamichud/widget/Widget.java | 58 ++---- .../dynamichud/widget/WidgetManager.java | 5 +- .../dynamichud/widgets/ItemWidget.java | 20 +- .../dynamichud/widgets/TextWidget.java | 20 +- 32 files changed, 644 insertions(+), 580 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/Input.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 3062df2..45cc39a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -2,7 +2,6 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; @@ -19,21 +18,18 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.entrypoint.EntrypointContainer; -import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; import net.fabricmc.loader.api.metadata.ModMetadata; -import net.fabricmc.loader.api.metadata.ModOrigin; -import net.fabricmc.loader.language.JavaLanguageAdapter; -import net.fabricmc.loader.language.LanguageAdapter; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.main.Main; import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; @Environment(EnvType.CLIENT) public class DynamicHUD implements ClientModInitializer { @@ -43,6 +39,7 @@ public class DynamicHUD implements ClientModInitializer { * Allows saving widgets across different mods with same save file name. */ public static final HashMap> FILE_MAP = new HashMap<>(); + public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); private static final List widgetRenderers = new ArrayList<>(); public static MinecraftClient MC = MinecraftClient.getInstance(); @@ -77,6 +74,16 @@ public static void openDynamicScreen(KeyBinding key, AbstractMoveableScreen scre } } + public void checkToEnableTestIntegration(){ + String[] args = FabricLoader.getInstance().getLaunchArguments(true); + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { + enableTestIntegration = Boolean.parseBoolean(args[i + 1]); + break; + } + } + } + @Override public void onInitializeClient() { printInfo("Initialising DynamicHud"); @@ -90,13 +97,7 @@ public void onInitializeClient() { //YACL load GlobalConfig.HANDLER.load(); - String[] args = FabricLoader.getInstance().getLaunchArguments(true); - for (int i = 0; i < args.length; i++) { - if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { - enableTestIntegration = Boolean.parseBoolean(args[i + 1]); - break; - } - } + checkToEnableTestIntegration(); printInfo("Integrating mods..."); List> integrations = new ArrayList<>(getRegisteredIntegrations()); @@ -110,81 +111,82 @@ public void onInitializeClient() { } for (EntrypointContainer entrypoint : integrations) { - ModMetadata metadata = entrypoint.getProvider().getMetadata(); - String modId = metadata.getId(); + ModMetadata metadata = entrypoint.getProvider().getMetadata(); + String modId = metadata.getId(); - printInfo(String.format("Supported mod with id %s was found!", modId)); + printInfo(String.format("Supported mod with id %s was found!", modId)); - AbstractMoveableScreen screen; - KeyBinding binding; - WidgetRenderer widgetRenderer; - File widgetsFile; - try { - DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); + AbstractMoveableScreen screen; + KeyBinding binding; + WidgetRenderer widgetRenderer; + File widgetsFile; + try { + DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); - //Calls the init method - DHIntegration.init(); + //Calls the init method + DHIntegration.init(); - //Gets the widget file to save and load the widgets from - widgetsFile = DHIntegration.getWidgetsFile(); + //Gets the widget file to save and load the widgets from + widgetsFile = DHIntegration.getWidgetsFile(); - // Adds / loads widgets from file - if (WidgetManager.doesWidgetFileExist(widgetsFile)) { - WidgetManager.loadWidgets(widgetsFile); - } else { - DHIntegration.addWidgets(); - } + // Adds / loads widgets from file + if (WidgetManager.doesWidgetFileExist(widgetsFile)) { + WidgetManager.loadWidgets(widgetsFile); + } else { + DHIntegration.addWidgets(); + } - //Calls the second init method - DHIntegration.initAfter(); + //Calls the second init method + DHIntegration.initAfter(); - // Get the instance of AbstractMoveableScreen - screen = Objects.requireNonNull(DHIntegration.getMovableScreen()); + // Get the instance of AbstractMoveableScreen + screen = Objects.requireNonNull(DHIntegration.getMovableScreen()); - // Get the keybind to open the screen instance - binding = DHIntegration.getKeyBind(); + // Get the keybind to open the screen instance + binding = DHIntegration.getKeyBind(); - //Register custom widget datas by WidgetManager.registerCustomWidgets(); - DHIntegration.registerCustomWidgets(); + //Register custom widget datas by WidgetManager.registerCustomWidgets(); + DHIntegration.registerCustomWidgets(); - //WidgetRenderer with widgets instance - widgetRenderer = DHIntegration.getWidgetRenderer(); - addWidgetRenderer(widgetRenderer); + //WidgetRenderer with widgets instance + widgetRenderer = DHIntegration.getWidgetRenderer(); + addWidgetRenderer(widgetRenderer); - List widgets = FILE_MAP.get(widgetsFile.getName()); + List widgets = FILE_MAP.get(widgetsFile.getName()); - if (widgets == null || widgets.isEmpty()) { - FILE_MAP.put(widgetsFile.getName(), widgetRenderer.getWidgets()); - } else { - widgets.addAll(widgetRenderer.getWidgets()); - FILE_MAP.put(widgetsFile.getName(), widgets); - } + if (widgets == null || widgets.isEmpty()) { + FILE_MAP.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + } else { + widgets.addAll(widgetRenderer.getWidgets()); + FILE_MAP.put(widgetsFile.getName(), widgets); + } - //Register events for rendering, saving, loading, and opening the hudEditor - ClientTickEvents.START_CLIENT_TICK.register((client) -> openDynamicScreen(binding, screen)); + //Register events for rendering, saving, loading, and opening the hudEditor + ClientTickEvents.START_CLIENT_TICK.register((client) -> openDynamicScreen(binding, screen)); - /* === Saving === */ + /* === Saving === */ + // Each mod is hooked to the fabric's event system to save its widget. - //When a player exits a world (SinglePlayer worlds) or a server stops - ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + //When a player exits a world (SinglePlayer worlds) or a server stops + ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - // When a resource pack is reloaded. - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + // When a resource pack is reloaded. + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - //When player disconnects - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + //When player disconnects + ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - //When minecraft closes - ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + //When minecraft closes + ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - printInfo(String.format("Integration of mod %s was successful", modId)); - } catch (Throwable e) { - if (e instanceof IOException) { - logger.warn("An error has occurred while loading widgets of mod {}", modId, e); - } else { - logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); - } - } + printInfo(String.format("Integration of mod %s was successful", modId)); + } catch (Throwable e) { + if (e instanceof IOException) { + logger.warn("An error has occurred while loading widgets of mod {}", modId, e); + } else { + logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); + } + } } printInfo("(DynamicHUD) Integration of supported mods was successful"); @@ -209,7 +211,7 @@ private List> getRegisteredIntegratio /** * This makes it so that if minecraft is launched with the program arguments *

- * {@code --dynamicHudTest true} + * {@code --dynamicHudTest true} *

* then it will * load the {@link DynamicHudTest} class as an entrypoint, eliminating any errors due to human incapacity of @@ -236,7 +238,7 @@ public DynamicHudIntegration getEntrypoint() { @Override public ModContainer getProvider() { - return FabricLoader.getInstance().getModContainer("dynamichud").orElseThrow(); + return FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow(); } }; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java index 484f981..0e25ed0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java @@ -9,7 +9,6 @@ import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import org.lwjgl.glfw.GLFW; -import org.lwjgl.system.NonnullDefault; import java.io.File; @@ -85,7 +84,7 @@ public interface DynamicHudIntegration { * WidgetManager.registerCustomWidget(TextWidget.DATA); * } * - * + *

* Custom widgets can be registered in any method in the interface * but to avoid any errors and mishaps it is recommended you add them here */ @@ -125,11 +124,11 @@ default KeyBinding getKeyBind() { *

* !! Should never be null !! *

- *

+ *

* * @return The movable screen. */ - AbstractMoveableScreen getMovableScreen(); + AbstractMoveableScreen getMovableScreen(); /** * To return a {@link WidgetRenderer} object. diff --git a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java index a7832cf..49ed9f4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java +++ b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java @@ -9,7 +9,7 @@ * Using the fabric event {@link HudRenderCallback} to render widgets in the game HUD. * Mouse positions are passed in the negatives even though theoretically it's in the centre of the screen. */ -public class HudRender implements HudRenderCallback{ +public class HudRender implements HudRenderCallback { @Override public void onHudRender(DrawContext drawContext, RenderTickCounter tickCounter) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java index 7cab250..668a7ed 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java @@ -3,7 +3,6 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import net.minecraft.client.gui.screen.Screen; public class ModMenuIntegration implements ModMenuApi { diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index 8621b99..eedd866 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -41,7 +41,7 @@ public static GlobalConfig get() { return INSTANCE; } - public final Screen createYACLGUI() { + public Screen createYACLGUI() { return YetAnotherConfigLib.createBuilder() .title(Text.literal("DynamicHUD config screen.")) .category(ConfigCategory.createBuilder() @@ -71,8 +71,8 @@ public final Screen createYACLGUI() { .option(Option.createBuilder() .name(Text.literal("Snap Size")) .description(OptionDescription.of(Text.literal("Grid size for snapping widgets"))) - .binding( 100, () -> this.snapSize, newVal -> this.snapSize = newVal) - .controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10,500)) + .binding(100, () -> this.snapSize, newVal -> this.snapSize = newVal) + .controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10, 500)) .build()) .build()) .build()) @@ -80,7 +80,8 @@ public final Screen createYACLGUI() { .build() .generateScreen(null); } - public float getScale(){ + + public float getScale() { return scale; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index c310b07..bab2136 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -47,7 +47,7 @@ public static void drawGradient(Matrix4f matrix4f, float x, float y, float width RenderSystem.defaultBlendFunc(); RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.setShader(GameRenderer::getPositionColorProgram); - + switch (direction) { case LEFT_RIGHT: bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(startRed, startGreen, startBlue, startAlpha); @@ -508,7 +508,7 @@ public static void drawFilledQuadrant(Matrix4f matrix4f, float xCenter, float yC float alpha = (float) (color >> 24 & 255) / 255.0F; Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); RenderSystem.setShader(GameRenderer::getPositionColorProgram); RenderSystem.enableBlend(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java index 8e8bcdd..53a96ce 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -14,7 +14,7 @@ public class TextureHelper { static MinecraftClient mc = MinecraftClient.getInstance(); public static NativeImage loadTexture(Identifier textureId) { - if(mc.getResourceManager().getResource(textureId).isPresent()) { + if (mc.getResourceManager().getResource(textureId).isPresent()) { try (InputStream inputStream = mc.getResourceManager().getResource(textureId).get().getInputStream()) { return NativeImage.read(inputStream); } catch (IOException e) { @@ -24,7 +24,7 @@ public static NativeImage loadTexture(Identifier textureId) { return null; } - public static NativeImage resizeTexture(NativeImage image, int newWidth, int newHeight) { + public static NativeImage resizeTexture(NativeImage image, int newWidth, int newHeight) { NativeImage result = new NativeImage(newWidth, newHeight, false); int oldWidth = image.getWidth(); @@ -41,49 +41,51 @@ public static NativeImage resizeTexture(NativeImage image, int newWidth, int ne return result; } + public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage image, int newWidth, int newHeight) { NativeImage result = new NativeImage(newWidth, newHeight, false); - float x_ratio = ((float)(image.getWidth()-1))/newWidth; - float y_ratio = ((float)(image.getHeight()-1))/newHeight; + float x_ratio = ((float) (image.getWidth() - 1)) / newWidth; + float y_ratio = ((float) (image.getHeight() - 1)) / newHeight; float x_diff, y_diff, blue, red, green; int offset, a, b, c, d, index; - for (int i=0;i>8)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>8)&0xff)*(x_diff)*(1-y_diff) + - ((c>>8)&0xff)*(y_diff)*(1-x_diff) + ((d>>8)&0xff)*(x_diff*y_diff); + green = ((a >> 8) & 0xff) * (1 - x_diff) * (1 - y_diff) + ((b >> 8) & 0xff) * (x_diff) * (1 - y_diff) + + ((c >> 8) & 0xff) * (y_diff) * (1 - x_diff) + ((d >> 8) & 0xff) * (x_diff * y_diff); // Red element - red = ((a>>16)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>16)&0xff)*(x_diff)*(1-y_diff) + - ((c>>16)&0xff)*(y_diff)*(1-x_diff) + ((d>>16)&0xff)*(x_diff*y_diff); + red = ((a >> 16) & 0xff) * (1 - x_diff) * (1 - y_diff) + ((b >> 16) & 0xff) * (x_diff) * (1 - y_diff) + + ((c >> 16) & 0xff) * (y_diff) * (1 - x_diff) + ((d >> 16) & 0xff) * (x_diff * y_diff); result.setColor(j, i, - ((((int)red)<<16)&0xff0000) | - ((((int)green)<<8)&0xff00) | - ((int)blue)&0xff); + ((((int) red) << 16) & 0xff0000) | + ((((int) green) << 8) & 0xff00) | + ((int) blue) & 0xff); } } return result; } - public static NativeImage invertTexture(NativeImage image) { + + public static NativeImage invertTexture(NativeImage image) { int width = image.getWidth(); int height = image.getHeight(); NativeImage result = new NativeImage(width, height, false); @@ -117,8 +119,8 @@ public static NativeImage rotateTexture(NativeImage image, int degrees) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int newX = (int)((x - centerX) * Math.cos(angle) - (y - centerY) * Math.sin(angle) + centerX); - int newY = (int)((x - centerX) * Math.sin(angle) + (y - centerY) * Math.cos(angle) + centerY); + int newX = (int) ((x - centerX) * Math.cos(angle) - (y - centerY) * Math.sin(angle) + centerX); + int newY = (int) ((x - centerX) * Math.sin(angle) + (y - centerY) * Math.cos(angle) + centerY); if (newX >= 0 && newX < width && newY >= 0 && newY < height) { result.setColor(newY, newX, image.getColor(x, y)); @@ -188,6 +190,7 @@ public static NativeImage applyGrayScaleFilter(NativeImage image) { return result; } + public static NativeImage cropTexture(NativeImage image, int x, int y, int width, int height) { NativeImage result = new NativeImage(width, height, false); @@ -263,9 +266,9 @@ public static int getAverageColor(NativeImage image) { } } - int redAverage = (int)(redTotal / pixelCount); - int greenAverage = (int)(greenTotal / pixelCount); - int blueAverage = (int)(blueTotal / pixelCount); + int redAverage = (int) (redTotal / pixelCount); + int greenAverage = (int) (greenTotal / pixelCount); + int blueAverage = (int) (blueTotal / pixelCount); return (redAverage << 16) | (greenAverage << 8) | blueAverage; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 95c4801..b26cf11 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -28,44 +28,50 @@ public void onDisplayed() { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { widgetRenderer.mouseDragged(mouseX, mouseY, button, GlobalConfig.get().getSnapSize()); - ContextMenuManager.getInstance().handleMouseDragged(mouseX,mouseY,button,deltaX,deltaY); + ContextMenuManager.getInstance().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return false; } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if(widgetRenderer.mouseClicked(mouseX, mouseY, button)){ - handleClickOnWidget(widgetRenderer.selectedWidget,mouseX,mouseY,button); + if (widgetRenderer.mouseClicked(mouseX, mouseY, button)) { + handleClickOnWidget(widgetRenderer.selectedWidget, mouseX, mouseY, button); } - ContextMenuManager.getInstance().handleMouseClicked(mouseX,mouseY,button); + ContextMenuManager.getInstance().mouseClicked(mouseX, mouseY, button); return false; } + @Override + public boolean charTyped(char chr, int modifiers) { + ContextMenuManager.getInstance().charTyped(chr); + return super.charTyped(chr, modifiers); + } + @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { widgetRenderer.mouseReleased(mouseX, mouseY, button); - ContextMenuManager.getInstance().handleMouseReleased(mouseX,mouseY,button); + ContextMenuManager.getInstance().mouseReleased(mouseX, mouseY, button); return false; } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyPressed(keyCode); - ContextMenuManager.getInstance().handleKeyPressed(keyCode, scanCode, modifiers); + ContextMenuManager.getInstance().keyPressed(keyCode, scanCode, modifiers); return super.keyPressed(keyCode, scanCode, modifiers); } @Override public boolean keyReleased(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyReleased(keyCode); - ContextMenuManager.getInstance().handleKeyReleased(keyCode, scanCode, modifiers); + ContextMenuManager.getInstance().keyReleased(keyCode, scanCode, modifiers); return super.keyReleased(keyCode, scanCode, modifiers); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { widgetRenderer.mouseScrolled(mouseX, mouseY, verticalAmount, horizontalAmount); - ContextMenuManager.getInstance().handleMouseScrolled(mouseX, mouseY, horizontalAmount,verticalAmount); + ContextMenuManager.getInstance().mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @@ -83,14 +89,14 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) if (this.client.world == null) { renderInGameBackground(drawContext); } - drawContext.drawText(client.textRenderer,title,client.getWindow().getScaledWidth()/2 - client.textRenderer.getWidth(title.getString())/2,textRenderer.fontHeight/2,-1,true); + drawContext.drawText(client.textRenderer, title, client.getWindow().getScaledWidth() / 2 - client.textRenderer.getWidth(title.getString()) / 2, textRenderer.fontHeight / 2, -1, true); // Draw each widget widgetRenderer.renderWidgets(drawContext, mouseX, mouseY); - ContextMenuManager.getInstance().renderAll(drawContext,mouseX,mouseY); + ContextMenuManager.getInstance().renderAll(drawContext, mouseX, mouseY); - if(GlobalConfig.get().shouldDisplayDescriptions()) { + if (GlobalConfig.get().shouldDisplayDescriptions()) { for (Widget widget : widgetRenderer.getWidgets()) { if (widget == null || widget.shiftDown) continue; @@ -101,7 +107,8 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) } } } - public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button){ + + public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) { } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/BooleanPool.java b/src/main/java/com/tanishisherewith/dynamichud/utils/BooleanPool.java index 9c518b5..aaf3abd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/BooleanPool.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/BooleanPool.java @@ -9,6 +9,7 @@ public class BooleanPool { public static void put(String key, boolean value) { pool.put(key, value); } + public static void remove(String key) { pool.remove(key); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java new file mode 100644 index 0000000..cd2ad2e --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java @@ -0,0 +1,22 @@ +package com.tanishisherewith.dynamichud.utils; + + +public interface Input { + boolean mouseClicked(double mouseX, double mouseY, int button); + + boolean mouseReleased(double mouseX, double mouseY, int button); + + boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY); + + void keyPressed(int key, int scanCode, int modifiers); + + void keyReleased(int key, int scanCode, int modifiers); + + void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount); + + default boolean isMouseOver(double mouseX, double mouseY, double x, double y, double width, double height) { + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + + void charTyped(char c); +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 8736a93..529bca9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -2,7 +2,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreen; +import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; import net.minecraft.client.gui.DrawContext; @@ -14,12 +14,13 @@ import java.util.Collections; import java.util.List; -public class ContextMenu { +public class ContextMenu implements Input { + public final Color darkerBackgroundColor; //The properties of a context menu protected final ContextMenuProperties properties; - private final List> options = new ArrayList<>(); // The list of options in the context menu + private final ContextMenuScreenFactory screenFactory; public int x, y; // Width is counted while the options are being rendered. // FinalWidth is the width at the end of the count. @@ -28,9 +29,7 @@ public class ContextMenu { private int height = 0, widgetHeight = 0; private boolean shouldDisplay = false; private float scale = 0.0f; - public final Color darkerBackgroundColor; private Screen parentScreen = null; - private final ContextMenuScreenFactory screenFactory; private boolean newScreenFlag = false; public ContextMenu(int x, int y, ContextMenuProperties properties) { @@ -64,37 +63,34 @@ public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, scale); properties.getSkin().setContextMenu(this); - properties.getSkin().renderContextMenu(drawContext,this,mouseX,mouseY); + properties.getSkin().renderContextMenu(drawContext, this, mouseX, mouseY); DrawHelper.stopScaling(drawContext.getMatrices()); } - public boolean isMouseOver(int mouseX, int mouseY, int x, int y, int width, int height){ - return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; - } public void update() { - if(!properties.enableAnimations()){ + if (!properties.enableAnimations()) { scale = 1.0f; return; } // Update the scale - if(shouldDisplay){ - scale += 0.1f; - } else{ - scale -= 0.1f; + if (shouldDisplay) { + scale += 0.1f; + } else { + scale -= 0.1f; } - scale = MathHelper.clamp(scale,0,1.0f); + scale = MathHelper.clamp(scale, 0, 1.0f); } public void close() { - if(properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null){ + if (properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null) { shouldDisplay = false; newScreenFlag = false; DynamicHUD.MC.setScreen(parentScreen); } - for(Option option: options){ + for (Option option : options) { option.onClose(); } shouldDisplay = false; @@ -118,56 +114,67 @@ public void toggleDisplay() { } } - public void mouseClicked(double mouseX, double mouseY, int button) { - if (!shouldDisplay) return; + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (!shouldDisplay) return false; for (Option option : options) { option.mouseClicked(mouseX, mouseY, button); } - properties.getSkin().mouseClicked(this,mouseX,mouseY,button); + return properties.getSkin().mouseClicked(this, mouseX, mouseY, button); } - public void mouseReleased(double mouseX, double mouseY, int button) { - if (!shouldDisplay) return; + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + if (!shouldDisplay) return false; for (Option option : options) { option.mouseReleased(mouseX, mouseY, button); } - properties.getSkin().mouseReleased(this,mouseX,mouseY,button); + return properties.getSkin().mouseReleased(this, mouseX, mouseY, button); } - public void mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { - if (!shouldDisplay) return; + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (!shouldDisplay) return false; for (Option option : options) { - option.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); + option.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } - properties.getSkin().mouseDragged(this,mouseX,mouseY,button,deltaX,deltaY); + return properties.getSkin().mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY); } + @Override public void keyPressed(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; for (Option option : options) { - option.keyPressed(key); + option.keyPressed(key, scanCode, modifiers); } - properties.getSkin().keyPressed(this,key,scanCode,modifiers); + properties.getSkin().keyPressed(this, key, scanCode, modifiers); } + @Override public void keyReleased(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; for (Option option : options) { - option.keyReleased(key); + option.keyReleased(key, scanCode, modifiers); } - properties.getSkin().keyReleased(this,key,scanCode,modifiers); + properties.getSkin().keyReleased(this, key, scanCode, modifiers); } + @Override public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - for(Option option: options){ - option.mouseScrolled(mouseX,mouseY,horizontalAmount,verticalAmount); + for (Option option : options) { + option.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } - properties.getSkin().mouseScrolled(this,mouseX,mouseY,horizontalAmount,verticalAmount); + properties.getSkin().mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount); + } + + @Override + public void charTyped(char c) { + } - public void set(int x,int y, int widgetHeight){ + public void set(int x, int y, int widgetHeight) { this.x = x; this.y = y; this.widgetHeight = widgetHeight; @@ -180,6 +187,7 @@ public int getX() { public int getY() { return y; } + public List> getOptions() { return Collections.unmodifiableList(options); } @@ -188,9 +196,18 @@ public int getHeight() { return height; } + public void setHeight(int height) { + this.height = height; + } + public int getFinalWidth() { return finalWidth; } + + public void setFinalWidth(int finalWidth) { + this.finalWidth = finalWidth; + } + public int getWidth() { return width; } @@ -199,30 +216,23 @@ public void setWidth(int width) { this.width = width; } - public void setFinalWidth(int finalWidth) { - this.finalWidth = finalWidth; - } - public ContextMenuProperties getProperties() { return properties; } + public void setWidgetHeight(int widgetHeight) { this.widgetHeight = widgetHeight; } - public void setHeight(int height) { - this.height = height; - } - public float getScale() { return scale; } - public void setVisible(boolean shouldDisplay) { - this.shouldDisplay = shouldDisplay; - } - public boolean isVisible() { return shouldDisplay; } + + public void setVisible(boolean shouldDisplay) { + this.shouldDisplay = shouldDisplay; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java index 29b5773..2be522e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java @@ -1,17 +1,17 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; +import com.tanishisherewith.dynamichud.utils.Input; import net.minecraft.client.gui.DrawContext; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -public class ContextMenuManager { +public class ContextMenuManager implements Input { private static final ContextMenuManager INSTANCE = new ContextMenuManager(); private final List providers = new ArrayList<>(); - private ContextMenuManager() {} + private ContextMenuManager() { + } public static ContextMenuManager getInstance() { return INSTANCE; @@ -30,34 +30,47 @@ public void renderAll(DrawContext drawContext, int mouseX, int mouseY) { } } - public void handleMouseClicked(double mouseX, double mouseY, int button) { + public void onClose() { + for (ContextMenuProvider provider : providers) { + provider.getContextMenu().close(); + } + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseClicked(mouseX, mouseY, button); } } + return false; } - public void handleMouseReleased(double mouseX, double mouseY, int button) { + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseReleased(mouseX, mouseY, button); } } + return false; } - public void handleMouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } } + return false; } - public void handleKeyPressed(int key, int scanCode, int modifiers) { + @Override + public void keyPressed(int key, int scanCode, int modifiers) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { @@ -66,7 +79,8 @@ public void handleKeyPressed(int key, int scanCode, int modifiers) { } } - public void handleKeyReleased(int key, int scanCode, int modifiers) { + @Override + public void keyReleased(int key, int scanCode, int modifiers) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { @@ -75,7 +89,8 @@ public void handleKeyReleased(int key, int scanCode, int modifiers) { } } - public void handleMouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + @Override + public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { @@ -83,9 +98,14 @@ public void handleMouseScrolled(double mouseX, double mouseY, double horizontalA } } } - public void onClose(){ - for(ContextMenuProvider provider: providers){ - provider.getContextMenu().close(); + + @Override + public void charTyped(char c) { + for (ContextMenuProvider provider : providers) { + ContextMenu contextMenu = provider.getContextMenu(); + if (contextMenu != null) { + contextMenu.charTyped(c); + } } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java index 330f561..2576b4e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -1,7 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ClassicSkin; -import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin; import java.awt.*; @@ -21,7 +20,8 @@ public class ContextMenuProperties { private boolean enableAnimations = true; private Skin skin = new ClassicSkin(); - private ContextMenuProperties() {} + private ContextMenuProperties() { + } public static Builder builder() { return new ContextMenuProperties().new Builder(); @@ -31,8 +31,84 @@ public static ContextMenuProperties createGenericSimplified() { return new ContextMenuProperties().new Builder().build(); } + // Getters for all properties + public Color getBackgroundColor() { + return backgroundColor; + } + + public Color getBorderColor() { + return borderColor; + } + + public float getBorderWidth() { + return borderWidth; + } + + public int getPadding() { + return padding; + } + + public int getHeightOffset() { + return heightOffset; + } + + public void setHeightOffset(int heightOffset) { + this.heightOffset = heightOffset; + } + + public boolean shouldDrawBorder() { + return drawBorder; + } + + public boolean shadow() { + return shadow; + } + + public boolean roundedCorners() { + return roundedCorners; + } + + public int getCornerRadius() { + return cornerRadius; + } + + public boolean hoverEffect() { + return hoverEffect; + } + + public Color getHoverColor() { + return hoverColor; + } + + public boolean enableAnimations() { + return enableAnimations; + } + + public Skin getSkin() { + return skin; + } + + public ContextMenuProperties copy() { + return ContextMenuProperties.builder() + .backgroundColor(backgroundColor) + .borderColor(borderColor) + .borderWidth(borderWidth) + .padding(padding) + .heightOffset(heightOffset) + .drawBorder(drawBorder) + .shadow(shadow) + .roundedCorners(roundedCorners) + .cornerRadius(cornerRadius) + .hoverEffect(hoverEffect) + .hoverColor(hoverColor) + .skin(skin) + .enableAnimations(enableAnimations) + .build(); + } + public class Builder { - private Builder() {} + private Builder() { + } public Builder backgroundColor(Color backgroundColor) { ContextMenuProperties.this.backgroundColor = backgroundColor; @@ -103,79 +179,4 @@ public ContextMenuProperties build() { return ContextMenuProperties.this; } } - - // Getters for all properties - public Color getBackgroundColor() { - return backgroundColor; - } - - public Color getBorderColor() { - return borderColor; - } - - public float getBorderWidth() { - return borderWidth; - } - - public int getPadding() { - return padding; - } - - public int getHeightOffset() { - return heightOffset; - } - - public boolean shouldDrawBorder() { - return drawBorder; - } - - public boolean shadow() { - return shadow; - } - - public boolean roundedCorners() { - return roundedCorners; - } - - public int getCornerRadius() { - return cornerRadius; - } - - public boolean hoverEffect() { - return hoverEffect; - } - - public Color getHoverColor() { - return hoverColor; - } - - public boolean enableAnimations() { - return enableAnimations; - } - - public Skin getSkin() { - return skin; - } - - public void setHeightOffset(int heightOffset) { - this.heightOffset = heightOffset; - } - - public ContextMenuProperties copy(){ - return ContextMenuProperties.builder() - .backgroundColor(backgroundColor) - .borderColor(borderColor) - .borderWidth(borderWidth) - .padding(padding) - .heightOffset(heightOffset) - .drawBorder(drawBorder) - .shadow(shadow) - .roundedCorners(roundedCorners) - .cornerRadius(cornerRadius) - .hoverEffect(hoverEffect) - .hoverColor(hoverColor) - .skin(skin) - .enableAnimations(enableAnimations) - .build(); - } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java index 08bd0ae..95d81b7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -1,19 +1,20 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.SkinRenderer; -import com.tanishisherewith.dynamichud.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import java.util.function.Consumer; import java.util.function.Supplier; -public abstract class Option { +public abstract class Option implements Input { + public T value = null; protected int x, y; protected int width = 0; protected int height = 0; - public T value = null; - protected Supplier shouldRender = () -> true; + protected Supplier shouldRender; protected Supplier getter; protected Consumer setter; protected T defaultValue = null; @@ -22,10 +23,10 @@ public abstract class Option { protected SkinRenderer> renderer; public Option(Supplier getter, Consumer setter) { - this(getter,setter,()->true); + this(getter, setter, () -> true); } - public Option(Supplier getter, Consumer setter, Supplier shouldRender,ContextMenuProperties properties) { + public Option(Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) { this.getter = getter; this.setter = setter; this.shouldRender = shouldRender; @@ -35,7 +36,7 @@ public Option(Supplier getter, Consumer setter, Supplier shouldRe } public Option(Supplier getter, Consumer setter, Supplier shouldRender) { - this(getter,setter,shouldRender,ContextMenuProperties.createGenericSimplified()); + this(getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified()); } public T get() { @@ -47,16 +48,16 @@ public void set(T value) { setter.accept(value); } - public void updateProperties(ContextMenuProperties properties){ + public void updateProperties(ContextMenuProperties properties) { this.properties = properties; this.renderer = properties.getSkin().getRenderer((Class>) this.getClass()); if (renderer == null) { - System.err.println("Renderer not found for class: " + this.getClass().getName()); + DynamicHUD.logger.error("Renderer not found for class: {}", this.getClass().getName()); throw new RuntimeException(); } } - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { this.x = x; this.y = y; @@ -65,30 +66,41 @@ public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) } public boolean mouseClicked(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY) || renderer.mouseClicked(this,mouseX,mouseY,button); - + return isMouseOver(mouseX, mouseY) || renderer.mouseClicked(this, mouseX, mouseY, button); } public boolean mouseReleased(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY) || renderer.mouseReleased(this,mouseX,mouseY,button); + return isMouseOver(mouseX, mouseY) || renderer.mouseReleased(this, mouseX, mouseY, button); } - public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { - return isMouseOver(mouseX, mouseY) || renderer.mouseDragged(this,mouseX,mouseY,button,deltaX,deltaY); + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return isMouseOver(mouseX, mouseY) || renderer.mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY); } - public void keyPressed(int key) { - renderer.keyPressed(this,key); + public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + renderer.mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount); } - public void keyReleased(int key) { - renderer.keyReleased(this,key); + + @Override + public void keyPressed(int key, int scanCode, int modifiers) { + renderer.keyPressed(this, key, scanCode, modifiers); } - public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - renderer.mouseScrolled(this,mouseX,mouseY,horizontalAmount,verticalAmount); + + @Override + public void charTyped(char c) { + } - //Called when the context menu closes - public void onClose(){} + @Override + public void keyReleased(int key, int scanCode, int modifiers) { + renderer.keyReleased(this, key, scanCode, modifiers); + } + + /** + * Called when the context menu closes + */ + public void onClose() { + } public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; @@ -107,38 +119,39 @@ public ContextMenuProperties getProperties() { return properties; } + public int getY() { + return y; + } + public void setY(int y) { this.y = y; } + public int getX() { + return x; + } + public void setX(int x) { this.x = x; } - public void setWidth(int width) { - this.width = width; + public int getHeight() { + return height; } public void setHeight(int height) { this.height = height; } - public int getY() { - return y; - } - - public int getX() { - return x; + public int getWidth() { + return width; } - public int getHeight() { - return height; + public void setWidth(int width) { + this.width = width; } - public int getWidth() { - return width; - } - public void set(int x, int y){ + public void set(int x, int y) { this.x = x; this.y = y; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java index 9584622..d398086 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java @@ -3,7 +3,6 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; -import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; @@ -12,7 +11,7 @@ public class ContextMenuScreen extends Screen { ContextMenu contextMenu; ContextMenuProperties properties; - protected ContextMenuScreen(ContextMenu menu,ContextMenuProperties properties) { + protected ContextMenuScreen(ContextMenu menu, ContextMenuProperties properties) { super(Text.of("ContextMenu screen")); this.contextMenu = menu; this.properties = properties; @@ -27,14 +26,14 @@ public void onDisplayed() { @Override public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { contextMenu.update(); - DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width /2, (float) height /2,contextMenu.getScale()); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width / 2, (float) height / 2, contextMenu.getScale()); properties.getSkin().setContextMenu(contextMenu); - properties.getSkin().renderContextMenu(drawContext,contextMenu,mouseX,mouseY); + properties.getSkin().renderContextMenu(drawContext, contextMenu, mouseX, mouseY); DrawHelper.stopScaling(drawContext.getMatrices()); - if(contextMenu.getScale() <= 0 && !contextMenu.isVisible()){ + if (contextMenu.getScale() <= 0 && !contextMenu.isVisible()) { contextMenu.close(); } } @@ -46,37 +45,37 @@ protected void renderDarkening(DrawContext context) { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - contextMenu.mouseClicked(mouseX,mouseY,button); + contextMenu.mouseClicked(mouseX, mouseY, button); return super.mouseClicked(mouseX, mouseY, button); } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - contextMenu.mouseDragged(mouseX,mouseY,button,deltaX,deltaY); + contextMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - contextMenu.mouseScrolled(mouseX,mouseY,horizontalAmount,verticalAmount); + contextMenu.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - contextMenu.mouseReleased(mouseX,mouseY,button); + contextMenu.mouseReleased(mouseX, mouseY, button); return super.mouseReleased(mouseX, mouseY, button); } @Override public boolean keyReleased(int keyCode, int scanCode, int modifiers) { - contextMenu.keyReleased(keyCode,scanCode,modifiers); + contextMenu.keyReleased(keyCode, scanCode, modifiers); return super.keyReleased(keyCode, scanCode, modifiers); } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - contextMenu.keyPressed(keyCode,scanCode,modifiers); + contextMenu.keyPressed(keyCode, scanCode, modifiers); return super.keyPressed(keyCode, scanCode, modifiers); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index c2366c8..08ffa66 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -13,7 +13,7 @@ public class BooleanOption extends Option { public String name = "Empty"; - private BooleanType booleanType; + private final BooleanType booleanType; public BooleanOption(String name, Supplier getter, Consumer setter, BooleanType booleanType) { super(getter, setter); @@ -21,25 +21,26 @@ public BooleanOption(String name, Supplier getter, Consumer se this.booleanType = booleanType; this.renderer.init(this); } + public BooleanOption(String name, Supplier getter, Consumer setter) { - this(name,getter,setter,BooleanType.TRUE_FALSE); + this(name, getter, setter, BooleanType.TRUE_FALSE); } public BooleanOption(String name, boolean defaultValue) { - this(name,defaultValue,BooleanType.TRUE_FALSE); + this(name, defaultValue, BooleanType.TRUE_FALSE); } - public BooleanOption(String name, boolean defaultValue,BooleanType type) { - this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),type); + public BooleanOption(String name, boolean defaultValue, BooleanType type) { + this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), type); BooleanPool.put(name, defaultValue); } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { value = get(); - super.render(drawContext, x, y,mouseX,mouseY); + super.render(drawContext, x, y, mouseX, mouseY); - // properties.getSkin().getRenderer(BooleanOption.class).render(drawContext,this,x,y,mouseX,mouseY); + // properties.getSkin().getRenderer(BooleanOption.class).render(drawContext,this,x,y,mouseX,mouseY); /* int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); @@ -56,25 +57,25 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { set(value); return true; } - return super.mouseClicked(mouseX,mouseY,button); + return super.mouseClicked(mouseX, mouseY, button); } public BooleanType getBooleanType() { return booleanType; } - public enum BooleanType{ + public enum BooleanType { ON_OFF(ScreenTexts::onOrOff), TRUE_FALSE(aBoolean -> aBoolean ? Text.of("True") : Text.of("False")), - YES_NO(aBoolean -> aBoolean ? ScreenTexts.YES: ScreenTexts.NO); + YES_NO(aBoolean -> aBoolean ? ScreenTexts.YES : ScreenTexts.NO); - private final Function function; + private final Function function; - BooleanType(Function function){ + BooleanType(Function function) { this.function = function; } - public Text getText(boolean val){ + public Text getText(boolean val) { return function.apply(val); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index fc52ce5..dc31a33 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -1,11 +1,9 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorGradientPicker; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; import java.awt.*; import java.util.function.Consumer; @@ -26,10 +24,10 @@ public ColorOption(String name, ContextMenu parentMenu, Supplier getter, } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { - super.render(drawContext, x, y,mouseX,mouseY); + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { + super.render(drawContext, x, y, mouseX, mouseY); - // properties.getSkin().getRenderer(ColorOption.class).render(drawContext,this,x,y,mouseX,mouseY); + // properties.getSkin().getRenderer(ColorOption.class).render(drawContext,this,x,y,mouseX,mouseY); /* int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); @@ -76,9 +74,9 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { colorPicker.mouseDragged(mouseX, mouseY, button); - return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } public ColorGradientPicker getColorPicker() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 59316eb..d51ef4a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -3,7 +3,6 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import org.apache.commons.lang3.Validate; import org.lwjgl.glfw.GLFW; @@ -14,11 +13,11 @@ public class DoubleOption extends Option { public String name = "Empty"; - float step = 0.1f; - private boolean isDragging = false; public double minValue = 0.0; public double maxValue = 0.0; + float step = 0.1f; ContextMenu parentMenu; + private boolean isDragging = false; public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { super(getter, setter); @@ -35,9 +34,9 @@ public DoubleOption(String name, double minValue, double maxValue, float step, S } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { value = get(); - super.render(drawContext, x, y,mouseX,mouseY); + super.render(drawContext, x, y, mouseX, mouseY); //properties.getSkin().getRenderer(DoubleOption.class).render(drawContext,this,x,y,mouseX,mouseY); @@ -108,10 +107,10 @@ public void step(double mouseX) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { if (isMouseOver(mouseX, mouseY) && isDragging) { step(mouseX); } - return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index ceace21..59de1b4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -2,9 +2,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; -import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -28,9 +26,9 @@ public EnumOption(String name, Supplier getter, Consumer setter, E[] value } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { value = get(); - super.render(drawContext, x, y,mouseX,mouseY); + super.render(drawContext, x, y, mouseX, mouseY); // properties.getSkin().getRenderer(EnumOption.class).render(drawContext,this,x,y,mouseX,mouseY); @@ -46,7 +44,7 @@ public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (super.mouseClicked(mouseX,mouseY,button)) { + if (super.mouseClicked(mouseX, mouseY, button)) { if (button == 0) { currentIndex = (currentIndex + 1) % values.length; if (currentIndex > values.length - 1) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index 382973f..c28def6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -2,9 +2,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; -import java.awt.*; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; @@ -29,9 +27,9 @@ public ListOption(String name, Supplier getter, Consumer setter, List v } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { value = get(); - super.render(drawContext, x, y,mouseX,mouseY); + super.render(drawContext, x, y, mouseX, mouseY); // properties.getSkin().getRenderer(ListOption.class).render(drawContext,this,x,y,mouseX,mouseY); /* diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index dae637d..7d169d4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -3,9 +3,7 @@ import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; -import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -28,15 +26,15 @@ public RunnableOption(String name, Supplier getter, Consumer s this.renderer.init(this); } - public RunnableOption(String name, boolean defaultValue,Runnable task) { - this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),task); + public RunnableOption(String name, boolean defaultValue, Runnable task) { + this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), task); BooleanPool.put(name, defaultValue); } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { value = get(); - super.render(drawContext, x, y,mouseX,mouseY); + super.render(drawContext, x, y, mouseX, mouseY); //properties.getSkin().getRenderer(RunnableOption.class).render(drawContext,this,x,y,mouseX,mouseY); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 737f815..6fbc3a8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -5,11 +5,8 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; -import java.awt.*; import java.util.Objects; -import java.util.Properties; import java.util.function.Consumer; import java.util.function.Supplier; @@ -30,25 +27,28 @@ public SubMenuOption(String name, ContextMenu parentMenu, Supplier gett Objects.requireNonNull(parentMenu, "Parent Menu cannot be null"); this.name = name; this.parentMenu = parentMenu; - this.subMenu = new ContextMenu(parentMenu.x + parentMenu.getFinalWidth(), this.y,properties); + this.subMenu = new ContextMenu(parentMenu.x + parentMenu.getFinalWidth(), this.y, properties); this.subMenu.getProperties().setHeightOffset(0); this.subMenu.setVisible(get()); this.renderer.init(this); } + public SubMenuOption(String name, ContextMenu parentMenu, ContextMenuProperties properties) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),properties); + this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), properties); } + public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { - this(name,parentMenu,getter,setter,parentMenu.getProperties().copy()); + this(name, parentMenu, getter, setter, parentMenu.getProperties().copy()); } + public SubMenuOption(String name, ContextMenu parentMenu) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value),parentMenu.getProperties().copy()); + this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), parentMenu.getProperties().copy()); } @Override - public void render(DrawContext drawContext, int x, int y,int mouseX,int mouseY) { - super.render(drawContext,x,y,mouseX,mouseY); - // properties.getSkin().getRenderer(SubMenuOption.class).render(drawContext,this,x,y,mouseX,mouseY); + public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { + super.render(drawContext, x, y, mouseX, mouseY); + // properties.getSkin().getRenderer(SubMenuOption.class).render(drawContext,this,x,y,mouseX,mouseY); } @Override @@ -69,9 +69,9 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { } @Override - public boolean mouseDragged(double mouseX, double mouseY, int button,double deltaX, double deltaY) { - subMenu.mouseDragged(mouseX, mouseY, button,deltaX, deltaY); - return super.mouseDragged(mouseX, mouseY, button,deltaX, deltaY); + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + subMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } public SubMenuOption getOption() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 9d1ed11..6ec3a7b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -19,9 +19,9 @@ public class ColorGradientPicker { private final ColorPickerButton colorPickerButton; private final AlphaSlider alphaSlider; private final int boxSize; + private final Color initialColor; private int x, y; private boolean display = false; - private final Color initialColor; public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { this.x = x; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java index 3afa00e..967bb14 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -25,7 +25,7 @@ public void render(DrawContext drawContext, int x, int y) { drawContext.getMatrices().push(); drawContext.getMatrices().translate(0, 0, 404); // Draw the button - drawContext.fill(x + 2, y + 2, x + width - 2, y + height - 2, isPicking() ? Color.GREEN.getRGB() : 0xFFAAAAAA); + drawContext.fill(x + 2, y + 2, x + width - 2, y + height - 2, isPicking() ? Color.GREEN.getRGB() : 0xFFAAAAAA); drawContext.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, "Pick", x + width / 2, y + (height - 8) / 2, 0xFFFFFFFF); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 1328571..9936f48 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -51,7 +51,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, // Adjust mouse coordinates based on the scale if (contextMenu.getProperties().hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, contextMenu.x + 1, yOffset - 1, contextMenu.getFinalWidth() - 2, option.getHeight())) { - drawBackground(matrices, contextMenu, properties, yOffset - 1,contextMenu.getFinalWidth(), option.getHeight() + 1, contextMenu.getProperties().getHoverColor().getRGB(),false); + drawBackground(matrices, contextMenu, properties, yOffset - 1, contextMenu.getFinalWidth(), option.getHeight() + 1, contextMenu.getProperties().getHoverColor().getRGB(), false); } option.render(drawContext, contextMenu.x + 4, yOffset, mouseX, mouseY); @@ -69,13 +69,13 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, } private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { - drawBackground(matrices, contextMenu, properties, contextMenu.y,contextMenu.getWidth(), contextMenu.getHeight(), properties.getBackgroundColor().getRGB(),properties.shadow()); + drawBackground(matrices, contextMenu, properties, contextMenu.y, contextMenu.getWidth(), contextMenu.getHeight(), properties.getBackgroundColor().getRGB(), properties.shadow()); } - private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset,int width, int height, int color,boolean shadow) { + private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset, int width, int height, int color, boolean shadow) { // Wow so good code. if (properties.roundedCorners()) { - if(shadow){ + if (shadow) { DrawHelper.drawRoundedRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), contextMenu.x, yOffset, @@ -87,7 +87,7 @@ private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, Conte 1, 1 ); - }else { + } else { DrawHelper.drawRoundedRectangle(matrices.peek().getPositionMatrix(), contextMenu.x, yOffset, @@ -98,7 +98,7 @@ private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, Conte ); } } else { - if(shadow){ + if (shadow) { DrawHelper.drawRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), contextMenu.x, yOffset, @@ -109,7 +109,7 @@ private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, Conte 1, 1 ); - }else { + } else { DrawHelper.drawRectangle(matrices.peek().getPositionMatrix(), contextMenu.x, yOffset, @@ -162,7 +162,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in option.setHeight(mc.textRenderer.fontHeight); option.setWidth(mc.textRenderer.getWidth(option.name) + 1); - int shadowOpacity = Math.min(option.value.getAlpha(),90); + int shadowOpacity = Math.min(option.value.getAlpha(), 90); DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), x + option.getWidth(), y - 1, @@ -178,6 +178,42 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in } } + public static class ClassicEnumRenderer> implements SkinRenderer> { + @Override + public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { + option.setHeight(mc.textRenderer.fontHeight + 1); + option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1); + + drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y, Color.WHITE.getRGB(), false); + drawContext.drawText(mc.textRenderer, Text.of(option.value.name()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); + } + } + + public static class ClassicSubMenuRenderer implements SkinRenderer { + @Override + public void render(DrawContext drawContext, SubMenuOption option, int x, int y, int mouseX, int mouseY) { + int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + option.setHeight(mc.textRenderer.fontHeight); + option.setWidth(mc.textRenderer.getWidth(option.name) + 1); + + option.getSubMenu().render(drawContext, x + option.getParentMenu().getFinalWidth(), y, mouseX, mouseY); + } + } + + public static class ClassicRunnableRenderer implements SkinRenderer { + Color DARK_RED = new Color(116, 0, 0); + Color DARK_GREEN = new Color(24, 132, 0, 226); + + @Override + public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) { + option.setHeight(mc.textRenderer.fontHeight); + option.setWidth(mc.textRenderer.getWidth("Run: " + option.name)); + int color = option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); + } + } + public class ClassicDoubleRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { @@ -218,17 +254,6 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i } } - public static class ClassicEnumRenderer> implements SkinRenderer> { - @Override - public void render(DrawContext drawContext, EnumOption option, int x, int y, int mouseX, int mouseY) { - option.setHeight(mc.textRenderer.fontHeight + 1); - option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1); - - drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y, Color.WHITE.getRGB(), false); - drawContext.drawText(mc.textRenderer, Text.of(option.value.name()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); - } - } - public class ClassicListRenderer implements SkinRenderer> { @Override public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { @@ -239,29 +264,4 @@ public void render(DrawContext drawContext, ListOption option, int x, int y, drawContext.drawText(mc.textRenderer, Text.of(option.value.toString()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false); } } - - public static class ClassicSubMenuRenderer implements SkinRenderer { - @Override - public void render(DrawContext drawContext, SubMenuOption option, int x, int y, int mouseX, int mouseY) { - int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); - option.setHeight(mc.textRenderer.fontHeight); - option.setWidth(mc.textRenderer.getWidth(option.name) + 1); - - option.getSubMenu().render(drawContext, x + option.getParentMenu().getFinalWidth(), y, mouseX, mouseY); - } - } - - public static class ClassicRunnableRenderer implements SkinRenderer { - Color DARK_RED = new Color(116, 0, 0); - Color DARK_GREEN = new Color(24, 132, 0, 226); - - @Override - public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) { - option.setHeight(mc.textRenderer.fontHeight); - option.setWidth(mc.textRenderer.getWidth("Run: " + option.name)); - int color = option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(option.name), x, y, color, false); - } - } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index 082c0a1..bbd7a33 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -8,7 +8,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ButtonTextures; -import net.minecraft.client.texture.Sprite; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -22,18 +21,16 @@ * It tries to imitate the minecraft look and provides various form of panel shades {@link PanelColor} */ public class MinecraftSkin extends Skin { - private static final MinecraftClient mc = MinecraftClient.getInstance(); - private static final int DEFAULT_SCROLLBAR_WIDTH = 10; - private static final int DEFAULT_PANEL_WIDTH = 248; - private static final int DEFAULT_PANEL_HEIGHT = 165; - private static final Identifier DEFAULT_BACKGROUND_PANEL = Identifier.of("minecraft", "textures/gui/demo_background.png"); - public static final ButtonTextures TEXTURES = new ButtonTextures( Identifier.ofVanilla("widget/button"), Identifier.ofVanilla("widget/button_disabled"), Identifier.ofVanilla("widget/button_highlighted") ); - + private static final MinecraftClient mc = MinecraftClient.getInstance(); + private static final int DEFAULT_SCROLLBAR_WIDTH = 10; + private static final int DEFAULT_PANEL_WIDTH = 248; + private static final int DEFAULT_PANEL_HEIGHT = 165; + private static final Identifier DEFAULT_BACKGROUND_PANEL = Identifier.of("minecraft", "textures/gui/demo_background.png"); private static final Identifier SCROLLER_TEXTURE = Identifier.ofVanilla("widget/scroller"); private static final Identifier SCROLL_BAR_BACKGROUND = Identifier.ofVanilla("widget/scroller_background"); @@ -47,50 +44,6 @@ public class MinecraftSkin extends Skin { private double scrollVelocity = 0; private int imageX, imageY; - public enum PanelColor { - COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f), - CREAMY(1.0f, 0.9f, 0.8f, 0.9f), - DARK_PANEL(0.2f, 0.2f, 0.2f, 0.9f), - FOREST_GREEN(0.0f, 0.6f, 0.2f, 0.9f), - GOLDEN_YELLOW(1.0f, 0.8f, 0.0f, 0.9f), - LAVENDER(0.8f, 0.6f, 1.0f, 0.9f), - LIGHT_BLUE(0.6f, 0.8f, 1.0f, 0.9f), - LIME_GREEN(0.7f, 1.0f, 0.3f, 0.9f), - MIDNIGHT_PURPLE(0.3f, 0.0f, 0.5f, 0.9f), - OCEAN_BLUE(0.0f, 0.5f, 1.0f, 0.9f), - ROSE_PINK(1.0f, 0.4f, 0.6f, 0.9f), - SKY_BLUE(0.5f, 0.8f, 1.0f, 0.9f), - SOFT_GREEN(0.6f, 1.0f, 0.6f, 0.9f), - SUNSET_ORANGE(1.0f, 0.5f, 0.0f, 0.9f), - WARM_YELLOW(1.0f, 1.0f, 0.6f, 0.9f), - CUSTOM(0.0f, 0.0f, 0.0f, 0.0f); // PlaceHolder for custom colors - - private float red; - private float green; - private float blue; - private float alpha; - - PanelColor(float red, float green, float blue, float alpha) { - this.red = red; - this.green = green; - this.blue = blue; - this.alpha = alpha; - } - - public void applyColor() { - RenderSystem.setShaderColor(red, green, blue, alpha); - } - - public static PanelColor custom(float red, float green, float blue, float alpha) { - PanelColor custom = CUSTOM; - custom.red = red; - custom.green = green; - custom.blue = blue; - custom.alpha = alpha; - return custom; - } - } - public MinecraftSkin(PanelColor color, Identifier backgroundPanel, int panelWidth, int panelHeight) { super(); this.panelColor = color; @@ -108,8 +61,9 @@ public MinecraftSkin(PanelColor color, Identifier backgroundPanel, int panelWidt setCreateNewScreen(true); } + public MinecraftSkin(PanelColor color) { - this(color,DEFAULT_BACKGROUND_PANEL,DEFAULT_PANEL_WIDTH,DEFAULT_PANEL_HEIGHT); + this(color, DEFAULT_BACKGROUND_PANEL, DEFAULT_PANEL_WIDTH, DEFAULT_PANEL_HEIGHT); } @Override @@ -122,7 +76,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int centerX = screenWidth / 2; int centerY = screenHeight / 2; - contextMenu.set(centerX,centerY,0); + contextMenu.set(centerX, centerY, 0); // Calculate the top-left corner of the image imageX = (screenWidth - panelWidth) / 2; @@ -133,11 +87,11 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, RenderSystem.enableDepthTest(); panelColor.applyColor(); drawContext.drawTexture(BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight); - RenderSystem.setShaderColor(1.0f,1.0f,1.0f,1.0f); - drawContext.drawGuiTexture(TEXTURES.get(true, isMouseOver(mouseX,mouseY,imageX + 3,imageY + 3,14,14)), imageX + 3,imageY + 3,14,14); - drawContext.drawText(mc.textRenderer,"X",imageX + 10 - mc.textRenderer.getWidth("X")/2 ,imageY + 6,-1,true); + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + drawContext.drawGuiTexture(TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14); + drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true); - DrawHelper.enableScissor(imageX,imageY + 2,screenWidth,panelHeight - 4); + DrawHelper.enableScissor(imageX, imageY + 2, screenWidth, panelHeight - 4); int yOffset = imageY + 10 - scrollOffset; contextMenu.setWidth(panelWidth - 4); contextMenu.setFinalWidth(panelWidth - 4); @@ -171,15 +125,14 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, private void drawScrollbar(DrawContext context) { int scrollbarX = imageX + panelWidth + 5; int scrollbarY = imageY; - - // Draw scrollbar background - context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.enableBlend(); - RenderSystem.enableDepthTest(); - context.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, DEFAULT_SCROLLBAR_WIDTH, panelHeight); - context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - if (maxScrollOffset > 0) { + // Draw scrollbar background + context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + context.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, DEFAULT_SCROLLBAR_WIDTH, panelHeight); + context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + float scrollPercentage = (float) scrollOffset / maxScrollOffset; int handleHeight = Math.max(15, (int) ((float) panelHeight * (panelHeight / (float) contextMenu.getHeight()))); int handleY = scrollbarY + (int) ((panelHeight - handleHeight) * scrollPercentage); @@ -189,7 +142,7 @@ private void drawScrollbar(DrawContext context) { } } - private boolean isMouseOver(double mouseX, double mouseY, double x, double y,double width, double height){ + private boolean isMouseOver(double mouseX, double mouseY, double x, double y, double width, double height) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } @@ -199,7 +152,7 @@ private void applyMomentum() { scrollOffset = MathHelper.clamp(scrollOffset, 0, maxScrollOffset); // Stop the scrolling if the velocity is very low or if we've reached the limits - if (Math.abs(scrollVelocity) < 0.12 || scrollOffset == 0 || scrollOffset-maxScrollOffset <= 3) { + if (Math.abs(scrollVelocity) < 0.12 || scrollOffset == 0 || scrollOffset - maxScrollOffset <= 3) { scrollVelocity = 0; } else { scrollVelocity *= 0.89; // Apply friction @@ -207,7 +160,6 @@ private void applyMomentum() { } } - @Override public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { scrollVelocity += verticalAmount; @@ -216,7 +168,7 @@ public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double @Override public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { - if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX,mouseY,imageX + 3,imageY + 3,14,14)){ + if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)) { contextMenu.close(); } @@ -239,10 +191,54 @@ public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int return super.mouseDragged(menu, mouseX, mouseY, button, deltaX, deltaY); } + public enum PanelColor { + COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f), + CREAMY(1.0f, 0.9f, 0.8f, 0.9f), + DARK_PANEL(0.2f, 0.2f, 0.2f, 0.9f), + FOREST_GREEN(0.0f, 0.6f, 0.2f, 0.9f), + GOLDEN_YELLOW(1.0f, 0.8f, 0.0f, 0.9f), + LAVENDER(0.8f, 0.6f, 1.0f, 0.9f), + LIGHT_BLUE(0.6f, 0.8f, 1.0f, 0.9f), + LIME_GREEN(0.7f, 1.0f, 0.3f, 0.9f), + MIDNIGHT_PURPLE(0.3f, 0.0f, 0.5f, 0.9f), + OCEAN_BLUE(0.0f, 0.5f, 1.0f, 0.9f), + ROSE_PINK(1.0f, 0.4f, 0.6f, 0.9f), + SKY_BLUE(0.5f, 0.8f, 1.0f, 0.9f), + SOFT_GREEN(0.6f, 1.0f, 0.6f, 0.9f), + SUNSET_ORANGE(1.0f, 0.5f, 0.0f, 0.9f), + WARM_YELLOW(1.0f, 1.0f, 0.6f, 0.9f), + CUSTOM(0.0f, 0.0f, 0.0f, 0.0f); // PlaceHolder for custom colors + + private float red; + private float green; + private float blue; + private float alpha; + + PanelColor(float red, float green, float blue, float alpha) { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + } + + public static PanelColor custom(float red, float green, float blue, float alpha) { + PanelColor custom = CUSTOM; + custom.red = red; + custom.green = green; + custom.blue = blue; + custom.alpha = alpha; + return custom; + } + + public void applyColor() { + RenderSystem.setShaderColor(red, green, blue, alpha); + } + } + public class MinecraftBooleanRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { - drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25 / 2 - 5, -1, true); option.set(x + panelWidth - 75, y); @@ -250,11 +246,11 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,width,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); Text text = option.getBooleanType().getText(option.value); int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer,text,(int) (option.getX() + (width/2.0f) -(mc.textRenderer.getWidth(text)/2.0f)) ,y + 5,color,true); + drawContext.drawText(mc.textRenderer, text, (int) (option.getX() + (width / 2.0f) - (mc.textRenderer.getWidth(text) / 2.0f)), y + 5, color, true); //drawContext.drawTexture(BOOLEAN_TEXTURE); option.setHeight(25); @@ -265,7 +261,7 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, @Override public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, int button) { - if(mouseX >= option.getX() && mouseX <= option.getX() + 50 && mouseY >= option.getY() && mouseY <= option.getY() + option.getHeight()){ + if (mouseX >= option.getX() && mouseX <= option.getX() + 50 && mouseY >= option.getY() && mouseY <= option.getY() + option.getHeight()) { option.set(!option.get()); } return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button); @@ -275,16 +271,16 @@ public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, public class MinecraftColorOptionRenderer implements SkinRenderer { @Override public void render(DrawContext drawContext, ColorOption option, int x, int y, int mouseX, int mouseY) { - drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25 / 2 - 5, -1, true); - option.set(x + panelWidth - 75 , y); + option.set(x + panelWidth - 75, y); int width = 20; drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX,mouseY)), option.getX(),y,width,20); - int shadowOpacity = Math.min(option.value.getAlpha(),45); + drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); + int shadowOpacity = Math.min(option.value.getAlpha(), 45); DrawHelper.drawRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), option.getX() + 4, y + 4, @@ -317,33 +313,34 @@ public void init(DoubleOption option) { @Override public void render(DrawContext drawContext, DoubleOption option, int x, int y, int mouseX, int mouseY) { - drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25 / 2 - 5, -1, true); option.setWidth(panelWidth - 150); option.setHeight(25); - option.set(x + panelWidth - 122,y); + option.set(x + panelWidth - 122, y); double sliderX = option.getX() + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.getWidth() - 8); - boolean isMouseOverHandle = isMouseOver(mouseX,mouseY, sliderX, y); + boolean isMouseOverHandle = isMouseOver(mouseX, mouseY, sliderX, y); RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.enableDepthTest(); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawGuiTexture(option.isMouseOver(mouseX,mouseY)? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20); - drawContext.drawGuiTexture(isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE , (int) Math.round(sliderX), y, 8, 20); + drawContext.drawGuiTexture(option.isMouseOver(mouseX, mouseY) ? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20); + drawContext.drawGuiTexture(isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE, (int) Math.round(sliderX), y, 8, 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawText(mc.textRenderer, String.valueOf(option.value),option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth(option.value.toString())/2 ,y + 5,16777215,false); + drawContext.drawText(mc.textRenderer, String.valueOf(option.value), option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth(option.value.toString()) / 2, y + 5, 16777215, false); } - private boolean isMouseOver(double mouseX, double mouseY, double x, double y){ + + private boolean isMouseOver(double mouseX, double mouseY, double x, double y) { return mouseX >= x && mouseX <= x + 10 && mouseY >= y && mouseY <= y + 20; } @Override public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) { - return isMouseOver(mouseX,mouseY,option.getX(),option.getY()); + return isMouseOver(mouseX, mouseY, option.getX(), option.getY()); } } @@ -365,17 +362,17 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y, option.setHeight(25); option.setWidth(maxWidth); - drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25 / 2 - 5, -1, true); option.set(x + panelWidth - maxWidth - 25, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,maxWidth,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); - drawContext.drawText(mc.textRenderer,text,option.getX() + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + drawContext.drawText(mc.textRenderer, text, option.getX() + maxWidth / 2 - mc.textRenderer.getWidth(text) / 2, y + 5, Color.CYAN.getRGB(), true); } } @@ -397,17 +394,17 @@ public void render(DrawContext drawContext, ListOption option, int x, int y, option.setHeight(25); option.setWidth(maxWidth); - drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25 / 2 - 5, -1, true); option.set(x + panelWidth - maxWidth - 25, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y,maxWidth,20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); - drawContext.drawText(mc.textRenderer,text,option.getX() + maxWidth/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.CYAN.getRGB(),true); + drawContext.drawText(mc.textRenderer, text, option.getX() + maxWidth / 2 - mc.textRenderer.getWidth(text) / 2, y + 5, Color.CYAN.getRGB(), true); } } @@ -417,17 +414,17 @@ public void render(DrawContext drawContext, SubMenuOption option, int x, int y, option.setHeight(20); option.setWidth(30); - drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name, x + 15, y + 25 / 2 - 5, -1, true); option.set(x + panelWidth - 75, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX,mouseY)), option.getX(),y, option.getWidth(),20); + drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = "Open"; - drawContext.drawText(mc.textRenderer,text,option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth(text)/2 ,y + 5,Color.YELLOW.getRGB(),true); + drawContext.drawText(mc.textRenderer, text, option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth(text) / 2, y + 5, Color.YELLOW.getRGB(), true); option.getSubMenu().render(drawContext, x + option.getParentMenu().getFinalWidth(), y, mouseX, mouseY); } @@ -442,16 +439,16 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y, option.setHeight(25); option.setWidth(26); - drawContext.drawText(mc.textRenderer, option.name.replaceFirst("Run: ","") + ": ", x + 15, y + 25/2 - 5, -1, true); + drawContext.drawText(mc.textRenderer, option.name.replaceFirst("Run: ", "") + ": ", x + 15, y + 25 / 2 - 5, -1, true); option.set(x + panelWidth - 75, y); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX,mouseY)), option.getX(),y, option.getWidth(),20); + drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawText(mc.textRenderer,"Run",option.getX() + option.getWidth()/2 - mc.textRenderer.getWidth("Run")/2 ,y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(),true); + drawContext.drawText(mc.textRenderer, "Run", option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth("Run") / 2, y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true); } } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java index b2007a3..867c949 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java @@ -1,7 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; @@ -13,14 +12,15 @@ public abstract class Skin { protected Map>, SkinRenderer>> renderers = new HashMap<>(); private boolean createNewScreen; - public > void addRenderer(Class optionClass, SkinRenderer renderer) { - renderers.put(optionClass, renderer); + public Skin(ContextMenu menu) { + this.contextMenu = menu; } - public Skin(ContextMenu menu){ - this.contextMenu = menu; + public Skin() { } - public Skin(){ + + public > void addRenderer(Class optionClass, SkinRenderer renderer) { + renderers.put(optionClass, renderer); } @SuppressWarnings("unchecked") @@ -50,9 +50,14 @@ public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int return false; } - public void keyPressed(ContextMenu menu, int key,int scanCode, int modifiers) {} - public void keyReleased(ContextMenu menu, int key,int scanCode, int modifiers) {} - public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount){} + public void keyPressed(ContextMenu menu, int key, int scanCode, int modifiers) { + } + + public void keyReleased(ContextMenu menu, int key, int scanCode, int modifiers) { + } + + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + } public boolean shouldCreateNewScreen() { return createNewScreen; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java index fc498de..8e7775f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java @@ -18,9 +18,15 @@ default boolean mouseDragged(T option, double mouseX, double mouseY, int button, return option.isMouseOver(mouseX, mouseY); } - default void keyPressed(T option, int key) {} + default void keyPressed(T option, int key, int scanCode, int modifiers) { + } + + default void keyReleased(T option, int key, int scanCode, int modifiers) { + } - default void keyReleased(T option, int key) {} - default void mouseScrolled(T option, double mouseX, double mouseY, double horizontalAmount, double verticalAmount){} - default void init(T option){} + default void mouseScrolled(T option, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + } + + default void init(T option) { + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 2e34341..ab3821a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -6,17 +6,12 @@ import com.tanishisherewith.dynamichud.utils.UID; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.option.VideoOptionsScreen; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; -import java.util.Properties; -import java.util.Set; - public abstract class Widget { - public enum Anchor { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER } - + private final Anchor anchor; // The chosen anchor point public WidgetData DATA; /** * This is the UID of the widget used to identify during loading and saving. @@ -26,23 +21,13 @@ public enum Anchor { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER } * @see #modId */ public UID uid = UID.generate(); - protected boolean isInEditor = false; - // Whether the widget is enabled and should be displayed. public boolean display = true; public boolean isDraggable = true; - - private int offsetX, offsetY; // Offset from the anchor point - //Boolean to check if the widget is being dragged public boolean dragging; - //To enable/disable snapping public boolean shiftDown = false; - - // Absolute position of the widget on screen in pixels. - protected int x, y; - protected boolean shouldScale = true; /** * An identifier for widgets to group them under one ID. *

@@ -52,6 +37,10 @@ public enum Anchor { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER } * @see #uid */ public String modId = "unknown"; + protected boolean isInEditor = false; + // Absolute position of the widget on screen in pixels. + protected int x, y; + protected boolean shouldScale = true; protected MinecraftClient mc = MinecraftClient.getInstance(); /** * Scale of the current widget. @@ -62,12 +51,12 @@ public enum Anchor { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER } //Dimensions of the widget protected WidgetBox widgetBox; int startX, startY; - private final Anchor anchor; // The chosen anchor point - + private int offsetX, offsetY; // Offset from the anchor point public Widget(WidgetData DATA, String modId) { - this(DATA,modId,Anchor.CENTER); + this(DATA, modId, Anchor.CENTER); } - public Widget(WidgetData DATA, String modId,Anchor anchor) { + + public Widget(WidgetData DATA, String modId, Anchor anchor) { this.DATA = DATA; widgetBox = new WidgetBox(0, 0, 0, 0); this.modId = modId; @@ -75,7 +64,6 @@ public Widget(WidgetData DATA, String modId,Anchor anchor) { init(); } - /** * This method is called at the end of the {@link Widget#Widget(WidgetData, String)} constructor. */ @@ -133,8 +121,8 @@ private int getAnchorY(int screenHeight) { // Update position based on anchor and offset void updatePosition(int screenWidth, int screenHeight) { - if(offsetX == 0 || offsetY == 0){ - calculateOffset(x,y,screenWidth,screenHeight); + if (offsetX == 0 || offsetY == 0) { + calculateOffset(x, y, screenWidth, screenHeight); } int anchorX = getAnchorX(screenWidth); @@ -148,10 +136,10 @@ void updatePosition(int screenWidth, int screenHeight) { public void setPosition(int x, int y) { this.x = x; this.y = y; - if(mc.getWindow() != null){ + if (mc.getWindow() != null) { //updatePercentages(); calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Set initial offset - updatePosition( mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Initial placement + updatePosition(mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Initial placement } } @@ -185,7 +173,7 @@ public final void render(DrawContext drawContext, int mouseX, int mouseY) { * Renders the widget on the editor screen. */ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { - if(!isInEditor) return; + if (!isInEditor) return; displayBg(drawContext); @@ -200,7 +188,6 @@ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY clampPosition(); } - /** * Renders the widget on the screen *

@@ -213,12 +200,10 @@ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY */ public abstract void renderWidget(DrawContext context, int mouseX, int mouseY); - /** * Renders the widget in the editor screen with a background. * Override this method without super call to remove the background. * Could also be used to display placeholder values. - * */ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { //displayBg(context); @@ -226,12 +211,10 @@ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { renderWidget(context, mouseX, mouseY); } - /* Input related methods. Override with super call to add your own input-based code like contextMenu */ - public boolean mouseClicked(double mouseX, double mouseY, int button) { if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { toggle(); - if(isDraggable) { + if (isDraggable) { startX = (int) (mouseX - x); startY = (int) (mouseY - y); dragging = true; @@ -240,13 +223,16 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } return false; } - public void clampPosition(){ + + /* Input related methods. Override with super call to add your own input-based code like contextMenu */ + + public void clampPosition() { this.x = (int) MathHelper.clamp(this.x, 0, mc.getWindow().getScaledWidth() - getWidth()); this.y = (int) MathHelper.clamp(this.y, 0, mc.getWindow().getScaledHeight() - getHeight()); } public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { - if(!isDraggable) return false; + if (!isDraggable) return false; if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { int newX = (int) (mouseX - startX); int newY = (int) (mouseY - startY); @@ -287,7 +273,6 @@ public void mouseReleased(double mouseX, double mouseY, int button) { public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { } - public boolean toggle() { return this.display = !this.display; } @@ -299,7 +284,6 @@ public void onClose() { /** * Displays a faint grayish background if enabled or faint reddish background if disabled. * Drawn with 2 pixel offset to all sides - * */ protected void displayBg(DrawContext context) { int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); @@ -372,6 +356,8 @@ public String toString() { '}'; } + public enum Anchor {TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER} + public abstract static class WidgetBuilder { protected int x; protected int y; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index d3afbcc..489a799 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -6,7 +6,6 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtList; -import net.minecraft.util.math.MathHelper; import java.io.DataOutputStream; import java.io.File; @@ -182,7 +181,7 @@ public static void loadWidgets(File file) throws IOException { widgets.clear(); if (file.exists() || (file = new File(file.getAbsolutePath() + ".backup")).exists()) { - if(!file.exists()){ + if (!file.exists()) { printWarn("Main file " + file.getAbsolutePath() + " was not found... Loading from a found backup file"); } @@ -205,7 +204,7 @@ public static void loadWidgets(File file) throws IOException { } } - public static boolean doesWidgetFileExist(File file){ + public static boolean doesWidgetFileExist(File file) { return file.exists() || new File(file.getAbsolutePath() + ".backup").exists(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java index 7b570ba..11d46e4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java @@ -12,27 +12,26 @@ * This is just an example widget, not supposed to be used. */ public class ItemWidget extends Widget { - public static WidgetData DATA = new WidgetData<>("ItemWidget","Displays item texture", ItemWidget::new); - public ItemStack item; - - public ItemWidget(ItemStack itemStack,String modId) { + public ItemStack item; public static WidgetData DATA = new WidgetData<>("ItemWidget", "Displays item texture", ItemWidget::new); + public ItemWidget(ItemStack itemStack, String modId) { super(DATA, modId); this.item = itemStack; } + public ItemWidget() { this(ItemStack.EMPTY, "empty"); } @Override public void renderWidget(DrawContext context, int mouseX, int mouseY) { - context.drawItem(item,x,y); + context.drawItem(item, x, y); widgetBox.setSizeAndPosition(getX(), getY(), 16, 16, this.shouldScale, GlobalConfig.get().getScale()); } @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); - tag.putInt("ItemID",Item.getRawId(item.getItem())); + tag.putInt("ItemID", Item.getRawId(item.getItem())); } @Override @@ -45,8 +44,9 @@ public void setItemStack(ItemStack item) { this.item = item; } - public static class Builder extends WidgetBuilder{ - ItemStack itemStack; + public static class Builder extends WidgetBuilder { + ItemStack itemStack; + public Builder setItemStack(ItemStack itemStack) { this.itemStack = itemStack; return self(); @@ -59,7 +59,9 @@ protected Builder self() { @Override public ItemWidget build() { - return new ItemWidget(itemStack,modID); + return new ItemWidget(itemStack, modID); } } + + } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 4db69cb..b14a296 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -7,7 +7,9 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.BooleanOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetData; @@ -16,26 +18,22 @@ import org.lwjgl.glfw.GLFW; import java.awt.*; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; public class TextWidget extends Widget implements ContextMenuProvider { public Color textColor; protected boolean shadow; // Whether to draw a shadow behind the text - public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); protected boolean rainbow; // Whether to apply a rainbow effect to the text + public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); protected int rainbowSpeed = 2; //Speed of the rainbow effect Supplier textSupplier; String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; private ContextMenu menu; - public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); } + /** * Searches for the supplier within the {@link DynamicValueRegistry#globalRegistry} using the given registryKey * @@ -85,7 +83,7 @@ public void createMenu() { menu.addOption(new BooleanOption("Shadow", () -> this.shadow, value -> this.shadow = value, BooleanOption.BooleanType.ON_OFF)); menu.addOption(new BooleanOption("Rainbow", () -> this.rainbow, value -> this.rainbow = value, BooleanOption.BooleanType.ON_OFF)); menu.addOption(new ColorOption("TextColor", menu, () -> this.textColor, value -> this.textColor = value)); - menu.addOption(new DoubleOption("RainbowSpeed", 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(),menu)); + menu.addOption(new DoubleOption("RainbowSpeed", 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu)); /* TEST AtomicReference option = new AtomicReference<>("Enum1"); @@ -111,7 +109,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow); widgetBox.setSizeAndPosition(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale()); } - menu.set(getX(),getY(),(int) Math.ceil(getHeight())); + menu.set(getX(), getY(), (int) Math.ceil(getHeight())); } @Override @@ -173,7 +171,7 @@ public void readFromTag(NbtCompound tag) { dynamicValueRegistry = dvr; return; } - createMenu(); + createMenu(); } @Override @@ -232,4 +230,6 @@ public TextWidget build() { return widget; } } + + } From 70df427f64d4794849ce36e3d1295f82d2a73651 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:54:19 +0530 Subject: [PATCH 08/40] Gradle Changes and stuff. --- .github/workflows/gradle.yml | 2 +- .../dynamichud/DynamicHudTest.java | 3 +- .../contextmenu/skinsystem/SkinRenderer.java | 2 +- .../dynamichud/widget/WidgetManager.java | 42 ++++++++++--------- .../dynamichud/widget/WidgetRenderer.java | 4 ++ 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ff0fffc..dc32e0f 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -48,7 +48,7 @@ jobs: path: build/libs/ - name: pre-release action - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@v2.0.8 with: tag_name: "latest" name: "DynamicHUD Pre-release" diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java index bc68bca..383cbed 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java @@ -87,8 +87,7 @@ public void initAfter() { @Override public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor Screen"), renderer) { - }; + return new AbstractMoveableScreen(Text.literal("Editor Screen"), renderer) {}; } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java index 8e7775f..a19887c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java @@ -3,7 +3,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; -public interface SkinRenderer> { +public interface SkinRenderer> { void render(DrawContext drawContext, T option, int x, int y, int mouseX, int mouseY); default boolean mouseClicked(T option, double mouseX, double mouseY, int button) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index 489a799..a2af510 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -180,27 +180,29 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti public static void loadWidgets(File file) throws IOException { widgets.clear(); - if (file.exists() || (file = new File(file.getAbsolutePath() + ".backup")).exists()) { - if (!file.exists()) { - printWarn("Main file " + file.getAbsolutePath() + " was not found... Loading from a found backup file"); - } + if (!file.exists()) { + DynamicHUD.logger.warn("Main file {} was not found... Loading from a found backup file", file.getAbsolutePath()); + file = new File(file.getAbsolutePath() + ".backup"); + } - NbtCompound rootTag = NbtIo.read(file.toPath()); - NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); - if (widgetList == null) { - printWarn("RootTag or WidgetList is null. File is either empty or corrupted: " + file); - return; - } - for (int i = 0; i < widgetList.size(); i++) { - NbtCompound widgetTag = widgetList.getCompound(i); - WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); - Widget widget = widgetData.createWidget(); - widget.readFromTag(widgetTag); - printInfo("Loaded Widget: " + widget); - widgets.add(widget); - } - } else { - printWarn("Widget File does not exist. Try saving one first"); + NbtCompound rootTag = NbtIo.read(file.toPath()); + + if (rootTag == null) { + printWarn("RootTag is null. File is either empty or corrupted: " + file); + return; + } + NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); + if (widgetList == null) { + printWarn("WidgetList is null. File is empty: " + file); + return; + } + for (int i = 0; i < widgetList.size(); i++) { + NbtCompound widgetTag = widgetList.getCompound(i); + WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); + Widget widget = widgetData.createWidget(); + widget.readFromTag(widgetTag); + printInfo("Loaded Widget: " + widget); + widgets.add(widget); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index c3eac55..630340f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -31,6 +31,10 @@ public WidgetRenderer(List widgets) { addScreen(ContextMenuScreen.class); } + public WidgetRenderer(String modID) { + this(WidgetManager.getWidgetsForMod(modID)); + } + public void addWidget(Widget widget) { widgets.add(widget); } From bbdba6dc941d033ca2d65dc455ddd99765c53880 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 22 Oct 2024 20:25:09 +0530 Subject: [PATCH 09/40] Removed ModMenuIntegration.java and added a DH button to option screen --- build.gradle | 2 -- gradle.properties | 3 +- .../dynamichud/ModMenuIntegration.java | 13 ------- .../dynamichud/mixins/OptionsScreenMixin.java | 36 +++++++++++++++++++ .../contextmenu/ContextMenuProperties.java | 2 ++ .../dynamichud/widgets/TextWidget.java | 2 +- src/main/resources/dynamichud.mixins.json | 4 ++- src/main/resources/fabric.mod.json | 3 -- 8 files changed, 43 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java diff --git a/build.gradle b/build.gradle index 9f94dfe..5bdb604 100644 --- a/build.gradle +++ b/build.gradle @@ -34,8 +34,6 @@ dependencies { modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}" - - modApi "com.terraformersmc:modmenu:${project.modmenu_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index e2dee65..b1efe41 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,5 +15,4 @@ archives_base_name = dynamichud # Dependencies fabric_version=0.102.1+1.21.1 -yacl_version=3.5.0+1.21-fabric -modmenu_version = 11.0.2 \ No newline at end of file +yacl_version=3.5.0+1.21-fabric \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java deleted file mode 100644 index 668a7ed..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.tanishisherewith.dynamichud; - -import com.tanishisherewith.dynamichud.config.GlobalConfig; -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; - - -public class ModMenuIntegration implements ModMenuApi { - @Override - public ConfigScreenFactory getModConfigScreenFactory() { - return parent -> GlobalConfig.get().createYACLGUI(); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java new file mode 100644 index 0000000..772b49d --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java @@ -0,0 +1,36 @@ +package com.tanishisherewith.dynamichud.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import com.tanishisherewith.dynamichud.config.GlobalConfig; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.DirectionalLayoutWidget; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.function.Supplier; + +@Mixin(OptionsScreen.class) +public abstract class OptionsScreenMixin extends Screen { + @Shadow protected abstract ButtonWidget createButton(Text message, Supplier screenSupplier); + + protected OptionsScreenMixin(Text title) { + super(title); + } + @Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/GridWidget$Adder;add(Lnet/minecraft/client/gui/widget/Widget;)Lnet/minecraft/client/gui/widget/Widget;", ordinal = 0)) + private void init(CallbackInfo ci, @Local(ordinal = 0) DirectionalLayoutWidget directionalLayoutWidget) { + DirectionalLayoutWidget directionalLayoutWidget2 = directionalLayoutWidget.add(DirectionalLayoutWidget.horizontal()); + + directionalLayoutWidget2.getMainPositioner().marginLeft(-26).marginY(-28); + + ButtonWidget widget = createButton(Text.of("DH"), () -> GlobalConfig.get().createYACLGUI()); + widget.setDimensions(20, 20); + + directionalLayoutWidget2.add(widget); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java index 2576b4e..ff70053 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -6,6 +6,8 @@ import java.awt.*; public class ContextMenuProperties { + //Note: Not all of these properties are used in all skins or all places. + private Color backgroundColor = new Color(107, 112, 126, 124); private Color borderColor = Color.BLACK; private float borderWidth = 1f; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index b14a296..64c1ef9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -30,10 +30,10 @@ public class TextWidget extends Widget implements ContextMenuProvider { String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; private ContextMenu menu; + public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); } - /** * Searches for the supplier within the {@link DynamicValueRegistry#globalRegistry} using the given registryKey * diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json index f40333e..f5d7c16 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -9,5 +9,7 @@ "injectors": { "defaultRequire": 1 }, - "client": [] + "client": [ + "OptionsScreenMixin" + ] } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 33a2089..6b9036c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,9 +20,6 @@ "entrypoints": { "client": [ "com.tanishisherewith.dynamichud.DynamicHUD" - ], - "modmenu": [ - "com.tanishisherewith.dynamichud.ModMenuIntegration" ] }, "mixins": [ From 5b7f7fbe8242f62f89e3acc190d2dd9d9b1ba643 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:26:19 +0530 Subject: [PATCH 10/40] Removed unnecessary methods and reverted TextWidget to use the ClassicSkin --- .../contextmenu/ContextMenuProperties.java | 5 +-- .../dynamichud/utils/contextmenu/Option.java | 3 +- .../contextmenu/options/BooleanOption.java | 15 ------- .../contextmenu/options/ColorOption.java | 35 +++------------ .../contextmenu/options/DoubleOption.java | 44 ------------------- .../utils/contextmenu/options/EnumOption.java | 17 ------- .../utils/contextmenu/options/ListOption.java | 15 ------- .../contextmenu/options/RunnableOption.java | 16 ------- .../contextmenu/options/SubMenuOption.java | 6 --- .../contextmenu/skinsystem/ClassicSkin.java | 4 +- .../contextmenu/skinsystem/ModernSkin.java | 11 +++++ .../dynamichud/widgets/TextWidget.java | 4 +- 12 files changed, 23 insertions(+), 152 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java index ff70053..84538b6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -22,15 +22,14 @@ public class ContextMenuProperties { private boolean enableAnimations = true; private Skin skin = new ClassicSkin(); - private ContextMenuProperties() { - } + private ContextMenuProperties() {} public static Builder builder() { return new ContextMenuProperties().new Builder(); } public static ContextMenuProperties createGenericSimplified() { - return new ContextMenuProperties().new Builder().build(); + return new ContextMenuProperties(); } // Getters for all properties diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java index 95d81b7..6ea6c40 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -52,7 +52,7 @@ public void updateProperties(ContextMenuProperties properties) { this.properties = properties; this.renderer = properties.getSkin().getRenderer((Class>) this.getClass()); if (renderer == null) { - DynamicHUD.logger.error("Renderer not found for class: {}", this.getClass().getName()); + DynamicHUD.logger.error("Renderer not found for class: {} in the following skin: {}", this.getClass().getName(), properties.getSkin()); throw new RuntimeException(); } } @@ -60,6 +60,7 @@ public void updateProperties(ContextMenuProperties properties) { public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { this.x = x; this.y = y; + this.value = get(); // Retrieve the renderer and ensure it is not null renderer.render(drawContext, this, x, y, mouseX, mouseY); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index 08ffa66..8a548ee 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -35,21 +35,6 @@ public BooleanOption(String name, boolean defaultValue, BooleanType type) { BooleanPool.put(name, defaultValue); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - value = get(); - super.render(drawContext, x, y, mouseX, mouseY); - - // properties.getSkin().getRenderer(BooleanOption.class).render(drawContext,this,x,y,mouseX,mouseY); - /* - int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); - this.height = mc.textRenderer.fontHeight; - this.width = mc.textRenderer.getWidth(name) + 1; - - */ - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index dc31a33..176d067 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -12,7 +12,7 @@ public class ColorOption extends Option { public String name = "Empty"; public boolean isVisible = false; - public ContextMenu parentMenu = null; + private ContextMenu parentMenu = null; private ColorGradientPicker colorPicker = null; public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { @@ -23,35 +23,6 @@ public ColorOption(String name, ContextMenu parentMenu, Supplier getter, this.renderer.init(this); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - super.render(drawContext, x, y, mouseX, mouseY); - - // properties.getSkin().getRenderer(ColorOption.class).render(drawContext,this,x,y,mouseX,mouseY); - - /* - int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); - this.height = mc.textRenderer.fontHeight; - this.width = mc.textRenderer.getWidth(name) + 8; - drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); - - int shadowOpacity = Math.min(value.getAlpha(),90); - DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), - x + width - 4, - y - 1, - 8, - 8, - 2, - value.getRGB(), - shadowOpacity, - 1, - 1); - - colorPicker.render(drawContext, this.x + parentMenu.finalWidth + 7, y - 10); - - */ - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY)) { @@ -88,4 +59,8 @@ public void onClose() { isVisible = false; colorPicker.close(); } + + public ContextMenu getParentMenu() { + return parentMenu; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index d51ef4a..7297320 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -33,50 +33,6 @@ public DoubleOption(String name, double minValue, double maxValue, float step, S this.renderer.init(this); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - value = get(); - super.render(drawContext, x, y, mouseX, mouseY); - - //properties.getSkin().getRenderer(DoubleOption.class).render(drawContext,this,x,y,mouseX,mouseY); - - /* - this.width = 35; - this.height = 16; - - // Draw the label - TextRenderer textRenderer = mc.textRenderer; - DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, 0.7f); - String labelText = name + ": " + String.format("%.1f", value); - int labelWidth = textRenderer.getWidth(labelText); - this.width = Math.max(this.width, labelWidth); - drawContext.drawTextWithShadow(textRenderer, labelText, x, y + 1, 0xFFFFFFFF); - DrawHelper.stopScaling(drawContext.getMatrices()); - - float handleWidth = 3; - float handleHeight = 8; - double handleX = x + (value - minValue) / (maxValue - minValue) * (width - handleWidth); - double handleY = y + textRenderer.fontHeight + 1 + ((2 - handleHeight) / 2); - - // Draw the slider - drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, width, handleX); - - // Draw the handle - - DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), - (float) handleX, - (float) handleY, - handleWidth, - handleHeight, - 1, - 0xFFFFFFFF, - 90, - 0.6f, - 0.6f); - - */ - } - public void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) { DrawHelper.drawRectangle(drawContext.getMatrices().peek().getPositionMatrix(), sliderX, sliderY, sliderWidth, 2, 0xFFFFFFFF); if (handleX - sliderX > 0) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index 59de1b4..dffd127 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -25,23 +25,6 @@ public EnumOption(String name, Supplier getter, Consumer setter, E[] value this.renderer.init(this); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - value = get(); - super.render(drawContext, x, y, mouseX, mouseY); - - // properties.getSkin().getRenderer(EnumOption.class).render(drawContext,this,x,y,mouseX,mouseY); - - /* - this.height = mc.textRenderer.fontHeight + 1; - this.width = mc.textRenderer.getWidth(name + ": " + value.name()) + 1; - - drawContext.drawText(mc.textRenderer, Text.of(name + ": "), x, y, Color.WHITE.getRGB(), false); - drawContext.drawText(mc.textRenderer, Text.of(value.name()), x + mc.textRenderer.getWidth(name + ": ") + 1, y, Color.CYAN.getRGB(), false); - - */ - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index c28def6..2a2c6f4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -26,21 +26,6 @@ public ListOption(String name, Supplier getter, Consumer setter, List v this.renderer.init(this); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - value = get(); - super.render(drawContext, x, y, mouseX, mouseY); - - // properties.getSkin().getRenderer(ListOption.class).render(drawContext,this,x,y,mouseX,mouseY); -/* - this.height = mc.textRenderer.fontHeight + 1; - this.width = mc.textRenderer.getWidth(name + ": " + value.toString()) + 1; - - drawContext.drawText(mc.textRenderer, Text.of(name + ": "), x, y, Color.WHITE.getRGB(), false); - drawContext.drawText(mc.textRenderer, Text.of(value.toString()), x + mc.textRenderer.getWidth(name + ": ") + 1, y, Color.CYAN.getRGB(), false); -*/ - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index 7d169d4..bf85c19 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -31,22 +31,6 @@ public RunnableOption(String name, boolean defaultValue, Runnable task) { BooleanPool.put(name, defaultValue); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - value = get(); - super.render(drawContext, x, y, mouseX, mouseY); - - //properties.getSkin().getRenderer(RunnableOption.class).render(drawContext,this,x,y,mouseX,mouseY); - - /* - this.height = mc.textRenderer.fontHeight; - this.width = mc.textRenderer.getWidth("Run: " + name); - int color = value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); - - */ - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 6fbc3a8..b9af8e0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -45,12 +45,6 @@ public SubMenuOption(String name, ContextMenu parentMenu) { this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), parentMenu.getProperties().copy()); } - @Override - public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) { - super.render(drawContext, x, y, mouseX, mouseY); - // properties.getSkin().getRenderer(SubMenuOption.class).render(drawContext,this,x,y,mouseX,mouseY); - } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 9936f48..72b59c5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -174,7 +174,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in 1, 1); - option.getColorPicker().render(drawContext, x + option.parentMenu.getFinalWidth() + 7, y - 10); + option.getColorPicker().render(drawContext, x + option.getParentMenu().getFinalWidth() + 7, y - 10); } } @@ -254,7 +254,7 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i } } - public class ClassicListRenderer implements SkinRenderer> { + public static class ClassicListRenderer implements SkinRenderer> { @Override public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { option.setHeight(mc.textRenderer.fontHeight + 1); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java new file mode 100644 index 0000000..b464092 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -0,0 +1,11 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; + +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import net.minecraft.client.gui.DrawContext; + +public class ModernSkin extends Skin{ + @Override + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 64c1ef9..cd15a26 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -74,9 +74,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis } public void createMenu() { - ContextMenuProperties properties = ContextMenuProperties.builder() - .skin(new MinecraftSkin(MinecraftSkin.PanelColor.DARK_PANEL)) - .build(); + ContextMenuProperties properties = ContextMenuProperties.createGenericSimplified(); menu = new ContextMenu(getX(), getY(), properties); menu.getProperties().getSkin().setContextMenu(menu); From 3f93c11d40edec0d388dac3953b372dc21214479 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 22 Oct 2024 23:21:23 +0530 Subject: [PATCH 11/40] Many refactors, renamed files, smoothened MinecraftSkin panel. Added a panel behind color option as well. Added color settings in YACL. --- .../dynamichud/config/GlobalConfig.java | 31 ++++++++++++++++ .../utils/contextmenu/ContextMenu.java | 31 ++++++++-------- .../contextmenuscreen/ContextMenuScreen.java | 1 + .../contextmenu/options/BooleanOption.java | 2 -- .../contextmenu/options/ColorOption.java | 26 +++++++------- .../contextmenu/options/DoubleOption.java | 1 - .../utils/contextmenu/options/EnumOption.java | 3 -- .../utils/contextmenu/options/ListOption.java | 3 -- .../contextmenu/{ => options}/Option.java | 3 +- .../contextmenu/options/RunnableOption.java | 2 -- .../contextmenu/options/SubMenuOption.java | 2 -- .../options/coloroption/AlphaSlider.java | 8 +++++ ...GradientPicker.java => ColorGradient.java} | 35 +++++++++++++++---- .../coloroption/ColorPickerButton.java | 4 ++- .../{GradientSlider.java => HueSlider.java} | 4 +-- ...GradientBox.java => SaturationHueBox.java} | 12 ++++--- .../contextmenu/skinsystem/ClassicSkin.java | 4 +-- .../contextmenu/skinsystem/MinecraftSkin.java | 21 ++++++++--- .../contextmenu/skinsystem/ModernSkin.java | 2 ++ .../utils/contextmenu/skinsystem/Skin.java | 2 +- .../contextmenu/skinsystem/SkinRenderer.java | 2 +- .../dynamichud/widget/Widget.java | 2 +- .../dynamichud/widgets/TextWidget.java | 2 +- 23 files changed, 135 insertions(+), 68 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/{ => options}/Option.java (96%) rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/{ColorGradientPicker.java => ColorGradient.java} (90%) rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/{GradientSlider.java => HueSlider.java} (97%) rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/{GradientBox.java => SaturationHueBox.java} (93%) diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index eedd866..23da97e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -1,17 +1,22 @@ package com.tanishisherewith.dynamichud.config; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; +import dev.isxander.yacl3.api.controller.ColorControllerBuilder; import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder; import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; import dev.isxander.yacl3.config.v2.api.SerialEntry; import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; +import dev.isxander.yacl3.config.v2.impl.autogen.ColorFieldImpl; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import java.awt.*; + public final class GlobalConfig { public static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) .id(Identifier.of("dynamichud", "dynamichud_config")) @@ -37,6 +42,12 @@ public final class GlobalConfig { @SerialEntry private int snapSize = 100; + @SerialEntry + private Color hudActiveColor = new Color(0, 0, 0, 128); + + @SerialEntry + private Color hudInactiveColor = new Color(255, 0, 0, 128); + public static GlobalConfig get() { return INSTANCE; } @@ -75,6 +86,18 @@ public Screen createYACLGUI() { .controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10, 500)) .build()) .build()) + .option(Option.createBuilder() + .name(Text.literal("Widget HUD Active Background Color")) + .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will be rendered"))) + .binding(new Color(0, 0, 0, 128), () -> this.hudActiveColor, newVal -> this.hudActiveColor = newVal) + .controller(ColorControllerBuilder::create) + .build()) + .option(Option.createBuilder() + .name(Text.literal("Widget HUD Inactive Background Color")) + .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered"))) + .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) + .controller(ColorControllerBuilder::create) + .build()) .build()) .save(HANDLER::save) .build() @@ -96,4 +119,12 @@ public boolean shouldDisplayDescriptions() { public int getSnapSize() { return snapSize; } + + public Color getHudInactiveColor() { + return hudInactiveColor; + } + + public Color getHudActiveColor() { + return hudActiveColor; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 529bca9..b56a408 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -5,6 +5,7 @@ import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.math.MathHelper; @@ -19,18 +20,18 @@ public class ContextMenu implements Input { public final Color darkerBackgroundColor; //The properties of a context menu protected final ContextMenuProperties properties; - private final List> options = new ArrayList<>(); // The list of options in the context menu - private final ContextMenuScreenFactory screenFactory; + protected final List> options = new ArrayList<>(); // The list of options in the context menu + protected final ContextMenuScreenFactory screenFactory; public int x, y; // Width is counted while the options are being rendered. // FinalWidth is the width at the end of the count. - private int width = 0; - private int finalWidth = 0; - private int height = 0, widgetHeight = 0; - private boolean shouldDisplay = false; - private float scale = 0.0f; - private Screen parentScreen = null; - private boolean newScreenFlag = false; + protected int width = 0; + protected int finalWidth = 0; + protected int height = 0, widgetHeight = 0; + protected boolean shouldDisplay = false; + protected float scale = 0.0f; + protected Screen parentScreen = null; + protected boolean newScreenFlag = false; public ContextMenu(int x, int y, ContextMenuProperties properties) { this(x, y, properties, new DefaultContextMenuScreenFactory()); @@ -85,16 +86,14 @@ public void update() { } public void close() { - if (properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null) { - shouldDisplay = false; - newScreenFlag = false; - DynamicHUD.MC.setScreen(parentScreen); - } + shouldDisplay = false; + newScreenFlag = false; for (Option option : options) { option.onClose(); } - shouldDisplay = false; - newScreenFlag = false; + if (properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null) { + DynamicHUD.MC.setScreen(parentScreen); + } } public void open() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java index d398086..64c6769 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java @@ -82,5 +82,6 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { @Override public void close() { contextMenu.close(); + contextMenu.setVisible(false); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index 8a548ee..9b68f63 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; import com.tanishisherewith.dynamichud.utils.BooleanPool; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.gui.DrawContext; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 176d067..f7c41fe 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -1,9 +1,7 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorGradientPicker; -import net.minecraft.client.gui.DrawContext; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorGradient; import java.awt.*; import java.util.function.Consumer; @@ -13,13 +11,13 @@ public class ColorOption extends Option { public String name = "Empty"; public boolean isVisible = false; private ContextMenu parentMenu = null; - private ColorGradientPicker colorPicker = null; + private ColorGradient colorGradient = null; public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { super(getter, setter); this.name = name; this.parentMenu = parentMenu; - colorPicker = new ColorGradientPicker(x + this.parentMenu.getFinalWidth(), y - 10, get(), this::set, 50, 100); + colorGradient = new ColorGradient(x + this.parentMenu.getFinalWidth(), y - 10, get(), this::set, 50, 100); this.renderer.init(this); } @@ -28,36 +26,36 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY)) { isVisible = !isVisible; if (isVisible) { - colorPicker.setPos(this.x + parentMenu.getFinalWidth() + 7, y - 10); - colorPicker.display(); + colorGradient.setPos(this.x + parentMenu.getFinalWidth() + 7, y - 10); + colorGradient.display(); } else { - colorPicker.close(); + colorGradient.close(); } } - colorPicker.mouseClicked(mouseX, mouseY, button); + colorGradient.mouseClicked(mouseX, mouseY, button); return super.mouseClicked(mouseX, mouseY, button); } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - colorPicker.mouseReleased(mouseX, mouseY, button); + colorGradient.mouseReleased(mouseX, mouseY, button); return super.mouseReleased(mouseX, mouseY, button); } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - colorPicker.mouseDragged(mouseX, mouseY, button); + colorGradient.mouseDragged(mouseX, mouseY, button); return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } - public ColorGradientPicker getColorPicker() { - return colorPicker; + public ColorGradient getColorGradient() { + return colorGradient; } @Override public void onClose() { isVisible = false; - colorPicker.close(); + colorGradient.close(); } public ContextMenu getParentMenu() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 7297320..8848cf9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -2,7 +2,6 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import org.apache.commons.lang3.Validate; import org.lwjgl.glfw.GLFW; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index dffd127..f2031e5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -1,8 +1,5 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.gui.DrawContext; - import java.util.function.Consumer; import java.util.function.Supplier; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index 2a2c6f4..624ebd9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -1,8 +1,5 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.gui.DrawContext; - import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java index 6ea6c40..1c295b3 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java @@ -1,7 +1,8 @@ -package com.tanishisherewith.dynamichud.utils.contextmenu; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.utils.Input; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.SkinRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index bf85c19..28cac3e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; import com.tanishisherewith.dynamichud.utils.BooleanPool; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.gui.DrawContext; import java.util.function.Consumer; import java.util.function.Supplier; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index b9af8e0..16928c2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -3,8 +3,6 @@ import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; -import net.minecraft.client.gui.DrawContext; import java.util.Objects; import java.util.function.Consumer; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java index c7a8794..c3c5824 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java @@ -63,6 +63,14 @@ public void setX(int x) { this.x = x; } + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java similarity index 90% rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java index 6ec3a7b..2dc749b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java @@ -11,11 +11,11 @@ import java.nio.ByteBuffer; import java.util.function.Consumer; -public class ColorGradientPicker { +public class ColorGradient { final MinecraftClient client = MinecraftClient.getInstance(); private final Consumer onColorSelected; // The callback to call when a color is selected - private final GradientSlider gradientSlider; - private final GradientBox gradientBox; + private final HueSlider gradientSlider; + private final SaturationHueBox gradientBox; private final ColorPickerButton colorPickerButton; private final AlphaSlider alphaSlider; private final int boxSize; @@ -23,13 +23,13 @@ public class ColorGradientPicker { private int x, y; private boolean display = false; - public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { + public ColorGradient(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { this.x = x; this.y = y; this.initialColor = initialColor; this.onColorSelected = onColorSelected; - this.gradientSlider = new GradientSlider(x, y, colors, 10); - this.gradientBox = new GradientBox(x, y + 20, boxSize); + this.gradientSlider = new HueSlider(x, y, colors, 10); + this.gradientBox = new SaturationHueBox(x, y + 20, boxSize); this.alphaSlider = new AlphaSlider(x, y, 10, boxSize, initialColor); float[] hsv = new float[3]; @@ -182,4 +182,27 @@ public void mouseDragged(double mouseX, double mouseY, int button) { onColorSelected.accept(alphaSlider.getColor()); } + public int getBoxSize() { + return boxSize; + } + + public boolean isDisplay() { + return display; + } + + public ColorPickerButton getColorPickerButton() { + return colorPickerButton; + } + + public AlphaSlider getAlphaSlider() { + return alphaSlider; + } + + public HueSlider getGradientSlider() { + return gradientSlider; + } + + public SaturationHueBox getGradientBox() { + return gradientBox; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java index 967bb14..aa04521 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -33,7 +33,9 @@ public void render(DrawContext drawContext, int x, int y) { public int getHeight() { return height; } - + public int getWidth() { + return width; + } public boolean onClick(double mouseX, double mouseY, int button) { if (button == 0) { if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java similarity index 97% rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java index 39f1ff7..d3cd0ba 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java @@ -5,7 +5,7 @@ import java.awt.*; -public class GradientSlider { +public class HueSlider { private final int width; private final int height; private int x; @@ -13,7 +13,7 @@ public class GradientSlider { private float hue = 0.0f; private boolean isDragging = false; - public GradientSlider(int x, int y, int width, int height) { + public HueSlider(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java similarity index 93% rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java index 49d7699..2332557 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java @@ -5,7 +5,7 @@ import java.awt.*; -public class GradientBox { +public class SaturationHueBox { private final int size; private int x; private int y; @@ -15,7 +15,7 @@ public class GradientBox { private boolean isDragging = false; - public GradientBox(int x, int y, int size) { + public SaturationHueBox(int x, int y, int size) { this.x = x; this.y = y; this.size = size; @@ -31,11 +31,11 @@ public void render(DrawContext drawContext, int x, int y) { DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size, 2); // Draw the handle - float handleSize = 3; + float handleSize = 1f; float handleX = x + 2 + saturation * size - handleSize / 2.0f; float handleY = y + 2 + (1.0f - value) * size - handleSize / 2.0f; - DrawHelper.drawFilledCircle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, 1, -1); + DrawHelper.drawFilledCircle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, handleSize, -1); drawContext.getMatrices().pop(); } @@ -104,4 +104,8 @@ public void setValue(float value) { public int getColor() { return Color.HSBtoRGB(hue, saturation, value); } + + public int getSize() { + return size; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 72b59c5..d810e29 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -3,7 +3,7 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -174,7 +174,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in 1, 1); - option.getColorPicker().render(drawContext, x + option.getParentMenu().getFinalWidth() + 7, y - 10); + option.getColorGradient().render(drawContext, x + option.getParentMenu().getFinalWidth() + 7, y - 10); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index bbd7a33..12c9d6e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -3,7 +3,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -86,7 +86,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); panelColor.applyColor(); - drawContext.drawTexture(BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight); + drawContext.drawTexture(BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight, 256, 254); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); drawContext.drawGuiTexture(TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14); drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true); @@ -251,11 +251,10 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, Text text = option.getBooleanType().getText(option.value); int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); drawContext.drawText(mc.textRenderer, text, (int) (option.getX() + (width / 2.0f) - (mc.textRenderer.getWidth(text) / 2.0f)), y + 5, color, true); - //drawContext.drawTexture(BOOLEAN_TEXTURE); option.setHeight(25); - //Widths dont matter in this skin + //Widths don't matter in this skin option.setWidth(width); } @@ -296,7 +295,19 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in option.setHeight(25); option.setWidth(width); - option.getColorPicker().render(drawContext, x + panelWidth + 10, y - 10); + DrawHelper.disableScissor(); // Disable scissor test for the color-picker + if(option.getColorGradient().isDisplay()) { + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + panelColor.applyColor(); + int colorGradientWidth = 28 + option.getColorGradient().getBoxSize() + option.getColorGradient().getAlphaSlider().getWidth() + option.getColorGradient().getColorPickerButton().getWidth(); + int colorGradientHeight = 18 + option.getColorGradient().getBoxSize() + option.getColorGradient().getGradientBox().getSize() + option.getColorGradient().getGradientSlider().getHeight(); + drawContext.drawTexture(BACKGROUND_PANEL, x + panelWidth + 3, y - 6, 0, 0, colorGradientWidth,colorGradientHeight, colorGradientWidth, colorGradientHeight); + RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); + } + option.getColorGradient().render(drawContext, x + panelWidth + 10, y - 10); + + DrawHelper.enableScissor(imageX, imageY + 2, panelWidth, panelHeight - 4); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index b464092..0792408 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -3,6 +3,8 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import net.minecraft.client.gui.DrawContext; + +//TODO: Complete this public class ModernSkin extends Skin{ @Override public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java index 867c949..fd4dbc7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java @@ -1,7 +1,7 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import net.minecraft.client.gui.DrawContext; import java.util.HashMap; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java index a19887c..bf03311 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/SkinRenderer.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem; -import com.tanishisherewith.dynamichud.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import net.minecraft.client.gui.DrawContext; public interface SkinRenderer> { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index ab3821a..a8a6a83 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -286,7 +286,7 @@ public void onClose() { * Drawn with 2 pixel offset to all sides */ protected void displayBg(DrawContext context) { - int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); + int backgroundColor = this.shouldDisplay() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB(); WidgetBox box = this.getWidgetBox(); DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), box.x, diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index cd15a26..7fd5f8d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -74,7 +74,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis } public void createMenu() { - ContextMenuProperties properties = ContextMenuProperties.createGenericSimplified(); + ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(MinecraftSkin.PanelColor.COFFEE_BROWN)).build(); menu = new ContextMenu(getX(), getY(), properties); menu.getProperties().getSkin().setContextMenu(menu); From 09cdc787ad4c98c9d36ba214ca4aa090591ed86c Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Fri, 25 Oct 2024 22:25:32 +0530 Subject: [PATCH 12/40] More changes to ModernSkin, OptionalGroups changes, some refactors and interface folder. --- .../dynamichud/DynamicHUD.java | 2 +- .../dynamichud/config/GlobalConfig.java | 13 +- .../dynamichud/helpers/DrawHelper.java | 19 + .../utils/contextmenu/ContextMenu.java | 38 +- .../contextmenu/ContextMenuProperties.java | 2 +- .../contextmenu/layout/LayoutContext.java | 83 +++ .../contextmenu/options/BooleanOption.java | 4 +- .../contextmenu/options/ColorOption.java | 8 +- .../contextmenu/options/DoubleOption.java | 22 +- .../utils/contextmenu/options/EnumOption.java | 4 +- .../utils/contextmenu/options/ListOption.java | 4 +- .../utils/contextmenu/options/Option.java | 47 +- .../contextmenu/options/OptionGroup.java | 114 +++ .../contextmenu/options/RunnableOption.java | 3 +- .../contextmenu/options/SubMenuOption.java | 6 +- .../options/coloroption/ColorGradient.java | 2 - .../contextmenu/skinsystem/ClassicSkin.java | 37 +- .../contextmenu/skinsystem/MinecraftSkin.java | 32 +- .../contextmenu/skinsystem/ModernSkin.java | 666 +++++++++++++++++- .../utils/contextmenu/skinsystem/Skin.java | 56 +- .../skinsystem/interfaces/GroupableSkin.java | 11 + .../{ => interfaces}/SkinRenderer.java | 11 +- .../dynamichud/widgets/ItemWidget.java | 8 +- .../dynamichud/widgets/TextWidget.java | 42 +- 24 files changed, 1095 insertions(+), 139 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/{ => interfaces}/SkinRenderer.java (71%) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 45cc39a..6790c1b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -86,7 +86,7 @@ public void checkToEnableTestIntegration(){ @Override public void onInitializeClient() { - printInfo("Initialising DynamicHud"); + printInfo("Initialising DynamicHUD"); // Add WidgetData of included widgets WidgetManager.registerCustomWidgets( diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index 23da97e..d67ae80 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -16,6 +16,7 @@ import net.minecraft.util.Identifier; import java.awt.*; +import java.util.LinkedList; public final class GlobalConfig { public static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) @@ -28,7 +29,7 @@ public final class GlobalConfig { private static final GlobalConfig INSTANCE = new GlobalConfig(); /** - * Common scale for all widgets. Set by the user using YACL. + * Common scale for all widgets. */ @SerialEntry private float scale = 1.0f; @@ -92,11 +93,11 @@ public Screen createYACLGUI() { .binding(new Color(0, 0, 0, 128), () -> this.hudActiveColor, newVal -> this.hudActiveColor = newVal) .controller(ColorControllerBuilder::create) .build()) - .option(Option.createBuilder() - .name(Text.literal("Widget HUD Inactive Background Color")) - .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered"))) - .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) - .controller(ColorControllerBuilder::create) + .option(Option.createBuilder() + .name(Text.literal("Widget HUD Inactive Background Color")) + .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered"))) + .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) + .controller(ColorControllerBuilder::create) .build()) .build()) .save(HANDLER::save) diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index bab2136..d59ac29 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.systems.VertexSorter; import com.tanishisherewith.dynamichud.DynamicHUD; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.*; @@ -12,10 +13,13 @@ import java.awt.*; +import static com.tanishisherewith.dynamichud.helpers.TextureHelper.mc; + /** * Credits: HeliosClient */ public class DrawHelper { + public static VertexSorter vertexSorter; /** * Draws a singular gradient rectangle on screen with the given parameters @@ -792,6 +796,21 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int drawContext.fill(x2 - 1, y1 + 1, x2, y2 - 1, color); } + public static void unscaledProjection() { + vertexSorter = RenderSystem.getVertexSorting(); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth(), mc.getWindow().getFramebufferHeight(), 0, 1000, 21000), VertexSorter.BY_Z); + } + + public static void scaledProjection() { + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), vertexSorter); + } + + public static void customScaledProjection(float scale) { + vertexSorter = RenderSystem.getVertexSorting(); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), VertexSorter.BY_Z); + } + + /** * This method assumes that the x, y coords are the origin of a widget. * diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index b56a408..c47d690 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -16,7 +16,6 @@ import java.util.List; public class ContextMenu implements Input { - public final Color darkerBackgroundColor; //The properties of a context menu protected final ContextMenuProperties properties; @@ -26,7 +25,6 @@ public class ContextMenu implements Input { // Width is counted while the options are being rendered. // FinalWidth is the width at the end of the count. protected int width = 0; - protected int finalWidth = 0; protected int height = 0, widgetHeight = 0; protected boolean shouldDisplay = false; protected float scale = 0.0f; @@ -116,8 +114,8 @@ public void toggleDisplay() { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!shouldDisplay) return false; - for (Option option : options) { - option.mouseClicked(mouseX, mouseY, button); + for (Option option : options) { + option.getRenderer().mouseClicked(option, mouseX, mouseY, button); } return properties.getSkin().mouseClicked(this, mouseX, mouseY, button); } @@ -125,8 +123,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { if (!shouldDisplay) return false; - for (Option option : options) { - option.mouseReleased(mouseX, mouseY, button); + for (Option option : options) { + option.getRenderer().mouseReleased(option,mouseX, mouseY, button); } return properties.getSkin().mouseReleased(this, mouseX, mouseY, button); } @@ -134,8 +132,8 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { if (!shouldDisplay) return false; - for (Option option : options) { - option.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + for (Option option : options) { + option.getRenderer().mouseDragged(option,mouseX, mouseY, button, deltaX, deltaY); } return properties.getSkin().mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY); } @@ -143,8 +141,8 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del @Override public void keyPressed(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; - for (Option option : options) { - option.keyPressed(key, scanCode, modifiers); + for (Option option : options) { + option.getRenderer().keyPressed(option,key, scanCode, modifiers); } properties.getSkin().keyPressed(this, key, scanCode, modifiers); @@ -153,8 +151,8 @@ public void keyPressed(int key, int scanCode, int modifiers) { @Override public void keyReleased(int key, int scanCode, int modifiers) { if (!shouldDisplay) return; - for (Option option : options) { - option.keyReleased(key, scanCode, modifiers); + for (Option option : options) { + option.getRenderer().keyReleased(option,key, scanCode, modifiers); } properties.getSkin().keyReleased(this, key, scanCode, modifiers); @@ -162,15 +160,17 @@ public void keyReleased(int key, int scanCode, int modifiers) { @Override public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - for (Option option : options) { - option.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + for (Option option : options) { + option.getRenderer().mouseScrolled(option,mouseX, mouseY, horizontalAmount, verticalAmount); } properties.getSkin().mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount); } @Override public void charTyped(char c) { - + for (Option option : options) { + option.charTyped(c); + } } public void set(int x, int y, int widgetHeight) { @@ -199,14 +199,6 @@ public void setHeight(int height) { this.height = height; } - public int getFinalWidth() { - return finalWidth; - } - - public void setFinalWidth(int finalWidth) { - this.finalWidth = finalWidth; - } - public int getWidth() { return width; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java index 84538b6..85a8657 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -14,7 +14,7 @@ public class ContextMenuProperties { private int padding = 5; // The amount of padding around the rectangle private int heightOffset = 4; // Height offset from the widget private boolean drawBorder = true; - private boolean shadow = false; + private boolean shadow = true; private boolean roundedCorners = true; private int cornerRadius = 3; private boolean hoverEffect = true; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java new file mode 100644 index 0000000..62e3f0c --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java @@ -0,0 +1,83 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.layout; + +import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; + +public class LayoutContext { + private final Offset indent; + private final Option parentOption; + + public LayoutContext() { + this(Offset.zero(), null); + } + + public LayoutContext(Offset margin, Option parentOption) { + this.indent = margin; + this.parentOption = parentOption; + } + + public Offset getIndent() { + return indent; + } + + public Option getParentOption() { + return parentOption; + } + + // Builder-style methods for creating new contexts + public LayoutContext withIndent(Offset indent) { + return new LayoutContext(indent, this.parentOption); + } + + public LayoutContext withParent(Option parent) { + return new LayoutContext(this.indent, parent); + } + + public LayoutContext addIndent(Offset additionalIndent) { + return new LayoutContext( + this.indent.add(additionalIndent), + this.parentOption + ); + } + + // Utility methods for calculating positions + public int getEffectiveX(int baseX) { + return baseX + indent.left; + } + + public int getEffectiveY(int baseY) { + return baseY + indent.top; + } + + public int getEffectiveWidth(int baseWidth) { + return baseWidth + indent.left; + } + + public int getEffectiveHeight(int baseHeight) { + return baseHeight + indent.top; + } + + public static class Offset { + public final int left; + public final int top; + + public Offset(int all) { + this(all, all); + } + + public Offset(int horizontal, int vertical) { + this.left = horizontal; + this.top = vertical; + } + + public static Offset zero() { + return new Offset(0); + } + + public Offset add(Offset other) { + return new Offset( + this.left + other.left, + this.top + other.top + ); + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index 9b68f63..ee382a7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -10,12 +10,10 @@ import java.util.function.Supplier; public class BooleanOption extends Option { - public String name = "Empty"; private final BooleanType booleanType; public BooleanOption(String name, Supplier getter, Consumer setter, BooleanType booleanType) { - super(getter, setter); - this.name = name; + super(name,getter, setter); this.booleanType = booleanType; this.renderer.init(this); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index f7c41fe..41a932d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -8,16 +8,14 @@ import java.util.function.Supplier; public class ColorOption extends Option { - public String name = "Empty"; public boolean isVisible = false; private ContextMenu parentMenu = null; private ColorGradient colorGradient = null; public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { - super(getter, setter); - this.name = name; + super(name,getter, setter); this.parentMenu = parentMenu; - colorGradient = new ColorGradient(x + this.parentMenu.getFinalWidth(), y - 10, get(), this::set, 50, 100); + colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); this.renderer.init(this); } @@ -26,7 +24,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY)) { isVisible = !isVisible; if (isVisible) { - colorGradient.setPos(this.x + parentMenu.getFinalWidth() + 7, y - 10); + colorGradient.setPos(this.x + parentMenu.getWidth() + 7, y - 10); colorGradient.display(); } else { colorGradient.close(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 8848cf9..0e470a1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -11,16 +11,14 @@ import java.util.function.Supplier; public class DoubleOption extends Option { - public String name = "Empty"; public double minValue = 0.0; public double maxValue = 0.0; - float step = 0.1f; + public float step = 0.1f; ContextMenu parentMenu; private boolean isDragging = false; public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { - super(getter, setter); - this.name = name; + super(name,getter, setter); this.value = get(); this.minValue = minValue; this.maxValue = maxValue; @@ -54,13 +52,19 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { return super.mouseReleased(mouseX, mouseY, button); } - public void step(double mouseX) { + private void step(double mouseX) { + this.step(mouseX,x); + } + + public void step(double mouseX,double x) { double newValue = minValue + (float) (mouseX - x) / width * (maxValue - minValue); // Round the new value to the nearest step newValue = Math.round(newValue / step) * step; + newValue = Math.clamp(newValue,minValue,maxValue); set(newValue); } + @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { if (isMouseOver(mouseX, mouseY) && isDragging) { @@ -68,4 +72,12 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del } return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } + + public void setDragging(boolean dragging) { + isDragging = dragging; + } + + public boolean isDragging() { + return isDragging; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index f2031e5..f28db96 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -5,12 +5,10 @@ public class EnumOption> extends Option { private final E[] values; - public String name = "Empty"; private int currentIndex = 0; public EnumOption(String name, Supplier getter, Consumer setter, E[] values) { - super(getter, setter); - this.name = name; + super(name,getter, setter); this.values = values; this.value = get(); for (int i = 0; i < values.length; i++) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index 624ebd9..5622356 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -6,12 +6,10 @@ public class ListOption extends Option { private final List values; - public String name = "Empty"; private int currentIndex = 0; public ListOption(String name, Supplier getter, Consumer setter, List values) { - super(getter, setter); - this.name = name; + super(name,getter, setter); this.values = values; this.value = getter.get(); for (int i = 0; i < values.size(); i++) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java index 1c295b3..5273ec6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java @@ -3,7 +3,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; -import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.SkinRenderer; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -11,6 +11,7 @@ import java.util.function.Supplier; public abstract class Option implements Input { + public String name = "Empty", description = ""; public T value = null; protected int x, y; protected int width = 0; @@ -23,11 +24,12 @@ public abstract class Option implements Input { protected ContextMenuProperties properties; protected SkinRenderer> renderer; - public Option(Supplier getter, Consumer setter) { - this(getter, setter, () -> true); + public Option(String name,Supplier getter, Consumer setter) { + this(name,getter, setter, () -> true); } - public Option(Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) { + public Option(String name,Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) { + this.name = name; this.getter = getter; this.setter = setter; this.shouldRender = shouldRender; @@ -36,8 +38,8 @@ public Option(Supplier getter, Consumer setter, Supplier shouldRe updateProperties(properties); } - public Option(Supplier getter, Consumer setter, Supplier shouldRender) { - this(getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified()); + public Option(String name,Supplier getter, Consumer setter, Supplier shouldRender) { + this(name,getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified()); } public T get() { @@ -68,41 +70,32 @@ public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY } public boolean mouseClicked(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY) || renderer.mouseClicked(this, mouseX, mouseY, button); + return isMouseOver(mouseX, mouseY); } public boolean mouseReleased(double mouseX, double mouseY, int button) { - return isMouseOver(mouseX, mouseY) || renderer.mouseReleased(this, mouseX, mouseY, button); + return isMouseOver(mouseX, mouseY); } public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - return isMouseOver(mouseX, mouseY) || renderer.mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY); + return isMouseOver(mouseX, mouseY); } - public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - renderer.mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount); - } + public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {} @Override - public void keyPressed(int key, int scanCode, int modifiers) { - renderer.keyPressed(this, key, scanCode, modifiers); - } + public void keyPressed(int key, int scanCode, int modifiers) {} @Override - public void charTyped(char c) { - - } + public void charTyped(char c) {} @Override - public void keyReleased(int key, int scanCode, int modifiers) { - renderer.keyReleased(this, key, scanCode, modifiers); - } + public void keyReleased(int key, int scanCode, int modifiers) {} /** * Called when the context menu closes */ - public void onClose() { - } + public void onClose() {} public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; @@ -157,4 +150,12 @@ public void set(int x, int y) { this.x = x; this.y = y; } + public Option description(String description){ + this.description = description; + return this; + } + + public SkinRenderer> getRenderer() { + return renderer; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java new file mode 100644 index 0000000..36a0b75 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java @@ -0,0 +1,114 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer; +import net.minecraft.client.gui.DrawContext; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +// A group is just another type of Option that contains other options +public class OptionGroup extends Option { + private final List

* - * @param context + * @param context DrawContext Object * @param mouseX X position of mouse. * @param mouseY Y position of mouse */ @@ -206,7 +201,7 @@ public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY * Could also be used to display placeholder values. */ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { - //displayBg(context); + //drawWidgetBackground(context); renderWidget(context, mouseX, mouseY); } @@ -224,7 +219,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return false; } - /* Input related methods. Override with super call to add your own input-based code like contextMenu */ + /* Input related methods. Override with **super call** to add your own input-based code like contextMenu */ public void clampPosition() { this.x = (int) MathHelper.clamp(this.x, 0, mc.getWindow().getScaledWidth() - getWidth()); @@ -285,9 +280,10 @@ public void onClose() { * Displays a faint grayish background if enabled or faint reddish background if disabled. * Drawn with 2 pixel offset to all sides */ - protected void displayBg(DrawContext context) { + protected void drawWidgetBackground(DrawContext context) { int backgroundColor = this.shouldDisplay() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB(); WidgetBox box = this.getWidgetBox(); + DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), box.x, box.y, From 7dbfb307e898b9d61dcb1bdbafbee6d22402e93f Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 8 Feb 2025 00:03:03 +0530 Subject: [PATCH 18/40] Some improvements to the code-base --- .gitignore | 2 + .../dynamichud/DynamicHUD.java | 4 - .../utils/contextmenu/ContextMenu.java | 35 ++++- .../utils/contextmenu/ContextMenuManager.java | 16 +-- .../contextmenu/ContextMenuProperties.java | 130 ++++++++---------- .../contextmenu/ContextMenuProvider.java | 2 +- .../contextmenuscreen/ContextMenuScreen.java | 4 +- .../ContextMenuScreenFactory.java | 2 +- .../DefaultContextMenuScreenFactory.java | 2 +- .../contextmenu/options/BooleanOption.java | 2 +- .../contextmenu/options/ColorOption.java | 6 +- .../contextmenu/options/DoubleOption.java | 4 +- .../contextmenu/options/SubMenuOption.java | 26 ++-- .../contextmenu/skinsystem/ClassicSkin.java | 10 +- .../contextmenu/skinsystem/MinecraftSkin.java | 10 +- .../contextmenu/skinsystem/ModernSkin.java | 12 +- .../utils/contextmenu/skinsystem/Skin.java | 24 ++-- .../utils/handlers/ScrollHandler.java | 19 ++- .../dynamichud/widgets/TextWidget.java | 6 +- 19 files changed, 166 insertions(+), 150 deletions(-) diff --git a/.gitignore b/.gitignore index 3c37caf..12044e6 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,5 @@ run/ # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar + +*.profileconfig.json diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 9d53d65..6790c1b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -21,10 +21,6 @@ import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.RenderLayers; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.util.BufferAllocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 79f6f0b..88294c6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -9,16 +9,20 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; -public class ContextMenu implements Input { +public class ContextMenu implements Input { public final Color darkerBackgroundColor; //The properties of a context menu - protected final ContextMenuProperties properties; + @NotNull + protected final T properties; protected final List> options = new ArrayList<>(); // The list of options in the context menu protected final ContextMenuScreenFactory screenFactory; public int x, y; @@ -31,16 +35,26 @@ public class ContextMenu implements Input { protected Screen parentScreen = null; protected boolean newScreenFlag = false; - public ContextMenu(int x, int y, ContextMenuProperties properties) { + @Nullable + private final ContextMenu parentMenu; + + public ContextMenu(int x, int y, T properties) { this(x, y, properties, new DefaultContextMenuScreenFactory()); } - public ContextMenu(int x, int y, ContextMenuProperties properties, ContextMenuScreenFactory screenFactory) { + public ContextMenu(int x, int y, T properties, ContextMenuScreenFactory screenFactory) { + this(x, y, properties, screenFactory,null); + } + public ContextMenu(int x, int y, @NotNull T properties, ContextMenuScreenFactory screenFactory, @Nullable ContextMenu parentMenu) { + Objects.requireNonNull(screenFactory, "ContextMenuScreenFactory cannot be null!"); + Objects.requireNonNull(properties, "ContextMenu Properties cannot be null!"); + this.x = x; this.y = y + properties.getHeightOffset(); this.properties = properties; this.screenFactory = screenFactory; this.darkerBackgroundColor = properties.getBackgroundColor().darker().darker().darker().darker().darker().darker(); + this.parentMenu = parentMenu; this.properties.getSkin().setContextMenu(this); } @@ -161,6 +175,7 @@ public void keyReleased(int key, int scanCode, int modifiers) { @Override public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + if (!shouldDisplay) return; for (Option option : options) { option.getRenderer().mouseScrolled(option,mouseX, mouseY, horizontalAmount, verticalAmount); } @@ -169,6 +184,7 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, @Override public void charTyped(char c) { + if (!shouldDisplay) return; for (Option option : options) { option.charTyped(c); } @@ -208,7 +224,7 @@ public void setWidth(int width) { this.width = width; } - public ContextMenuProperties getProperties() { + public @NotNull T getProperties() { return properties; } @@ -216,6 +232,15 @@ public void setWidgetHeight(int widgetHeight) { this.widgetHeight = widgetHeight; } + @Nullable + public ContextMenu getParentMenu() { + return parentMenu; + } + + public ContextMenu createSubMenu(int x, int y, K properties){ + return new ContextMenu<>(x,y,properties, screenFactory,this); + } + public float getScale() { return scale; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java index 4a51440..4aa8ae9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java @@ -22,7 +22,7 @@ public void registerProvider(ContextMenuProvider provider) { public void renderAll(DrawContext drawContext, int mouseX, int mouseY) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.render(drawContext, contextMenu.getX(), contextMenu.getY(), mouseX, mouseY); } @@ -38,7 +38,7 @@ public void onClose() { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseClicked(mouseX, mouseY, button); } @@ -49,7 +49,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseReleased(mouseX, mouseY, button); } @@ -60,7 +60,7 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } @@ -71,7 +71,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del @Override public void keyPressed(int key, int scanCode, int modifiers) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.keyPressed(key, scanCode, modifiers); } @@ -81,7 +81,7 @@ public void keyPressed(int key, int scanCode, int modifiers) { @Override public void keyReleased(int key, int scanCode, int modifiers) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.keyReleased(key, scanCode, modifiers); } @@ -91,7 +91,7 @@ public void keyReleased(int key, int scanCode, int modifiers) { @Override public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @@ -101,7 +101,7 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, @Override public void charTyped(char c) { for (ContextMenuProvider provider : providers) { - ContextMenu contextMenu = provider.getContextMenu(); + ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { contextMenu.charTyped(c); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java index 7199709..43989b1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java @@ -4,29 +4,29 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin; import java.awt.*; -import java.lang.reflect.InvocationTargetException; +/** + * Note: Not all of these properties are used in all skins or all places. + */ public class ContextMenuProperties { - //Note: Not all of these properties are used in all skins or all places. - - private Color backgroundColor = new Color(107, 112, 126, 124); - private Color borderColor = Color.BLACK; - private float borderWidth = 1f; - private int padding = 5; // The amount of padding around the rectangle - private int heightOffset = 4; // Height offset from the widget - private boolean drawBorder = true; - private boolean shadow = true; - private boolean roundedCorners = true; - private int cornerRadius = 3; - private boolean hoverEffect = true; - private Color hoverColor = new Color(42, 42, 42, 150); - private boolean enableAnimations = true; - private Skin skin = new ClassicSkin(); - - private ContextMenuProperties() {} - - public static Builder builder() { - return new ContextMenuProperties().new Builder(); + protected Color backgroundColor = new Color(107, 112, 126, 124); + protected Color borderColor = Color.BLACK; + protected float borderWidth = 1f; + protected int padding = 5; // The amount of padding around the rectangle + protected int heightOffset = 4; // Height offset from the widget + protected boolean drawBorder = true; + protected boolean shadow = true; + protected boolean roundedCorners = true; + protected int cornerRadius = 3; + protected boolean hoverEffect = true; + protected Color hoverColor = new Color(42, 42, 42, 150); + protected boolean enableAnimations = true; + protected Skin skin = new ClassicSkin(); + + protected ContextMenuProperties() {} + + public static Builder builder() { + return new Builder<>(new ContextMenuProperties()); } public static ContextMenuProperties createGenericSimplified() { @@ -90,24 +90,10 @@ public Skin getSkin() { return skin; } - public ContextMenuProperties copy() { - return ContextMenuProperties.builder() - .backgroundColor(backgroundColor) - .borderColor(borderColor) - .borderWidth(borderWidth) - .padding(padding) - .heightOffset(heightOffset) - .drawBorder(drawBorder) - .shadow(shadow) - .roundedCorners(roundedCorners) - .cornerRadius(cornerRadius) - .hoverEffect(hoverEffect) - .hoverColor(hoverColor) - .skin(skin) - .enableAnimations(enableAnimations) - .build(); + public ContextMenuProperties clone() { + return cloneToBuilder().build(); } - public Builder copyAsBuilder() { + public Builder cloneToBuilder() { return ContextMenuProperties.builder() .backgroundColor(backgroundColor) .borderColor(borderColor) @@ -120,86 +106,88 @@ public Builder copyAsBuilder() { .cornerRadius(cornerRadius) .hoverEffect(hoverEffect) .hoverColor(hoverColor) - .skin(skin) .enableAnimations(enableAnimations); } - public ContextMenuProperties copyNewSkin() { - return this.copyAsBuilder() + public ContextMenuProperties cloneWithSkin() { + return this.cloneToBuilder() .skin(skin) .build(); } - public class Builder { - private Builder() { + public static class Builder { + protected final T properties; + + protected Builder(T properties) { + this.properties = properties; } - public Builder backgroundColor(Color backgroundColor) { - ContextMenuProperties.this.backgroundColor = backgroundColor; + public Builder backgroundColor(Color backgroundColor) { + properties.backgroundColor = backgroundColor; return this; } - public Builder borderColor(Color borderColor) { - ContextMenuProperties.this.borderColor = borderColor; + public Builder borderColor(Color borderColor) { + properties.borderColor = borderColor; return this; } - public Builder skin(Skin skin) { - ContextMenuProperties.this.skin = skin; + public Builder skin(Skin skin) { + properties.skin = skin; return this; } - public Builder borderWidth(float borderWidth) { - ContextMenuProperties.this.borderWidth = borderWidth; + public Builder borderWidth(float borderWidth) { + properties.borderWidth = borderWidth; return this; } - public Builder padding(int padding) { - ContextMenuProperties.this.padding = padding; + public Builder padding(int padding) { + properties.padding = padding; return this; } - public Builder heightOffset(int heightOffset) { - ContextMenuProperties.this.heightOffset = heightOffset; + public Builder heightOffset(int heightOffset) { + properties.heightOffset = heightOffset; return this; } - public Builder drawBorder(boolean drawBorder) { - ContextMenuProperties.this.drawBorder = drawBorder; + public Builder drawBorder(boolean drawBorder) { + properties.drawBorder = drawBorder; return this; } - public Builder shadow(boolean shadow) { - ContextMenuProperties.this.shadow = shadow; + public Builder shadow(boolean shadow) { + properties.shadow = shadow; return this; } - public Builder roundedCorners(boolean roundedCorners) { - ContextMenuProperties.this.roundedCorners = roundedCorners; + public Builder roundedCorners(boolean roundedCorners) { + properties.roundedCorners = roundedCorners; return this; } - public Builder cornerRadius(int cornerRadius) { - ContextMenuProperties.this.cornerRadius = cornerRadius; + public Builder cornerRadius(int cornerRadius) { + properties.cornerRadius = cornerRadius; return this; } - public Builder hoverEffect(boolean hoverEffect) { - ContextMenuProperties.this.hoverEffect = hoverEffect; + public Builder hoverEffect(boolean hoverEffect) { + properties.hoverEffect = hoverEffect; return this; } - public Builder hoverColor(Color hoverColor) { - ContextMenuProperties.this.hoverColor = hoverColor; + public Builder hoverColor(Color hoverColor) { + properties.hoverColor = hoverColor; return this; } - public Builder enableAnimations(boolean enableAnimations) { - ContextMenuProperties.this.enableAnimations = enableAnimations; + public Builder enableAnimations(boolean enableAnimations) { + properties.enableAnimations = enableAnimations; return this; } - public ContextMenuProperties build() { - return ContextMenuProperties.this; + public T build() { + return properties; } } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java index 0541de5..995f2c4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProvider.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.utils.contextmenu; public interface ContextMenuProvider { - ContextMenu getContextMenu(); + ContextMenu getContextMenu(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java index 64c6769..1ccfce4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java @@ -8,10 +8,10 @@ import net.minecraft.text.Text; public class ContextMenuScreen extends Screen { - ContextMenu contextMenu; + ContextMenu contextMenu; ContextMenuProperties properties; - protected ContextMenuScreen(ContextMenu menu, ContextMenuProperties properties) { + protected ContextMenuScreen(ContextMenu menu, ContextMenuProperties properties) { super(Text.of("ContextMenu screen")); this.contextMenu = menu; this.properties = properties; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java index 9475b76..6dea3ec 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java @@ -10,5 +10,5 @@ * This can also be used for developers to provide a new custom screen by them or for a custom skin. */ public interface ContextMenuScreenFactory { - Screen create(ContextMenu contextMenu, ContextMenuProperties properties); + Screen create(ContextMenu contextMenu, ContextMenuProperties properties); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java index 90bd220..b156347 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java @@ -9,7 +9,7 @@ */ public class DefaultContextMenuScreenFactory implements ContextMenuScreenFactory { @Override - public Screen create(ContextMenu contextMenu, ContextMenuProperties properties) { + public Screen create(ContextMenu contextMenu, ContextMenuProperties properties) { return new ContextMenuScreen(contextMenu, properties); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index ee382a7..93ff89c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -34,7 +34,7 @@ public BooleanOption(String name, boolean defaultValue, BooleanType type) { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { - value = !value; + this.value = !this.value; set(value); return true; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 41a932d..bb4d1cb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -9,10 +9,10 @@ public class ColorOption extends Option { public boolean isVisible = false; - private ContextMenu parentMenu = null; + private ContextMenu parentMenu = null; private ColorGradient colorGradient = null; - public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { super(name,getter, setter); this.parentMenu = parentMenu; colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); @@ -56,7 +56,7 @@ public void onClose() { colorGradient.close(); } - public ContextMenu getParentMenu() { + public ContextMenu getParentMenu() { return parentMenu; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 0e470a1..2b69574 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -14,10 +14,10 @@ public class DoubleOption extends Option { public double minValue = 0.0; public double maxValue = 0.0; public float step = 0.1f; - ContextMenu parentMenu; + ContextMenu parentMenu; private boolean isDragging = false; - public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { + public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { super(name,getter, setter); this.value = get(); this.minValue = minValue; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 0d7008c..aed4a94 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -16,29 +16,27 @@ * The {@link #setter} returns a boolean value depending on if the subMenu is visible or not */ public class SubMenuOption extends Option { - private final ContextMenu subMenu; - private final ContextMenu parentMenu; + private final ContextMenu subMenu; - public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter, ContextMenuProperties properties) { + public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter, T properties) { super(name,getter, setter); - Objects.requireNonNull(parentMenu, "Parent Context Menu cannot be null in " + name + " SubMenu option"); - this.parentMenu = parentMenu; - this.subMenu = new ContextMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties); + Objects.requireNonNull(parentMenu, "Parent Context Menu cannot be null in [" + name + "] SubMenu option"); + this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties); this.subMenu.getProperties().setHeightOffset(0); this.subMenu.setVisible(get()); this.renderer.init(this); } - public SubMenuOption(String name, ContextMenu parentMenu, ContextMenuProperties properties) { + public SubMenuOption(String name, ContextMenu parentMenu, T properties) { this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), properties); } - public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { - this(name, parentMenu, getter, setter, parentMenu.getProperties().copyNewSkin()); + public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + this(name, parentMenu, getter, setter, parentMenu.getProperties().cloneWithSkin()); } - public SubMenuOption(String name, ContextMenu parentMenu) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), parentMenu.getProperties().copyNewSkin()); + public SubMenuOption(String name, ContextMenu parentMenu) { + this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), parentMenu.getProperties().cloneWithSkin()); } @Override @@ -68,11 +66,11 @@ public SubMenuOption getOption() { return this; } - public ContextMenu getSubMenu() { + public ContextMenu getSubMenu() { return subMenu; } - public ContextMenu getParentMenu() { - return parentMenu; + public ContextMenu getParentMenu() { + return subMenu.getParentMenu(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 8daf560..26f5710 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -33,7 +33,7 @@ public ClassicSkin() { } @Override - public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { this.contextMenu = contextMenu; MatrixStack matrices = drawContext.getMatrices(); @@ -65,12 +65,13 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, } } - private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { + private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { drawBackground(matrices, contextMenu, properties, contextMenu.y, contextMenu.getWidth(), contextMenu.getHeight(), properties.getBackgroundColor().getRGB(), properties.shadow()); } - private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset, int width, int height, int color, boolean shadow) { + private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties, int yOffset, int width, int height, int color, boolean shadow) { if (properties.roundedCorners()) { + // Rounded if (shadow) { DrawHelper.drawRoundedRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), contextMenu.x, @@ -94,6 +95,7 @@ private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, Conte ); } } else { + // Normal if (shadow) { DrawHelper.drawRectangleWithShadowBadWay(matrices.peek().getPositionMatrix(), contextMenu.x, @@ -117,7 +119,7 @@ private void drawBackground(MatrixStack matrices, ContextMenu contextMenu, Conte } } - private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { + private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, ContextMenuProperties properties) { if (properties.roundedCorners()) { DrawHelper.drawOutlineRoundedBox(matrices.peek().getPositionMatrix(), contextMenu.x, diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index 16c1d33..21f92f0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -105,7 +105,7 @@ private void initOptionGroups(){ @Override - public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { this.contextMenu = contextMenu; initOptionGroups(); @@ -237,7 +237,7 @@ private int getContentHeight() { } @Override - public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { if (isMouseOver(mouseX, mouseY, imageX, imageY, panelWidth, panelHeight)) { scrollHandler.mouseScrolled(verticalAmount); } @@ -247,7 +247,7 @@ public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double } @Override - public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { if(isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)) { mc.getSoundManager().play(PositionedSoundInstance.master( @@ -296,7 +296,7 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int } @Override - public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { scrollHandler.stopDragging(); groupScrollHandler.stopDragging(); @@ -305,7 +305,7 @@ public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int } @Override - public boolean mouseDragged(ContextMenu menu,double mouseX, double mouseY, int button, double deltaX, double deltaY) { + public boolean mouseDragged(ContextMenu menu,double mouseX, double mouseY, int button, double deltaX, double deltaY) { if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { if(isMouseOver(mouseX,mouseY,imageX + panelWidth + 5,imageY - 5,DEFAULT_SCROLLBAR_WIDTH + 5,panelHeight + 10)) { scrollHandler.updateScrollPosition(mouseY); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index d8f92b2..07ca88c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -124,7 +124,7 @@ private void drawScrollbar(DrawContext drawContext) { } @Override - public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { + public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { //This is equivalent to "Auto" GUI scale in minecraft options SCALE_FACTOR = mc.getWindow().calculateScaleFactor(0, mc.forcesUnicodeFont()); @@ -283,19 +283,19 @@ private int getMaxScrollOffset() { } @Override - public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { super.mouseScrolled(menu, mouseX, mouseY, horizontalAmount, verticalAmount); scrollHandler.mouseScrolled(verticalAmount); } @Override - public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { scrollHandler.stopDragging(); return super.mouseReleased(menu, mouseX, mouseY, button); } @Override - public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { mouseX = mc.mouse.getX()/SCALE_FACTOR; mouseY = mc.mouse.getY()/SCALE_FACTOR; @@ -305,7 +305,7 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int if(button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) { int optionStartX = contextMenuX + (int) (width * 0.2f) + 10; - int yOffset =contextMenu.y + 22 - scrollHandler.getScrollOffset(); + int yOffset = contextMenu.y + 22 - scrollHandler.getScrollOffset(); for (Option option : getOptions(contextMenu)) { if (!option.shouldRender()) continue; @@ -329,7 +329,7 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int return super.mouseClicked(menu, mouseX, mouseY, button); } @Override - public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { + public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { mouseX = mc.mouse.getX()/SCALE_FACTOR; mouseY = mc.mouse.getY()/SCALE_FACTOR; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java index 43624dc..04fc50a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java @@ -16,11 +16,11 @@ public abstract class Skin { protected static final MinecraftClient mc = MinecraftClient.getInstance(); - protected ContextMenu contextMenu; + protected ContextMenu contextMenu; protected Map>, Supplier>>> renderers = new HashMap<>(); private boolean createNewScreen; - public Skin(ContextMenu menu) { + public Skin(ContextMenu menu) { this.contextMenu = menu; } @@ -57,7 +57,7 @@ protected List> flattenOptions(List> options) { for (Option option : options) { if (option instanceof OptionGroup group) { // Create a new list with type List> - ArrayList groupOptions = new ArrayList<>(group.getGroupOptions()); + ArrayList> groupOptions = new ArrayList<>(group.getGroupOptions()); flattened.addAll(flattenOptions(groupOptions)); } else { flattened.add(option); @@ -67,11 +67,11 @@ protected List> flattenOptions(List> options) { return flattened; } - protected List> getOptions(ContextMenu menu){ + protected List> getOptions(ContextMenu menu){ return supportsGroups() ? menu.getOptions() : flattenOptions(menu.getOptions()); } - public void setContextMenu(ContextMenu contextMenu) { + public void setContextMenu(ContextMenu contextMenu) { this.contextMenu = contextMenu; } @@ -79,27 +79,27 @@ public void setRenderers(Map>, Supplier contextMenu, int mouseX, int mouseY); - public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) { return false; } - public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { + public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY, int button) { return false; } - public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { + public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) { return false; } - public void keyPressed(ContextMenu menu, int key, int scanCode, int modifiers) { + public void keyPressed(ContextMenu menu, int key, int scanCode, int modifiers) { } - public void keyReleased(ContextMenu menu, int key, int scanCode, int modifiers) { + public void keyReleased(ContextMenu menu, int key, int scanCode, int modifiers) { } - public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { } public boolean shouldCreateNewScreen() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java index 05fbfae..ba7913e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java @@ -3,13 +3,13 @@ import net.minecraft.util.math.MathHelper; public class ScrollHandler { - private int scrollOffset; - private double scrollVelocity; - private long lastScrollTime; - private boolean isDragging; - private int maxScrollOffset; - private static final double SCROLL_SPEED = 1; - private double lastMouseY; + protected int scrollOffset; + protected double scrollVelocity; + protected long lastScrollTime; + protected boolean isDragging; + protected int maxScrollOffset; + protected double SCROLL_SPEED = 1; + protected double lastMouseY; public ScrollHandler() { this.scrollOffset = 0; @@ -71,4 +71,9 @@ public int getScrollOffset() { public boolean isOffsetWithinBounds(int offset){ return scrollOffset + offset >= 0 && scrollOffset + offset <= maxScrollOffset; } + + public ScrollHandler setScrollSpeed(double scrollSpeed) { + this.SCROLL_SPEED = scrollSpeed; + return this; + } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index f8644bf..e45a575 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -33,7 +33,7 @@ public class TextWidget extends Widget implements ContextMenuProvider { Supplier textSupplier; String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; - private ContextMenu menu; + private ContextMenu menu; public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); @@ -73,7 +73,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis public void createMenu() { ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(MinecraftSkin.PanelColor.MIDNIGHT_PURPLE)).build(); - menu = new ContextMenu(getX(), getY(), properties); + menu = new ContextMenu<>(getX(), getY(), properties); menu.addOption(new BooleanOption("Shadow", () -> this.shadow, value -> this.shadow = value, BooleanOption.BooleanType.ON_OFF @@ -194,7 +194,7 @@ public void readFromTag(NbtCompound tag) { } @Override - public ContextMenu getContextMenu() { + public ContextMenu getContextMenu() { return menu; } From ab605095d3e911866ab35bfe36b0f6e8de1a8c8b Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 8 Feb 2025 00:05:33 +0530 Subject: [PATCH 19/40] Update upload-artifact --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 1f405ce..2c89f9c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -35,7 +35,7 @@ jobs: - name: capture build artifacts if: ${{ runner.os == 'Linux' && matrix.java == '21' }} # Only upload artifacts built from the latest java on one OS - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Dynamichud path: build/libs/ From 59d1de4ca8f5dd13f0c242db9aa1f1687cf8d105 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sun, 9 Feb 2025 16:36:53 +0530 Subject: [PATCH 20/40] Easing --- .../helpers/animationhelper/Animation.java | 63 +++++++++++ .../animationhelper/AnimationProperty.java | 7 ++ .../helpers/animationhelper/Easing.java | 83 +++++++++++++++ .../helpers/animationhelper/EasingType.java | 35 ++++++ .../animations/CompositeAnimation.java | 100 ++++++++++++++++++ .../animations/ValueAnimation.java | 49 +++++++++ .../screens/AbstractMoveableScreen.java | 4 +- .../dynamichud/widget/Widget.java | 45 +++++--- 8 files changed, 369 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java new file mode 100644 index 0000000..a600118 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java @@ -0,0 +1,63 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper; + +import java.util.ArrayList; +import java.util.List; + +public abstract class Animation { + public long startTime; + public long duration; + protected boolean running = false; + protected boolean finished = false; + protected EasingType easing = EasingType.LINEAR; + protected final List completionCallbacks = new ArrayList<>(); + + public void start() { + startTime = System.currentTimeMillis(); + running = true; + finished = false; + } + + public void stop() { + running = false; + finished = true; + } + + public void update() { + if (!running || finished) return; + + long elapsed = System.currentTimeMillis() - startTime; + float progress = Math.min(elapsed / (float) duration, 1.0f); + float easedProgress = Easing.apply(easing, progress); + + applyAnimation(easedProgress); + + if (progress >= 1.0f) { + finish(); + } + } + + protected abstract void applyAnimation(float progress); + + public Animation duration(long durationMs) { + this.duration = durationMs; + return this; + } + + public Animation easing(EasingType easing) { + this.easing = easing; + return this; + } + + public Animation onComplete(Runnable callback) { + completionCallbacks.add(callback); + return this; + } + + public void finish() { + finished = true; + running = false; + completionCallbacks.forEach(Runnable::run); + } + + public boolean isFinished() { return finished; } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java new file mode 100644 index 0000000..40a1b0b --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java @@ -0,0 +1,7 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper; + +// AnimationProperty.java +public interface AnimationProperty { + T get(); + void set(T value); +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java new file mode 100644 index 0000000..c917fa3 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java @@ -0,0 +1,83 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper; + +public class Easing { + public static float apply(EasingType easingType, float progress) { + return switch (easingType) { + case LINEAR -> progress; + case EASE_IN_SINE -> (float) (1 - Math.cos((progress * Math.PI) / 2)); + case EASE_OUT_SINE -> (float) Math.sin((progress * Math.PI) / 2); + case EASE_IN_OUT_SINE -> (float) (-(Math.cos(Math.PI * progress) - 1) / 2); + case EASE_IN_QUAD -> progress * progress; + case EASE_OUT_QUAD -> 1 - (1 - progress) * (1 - progress); + case EASE_IN_OUT_QUAD -> progress < 0.5 ? 2 * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 2) / 2); + case EASE_IN_CUBIC -> progress * progress * progress; + case EASE_OUT_CUBIC -> (float) (1 - Math.pow(1 - progress, 3)); + case EASE_IN_OUT_CUBIC -> progress < 0.5 ? 4 * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 3) / 2); + case EASE_IN_QUART -> progress * progress * progress * progress; + case EASE_OUT_QUART -> (float) (1 - Math.pow(1 - progress, 4)); + case EASE_IN_OUT_QUART -> progress < 0.5 ? 8 * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 4) / 2); + case EASE_IN_QUINT -> progress * progress * progress * progress * progress; + case EASE_OUT_QUINT -> (float) (1 - Math.pow(1 - progress, 5)); + case EASE_IN_OUT_QUINT -> progress < 0.5 ? 16 * progress * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 5) / 2); + case EASE_IN_EXPO -> (float) (progress == 0 ? 0 : Math.pow(2, 10 * progress - 10)); + case EASE_OUT_EXPO -> (float) (progress == 1 ? 1 : 1 - Math.pow(2, -10 * progress)); + case EASE_IN_OUT_EXPO -> { + if (progress == 0 || progress == 1) yield progress; + yield (float) (progress < 0.5 + ? Math.pow(2, 20 * progress - 10) / 2 + : (2 - Math.pow(2, -20 * progress + 10)) / 2); + } + case EASE_IN_CIRC -> (float) (1 - Math.sqrt(1 - Math.pow(progress, 2))); + case EASE_OUT_CIRC -> (float) Math.sqrt(1 - Math.pow(progress - 1, 2)); + case EASE_IN_OUT_CIRC -> progress < 0.5 + ? (float) ((1 - Math.sqrt(1 - Math.pow(2 * progress, 2))) / 2) + : (float) ((Math.sqrt(1 - Math.pow(-2 * progress + 2, 2)) + 1) / 2); + case EASE_IN_BACK -> (float) (2.70158 * progress * progress * progress - 1.70158 * progress * progress); + case EASE_OUT_BACK -> { + float c1 = 1.70158f; + float c3 = c1 + 1; + yield (float) (1 + c3 * Math.pow(progress - 1, 3) + c1 * Math.pow(progress - 1, 2)); + } + case EASE_IN_OUT_BACK -> { + float c1 = 1.70158f; + float c2 = c1 * 1.525f; + yield (float) (progress < 0.5 + ? (Math.pow(2 * progress, 2) * ((c2 + 1) * 2 * progress - c2)) / 2 + : (Math.pow(2 * progress - 2, 2) * ((c2 + 1) * (progress * 2 - 2) + c2) + 2) / 2); + } + case EASE_IN_ELASTIC -> { + float c4 = (float) (2 * Math.PI / 3); + yield progress == 0 ? 0 : progress == 1 ? 1 : (float) (-Math.pow(2, 10 * progress - 10) * Math.sin((progress * 10 - 10.75) * c4)); + } + case EASE_OUT_ELASTIC -> { + float c4 = (float) (2 * Math.PI / 3); + yield progress == 0 ? 0 : progress == 1 ? 1 : (float) (Math.pow(2, -10 * progress) * Math.sin((progress * 10 - 0.75) * c4) + 1); + } + case EASE_IN_OUT_ELASTIC -> { + float c5 = (float) (2 * Math.PI / 4.5); + yield progress == 0 ? 0 : progress == 1 ? 1 : progress < 0.5 + ? (float) (-(Math.pow(2, 20 * progress - 10) * Math.sin((20 * progress - 11.125) * c5)) / 2) + : (float) (Math.pow(2, -20 * progress + 10) * Math.sin((20 * progress - 11.125) * c5) / 2 + 1); + } + case EASE_IN_BOUNCE -> 1 - bounceOut(1 - progress); + case EASE_OUT_BOUNCE -> bounceOut(progress); + case EASE_IN_OUT_BOUNCE -> progress < 0.5 + ? (1 - bounceOut(1 - 2 * progress)) / 2 + : (1 + bounceOut(2 * progress - 1)) / 2; + }; + } + + private static float bounceOut(float progress) { + float n1 = 7.5625f; + float d1 = 2.75f; + if (progress < 1 / d1) { + return n1 * progress * progress; + } else if (progress < 2 / d1) { + return n1 * (progress -= 1.5f / d1) * progress + 0.75f; + } else if (progress < 2.5 / d1) { + return n1 * (progress -= 2.25f / d1) * progress + 0.9375f; + } else { + return n1 * (progress -= 2.625f / d1) * progress + 0.984375f; + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java new file mode 100644 index 0000000..c91405a --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java @@ -0,0 +1,35 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper; + +public enum EasingType { + LINEAR, + EASE_IN_SINE, + EASE_OUT_SINE, + EASE_IN_OUT_SINE, + EASE_IN_QUAD, + EASE_OUT_QUAD, + EASE_IN_OUT_QUAD, + EASE_IN_CUBIC, + EASE_OUT_CUBIC, + EASE_IN_OUT_CUBIC, + EASE_IN_QUART, + EASE_OUT_QUART, + EASE_IN_OUT_QUART, + EASE_IN_QUINT, + EASE_OUT_QUINT, + EASE_IN_OUT_QUINT, + EASE_IN_EXPO, + EASE_OUT_EXPO, + EASE_IN_OUT_EXPO, + EASE_IN_CIRC, + EASE_OUT_CIRC, + EASE_IN_OUT_CIRC, + EASE_IN_BACK, + EASE_OUT_BACK, + EASE_IN_OUT_BACK, + EASE_IN_ELASTIC, + EASE_OUT_ELASTIC, + EASE_IN_OUT_ELASTIC, + EASE_IN_BOUNCE, + EASE_OUT_BOUNCE, + EASE_IN_OUT_BOUNCE; +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java new file mode 100644 index 0000000..d52eb7e --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java @@ -0,0 +1,100 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper.animations; + +import com.tanishisherewith.dynamichud.helpers.animationhelper.Animation; + +import java.util.ArrayList; +import java.util.List; + +public class CompositeAnimation extends Animation { + private final List children = new ArrayList<>(); + private final boolean parallel; + private int currentChildIndex = 0; + private long[] childStartTimes; + + public CompositeAnimation(boolean parallel) { + this.parallel = parallel; + } + + public CompositeAnimation add(Animation animation) { + children.add(animation); + return this; + } + + @Override + public void start() { + super.start(); + if (parallel) { + children.forEach(Animation::start); + } else { + // Calculate total duration as sum of children's durations + this.duration = children.stream().mapToLong(a -> a.duration).sum(); + childStartTimes = new long[children.size()]; + long accumulated = 0; + for (int i = 0; i < children.size(); i++) { + childStartTimes[i] = accumulated; + accumulated += children.get(i).duration; + } + startChild(0); + } + } + + private void startChild(int index) { + if (index < children.size()) { + Animation child = children.get(index); + child.start(); + // Adjust child's start time to match group timeline + child.startTime = this.startTime + childStartTimes[index]; + } + } + + @Override + protected void applyAnimation(float progress) { + if (parallel) { + children.forEach(Animation::update); + } else { + long elapsed = System.currentTimeMillis() - startTime; + + // Find active child + for (int i = 0; i < children.size(); i++) { + long childDuration = children.get(i).duration; + if (elapsed < childStartTimes[i] + childDuration) { + if (currentChildIndex != i) { + currentChildIndex = i; + startChild(i); + } + children.get(i).update(); + break; + } + } + } + } + + @Override + public void stop() { + super.stop(); + children.forEach(Animation::stop); + } + + @Override + public boolean isFinished() { + if (parallel) { + return children.stream().allMatch(Animation::isFinished); + } else { + long elapsed = System.currentTimeMillis() - startTime; + return elapsed >= duration; + } + } + + @Override + public void finish() { + // Ensure all children finish properly + if (!parallel) { + children.forEach(child -> { + if (!child.isFinished()) { + child.finish(); + } + }); + } + super.finish(); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java new file mode 100644 index 0000000..cc829ed --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java @@ -0,0 +1,49 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper.animations; + +import com.tanishisherewith.dynamichud.helpers.animationhelper.Animation; +import com.tanishisherewith.dynamichud.helpers.animationhelper.AnimationProperty; +import com.tanishisherewith.dynamichud.helpers.animationhelper.Easing; +import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType; + +public class ValueAnimation extends Animation { + private final AnimationProperty property; + private float startValue; + private float endValue; + private EasingType easing; + private float value; + + public ValueAnimation(AnimationProperty property, float start, float end, EasingType easingType) { + this.property = property; + this.startValue = start; + this.endValue = end; + this.easing = easingType; + } + public ValueAnimation(AnimationProperty property, float start, float end) { + this(property,start,end,EasingType.LINEAR); + } + + @Override + protected void applyAnimation(float progress) { + value = startValue + (endValue - startValue) * Easing.apply(easing,progress); + property.set(value); + } + + public ValueAnimation setEasing(EasingType easing) { + this.easing = easing; + return this; + } + + public ValueAnimation setStartValue(float startValue) { + this.startValue = startValue; + return this; + } + + public ValueAnimation setEndValue(float endValue) { + this.endValue = endValue; + return this; + } + + public float getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index b26cf11..ca3a359 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -98,10 +98,10 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) if (GlobalConfig.get().shouldDisplayDescriptions()) { for (Widget widget : widgetRenderer.getWidgets()) { - if (widget == null || widget.shiftDown) continue; + if (widget == null || widget.isShiftDown) continue; if (widget.getWidgetBox().isMouseOver(mouseX, mouseY)) { - drawContext.drawTooltip(client.textRenderer, Text.of(widget.DATA.description()), mouseX, mouseY); + drawContext.drawTooltip(client.textRenderer, widget.tooltipText, mouseX, mouseY); break; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index fa4b0f7..89902e6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -6,10 +6,12 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; public abstract class Widget { + public static MinecraftClient mc = MinecraftClient.getInstance(); public WidgetData DATA; /** * This is the UID of the widget used to identify during loading and saving. @@ -20,12 +22,12 @@ public abstract class Widget { */ public UID uid = UID.generate(); // Whether the widget is enabled and should be displayed. - public boolean display = true; - public boolean isDraggable = true; + protected boolean isVisible = true; + protected boolean isDraggable = true; //Boolean to check if the widget is being dragged public boolean dragging; //To enable/disable snapping - public boolean shiftDown = false; + public boolean isShiftDown = false; /** * An identifier for widgets to group them under one ID. *

@@ -35,18 +37,23 @@ public abstract class Widget { * @see #uid */ public String modId = "unknown"; + + public Text tooltipText; + // Boolean to know if the widget is currently being displayed in an instance of AbstractMoveableScreen protected boolean isInEditor = false; // Absolute position of the widget on screen in pixels. protected int x, y; + protected boolean shouldScale = true; - protected MinecraftClient mc = MinecraftClient.getInstance(); private final Anchor anchor; // The chosen anchor point //Dimensions of the widget protected WidgetBox widgetBox; + int startX, startY; private int offsetX, offsetY; // Offset from the anchor point + public Widget(WidgetData DATA, String modId) { this(DATA, modId, Anchor.CENTER); } @@ -56,6 +63,7 @@ public Widget(WidgetData DATA, String modId, Anchor anchor) { widgetBox = new WidgetBox(0, 0, 0, 0); this.modId = modId; this.anchor = anchor; + this.tooltipText = Text.of(DATA.description()); init(); } @@ -151,7 +159,7 @@ public boolean isOverlapping(Widget other) { * Renders the widget on the screen. */ public final void render(DrawContext drawContext, int mouseX, int mouseY) { - if (!shouldDisplay()) return; + if (!isVisible()) return; if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().getScale()); @@ -234,7 +242,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi // Divides the screen into several "grid boxes" which the elements snap to. // Higher the snapSize, more the grid boxes - if (this.shiftDown) { + if (this.isShiftDown) { // Calculate the size of each snap box int snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; int snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; @@ -269,11 +277,11 @@ public void mouseScrolled(double mouseX, double mouseY, double vAmount, double h } public boolean toggle() { - return this.display = !this.display; + return this.isVisible = !this.isVisible; } public void onClose() { - this.shiftDown = false; + this.isShiftDown = false; } /** @@ -281,7 +289,7 @@ public void onClose() { * Drawn with 2 pixel offset to all sides */ protected void drawWidgetBackground(DrawContext context) { - int backgroundColor = this.shouldDisplay() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB(); + int backgroundColor = this.isVisible() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB(); WidgetBox box = this.getWidgetBox(); DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), @@ -292,12 +300,19 @@ protected void drawWidgetBackground(DrawContext context) { backgroundColor); } + /** + * Set the tooltip text of the widget + */ + protected void setTooltipText(Text text){ + this.tooltipText = text; + } + public void readFromTag(NbtCompound tag) { modId = tag.getString("modId"); uid = new UID(tag.getString("UID")); x = tag.getInt("x"); y = tag.getInt("y"); - display = tag.getBoolean("Display"); + isVisible = tag.getBoolean("isVisible"); isDraggable = tag.getBoolean("isDraggable"); shouldScale = tag.getBoolean("shouldScale"); } @@ -315,12 +330,12 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("shouldScale", shouldScale); tag.putInt("x", x); tag.putInt("y", y); - tag.putBoolean("Display", display); + tag.putBoolean("Display", isVisible); } - public boolean shouldDisplay() { - return display; + public boolean isVisible() { + return isVisible; } public WidgetBox getWidgetBox() { @@ -345,9 +360,9 @@ public String toString() { "uniqueId='" + uid.getUniqueID() + '\'' + ", x=" + x + ", y=" + y + - ", display=" + display + + ", isVisible=" + isVisible + ", isDraggable=" + isDraggable + - ", shiftDown=" + shiftDown + + ", shiftDown=" + isShiftDown + ", shouldScale=" + shouldScale + '}'; } From b0dbca6c0b41bddaae8447a8cce9b3e34a5bd60f Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:31:19 +0530 Subject: [PATCH 21/40] Option complexity, some changes to animations, MathAnimations, changes to color option, and chroma text for TextWidget rainbow. --- .../dynamichud/DynamicHUD.java | 2 +- .../dynamichud/DynamicHudIntegration.java | 20 ---- .../dynamichud/config/GlobalConfig.java | 26 ++-- .../dynamichud/helpers/ColorHelper.java | 41 +++++++ .../dynamichud/helpers/DrawHelper.java | 30 +++++ .../dynamichud/helpers/TextureHelper.java | 2 - .../animations/CompositeAnimation.java | 2 +- .../animations/MathAnimations.java | 111 ++++++++++++++++++ .../animations/ValueAnimation.java | 3 +- .../screens/AbstractMoveableScreen.java | 5 +- .../utils/contextmenu/ContextMenu.java | 6 + .../contextmenu/options/ColorOption.java | 2 +- .../contextmenu/options/DoubleOption.java | 10 +- .../utils/contextmenu/options/Option.java | 25 +++- .../contextmenu/options/OptionGroup.java | 2 +- .../options/coloroption/AlphaSlider.java | 2 +- .../options/coloroption/ColorGradient.java | 96 ++++----------- .../coloroption/ColorPickerButton.java | 2 + .../options/coloroption/HueSlider.java | 7 +- .../options/coloroption/SaturationHueBox.java | 17 +-- .../contextmenu/skinsystem/MinecraftSkin.java | 14 ++- .../contextmenu/skinsystem/ModernSkin.java | 1 + .../dynamichud/widget/Widget.java | 2 +- .../dynamichud/widget/WidgetManager.java | 3 +- .../dynamichud/widget/WidgetRenderer.java | 4 +- .../dynamichud/widgets/TextWidget.java | 38 +++++- 26 files changed, 335 insertions(+), 138 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 6790c1b..9b24993 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -140,7 +140,7 @@ public void onInitializeClient() { DHIntegration.initAfter(); // Get the instance of AbstractMoveableScreen - screen = Objects.requireNonNull(DHIntegration.getMovableScreen()); + screen = Objects.requireNonNull(DHIntegration.getMovableScreen(), "AbstractMovableScreen instance should not be null!"); // Get the keybind to open the screen instance binding = DHIntegration.getKeyBind(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java index 0e25ed0..1a8f8df 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java @@ -16,26 +16,6 @@ * This interface provides methods for integrating DynamicHud into a mod. */ public interface DynamicHudIntegration { - /** - * The category for the key binding. - */ - String KEYBIND_CATEGORY = "DynamicHud"; - - /** - * The translation key for the editor screen. - */ - String TRANSLATION_KEY = "DynamicHud Editor Screen"; - - /** - * The input type for the key binding. - */ - InputUtil.Type INPUT_TYPE = InputUtil.Type.KEYSYM; - - /** - * The key code for the key binding. - */ - int KEY = GLFW.GLFW_KEY_RIGHT_SHIFT; - /** * The key binding for opening the editor screen. */ diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index bf36ae0..c771c26 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -1,22 +1,16 @@ package com.tanishisherewith.dynamichud.config; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; import dev.isxander.yacl3.api.*; -import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; -import dev.isxander.yacl3.api.controller.ColorControllerBuilder; -import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; -import dev.isxander.yacl3.api.controller.IntegerFieldControllerBuilder; +import dev.isxander.yacl3.api.controller.*; import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; import dev.isxander.yacl3.config.v2.api.SerialEntry; import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; -import dev.isxander.yacl3.config.v2.impl.autogen.ColorFieldImpl; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; import net.minecraft.util.Identifier; import java.awt.*; -import java.util.LinkedList; public final class GlobalConfig { public static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) @@ -39,9 +33,14 @@ public final class GlobalConfig { @SerialEntry private boolean showColorPickerPreview = true; + @SerialEntry private boolean forceSameContextMenuSkin = true; + //These package names are getting seriously long + @SerialEntry + private com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity complexity = com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.Simple; + @SerialEntry private int snapSize = 100; @@ -101,6 +100,15 @@ public Screen createYACLGUI() { .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) .controller(ColorControllerBuilder::create) .build()) + .option(Option.createBuilder() + .name(Text.literal("Settings Complexity")) + .description(OptionDescription.of(Text.literal("The level of options to display. Options equal to or below this level will be displayed"))) + .binding(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.Simple, () -> this.complexity, newVal -> this.complexity = newVal) + .controller((option) -> EnumControllerBuilder.create(option) + .enumClass(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.class) + .formatValue(value -> Text.of(value.name())) + ) + .build()) .build()) .save(HANDLER::save) .build() @@ -130,4 +138,8 @@ public Color getHudInactiveColor() { public Color getHudActiveColor() { return hudActiveColor; } + + public com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity complexity(){ + return complexity; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java index 4dcc0db..3e57446 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java @@ -1,8 +1,14 @@ package com.tanishisherewith.dynamichud.helpers; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; import net.minecraft.util.math.MathHelper; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; import java.awt.*; +import java.math.BigInteger; +import java.nio.ByteBuffer; /** * This class provides helper methods for working with colors. @@ -168,6 +174,41 @@ public static Color changeAlpha(Color color, int alpha) { return new Color(0); } + public static int[] getMousePixelColor(double mouseX, double mouseY){ + Framebuffer framebuffer = MinecraftClient.getInstance().getFramebuffer(); + if (framebuffer != null) { + int x = (int) (mouseX * framebuffer.textureWidth / MinecraftClient.getInstance().getWindow().getScaledWidth()); + int y = (int) ((MinecraftClient.getInstance().getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / MinecraftClient.getInstance().getWindow().getScaledHeight()); + + try { + // Calculate the size of the buffer needed to store the texture data + int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; + ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); + // Bind the texture from the framebuffer + GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); + // Read the texture data into the buffer + GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); + + // Calculate the index of the pixel in the buffer + int index = (x + y * framebuffer.textureWidth) * 4; + + // Check if the index is within the bounds of the buffer + if (index >= 0 && index + 3 < bufferSize) { + int blue = buffer.get(index) & 0xFF; + int green = buffer.get(index + 1) & 0xFF; + int red = buffer.get(index + 2) & 0xFF; + + return new int[]{red,green,blue}; + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + System.err.println("Framebuffer is null"); + } + return null; + } + public static int fromRGBA(int r, int g, int b, int a) { return (r << 16) + (g << 8) + (b) + (a << 24); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index 7907d89..eac55e0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -11,6 +11,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Util; import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.NotNull; import org.joml.Matrix4f; import org.lwjgl.opengl.GL40C; @@ -248,6 +249,35 @@ public static void drawRainbowGradientRectangle(Matrix4f matrix4f, float x, floa RenderSystem.disableBlend(); } + /** + * Draw chroma text (text with a nice rainbow effect) + * @param drawContext A drawContext object + * @param text The text to display + * @param x X pos of text + * @param y Y pos of text + * @param speed Speed of rainbow + * @param saturation Saturation of the rainbow colors + * @param brightness Brightness of the rainbow colors + * @param spread How much the color difference should be between each character (ideally between 0.001 to 0.2) + * @param shadow Whether to render the text as shadow. + */ + public static void drawChromaText(@NotNull DrawContext drawContext, String text, int x, int y, float speed, float saturation, float brightness, float spread, boolean shadow) { + long time = System.currentTimeMillis(); // Get the current time for animation + int length = text.length(); + + for (int i = 0; i < length; i++) { + // Calculate the hue for the current character + float hue = (time % (int) (5000 / speed)) / (5000f / speed) + (i * spread); // Adjust the hue based on time and character position + hue = MathHelper.floorMod(hue, 1.0f); // Ensure the hue stays within the range [0, 1] + + // Convert the hue to an RGB color + int color = Color.HSBtoRGB(hue, saturation, brightness); + + // Draw the character with the calculated color + drawContext.drawText(mc.textRenderer, String.valueOf(text.charAt(i)), x + mc.textRenderer.getWidth(text.substring(0, i)), y, color, shadow); + } + } + public static void drawRainbowGradient(float x, float y, float width, float height) { Matrix4f matrix4f = RenderSystem.getModelViewMatrix(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java index 53a96ce..8939443 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -272,6 +272,4 @@ public static int getAverageColor(NativeImage image) { return (redAverage << 16) | (greenAverage << 8) | blueAverage; } - - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java index d52eb7e..27f091c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/CompositeAnimation.java @@ -28,7 +28,7 @@ public void start() { } else { // Calculate total duration as sum of children's durations this.duration = children.stream().mapToLong(a -> a.duration).sum(); - childStartTimes = new long[children.size()]; + this.childStartTimes = new long[children.size()]; long accumulated = 0; for (int i = 0; i < children.size(); i++) { childStartTimes[i] = accumulated; diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java new file mode 100644 index 0000000..936219e --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java @@ -0,0 +1,111 @@ +package com.tanishisherewith.dynamichud.helpers.animationhelper.animations; + +import net.minecraft.util.math.Vec2f; +import net.minecraft.util.math.random.Random; + +public class MathAnimations { + // SHAKE: Random offset animation with smooth decay + public static float shake(float intensity, float frequency, float decay) { + long time = System.currentTimeMillis(); + return (float) (Math.sin(time * frequency) * + Math.exp(-decay * time) * intensity); + } + + // 2D Shake with different X/Y frequencies + public static Vec2f shake2D(float intensity, float freqX, float freqY) { + return new Vec2f( + (float) Math.sin(System.currentTimeMillis() * freqX) * intensity, + (float) Math.cos(System.currentTimeMillis() * freqY) * intensity + ); + } + + // FLICKER: Random flashing effect + public static float flicker(float min, float max, float chance) { + Random rand = Random.create(); + return rand.nextFloat() < chance ? + min + (max - min) * rand.nextFloat() : + max; + } + + // CIRCULAR MOTION: Perfect for rotation/orbital animations + public static Vec2f circularMotion(float radius, float speed, float phase) { + double angle = Math.toRadians((System.currentTimeMillis() * speed) % 360 + phase); + return new Vec2f( + (float) (Math.cos(angle) * radius), + (float) (Math.sin(angle) * radius) + ); + } + + // SAWTOOTH WAVE: Linear rise with sudden drop + public static float sawtooth(float period, float min, float max) { + float phase = (System.currentTimeMillis() % period) / period; + return min + (max - min) * phase; + } + + // TRIANGULAR WAVE: Linear rise and fall + public static float triangleWave(float period, float min, float max) { + float halfPeriod = period / 2; + float phase = (System.currentTimeMillis() % period); + float value = phase < halfPeriod ? + (phase / halfPeriod) : + 2 - (phase / halfPeriod); + return min + (max - min) * value; + } + + // BOUNCE: Simulates physical bouncing + public static float bounce(float dropHeight, float gravity, float dampening) { + float t = System.currentTimeMillis() / 1000f; + return (float) (dropHeight * Math.abs(Math.sin(t * Math.sqrt(gravity))) * + Math.exp(-dampening * t)); + } + + // PULSE: Smooth heartbeat-like effect + public static float pulse1(float base, float amplitude, float frequency) { + return (float) (base + amplitude * + (0.5 + 0.5 * Math.sin(System.currentTimeMillis() * frequency))); + } + + // SPIRAL: Circular motion with expanding radius + public static Vec2f spiral(float baseRadius, float expansionRate, float speed) { + float t = System.currentTimeMillis() / 1000f; + return new Vec2f( + (float) ((baseRadius + expansionRate * t) * Math.cos(t * speed)), + (float) ((baseRadius + expansionRate * t) * Math.sin(t * speed)) + ); + } + + // Continuous pulsating effect using sine wave + public static float pulse2(float speed, float min, float max) { + return (float) ((Math.sin(System.currentTimeMillis() * speed) + 1) / 2 * (max - min) + min); + } + + // Linear interpolation between values over time + public static float lerp(float start, float end, long startTime, float duration) { + float progress = (System.currentTimeMillis() - startTime) / duration; + progress = Math.min(1, Math.max(0, progress)); // Clamp 0-1 + return start + (end - start) * progress; + } + + // Bouncing animation using quadratic ease-out + public static float bounce(float start, float end, long startTime, float duration) { + float time = System.currentTimeMillis() - startTime; + time /= duration; + return end * (1 - (time - 1) * (time - 1)) + start; + } + + // Continuous rotation using modulo + public static float continuousRotation(float speed) { + return (System.currentTimeMillis() % (360_000 / speed)) * (speed / 1000); + } + + // Elastic wobble effect + public static float elasticWobble(float speed, float magnitude) { + return (float) (Math.sin(System.currentTimeMillis() * speed) * + Math.exp(-0.001 * System.currentTimeMillis()) * magnitude); + } + + // Infinite rotation + public static float infiniteRotation(float speed) { + return (System.currentTimeMillis() % (360_000 / speed)) * (speed / 1000); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java index cc829ed..1832aa8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java @@ -18,13 +18,14 @@ public ValueAnimation(AnimationProperty property, float start, float end, this.endValue = end; this.easing = easingType; } + public ValueAnimation(AnimationProperty property, float start, float end) { this(property,start,end,EasingType.LINEAR); } @Override protected void applyAnimation(float progress) { - value = startValue + (endValue - startValue) * Easing.apply(easing,progress); + this.value = startValue + (endValue - startValue) * Easing.apply(easing,progress); property.set(value); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index ca3a359..fc36f5e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -85,7 +85,6 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou */ @Override public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { - assert this.client != null; if (this.client.world == null) { renderInGameBackground(drawContext); } @@ -108,9 +107,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) } } - public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) { - - } + public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) {} @Override public void close() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 88294c6..fb12b2f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -126,6 +126,12 @@ public void toggleDisplay() { } } + public void resetAllOptions(){ + for(Option option: options){ + option.reset(); + } + } + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!shouldDisplay) return false; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index bb4d1cb..6c6ad24 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -15,7 +15,7 @@ public class ColorOption extends Option { public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { super(name,getter, setter); this.parentMenu = parentMenu; - colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); + this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); this.renderer.init(this); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 2b69574..d4a55bd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -3,17 +3,19 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.math.MathHelper; import org.apache.commons.lang3.Validate; import org.lwjgl.glfw.GLFW; +import org.lwjgl.system.MathUtil; import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; public class DoubleOption extends Option { - public double minValue = 0.0; - public double maxValue = 0.0; - public float step = 0.1f; + public double minValue; + public double maxValue; + public float step; ContextMenu parentMenu; private boolean isDragging = false; @@ -56,7 +58,7 @@ private void step(double mouseX) { this.step(mouseX,x); } - public void step(double mouseX,double x) { + public void step(double mouseX, double x) { double newValue = minValue + (float) (mouseX - x) / width * (maxValue - minValue); // Round the new value to the nearest step newValue = Math.round(newValue / step) * step; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java index a8723cc..0b73009 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer; @@ -23,6 +24,7 @@ public abstract class Option implements Input { protected MinecraftClient mc = MinecraftClient.getInstance(); protected ContextMenuProperties properties; protected SkinRenderer> renderer; + protected Complexity complexity = Complexity.Simple; public Option(String name,Supplier getter, Consumer setter) { this(name,getter, setter, () -> true); @@ -33,8 +35,8 @@ public Option(String name,Supplier getter, Consumer setter, Supplier setShouldRender(Supplier shouldRender) { } public boolean shouldRender() { - return shouldRender.get(); + return shouldRender.get() && GlobalConfig.get().complexity().ordinal() >= complexity.ordinal(); + } + public void reset(){ + this.value = get(); } public ContextMenuProperties getProperties() { @@ -154,6 +159,10 @@ public Option description(String description){ this.description = description; return this; } + public Option withComplexity(Complexity complexity){ + this.complexity = complexity; + return this; + } public SkinRenderer> getRenderer() { return renderer; @@ -166,4 +175,14 @@ public String getName() { public String getDescription() { return description; } + + /** + * How complex do you think this option is for a daily normal user. + * For example, some options may be advanced and not needed for casual players but are helpful in customisation + */ + public enum Complexity { + Simple, + Enhanced, + Pro + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java index 39a8e3e..0e4b148 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java @@ -11,7 +11,7 @@ // A group is just another type of Option that contains other options public class OptionGroup extends Option { private final List> groupOptions = new ArrayList<>(); - protected boolean expanded = false; // Skins can choose to use this or ignore it + protected boolean expanded; // Skins can choose to use this or ignore it public OptionGroup(String name) { super(name, () -> null, (v) -> {}, () -> true); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java index c3c5824..69d8ece 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java @@ -22,7 +22,7 @@ public AlphaSlider(int x, int y, int width, int height, Color color) { this.color = color; this.x = x; this.y = y; - alpha = color.getAlpha() / 255f; + this.alpha = color.getAlpha() / 255f; } public void render(DrawContext drawContext, int x, int y) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java index 7e7e4d3..3e5d38e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java @@ -1,6 +1,8 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; +import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.gui.DrawContext; @@ -30,14 +32,13 @@ public ColorGradient(int x, int y, Color initialColor, Consumer onColorSe this.gradientBox = new SaturationHueBox(x, y + 20, boxSize); this.alphaSlider = new AlphaSlider(x, y, 10, boxSize, initialColor); - float[] hsv = new float[3]; - Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), hsv); + float[] hsv = Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), null); this.boxSize = boxSize; - this.gradientSlider.setHue(hsv[0]); this.gradientBox.setHue(hsv[0]); this.gradientBox.setSaturation(hsv[1]); this.gradientBox.setValue(hsv[2]); + this.gradientSlider.setHue(hsv[0]); this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 30, 18); } @@ -66,37 +67,18 @@ public void render(DrawContext drawContext, int x1, int y1, int mouseX, int mous alphaSlider.render(drawContext, x + 10 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking() && GlobalConfig.get().showColorPickerPreview()) { - // Draw the preview box near cursor - Framebuffer framebuffer = client.getFramebuffer(); - if (framebuffer != null) { - //Translate cursor screen position to minecraft's scaled windo - int x = mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth(); - int y = (client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight(); - - try { - int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; - - ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); - GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); - - int index = (x + y * framebuffer.textureWidth) * 4; - if (index >= 0 && index + 3 < bufferSize) { - int blue = buffer.get(index) & 0xFF; - int green = buffer.get(index + 1) & 0xFF; - int red = buffer.get(index + 2) & 0xFF; - - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0, 0, 500); - drawContext.fill(mouseX + 10, mouseY, mouseX + 26, mouseY + 16, -1); - drawContext.fill(mouseX + 11, mouseY + 1, mouseX + 25, mouseY + 15, (red << 16) | (green << 8) | blue | 0xFF000000); - drawContext.getMatrices().pop(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } else { - System.err.println("Framebuffer is null"); + int[] colors = ColorHelper.getMousePixelColor(mouseX,mouseY); + if(colors != null) { + int red = colors[0]; + int green = colors[1]; + int blue = colors[2]; + + //Draw the preview box near the mouse pointer + drawContext.getMatrices().push(); + drawContext.getMatrices().translate(0, 0, 2500); + drawContext.fill(mouseX + 10, mouseY, mouseX + 26, mouseY + 16, -1); + drawContext.fill(mouseX + 11, mouseY + 1, mouseX + 25, mouseY + 15, (red << 16) | (green << 8) | blue | 0xFF000000); + drawContext.getMatrices().pop(); } } } @@ -113,43 +95,17 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } else if (gradientBox.isMouseOver(mouseX, mouseY)) { gradientBox.onClick(mouseX, mouseY, button); } else if (colorPickerButton.isPicking()) { - Framebuffer framebuffer = client.getFramebuffer(); - if (framebuffer != null) { - int x = (int) (mouseX * framebuffer.textureWidth / client.getWindow().getScaledWidth()); - int y = (int) ((client.getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / client.getWindow().getScaledHeight()); - - try { - // Calculate the size of the buffer needed to store the texture data - int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; - - ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); - // Bind the texture from the framebuffer - GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); - // Read the texture data into the buffer - GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); - - // Calculate the index of the pixel in the buffer - int index = (x + y * framebuffer.textureWidth) * 4; - - // Check if the index is within the bounds of the buffer - if (index >= 0 && index + 3 < bufferSize) { - int blue = buffer.get(index) & 0xFF; - int green = buffer.get(index + 1) & 0xFF; - int red = buffer.get(index + 2) & 0xFF; - - float[] hsv = Color.RGBtoHSB(red, green, blue, null); - gradientSlider.setHue(hsv[0]); - gradientBox.setHue(hsv[0]); - gradientBox.setSaturation(hsv[1]); - gradientBox.setValue(hsv[2]); - - colorPickerButton.setPicking(false); - } - } catch (Exception e) { - e.printStackTrace(); - } + int[] colors = ColorHelper.getMousePixelColor(mouseX,mouseY); + if(colors != null) { + float[] hsv = Color.RGBtoHSB(colors[0], colors[1], colors[2], null); + gradientSlider.setHue(hsv[0]); + gradientBox.setHue(hsv[0]); + gradientBox.setSaturation(hsv[1]); + gradientBox.setValue(hsv[2]); + + colorPickerButton.setPicking(false); } else { - System.err.println("Framebuffer is null"); + DynamicHUD.logger.error("Invalid RGB pixel color at mouse pointer"); } } alphaSlider.setColor(new Color(gradientBox.getColor())); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java index aa04521..4d9b711 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -33,9 +33,11 @@ public void render(DrawContext drawContext, int x, int y) { public int getHeight() { return height; } + public int getWidth() { return width; } + public boolean onClick(double mouseX, double mouseY, int button) { if (button == 0) { if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java index d3cd0ba..ef05b2d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java @@ -70,7 +70,7 @@ public void onClick(double mouseX, double mouseY, int button) { if (mouseX >= handleX && mouseX <= handleX + handleWidth && mouseY >= handleY && mouseY <= handleY + handleHeight) { this.isDragging = true; } else if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { - hue = (float) (mouseX - x) / width; + this.hue = (float) (mouseX - x) / this.width; this.isDragging = true; } } @@ -88,9 +88,8 @@ public void onRelease(double mouseX, double mouseY, int button) { public void onDrag(double mouseX, double mouseY, int button) { if (isDragging) { - hue = (float) (mouseX - x) / width; - hue = Math.max(0, hue); - hue = Math.min(1, hue); + this.hue = (float) (mouseX - x) / this.width; + this.hue = Math.clamp(this.hue, 0.0f, 1.0f); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java index 2332557..75c4081 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java @@ -60,8 +60,11 @@ public void onClick(double mouseX, double mouseY, int button) { if (mouseX >= handleX && mouseX <= handleX + handleSize && mouseY >= handleY && mouseY <= handleY + handleSize) { this.isDragging = true; } else if (mouseX >= x && mouseX <= x + size && mouseY >= y && mouseY <= y + size) { - saturation = (float) (mouseX - x) / size; - value = 1.0f - (float) (mouseY - y) / size; + this.saturation = (float) (mouseX - x) / size; + this.value= 1.0f - (float) (mouseY - y) / size; + + this.saturation = Math.clamp(saturation,0.0f,1.0f); + this.value = Math.clamp(value,0.0f,1.0f); this.isDragging = true; } } @@ -79,13 +82,11 @@ public void onRelease(double mouseX, double mouseY, int button) { public void onDrag(double mouseX, double mouseY, int button) { if (isDragging) { - saturation = (float) (mouseX - x) / size; - saturation = Math.max(0, saturation); - saturation = Math.min(1, saturation); + this.saturation = (float) (mouseX - x) / size; + this.value= 1.0f - (float) (mouseY - y) / size; - value = 1.0f - (float) (mouseY - y) / size; - value = Math.max(0, value); - value = Math.min(1, value); + this.saturation = Math.clamp(saturation,0.0f,1.0f); + this.value = Math.clamp(value,0.0f,1.0f); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index 21f92f0..d4cef43 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -18,6 +18,8 @@ import org.lwjgl.glfw.GLFW; import java.awt.*; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.function.IntSupplier; @@ -188,7 +190,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) DrawHelper.drawScrollableText(drawContext,mc.textRenderer,Text.literal(group.getName()),groupX + groupPanelWidth/2,groupX + 2,yOffset,groupX + groupPanelWidth - 2, yOffset + 20,-1); - //Scrollable text uses scissor so we need to enable the context menu scissor again + //Scrollable text uses scissor, so we need to enable the context menu scissor again this.enableContextMenuScissor(); yOffset += 20; // Space for the header @@ -206,7 +208,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) private int renderSelectedGroupOptions(DrawContext drawContext, int mouseX, int mouseY) { int yOffset = imageY + 12 - scrollHandler.getScrollOffset(); for (Option option : selectedGroup.getGroupOptions()) { - if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight) { + if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight && option.shouldRender()) { option.render(drawContext, imageX + 4, yOffset, mouseX, mouseY); } yOffset += option.getHeight() + 1; @@ -470,7 +472,7 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i option.setHeight(25); option.setPosition(x + panelWidth - 122, y); - double sliderX = option.getX() + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.getWidth() - 8); + double sliderX = option.getX() + ((option.value - option.minValue) / (option.maxValue - option.minValue)) * (option.getWidth() - 8); boolean isMouseOverHandle = isMouseOver(mouseX, mouseY, sliderX, y, 10, 20); RenderSystem.enableBlend(); @@ -483,8 +485,12 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); + // Determine the number of decimal places in option.step + int decimalPlaces = String.valueOf(option.step).split("\\.")[1].length(); - drawContext.drawText(mc.textRenderer, String.valueOf(option.value), option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth(option.value.toString()) / 2, y + 5, 16777215, false); + // Format option.value to the determined number of decimal places + String formattedValue = String.format("%." + decimalPlaces + "f", option.value); + drawContext.drawText(mc.textRenderer, formattedValue, option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth(formattedValue) / 2, y + 5, 16777215, false); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index 07ca88c..3b89bfe 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -102,6 +102,7 @@ public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX, int yOffset = groupY + 16 + getGroupIndent().top; for (Option option : group.getGroupOptions()) { if (!option.shouldRender()) continue; + option.render(drawContext, groupX + getGroupIndent().left, yOffset, mouseX, mouseY); yOffset += option.getHeight() + 1; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 89902e6..84e27c0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -330,7 +330,7 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("shouldScale", shouldScale); tag.putInt("x", x); tag.putInt("y", y); - tag.putBoolean("Display", isVisible); + tag.putBoolean("isVisible", isVisible); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index a2af510..9437b07 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -4,6 +4,7 @@ import com.tanishisherewith.dynamichud.mixins.ScreenMixin; import net.fabricmc.fabric.api.util.NbtType; import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtList; @@ -191,7 +192,7 @@ public static void loadWidgets(File file) throws IOException { printWarn("RootTag is null. File is either empty or corrupted: " + file); return; } - NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); + NbtList widgetList = rootTag.getList("widgets", NbtElement.COMPOUND_TYPE); if (widgetList == null) { printWarn("WidgetList is null. File is empty: " + file); return; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index 630340f..5893b6c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -131,7 +131,7 @@ public void keyPressed(int keyCode) { Screen currentScreen = DynamicHUD.MC.currentScreen; if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { - widget.shiftDown = true; + widget.isShiftDown = true; } } } @@ -140,7 +140,7 @@ public void keyReleased(int keyCode) { Screen currentScreen = DynamicHUD.MC.currentScreen; if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { - widget.shiftDown = false; + widget.isShiftDown = false; } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index e45a575..de302ec 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; @@ -30,6 +31,7 @@ public class TextWidget extends Widget implements ContextMenuProvider { protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text protected int rainbowSpeed = 2; //Speed of the rainbow effect + protected float rainbowSpread = 0.01f, rainbowSat = 1.0f, rainbowBrightness = 1.0f; Supplier textSupplier; String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; @@ -93,6 +95,27 @@ public void createMenu() { () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu) .setShouldRender(() -> this.rainbow) ); + menu.addOption(new DoubleOption( + "Rainbow Spread", + 0.001f, 0.15f, 0.001f, + () -> (double) this.rainbowSpread, value -> this.rainbowSpread = value.floatValue(), menu) + .setShouldRender(() -> this.rainbow) + .withComplexity(Option.Complexity.Enhanced) + ); + menu.addOption(new DoubleOption( + "Rainbow Saturation", + 0, 1.0f, 0.1f, + () -> (double) this.rainbowSat, value -> this.rainbowSat = value.floatValue(), menu) + .setShouldRender(() -> this.rainbow) + .withComplexity(Option.Complexity.Pro) + ); + menu.addOption(new DoubleOption( + "Rainbow Brightness", + 0, 1.0f, 0.01f, + () -> (double) this.rainbowBrightness, value -> this.rainbowBrightness = value.floatValue(), menu) + .setShouldRender(() -> this.rainbow) + .withComplexity(Option.Complexity.Pro) + ); /* OptionGroup group = new OptionGroup("Color"); @@ -122,10 +145,14 @@ public void createMenu() { @Override public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { - int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) : textColor.getRGB(); + int color = /*rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) :*/ textColor.getRGB(); if (textSupplier != null) { String text = textSupplier.get(); - drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow); + if(rainbow){ + DrawHelper.drawChromaText(drawContext,text,getX() + 2, getY() + 2, rainbowSpeed/2f,rainbowSat,rainbowBrightness,rainbowSpread,shadow); + } else { + drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow); + } widgetBox.setSizeAndPosition(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale()); } menu.set(getX(), getY(), (int) Math.ceil(getHeight())); @@ -163,6 +190,10 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("Rainbow", rainbow); tag.putInt("TextColor", textColor.getRGB()); tag.putInt("RainbowSpeed", rainbowSpeed); + tag.putFloat("RainbowSpread", rainbowSpread); + tag.putFloat("RainbowSaturation", rainbowSat); + tag.putFloat("RainbowBrightness", rainbowBrightness); + // If true then it means that we should use local registry and if false (i.e. null) then use global registry tag.putBoolean("DynamicValueRegistry", dynamicValueRegistry != null); } @@ -173,6 +204,9 @@ public void readFromTag(NbtCompound tag) { this.shadow = tag.getBoolean("Shadow"); this.rainbow = tag.getBoolean("Rainbow"); this.rainbowSpeed = tag.getInt("RainbowSpeed"); + this.rainbowSpread = tag.getInt("RainbowSpread"); + this.rainbowSat = tag.getInt("RainbowSaturation"); + this.rainbowBrightness = tag.getInt("RainbowBrightness"); this.textColor = new Color(tag.getInt("TextColor")); this.dynamicRegistryKey = tag.getString("DynamicRegistryKey"); From 92073b46b930b95e2cdf5c05be6617d93083629f Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:42:28 +0530 Subject: [PATCH 22/40] Removed color picker button. --- .../dynamichud/helpers/ColorHelper.java | 74 +++++++++++-------- .../animations/MathAnimations.java | 12 +-- .../animations/ValueAnimation.java | 6 +- .../options/coloroption/ColorGradient.java | 9 ++- .../contextmenu/skinsystem/ModernSkin.java | 36 ++++----- .../dynamichud/widgets/TextWidget.java | 2 +- 6 files changed, 72 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java index 3e57446..32d75da 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java @@ -2,9 +2,11 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.util.Window; import net.minecraft.util.math.MathHelper; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL30; import java.awt.*; import java.math.BigInteger; @@ -174,39 +176,47 @@ public static Color changeAlpha(Color color, int alpha) { return new Color(0); } - public static int[] getMousePixelColor(double mouseX, double mouseY){ - Framebuffer framebuffer = MinecraftClient.getInstance().getFramebuffer(); - if (framebuffer != null) { - int x = (int) (mouseX * framebuffer.textureWidth / MinecraftClient.getInstance().getWindow().getScaledWidth()); - int y = (int) ((MinecraftClient.getInstance().getWindow().getScaledHeight() - mouseY) * framebuffer.textureHeight / MinecraftClient.getInstance().getWindow().getScaledHeight()); - - try { - // Calculate the size of the buffer needed to store the texture data - int bufferSize = framebuffer.textureWidth * framebuffer.textureHeight * 4; - ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize); - // Bind the texture from the framebuffer - GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.getColorAttachment()); - // Read the texture data into the buffer - GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, buffer); - - // Calculate the index of the pixel in the buffer - int index = (x + y * framebuffer.textureWidth) * 4; - - // Check if the index is within the bounds of the buffer - if (index >= 0 && index + 3 < bufferSize) { - int blue = buffer.get(index) & 0xFF; - int green = buffer.get(index + 1) & 0xFF; - int red = buffer.get(index + 2) & 0xFF; - - return new int[]{red,green,blue}; - } - } catch (Exception e) { - e.printStackTrace(); - } - } else { - System.err.println("Framebuffer is null"); + public static int[] getMousePixelColor(double mouseX, double mouseY) { + MinecraftClient client = MinecraftClient.getInstance(); + Framebuffer framebuffer = client.getFramebuffer(); + Window window = client.getWindow(); + + // Get the window and framebuffer dimensions + int windowWidth = window.getWidth(); + int windowHeight = window.getHeight(); + int framebufferWidth = framebuffer.textureWidth; + int framebufferHeight = framebuffer.textureHeight; + + // Calculate scaling factors + double scaleX = (double) framebufferWidth / windowWidth; + double scaleY = (double) framebufferHeight / windowHeight; + + // Convert mouse coordinates to framebuffer coordinates + int x = (int) (mouseX * scaleX); + int y = (int) ((windowHeight - mouseY) * scaleY); + + // Ensure the coordinates are within the framebuffer bounds + if (x < 0 || x >= framebufferWidth || y < 0 || y >= framebufferHeight) { + System.err.println("Mouse coordinates are out of bounds"); + return null; } - return null; + + // Allocate a buffer to store the pixel data + ByteBuffer buffer = ByteBuffer.allocateDirect(4); // 4 bytes for RGBA + + // Bind the framebuffer for reading + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffer.fbo); + + // Read the pixel at the mouse position + GL11.glReadPixels(x, y, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); + + // Extract the color components from the buffer + int red = buffer.get(0) & 0xFF; + int green = buffer.get(1) & 0xFF; + int blue = buffer.get(2) & 0xFF; + int alpha = buffer.get(3) & 0xFF; + + return new int[]{red, green, blue, alpha}; } public static int fromRGBA(int r, int g, int b, int a) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java index 936219e..d47d0ce 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java @@ -1,5 +1,7 @@ package com.tanishisherewith.dynamichud.helpers.animationhelper.animations; +import com.tanishisherewith.dynamichud.helpers.animationhelper.Easing; +import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType; import net.minecraft.util.math.Vec2f; import net.minecraft.util.math.random.Random; @@ -81,9 +83,12 @@ public static float pulse2(float speed, float min, float max) { // Linear interpolation between values over time public static float lerp(float start, float end, long startTime, float duration) { + return lerp(start,end,startTime,duration,EasingType.LINEAR); + } + public static float lerp(float start, float end, long startTime, float duration, EasingType easing) { float progress = (System.currentTimeMillis() - startTime) / duration; progress = Math.min(1, Math.max(0, progress)); // Clamp 0-1 - return start + (end - start) * progress; + return start + (end - start) * Easing.apply(easing,progress); } // Bouncing animation using quadratic ease-out @@ -103,9 +108,4 @@ public static float elasticWobble(float speed, float magnitude) { return (float) (Math.sin(System.currentTimeMillis() * speed) * Math.exp(-0.001 * System.currentTimeMillis()) * magnitude); } - - // Infinite rotation - public static float infiniteRotation(float speed) { - return (System.currentTimeMillis() % (360_000 / speed)) * (speed / 1000); - } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java index 1832aa8..af10979 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java @@ -29,17 +29,17 @@ protected void applyAnimation(float progress) { property.set(value); } - public ValueAnimation setEasing(EasingType easing) { + public ValueAnimation easing(EasingType easing) { this.easing = easing; return this; } - public ValueAnimation setStartValue(float startValue) { + public ValueAnimation startValue(float startValue) { this.startValue = startValue; return this; } - public ValueAnimation setEndValue(float endValue) { + public ValueAnimation endValue(float endValue) { this.endValue = endValue; return this; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java index 3e5d38e..704d809 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java @@ -63,7 +63,7 @@ public void render(DrawContext drawContext, int x1, int y1, int mouseX, int mous } gradientSlider.render(drawContext, x, y + client.textRenderer.fontHeight + 4); gradientBox.render(drawContext, x, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); - colorPickerButton.render(drawContext, x + 24 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); + // colorPickerButton.render(drawContext, x + 24 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); alphaSlider.render(drawContext, x + 10 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking() && GlobalConfig.get().showColorPickerPreview()) { @@ -87,14 +87,14 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!display) { return false; } - if (colorPickerButton.onClick(mouseX, mouseY, button)) { + /*if (colorPickerButton.onClick(mouseX, mouseY, button)) { return true; - } else if (gradientSlider.isMouseOver(mouseX, mouseY)) { + } else*/ if (gradientSlider.isMouseOver(mouseX, mouseY)) { gradientSlider.onClick(mouseX, mouseY, button); gradientBox.setHue(gradientSlider.getHue()); } else if (gradientBox.isMouseOver(mouseX, mouseY)) { gradientBox.onClick(mouseX, mouseY, button); - } else if (colorPickerButton.isPicking()) { + } /* else if (colorPickerButton.isPicking()) { int[] colors = ColorHelper.getMousePixelColor(mouseX,mouseY); if(colors != null) { float[] hsv = Color.RGBtoHSB(colors[0], colors[1], colors[2], null); @@ -108,6 +108,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { DynamicHUD.logger.error("Invalid RGB pixel color at mouse pointer"); } } + */ alphaSlider.setColor(new Color(gradientBox.getColor())); alphaSlider.onClick(mouseX, mouseY, button); onColorSelected.accept(alphaSlider.getColor()); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index 3b89bfe..fe8fa75 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -3,6 +3,8 @@ import com.mojang.blaze3d.systems.RenderSystem; import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType; +import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutContext; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; @@ -345,33 +347,24 @@ public Color getThemeColor() { } public class ModernBooleanRenderer implements SkinRenderer { - private float animationProgress = 0f; - private boolean animating = false; + private long animationStartTime; @Override public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) { int backgroundWidth = (int) (width * 0.8f - 14); option.setHeight(14); - option.setPosition(x,y); + option.setPosition(x, y); option.setWidth(backgroundWidth); MatrixStack matrices = drawContext.getMatrices(); - // Animate the toggle - if (animating) { - animationProgress += 0.1f; // Adjust speed as needed - if (animationProgress >= 1f) { - animationProgress = 0f; - animating = false; - } - } - + // Calculate the current progress of the animation int toggleBgX = x + backgroundWidth - 30; // Background boolean active = option.get(); Color backgroundColor = active ? getThemeColor() : DARKER_GRAY; - Color hoveredColor = isMouseOver(mouseX,mouseY,toggleBgX,y + 2,14,7) ? backgroundColor.darker() : backgroundColor; + Color hoveredColor = isMouseOver(mouseX, mouseY, toggleBgX, y + 2, 14, 7) ? backgroundColor.darker() : backgroundColor; DrawHelper.drawRoundedRectangleWithShadowBadWay( matrices.peek().getPositionMatrix(), @@ -382,10 +375,10 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, ); // Draw toggle circle - float toggleX = active ? toggleBgX + 10 : toggleBgX + 4; - if (animating) { - toggleX = MathHelper.lerp(animationProgress, active ? toggleBgX + 4 : toggleBgX + 10, toggleX); - } + float startX = active ? toggleBgX + 4 : toggleBgX + 10; + float endX = active ? toggleBgX + 10 : toggleBgX + 4; + EasingType easingType = active ? EasingType.EASE_IN_CUBIC : EasingType.EASE_OUT_QUAD; + float toggleX = MathAnimations.lerp(startX, endX, animationStartTime, 200f, easingType); DrawHelper.drawFilledCircle(matrices.peek().getPositionMatrix(), toggleX, y + 2 + 3.3f, 2.8f, Color.WHITE.getRGB()); @@ -402,21 +395,22 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, @Override public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, int button) { - mouseX = mc.mouse.getX()/SCALE_FACTOR; - mouseY = mc.mouse.getY()/SCALE_FACTOR; + mouseX = mc.mouse.getX() / SCALE_FACTOR; + mouseY = mc.mouse.getY() / SCALE_FACTOR; int backgroundWidth = (int) (width * 0.8f - 14); int toggleBgX = option.getX() + backgroundWidth - 30; - if(isMouseOver(mouseX,mouseY,toggleBgX,option.getY(),14,option.getHeight())){ + if (isMouseOver(mouseX, mouseY, toggleBgX, option.getY(), 14, option.getHeight())) { option.set(!option.get()); - animating = true; + animationStartTime = System.currentTimeMillis(); return true; } return false; } } + public class ModernColorOptionRenderer implements SkinRenderer { private static final float ANIMATION_SPEED = 0.1f; private float scale = 0f; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index de302ec..0d112dd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -73,7 +73,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis } public void createMenu() { - ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(MinecraftSkin.PanelColor.MIDNIGHT_PURPLE)).build(); + ContextMenuProperties properties = ContextMenuProperties.builder().skin(new ModernSkin()).build(); menu = new ContextMenu<>(getX(), getY(), properties); menu.addOption(new BooleanOption("Shadow", From 901a671bfc9028fc4e14e78277011a11002589eb Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 13 Feb 2025 22:10:25 +0530 Subject: [PATCH 23/40] Warning Screen for invalid mods. --- .../dynamichud/DynamicHUD.java | 20 ++++++ .../dynamichud/DynamicHudTest.java | 4 +- .../dynamichud/internal/ModError.java | 3 + .../{utils => internal}/System.java | 4 +- .../dynamichud/{utils => internal}/UID.java | 2 +- .../dynamichud/internal/WarningScreen.java | 72 +++++++++++++++++++ .../utils/DynamicValueRegistry.java | 2 + .../contextmenu/skinsystem/ModernSkin.java | 43 ++++++----- .../dynamichud/widget/Widget.java | 2 +- .../dynamichud/widgets/TextWidget.java | 11 ++- 10 files changed, 140 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java rename src/main/java/com/tanishisherewith/dynamichud/{utils => internal}/System.java (83%) rename src/main/java/com/tanishisherewith/dynamichud/{utils => internal}/UID.java (93%) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 9b24993..141d6a4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -1,7 +1,10 @@ package com.tanishisherewith.dynamichud; import com.tanishisherewith.dynamichud.config.GlobalConfig; +import com.tanishisherewith.dynamichud.internal.ModError; +import com.tanishisherewith.dynamichud.internal.WarningScreen; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; @@ -20,6 +23,7 @@ import net.fabricmc.loader.api.entrypoint.EntrypointContainer; import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,6 +114,8 @@ public void onInitializeClient() { } } + List invalid_implementations = new ArrayList<>(); + for (EntrypointContainer entrypoint : integrations) { ModMetadata metadata = entrypoint.getProvider().getMetadata(); String modId = metadata.getId(); @@ -186,14 +192,28 @@ public void onInitializeClient() { } else { logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); } + invalid_implementations.add(new ModError(modId, e.getLocalizedMessage().trim())); } } printInfo("(DynamicHUD) Integration of supported mods was successful"); //In game screen render. HudRenderCallback.EVENT.register(new HudRender()); + + if(!invalid_implementations.isEmpty()){ + BooleanPool.put("WarningScreen", false); + ClientTickEvents.START_CLIENT_TICK.register((client)->{ + if(BooleanPool.get("WarningScreen")) return; + + if(MC.currentScreen instanceof TitleScreen) { + MC.executeTask(()->MC.setScreen(new WarningScreen(invalid_implementations))); + BooleanPool.put("WarningScreen", true); + } + }); + } } + private void saveWidgetsSafely(File widgetsFile, List widgets) { try { WidgetManager.saveWidgets(widgetsFile, widgets); diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java index 5a093a7..1384991 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java @@ -6,6 +6,8 @@ import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.widgets.TextWidget; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; @@ -29,7 +31,7 @@ public void init() { registry.registerLocal("DynamicHUD", () -> "DynamicHUD"); FPSWidget = new TextWidget.Builder() - .setX(250) + .setX(MinecraftClient.getInstance().getWindow().getScaledWidth()/2) .setY(100) .setDraggable(true) .rainbow(false) diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java new file mode 100644 index 0000000..c62e177 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java @@ -0,0 +1,3 @@ +package com.tanishisherewith.dynamichud.internal; + +public record ModError(String modName,String errorMessage) { } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/System.java b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java similarity index 83% rename from src/main/java/com/tanishisherewith/dynamichud/utils/System.java rename to src/main/java/com/tanishisherewith/dynamichud/internal/System.java index 3cbc6a0..6651234 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java @@ -1,4 +1,6 @@ -package com.tanishisherewith.dynamichud.utils; +package com.tanishisherewith.dynamichud.internal; + +import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/UID.java b/src/main/java/com/tanishisherewith/dynamichud/internal/UID.java similarity index 93% rename from src/main/java/com/tanishisherewith/dynamichud/utils/UID.java rename to src/main/java/com/tanishisherewith/dynamichud/internal/UID.java index 6a1735f..e31e0d5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/UID.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/UID.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.utils; +package com.tanishisherewith.dynamichud.internal; import java.util.Random; diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java new file mode 100644 index 0000000..329ade2 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java @@ -0,0 +1,72 @@ +package com.tanishisherewith.dynamichud.internal; + +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.OrderedText; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Util; +import net.minecraft.util.crash.CrashReportSection; + +import java.awt.*; +import java.io.File; +import java.util.List; + +public class WarningScreen extends Screen { + private final List modErrors; + + public WarningScreen(List modErrors) { + super(Text.of("DynamicHUD Warning")); + this.modErrors = modErrors; + } + + @Override + protected void init() { + ButtonWidget confirmButton = ButtonWidget.builder(Text.of("I Understand"), button -> MinecraftClient.getInstance().setScreen(null)) + .dimensions(this.width / 2 - 100, this.height - 40, 200, 20) + .narrationSupplier((e)-> Text.literal("I understand")) + .build(); + + ButtonWidget logs_folder = ButtonWidget.builder(Text.of("Open logs"), button -> { + File logsFolder = new File(MinecraftClient.getInstance().runDirectory, "logs"); + Util.getOperatingSystem().open(logsFolder); + }) + .dimensions(this.width / 2 - 100, this.height - 70, 200, 20) + .narrationSupplier((e)-> Text.literal("Open logs")) + .build(); + + // Add "I Understand" button + this.addDrawableChild(confirmButton); + this.addDrawableChild(logs_folder); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + + context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 20, 0xFFFFFF); + context.drawCenteredTextWithShadow(this.textRenderer, "Mods with invalid implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB()); + + int y = 60; + for (ModError error : modErrors) { + Text modName = Text.literal( "> \"" + error.modName() + "\"").formatted(Formatting.RED); + context.drawText(this.textRenderer, modName, this.width / 2 - 100, y, -1, false); + List errorMessage = this.textRenderer.wrapLines(Text.literal( "Error: " + error.errorMessage()), this.width/2); + + if(mouseX >= this.width/2 - 100 && mouseX <= this.width/2 - 100 + this.textRenderer.getWidth(modName) && mouseY >= y && mouseY <= y + this.textRenderer.fontHeight){ + context.drawOrderedTooltip(textRenderer,errorMessage,mouseX,mouseY); + } + y += 11; // Space between mod errors + } + + y += 5; + context.drawCenteredTextWithShadow(this.textRenderer, Text.of("Please report this problem to the respective mod owners."), this.width / 2, y, -1); + context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Widgets of these mods won't work.").formatted(Formatting.YELLOW), this.width / 2, y + 10,-1); + context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Check latest.log for more details").formatted(Formatting.ITALIC), this.width / 2, y + 30,-1); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index f3c8390..8e7a169 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -1,5 +1,7 @@ package com.tanishisherewith.dynamichud.utils; +import com.tanishisherewith.dynamichud.internal.System; + import java.util.ArrayList; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index fe8fa75..c5f87bc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -18,6 +18,7 @@ import net.minecraft.text.OrderedText; import net.minecraft.text.StringVisitable; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec2f; import org.lwjgl.glfw.GLFW; import java.awt.*; @@ -708,7 +709,9 @@ public boolean mouseClicked(EnumOption option, double mouseX, double mouseY, int leftX = x + contextMenuWidth - 30; boolean hoveredOverLeft = isMouseOver(mouseX,mouseY,leftX,y,mc.textRenderer.getWidth("<") + 5,mc.textRenderer.fontHeight); boolean hoveredOverRight = isMouseOver(mouseX,mouseY,leftX + mc.textRenderer.getWidth("<") + 6,y,mc.textRenderer.getWidth(">") + 5,mc.textRenderer.fontHeight); - if (hoveredOverLeft || hoveredOverRight || isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2)) { + boolean hoveredOverMainLabel = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2); + + if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) { E[] values = option.getValues(); int index = Arrays.asList(values).indexOf(option.value); @@ -730,8 +733,10 @@ public boolean mouseClicked(EnumOption option, double mouseX, double mouseY, } public class ModernListRenderer implements SkinRenderer> { + @Override public void render(DrawContext drawContext, ListOption option, int x, int y, int mouseX, int mouseY) { + // Set dimensions for the main label and dropdown area option.setHeight(mc.textRenderer.fontHeight + 2); @@ -788,35 +793,41 @@ public void render(DrawContext drawContext, ListOption option, int x, int y, @Override public boolean mouseClicked(ListOption option, double mouseX, double mouseY, int button) { - if(option.getValues().isEmpty()) return false; + if (option.getValues().isEmpty()) return false; - mouseX = mc.mouse.getX() / SCALE_FACTOR; - mouseY = mc.mouse.getY() / SCALE_FACTOR; + mouseX /= SCALE_FACTOR; + mouseY /= SCALE_FACTOR; int x = option.getX(); int y = option.getY(); String mainLabel = option.name + ": "; String selectedOption = option.get().toString(); - // Check if the main label is clicked to cycle - // "<" and ">" buttons - int contextMenuWidth = (int)(width * 0.8f - 14); + // Calculate positions + int contextMenuWidth = (int) (width * 0.8f - 14); int leftX = x + contextMenuWidth - 30; - boolean hoveredOverLeft = isMouseOver(mouseX,mouseY,leftX,y,mc.textRenderer.getWidth("<") + 5,mc.textRenderer.fontHeight); - boolean hoveredOverRight = isMouseOver(mouseX,mouseY,leftX + mc.textRenderer.getWidth("<") + 6,y,mc.textRenderer.getWidth(">") + 5,mc.textRenderer.fontHeight); - if (hoveredOverLeft || hoveredOverRight || isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2)) { + + // Check hover states + boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight); + boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.textRenderer.getWidth("<") + 6, y, mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight); + boolean hoveredOverMainLabel = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2); + + // Check if any area is clicked + if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) { List values = option.getValues(); int currentIndex = values.indexOf(option.value); + int nextIndex; + // Determine the next index based on the button clicked if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || hoveredOverLeft) { - // Cycle forward (left-click) - int nextIndex = (currentIndex + 1) % values.size(); - option.set(values.get(nextIndex)); + nextIndex = (currentIndex + 1) % values.size(); // Cycle forward } else if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT || hoveredOverRight) { - // Cycle backward (right-click) - int nextIndex = (currentIndex - 1 + values.size()) % values.size(); - option.set(values.get(nextIndex)); + nextIndex = (currentIndex - 1 + values.size()) % values.size(); // Cycle backward + } else { + return false; // No valid click } + + option.set(values.get(nextIndex)); return true; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 84e27c0..3f0f7c2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -2,7 +2,7 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.utils.UID; +import com.tanishisherewith.dynamichud.internal.UID; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 0d112dd..448c1c3 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -27,6 +27,8 @@ public class TextWidget extends Widget implements ContextMenuProvider { public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); + private ContextMenu menu; + public Color textColor; protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text @@ -35,7 +37,6 @@ public class TextWidget extends Widget implements ContextMenuProvider { Supplier textSupplier; String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; - private ContextMenu menu; public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); @@ -47,7 +48,7 @@ public TextWidget() { public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow, Color color, String modID) { super(DATA, modID); this.dynamicRegistryKey = dynamicRegistryKey; - textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); + this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; this.textColor = color; @@ -140,11 +141,15 @@ public void createMenu() { subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows3", () -> this.shadow, value -> this.shadow = value)); subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows4", () -> this.shadow, value -> this.shadow = value)); menu.addOption(subMenuOption); - // */ + + */ + } @Override public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { + if(menu == null) return; + int color = /*rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) :*/ textColor.getRGB(); if (textSupplier != null) { String text = textSupplier.get(); From 78f9b8a173623cb98f9a7279984d1c48a06f8101 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 17 Feb 2025 17:42:08 +0530 Subject: [PATCH 24/40] Removed boilerplate, new integration helper classes and DynamicHudConfigurator --- .../dynamichud/DynamicHUD.java | 228 +----------------- .../dynamichud/HudRender.java | 3 +- ...namicHudTest.java => IntegrationTest.java} | 51 ++-- .../integration/DefaultIntegrationImpl.java | 27 +++ .../integration/DynamicHudConfigurator.java | 119 +++++++++ .../DynamicHudIntegration.java | 45 +--- .../integration/IntegrationManager.java | 218 +++++++++++++++++ .../dynamichud/internal/ModError.java | 2 +- .../dynamichud/mixins/ScreenMixin.java | 5 +- .../screens/AbstractMoveableScreen.java | 6 +- .../dynamichud/widget/WidgetData.java | 1 - .../dynamichud/widget/WidgetRenderer.java | 9 + .../dynamichud/widgets/TextWidget.java | 9 +- src/main/resources/fabric.mod.json | 4 + 14 files changed, 417 insertions(+), 310 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/{DynamicHudTest.java => IntegrationTest.java} (63%) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java rename src/main/java/com/tanishisherewith/dynamichud/{ => integration}/DynamicHudIntegration.java (71%) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 141d6a4..02d0ea6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -1,62 +1,24 @@ package com.tanishisherewith.dynamichud; import com.tanishisherewith.dynamichud.config.GlobalConfig; -import com.tanishisherewith.dynamichud.internal.ModError; -import com.tanishisherewith.dynamichud.internal.WarningScreen; -import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.utils.BooleanPool; -import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.integration.IntegrationManager; import com.tanishisherewith.dynamichud.widget.WidgetManager; -import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.widgets.ItemWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import net.fabricmc.loader.api.entrypoint.EntrypointContainer; -import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; - @Environment(EnvType.CLIENT) public class DynamicHUD implements ClientModInitializer { - /** - * This is a map to store the list of widgets for each widget file to be saved. - *

- * Allows saving widgets across different mods with same save file name. - */ - public static final HashMap> FILE_MAP = new HashMap<>(); - - public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); - private static final List widgetRenderers = new ArrayList<>(); public static MinecraftClient MC = MinecraftClient.getInstance(); + public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); public static String MOD_ID = "dynamichud"; - private static boolean enableTestIntegration = false; - - public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { - widgetRenderers.add(widgetRenderer); - } - public static List getWidgetRenderers() { - return widgetRenderers; - } public static void printInfo(String msg) { logger.info(msg); @@ -66,201 +28,17 @@ public static void printWarn(String msg) { logger.warn(msg); } - /** - * Opens the MovableScreen when the specified key is pressed. - * - * @param key The key to listen for - * @param screen The AbstractMoveableScreen instance to use to set the screen - */ - public static void openDynamicScreen(KeyBinding key, AbstractMoveableScreen screen) { - if (key.wasPressed()) { - MC.setScreen(screen); - } - } - - public void checkToEnableTestIntegration(){ - String[] args = FabricLoader.getInstance().getLaunchArguments(true); - for (int i = 0; i < args.length; i++) { - if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { - enableTestIntegration = Boolean.parseBoolean(args[i + 1]); - break; - } - } - } - @Override public void onInitializeClient() { printInfo("Initialising DynamicHUD"); - // Add WidgetData of included widgets - WidgetManager.registerCustomWidgets( - TextWidget.DATA, - ItemWidget.DATA - ); - //YACL load GlobalConfig.HANDLER.load(); - checkToEnableTestIntegration(); - - printInfo("Integrating mods..."); - List> integrations = new ArrayList<>(getRegisteredIntegrations()); - - if (enableTestIntegration) { - EntrypointContainer testIntegration = getTestIntegration(); - if (testIntegration != null) { - integrations.add(testIntegration); - printInfo("Test integration enabled and loaded successfully."); - } - } - - List invalid_implementations = new ArrayList<>(); - - for (EntrypointContainer entrypoint : integrations) { - ModMetadata metadata = entrypoint.getProvider().getMetadata(); - String modId = metadata.getId(); - - printInfo(String.format("Supported mod with id %s was found!", modId)); - - AbstractMoveableScreen screen; - KeyBinding binding; - WidgetRenderer widgetRenderer; - File widgetsFile; - try { - DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); - - //Calls the init method - DHIntegration.init(); - - //Gets the widget file to save and load the widgets from - widgetsFile = DHIntegration.getWidgetsFile(); - - // Adds / loads widgets from file - if (WidgetManager.doesWidgetFileExist(widgetsFile)) { - WidgetManager.loadWidgets(widgetsFile); - } else { - DHIntegration.addWidgets(); - } - - //Calls the second init method - DHIntegration.initAfter(); - - // Get the instance of AbstractMoveableScreen - screen = Objects.requireNonNull(DHIntegration.getMovableScreen(), "AbstractMovableScreen instance should not be null!"); - - // Get the keybind to open the screen instance - binding = DHIntegration.getKeyBind(); - - //Register custom widget datas by WidgetManager.registerCustomWidgets(); - DHIntegration.registerCustomWidgets(); - - //WidgetRenderer with widgets instance - widgetRenderer = DHIntegration.getWidgetRenderer(); - addWidgetRenderer(widgetRenderer); - - List widgets = FILE_MAP.get(widgetsFile.getName()); - - if (widgets == null || widgets.isEmpty()) { - FILE_MAP.put(widgetsFile.getName(), widgetRenderer.getWidgets()); - } else { - widgets.addAll(widgetRenderer.getWidgets()); - FILE_MAP.put(widgetsFile.getName(), widgets); - } - - //Register events for rendering, saving, loading, and opening the hudEditor - ClientTickEvents.START_CLIENT_TICK.register((client) -> openDynamicScreen(binding, screen)); - - /* === Saving === */ - // Each mod is hooked to the fabric's event system to save its widget. - - //When a player exits a world (SinglePlayer worlds) or a server stops - ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - - // When a resource pack is reloaded. - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - - //When player disconnects - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - - //When minecraft closes - ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); - - printInfo(String.format("Integration of mod %s was successful", modId)); - } catch (Throwable e) { - if (e instanceof IOException) { - logger.warn("An error has occurred while loading widgets of mod {}", modId, e); - } else { - logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); - } - invalid_implementations.add(new ModError(modId, e.getLocalizedMessage().trim())); - } - } - printInfo("(DynamicHUD) Integration of supported mods was successful"); + IntegrationManager.integrate(); //In game screen render. HudRenderCallback.EVENT.register(new HudRender()); - - if(!invalid_implementations.isEmpty()){ - BooleanPool.put("WarningScreen", false); - ClientTickEvents.START_CLIENT_TICK.register((client)->{ - if(BooleanPool.get("WarningScreen")) return; - - if(MC.currentScreen instanceof TitleScreen) { - MC.executeTask(()->MC.setScreen(new WarningScreen(invalid_implementations))); - BooleanPool.put("WarningScreen", true); - } - }); - } - } - - - private void saveWidgetsSafely(File widgetsFile, List widgets) { - try { - WidgetManager.saveWidgets(widgetsFile, widgets); - } catch (IOException e) { - logger.error("Failed to save widgets. Widgets passed: {}", widgets); - throw new RuntimeException(e); - } - } - - private List> getRegisteredIntegrations() { - return new ArrayList<>(FabricLoader.getInstance() - .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class)); - } - - /** - * This makes it so that if minecraft is launched with the program arguments - *

- * {@code --dynamicHudTest true} - *

- * then it will - * load the {@link DynamicHudTest} class as an entrypoint, eliminating any errors due to human incapacity of - * adding/removing a single line from the `fabric.mod.json` - */ - private EntrypointContainer getTestIntegration() { - DynamicHudIntegration testIntegration; - try { - Class testClass = Class.forName("com.tanishisherewith.dynamichud.DynamicHudTest"); - testIntegration = (DynamicHudIntegration) testClass.getDeclaredConstructor().newInstance(); - } catch (ClassNotFoundException e) { - logger.info("DynamicHudTest class not found. Skipping test integration."); - return null; - } catch (Exception e) { - logger.error("Error instantiating DynamicHudTest", e); - return null; - } - - return new EntrypointContainer<>() { - @Override - public DynamicHudIntegration getEntrypoint() { - return testIntegration; - } - - @Override - public ModContainer getProvider() { - return FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow(); - } - }; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java index 49ed9f4..63ae883 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java +++ b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud; +import com.tanishisherewith.dynamichud.integration.IntegrationManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.gui.DrawContext; @@ -13,7 +14,7 @@ public class HudRender implements HudRenderCallback { @Override public void onHudRender(DrawContext drawContext, RenderTickCounter tickCounter) { - for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { + for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) { widgetRenderer.renderWidgets(drawContext, -120, -120); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java similarity index 63% rename from src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java rename to src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 1384991..1d98d6c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -1,24 +1,19 @@ package com.tanishisherewith.dynamichud; +import com.tanishisherewith.dynamichud.integration.DynamicHudConfigurator; +import com.tanishisherewith.dynamichud.integration.DynamicHudIntegration; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetManager; -import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.widgets.TextWidget; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; -import java.util.List; - -public class DynamicHudTest implements DynamicHudIntegration { +public class IntegrationTest implements DynamicHudIntegration { TextWidget FPSWidget; TextWidget HelloWidget; TextWidget DynamicHUDWidget; DynamicValueRegistry registry; - WidgetRenderer renderer; @Override public void init() { @@ -31,8 +26,8 @@ public void init() { registry.registerLocal("DynamicHUD", () -> "DynamicHUD"); FPSWidget = new TextWidget.Builder() - .setX(MinecraftClient.getInstance().getWindow().getScaledWidth()/2) - .setY(100) + .setX(250) + .setY(150) .setDraggable(true) .rainbow(false) .setDRKey("FPS") @@ -49,6 +44,7 @@ public void init() { .setDVR(registry) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) + .shadow(true) .build(); DynamicHUDWidget = new TextWidget.Builder() @@ -65,10 +61,17 @@ public void init() { } @Override - public void addWidgets() { - WidgetManager.addWidget(FPSWidget); - WidgetManager.addWidget(HelloWidget); - WidgetManager.addWidget(DynamicHUDWidget); + public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { + configurator.addWidget(FPSWidget) + .addWidget(HelloWidget) + .addWidget(DynamicHUDWidget) + .configureRenderer(renderer -> { + renderer.shouldRenderInGameHud(true); + renderer.addScreen(TitleScreen.class); + }) + .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {}); + + return configurator; } @Override @@ -76,24 +79,4 @@ public void registerCustomWidgets() { //WidgetManager.addWidgetData(MyWidget.DATA); } - public void initAfter() { - List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); - - renderer = new WidgetRenderer(widgets); - renderer.shouldRenderInGameHud(true); - - //This will make widgets render in the titlescreen as well. - renderer.addScreen(TitleScreen.class); - } - - @Override - public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor Screen"), renderer) {}; - } - - @Override - public WidgetRenderer getWidgetRenderer() { - return renderer; - } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java new file mode 100644 index 0000000..fda9425 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java @@ -0,0 +1,27 @@ +package com.tanishisherewith.dynamichud.integration; + +import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widgets.ItemWidget; +import com.tanishisherewith.dynamichud.widgets.TextWidget; + +/** + * The default implementation for included widgets. + */ +public class DefaultIntegrationImpl implements DynamicHudIntegration { + @Override + public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { + configurator.markAsUtility = true; + return configurator; + } + + @Override + public void init() {} + + @Override + public void registerCustomWidgets() { + WidgetManager.registerCustomWidgets( + TextWidget.DATA, + ItemWidget.DATA + ); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java new file mode 100644 index 0000000..0ba2e2f --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java @@ -0,0 +1,119 @@ +package com.tanishisherewith.dynamichud.integration; + +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import org.jetbrains.annotations.ApiStatus; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +import static com.tanishisherewith.dynamichud.integration.IntegrationManager.FILE_MAP; + +public class DynamicHudConfigurator { + private final List widgets = new ArrayList<>(); + private WidgetRenderer renderer; + private Consumer> saveHandler = widgetsList -> {}; + private AbstractMoveableScreen screen = null; + public boolean markAsUtility = false; // A.k.a we don't want this mod to display a hud. + + public DynamicHudConfigurator addWidget(Widget widget){ + this.widgets.add(widget); + return this; + } + + public DynamicHudConfigurator configureRenderer(Consumer wrConsumer) { + return configureRenderer(wrConsumer, widgets); + } + + public DynamicHudConfigurator configureRenderer(Consumer wrConsumer, List widgets) { + this.renderer = new WidgetRenderer(widgets); + wrConsumer.accept(renderer); + return this; + } + /** + * Called before saving these widgets + */ + public DynamicHudConfigurator onSave(Consumer> saveHandler){ + this.saveHandler = saveHandler; + return this; + } + + /** + * Returns the movable screen for the hud screen. + *

+ *

+ * !! Should never be null !! + *

+ *

+ * */ + public DynamicHudConfigurator withMoveableScreen(Function screenProvider) { + this.screen = screenProvider.apply(this); + return this; + } + + /** + * Batch operation + */ + public DynamicHudConfigurator modifyWidgets(Consumer operation) { + widgets.forEach(operation); + return this; + } + + public List getWidgets() { return Collections.unmodifiableList(widgets); } + + public WidgetRenderer getRenderer() { return renderer; } + + public final Consumer> getSaveHandler() { return saveHandler; } + + public final AbstractMoveableScreen getMovableScreen() { + return screen; + } + + /** + * Internal method to save these widgets using fabric API events. + */ + @ApiStatus.Internal + public void setupSaveEvents(File widgetsFile){ + /* === Saving === */ + // Each mod is hooked to the fabric's event system to save its widget. + + //When a player exits a world (SinglePlayer worlds) or a server stops + ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + + // When a resource pack is reloaded. + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + + //When player disconnects + ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + + //When minecraft closes + ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); + } + + @ApiStatus.Internal + public final void registerWidgets(){ + widgets.forEach(WidgetManager::addWidget); + } + + private void saveWidgetsSafely(File widgetsFile, List widgets) { + try { + this.saveHandler.accept(widgets); + WidgetManager.saveWidgets(widgetsFile, widgets); + } catch (IOException e) { + DynamicHUD.logger.error("Failed to save widgets. Widgets passed: {}", widgets); + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java similarity index 71% rename from src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java rename to src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java index 1a8f8df..e4b3f71 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud; +package com.tanishisherewith.dynamichud.integration; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.widget.WidgetData; @@ -41,6 +41,13 @@ public interface DynamicHudIntegration { */ File WIDGETS_FILE = new File(FILE_DIRECTORY, FILENAME); + + /** + * Entry point for configuring DynamicHUD integration. + * @param configurator Configuration context + */ + DynamicHudConfigurator configure(DynamicHudConfigurator configurator); + /** * Initializes the DynamicHud integration. *

@@ -49,11 +56,6 @@ public interface DynamicHudIntegration { */ void init(); - /** - * To be used to add widgets using {@link WidgetManager}. - */ - void addWidgets(); - /** * To register custom widgets. This method can be overridden by implementations. *

@@ -71,15 +73,6 @@ public interface DynamicHudIntegration { default void registerCustomWidgets() { } - /** - * Performs any necessary initialization after the widgets have been added. This method can be overridden by implementations. - *

- * Suggested to be used to initialize a {@link WidgetRenderer} object with the added widgets. - *

- */ - default void initAfter() { - } - /** * Returns the file where widgets are to be saved and loaded from. * @@ -97,26 +90,4 @@ default File getWidgetsFile() { default KeyBinding getKeyBind() { return EDITOR_SCREEN_KEY_BINDING; } - - /** - * Returns the movable screen for the DynamicHud. - *

- *

- * !! Should never be null !! - *

- *

- * - * @return The movable screen. - */ - AbstractMoveableScreen getMovableScreen(); - - /** - * To return a {@link WidgetRenderer} object. - * By default, it returns a widget renderer consisting of all widgets in the {@link WidgetManager} - * - * @return The widget renderer. - */ - default WidgetRenderer getWidgetRenderer() { - return new WidgetRenderer(WidgetManager.getWidgets()); - } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java new file mode 100644 index 0000000..078a807 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java @@ -0,0 +1,218 @@ +package com.tanishisherewith.dynamichud.integration; + +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.internal.ModError; +import com.tanishisherewith.dynamichud.internal.WarningScreen; +import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.utils.BooleanPool; +import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; +import net.fabricmc.loader.api.entrypoint.EntrypointContainer; +import net.fabricmc.loader.api.metadata.ModMetadata; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.option.KeyBinding; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; + +public final class IntegrationManager { + + /** + * This is a map to store the list of widgets for each widget file to be saved. + *

+ * Allows saving widgets across different mods with same save file name. + */ + public static final Map> FILE_MAP = new HashMap<>(); + private static final List widgetRenderers = new ArrayList<>(); + + private static boolean enableTestIntegration = false; + + + public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { + widgetRenderers.add(widgetRenderer); + } + + public static List getWidgetRenderers() { + return widgetRenderers; + } + + /** + * Opens the MovableScreen when the specified key is pressed. + * + * @param key The key to listen for + * @param screen The AbstractMoveableScreen instance to use to set the screen + */ + public static void openScreen(KeyBinding key, AbstractMoveableScreen screen) { + if (key.wasPressed()) { + DynamicHUD.MC.setScreen(screen); + } + } + + private static void checkToEnableTestIntegration(){ + String[] args = FabricLoader.getInstance().getLaunchArguments(true); + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { + enableTestIntegration = Boolean.parseBoolean(args[i + 1]); + break; + } + } + } + + public static void integrate(){ + checkToEnableTestIntegration(); + + printInfo("Integrating mods..."); + + var integrations = new ArrayList<>(getRegisteredIntegrations()); + + if (enableTestIntegration) { + EntrypointContainer testIntegration = getTestIntegration(); + if (testIntegration != null) { + integrations.add(testIntegration); + printInfo("Test integration enabled and loaded successfully."); + } + } + + List invalid_implementations = new ArrayList<>(); + + integrations.forEach(container -> { + //Register custom widget data's by WidgetManager.registerCustomWidgets() first for every entrypoint + container.getEntrypoint().registerCustomWidgets(); + }); + + for (var entrypoint : integrations) { + ModMetadata metadata = entrypoint.getProvider().getMetadata(); + String modId = metadata.getId(); + + AbstractMoveableScreen screen; + KeyBinding binding; + WidgetRenderer widgetRenderer; + File widgetsFile; + try { + DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); + + //Calls the init method + DHIntegration.init(); + + DynamicHudConfigurator configurator = DHIntegration.configure(new DynamicHudConfigurator()); + + if(configurator.markAsUtility) { + printInfo(String.format("Supported utility mod with id %s was found!", modId)); + continue; + } + + printInfo(String.format("Supported mod with id %s was found!", modId)); + + + //Gets the widget file to save and load the widgets from + widgetsFile = DHIntegration.getWidgetsFile(); + + // Get the instance of AbstractMoveableScreen + screen = Objects.requireNonNull(configurator.getMovableScreen(), "AbstractMovableScreen instance should not be null!"); + + // Adds / loads widgets from file + if (WidgetManager.doesWidgetFileExist(widgetsFile)) { + WidgetManager.loadWidgets(widgetsFile); + } else { + configurator.registerWidgets(); + } + + // Get the keybind to open the screen instance + binding = DHIntegration.getKeyBind(); + + //WidgetRenderer with widgets instance + widgetRenderer = configurator.getRenderer(); + + addWidgetRenderer(widgetRenderer); + + updateFileMap(widgetsFile.getName(), widgetRenderer.getWidgets()); + + //Register events for rendering, saving, loading, and opening the hudEditor + ClientTickEvents.START_CLIENT_TICK.register((client) -> openScreen(binding, screen)); + + configurator.setupSaveEvents(widgetsFile); + + printInfo(String.format("Integration of mod %s was successful", modId)); + } catch (Throwable e) { + if (e instanceof IOException) { + DynamicHUD.logger.warn("An IO error has occurred while loading widgets of mod {}", modId, e); + } else { + DynamicHUD.logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); + } + invalid_implementations.add(new ModError(modId, e.getLocalizedMessage().trim())); + } + } + printInfo("(DynamicHUD) Integration of supported mods was successful"); + + + if(!invalid_implementations.isEmpty()){ + BooleanPool.put("WarningScreen", false); + + ClientTickEvents.START_CLIENT_TICK.register((client)->{ + if(BooleanPool.get("WarningScreen")) return; + + if(DynamicHUD.MC.currentScreen instanceof TitleScreen) { + DynamicHUD.MC.setScreen(new WarningScreen(invalid_implementations)); + BooleanPool.put("WarningScreen", true); + } + }); + } + + } + + private static void updateFileMap(String fileName, List widgets) { + FILE_MAP.compute(fileName, (k, v) -> { + // Concat existing and the new widget list. + if (v == null) return new ArrayList<>(widgets); + v.addAll(widgets); + return v; + }); + } + + private static List> getRegisteredIntegrations() { + return new ArrayList<>(FabricLoader.getInstance() + .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class)); + } + + /** + * This makes it so that if minecraft is launched with the program arguments + *

+ * {@code --dynamicHudTest true} + *

+ * then it will + * load the {@link com.tanishisherewith.dynamichud.IntegrationTest} class as an entrypoint, eliminating any errors due to human incapacity of + * adding/removing a single line from the `fabric.mod.json` + */ + private static EntrypointContainer getTestIntegration() { + DynamicHudIntegration testIntegration; + try { + Class testClass = Class.forName("com.tanishisherewith.dynamichud.IntegrationTest"); + testIntegration = (DynamicHudIntegration) testClass.getDeclaredConstructor().newInstance(); + } catch (ClassNotFoundException e) { + DynamicHUD.logger.info("DynamicHudTest class not found. Skipping test integration."); + return null; + } catch (Exception e) { + DynamicHUD.logger.error("Error instantiating DynamicHudTest", e); + return null; + } + + return new EntrypointContainer<>() { + @Override + public DynamicHudIntegration getEntrypoint() { + return testIntegration; + } + + @Override + public ModContainer getProvider() { + return FabricLoader.getInstance().getModContainer(DynamicHUD.MOD_ID).orElseThrow(); + } + }; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java index c62e177..d81a04d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java @@ -1,3 +1,3 @@ package com.tanishisherewith.dynamichud.internal; -public record ModError(String modName,String errorMessage) { } +public record ModError(String modName,String errorMessage) {} diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index 8f8680e..60f368f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.mixins; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.integration.IntegrationManager; import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.minecraft.client.MinecraftClient; @@ -22,7 +23,7 @@ public abstract class ScreenMixin { @Inject(at = @At("RETURN"), method = "render") private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { + for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) { widgetRenderer.renderWidgets(context, mouseX, mouseY); } } @@ -35,7 +36,7 @@ private void onScreenResize(MinecraftClient client, int width, int height, Callb @Inject(at = @At("HEAD"), method = "close") private void onClose(CallbackInfo ci) { - for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { + for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) { widgetRenderer.onCloseScreen(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index fc36f5e..49b49e5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -29,7 +29,7 @@ public void onDisplayed() { public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { widgetRenderer.mouseDragged(mouseX, mouseY, button, GlobalConfig.get().getSnapSize()); ContextMenuManager.getInstance().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - return false; + return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); } @Override @@ -38,7 +38,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { handleClickOnWidget(widgetRenderer.selectedWidget, mouseX, mouseY, button); } ContextMenuManager.getInstance().mouseClicked(mouseX, mouseY, button); - return false; + return super.mouseClicked(mouseX, mouseY, button); } @Override @@ -51,7 +51,7 @@ public boolean charTyped(char chr, int modifiers) { public boolean mouseReleased(double mouseX, double mouseY, int button) { widgetRenderer.mouseReleased(mouseX, mouseY, button); ContextMenuManager.getInstance().mouseReleased(mouseX, mouseY, button); - return false; + return super.mouseReleased(mouseX, mouseY, button); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java index 0305a78..e71f8d5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java @@ -16,5 +16,4 @@ public String description() { public Widget createWidget() { return widgetFactory.get(); } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index 5893b6c..6389f97 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -17,6 +17,7 @@ public class WidgetRenderer { public Widget selectedWidget = null; List widgets; private boolean renderInGameHud = true; + private int Z_Index = 10; /** * Add the list of widgets the widgetRenderer should render @@ -52,6 +53,9 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { Screen currentScreen = DynamicHUD.MC.currentScreen; + context.getMatrices().push(); + context.getMatrices().translate(0,0, Z_Index); + //Render in game hud if (currentScreen == null && renderInGameHud) { for (Widget widget : widgets) { @@ -76,6 +80,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { widget.render(context, 0, 0); } } + context.getMatrices().pop(); } public boolean mouseClicked(double mouseX, double mouseY, int button) { @@ -168,4 +173,8 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } } } + public WidgetRenderer withZIndex(int z_Index){ + this.Z_Index = z_Index; + return this; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 448c1c3..2f11940 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -1,7 +1,7 @@ package com.tanishisherewith.dynamichud.widgets; +import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; @@ -18,10 +18,6 @@ import org.lwjgl.glfw.GLFW; import java.awt.*; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; public class TextWidget extends Widget implements ContextMenuProvider { @@ -74,7 +70,8 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegis } public void createMenu() { - ContextMenuProperties properties = ContextMenuProperties.builder().skin(new ModernSkin()).build(); + boolean dark_mode = false; + ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(dark_mode ? MinecraftSkin.PanelColor.DARK_PANEL : MinecraftSkin.PanelColor.CREAMY)).build(); menu = new ContextMenu<>(getX(), getY(), properties); menu.addOption(new BooleanOption("Shadow", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 6b9036c..60d60a6 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -18,6 +18,10 @@ "license": "MIT", "environment": "client", "entrypoints": { + "dynamicHud": [ + "com.tanishisherewith.dynamichud.integration.DefaultIntegrationImpl" + ], + "client": [ "com.tanishisherewith.dynamichud.DynamicHUD" ] From e840431658de5f7d5a019728e02b392bff91e9d9 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:50:05 +0530 Subject: [PATCH 25/40] Improved code and readability --- .../dynamichud/IntegrationTest.java | 10 +- .../dynamichud/internal/RegistrySource.java | 6 + .../dynamichud/internal/System.java | 2 + .../utils/DynamicValueRegistry.java | 51 ++++--- .../dynamichud/widgets/TextWidget.java | 140 +++++++++--------- 5 files changed, 113 insertions(+), 96 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 1d98d6c..28dacc6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -30,7 +30,7 @@ public void init() { .setY(150) .setDraggable(true) .rainbow(false) - .setDRKey("FPS") + .withRegistryKey("FPS") .setModID(DynamicHUD.MOD_ID) .shouldScale(false) .build(); @@ -40,8 +40,8 @@ public void init() { .setY(100) .setDraggable(true) .rainbow(false) - .setDRKey("Hello") - .setDVR(registry) + .withRegistryKey("Hello") + .withValueRegistry(registry) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) .shadow(true) @@ -52,8 +52,8 @@ public void init() { .setY(0) .setDraggable(false) .rainbow(true) - .setDRKey("DynamicHUD") - .setDVR(registry) + .withRegistryKey("DynamicHUD") + .withValueRegistry(registry) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) .build(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java b/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java new file mode 100644 index 0000000..f8dacea --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java @@ -0,0 +1,6 @@ +package com.tanishisherewith.dynamichud.internal; + +public enum RegistrySource { + GLOBAL, + LOCAL; +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java index 6651234..2d426d5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -13,6 +14,7 @@ public abstract class System { public System(String modId) { this.modId = modId; + instances.computeIfAbsent(modId, k -> new ArrayList<>()).add((DynamicValueRegistry) this); } public static List getInstances(String modId) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index 8e7a169..c3d37b2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -2,9 +2,7 @@ import com.tanishisherewith.dynamichud.internal.System; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.function.Supplier; /** @@ -27,12 +25,12 @@ public class DynamicValueRegistry extends System { * * @see #localRegistry */ - private static final Map> globalRegistry = new HashMap<>(); + private static final Map> GLOBAL_REGISTRY = new HashMap<>(); /** * A map that holds the local registry of suppliers. * - * @see #globalRegistry + * @see #GLOBAL_REGISTRY */ private final Map> localRegistry = new HashMap<>(); @@ -43,7 +41,6 @@ public class DynamicValueRegistry extends System { */ public DynamicValueRegistry(String modId) { super(modId); - instances.computeIfAbsent(modId, k -> new ArrayList<>()).add(this); } /** @@ -53,7 +50,7 @@ public DynamicValueRegistry(String modId) { * @param supplier The supplier to be registered. */ public static void registerGlobal(String key, Supplier supplier) { - globalRegistry.put(key, supplier); + GLOBAL_REGISTRY.put(key, supplier); } /** @@ -63,7 +60,7 @@ public static void registerGlobal(String key, Supplier supplier) { * @return The supplier registered under the given key, or null if no such supplier exists. */ public static Supplier getGlobal(String key) { - return globalRegistry.get(key); + return GLOBAL_REGISTRY.get(key); } /** @@ -83,15 +80,7 @@ public void registerLocal(String key, Supplier supplier) { * @return The supplier registered under the given key, or null if no such supplier exists. */ public Supplier get(String key) { - // First, try to get the supplier from the local registry - Supplier supplier = localRegistry.get(key); - - // If the supplier is not in the local registry, try the global registry - if (supplier == null) { - supplier = globalRegistry.get(key); - } - - return supplier; + return localRegistry.getOrDefault(key, GLOBAL_REGISTRY.get(key)); } /** @@ -100,6 +89,34 @@ public Supplier get(String key) { * @param map The map to be set as the local registry. */ public void setLocalRegistry(Map> map) { + localRegistry.clear(); localRegistry.putAll(map); } + /** + * Retrieves all instances of DynamicValueRegistry for a specific mod ID. + * + * @param modId The mod ID to search for. + * @return A list of DynamicValueRegistry instances, or an empty list if none exist. + */ + public static List getInstances(String modId) { + return instances.getOrDefault(modId, Collections.emptyList()); + } + + /** + * Removes a supplier from the global registry. + * + * @param key The key of the supplier to remove. + */ + public static void removeGlobal(String key) { + GLOBAL_REGISTRY.remove(key); + } + + /** + * Removes a supplier from the local registry. + * + * @param key The key of the supplier to remove. + */ + public void removeLocal(String key) { + localRegistry.remove(key); + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 2f11940..a7b1805 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -1,8 +1,8 @@ package com.tanishisherewith.dynamichud.widgets; -import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.internal.RegistrySource; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; @@ -10,7 +10,6 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; -import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ModernSkin; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -29,46 +28,57 @@ public class TextWidget extends Widget implements ContextMenuProvider { protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text protected int rainbowSpeed = 2; //Speed of the rainbow effect - protected float rainbowSpread = 0.01f, rainbowSat = 1.0f, rainbowBrightness = 1.0f; + protected float rainbowSpread = 0.01f, rainbowSaturation = 1.0f, rainbowBrightness = 1.0f; Supplier textSupplier; - String dynamicRegistryKey; - DynamicValueRegistry dynamicValueRegistry = null; + private String registryKey; + private RegistrySource registrySource; + private final DynamicValueRegistry valueRegistry; public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); } - /** - * Searches for the supplier within the {@link DynamicValueRegistry#globalRegistry} using the given registryKey - */ - public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow, Color color, String modID) { + public TextWidget(String registryKey, boolean shadow, boolean rainbow, Color color, String modID) { super(DATA, modID); - this.dynamicRegistryKey = dynamicRegistryKey; - this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); + this.registrySource = RegistrySource.GLOBAL; + this.registryKey = registryKey; this.shadow = shadow; this.rainbow = rainbow; this.textColor = color; + this.valueRegistry = null; + initializeTextSupplier(); createMenu(); ContextMenuManager.getInstance().registerProvider(this); } - /** - * Searches for the supplier within the {@link DynamicValueRegistry#localRegistry} using the given registryKey and registryValue - */ - public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegistryKey, boolean shadow, boolean rainbow, Color color, String modID) { + public TextWidget(DynamicValueRegistry valueRegistry, String registryKey, boolean shadow, + boolean rainbow, Color color, String modID) { super(DATA, modID); - this.dynamicRegistryKey = dynamicRegistryKey; - this.dynamicValueRegistry = dynamicValueRegistry; - if (dynamicValueRegistry != null) { - textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); - } - this.textColor = color; + this.registrySource = RegistrySource.LOCAL; + this.valueRegistry = valueRegistry; + this.registryKey = registryKey; this.shadow = shadow; this.rainbow = rainbow; + this.textColor = color; + initializeTextSupplier(); createMenu(); ContextMenuManager.getInstance().registerProvider(this); } + @SuppressWarnings("unchecked") + private void initializeTextSupplier() { + switch (registrySource) { + case GLOBAL: + this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(registryKey); + break; + case LOCAL: + if (valueRegistry != null) { + this.textSupplier = (Supplier) valueRegistry.get(registryKey); + } + break; + } + } + public void createMenu() { boolean dark_mode = false; ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(dark_mode ? MinecraftSkin.PanelColor.DARK_PANEL : MinecraftSkin.PanelColor.CREAMY)).build(); @@ -103,7 +113,7 @@ public void createMenu() { menu.addOption(new DoubleOption( "Rainbow Saturation", 0, 1.0f, 0.1f, - () -> (double) this.rainbowSat, value -> this.rainbowSat = value.floatValue(), menu) + () -> (double) this.rainbowSaturation, value -> this.rainbowSaturation = value.floatValue(), menu) .setShouldRender(() -> this.rainbow) .withComplexity(Option.Complexity.Pro) ); @@ -151,7 +161,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { if (textSupplier != null) { String text = textSupplier.get(); if(rainbow){ - DrawHelper.drawChromaText(drawContext,text,getX() + 2, getY() + 2, rainbowSpeed/2f,rainbowSat,rainbowBrightness,rainbowSpread,shadow); + DrawHelper.drawChromaText(drawContext,text,getX() + 2, getY() + 2, rainbowSpeed/2f,rainbowSaturation,rainbowBrightness,rainbowSpread,shadow); } else { drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow); } @@ -187,45 +197,31 @@ public void onClose() { @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); - tag.putString("DynamicRegistryKey", dynamicRegistryKey); + tag.putString("RegistryKey", registryKey); tag.putBoolean("Shadow", shadow); tag.putBoolean("Rainbow", rainbow); tag.putInt("TextColor", textColor.getRGB()); tag.putInt("RainbowSpeed", rainbowSpeed); tag.putFloat("RainbowSpread", rainbowSpread); - tag.putFloat("RainbowSaturation", rainbowSat); + tag.putFloat("RainbowSaturation", rainbowSaturation); tag.putFloat("RainbowBrightness", rainbowBrightness); - - // If true then it means that we should use local registry and if false (i.e. null) then use global registry - tag.putBoolean("DynamicValueRegistry", dynamicValueRegistry != null); + tag.putString("RegistrySource", registrySource.name()); } @Override public void readFromTag(NbtCompound tag) { super.readFromTag(tag); - this.shadow = tag.getBoolean("Shadow"); - this.rainbow = tag.getBoolean("Rainbow"); - this.rainbowSpeed = tag.getInt("RainbowSpeed"); - this.rainbowSpread = tag.getInt("RainbowSpread"); - this.rainbowSat = tag.getInt("RainbowSaturation"); - this.rainbowBrightness = tag.getInt("RainbowBrightness"); - this.textColor = new Color(tag.getInt("TextColor")); - this.dynamicRegistryKey = tag.getString("DynamicRegistryKey"); - - // If true then it means that we should use local registry and if false (i.e. null) then use global registry - boolean dvrObj = tag.getBoolean("DynamicValueRegistry"); - if (!dvrObj) { - this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); - return; - } - - for (DynamicValueRegistry dvr : DynamicValueRegistry.getInstances(modId)) { - //Unfortunately, this method takes the value from the first local registry with the key. - //It returns to prevent overriding with other registries - this.textSupplier = (Supplier) dvr.get(dynamicRegistryKey); - dynamicValueRegistry = dvr; - return; - } + shadow = tag.getBoolean("Shadow"); + rainbow = tag.getBoolean("Rainbow"); + rainbowSpeed = tag.getInt("RainbowSpeed"); + rainbowSpread = tag.getFloat("RainbowSpread"); + rainbowSaturation = tag.getFloat("RainbowSaturation"); + rainbowBrightness = tag.getFloat("RainbowBrightness"); + textColor = new Color(tag.getInt("TextColor")); + registryKey = tag.getString("RegistryKey"); + registrySource = RegistrySource.valueOf(tag.getString("RegistrySource")); + + initializeTextSupplier(); createMenu(); } @@ -235,35 +231,35 @@ public ContextMenu getContextMenu() { } public static class Builder extends WidgetBuilder { - protected boolean shadow = false; - protected boolean rainbow = false; - protected String dynamicRegistryKey = ""; - DynamicValueRegistry dynamicValueRegistry = null; - Color textColor = Color.WHITE; + private boolean shadow = false; + private boolean rainbow = false; + private String registryKey = ""; + private DynamicValueRegistry valueRegistry = null; + private Color textColor = Color.WHITE; public Builder shadow(boolean shadow) { this.shadow = shadow; - return self(); + return this; } public Builder rainbow(boolean rainbow) { this.rainbow = rainbow; - return self(); + return this; } - public Builder setDRKey(String dynamicRegistryKey) { - this.dynamicRegistryKey = dynamicRegistryKey; - return self(); + public Builder withRegistryKey(String registryKey) { + this.registryKey = registryKey; + return this; } - public Builder setDVR(DynamicValueRegistry dynamicValueRegistry) { - this.dynamicValueRegistry = dynamicValueRegistry; - return self(); + public Builder withValueRegistry(DynamicValueRegistry valueRegistry) { + this.valueRegistry = valueRegistry; + return this; } - public Builder setTextColor(Color textColor) { + public Builder textColor(Color textColor) { this.textColor = textColor; - return self(); + return this; } @Override @@ -273,18 +269,14 @@ protected Builder self() { @Override public TextWidget build() { - TextWidget widget; - if (dynamicValueRegistry == null) { - widget = new TextWidget(dynamicRegistryKey, shadow, rainbow, textColor, modID); - } else { - widget = new TextWidget(dynamicValueRegistry, dynamicRegistryKey, shadow, rainbow, textColor, modID); - } + TextWidget widget = (valueRegistry == null) ? + new TextWidget(registryKey, shadow, rainbow, textColor, modID) : + new TextWidget(valueRegistry, registryKey, shadow, rainbow, textColor, modID); + widget.setPosition(x, y); widget.setDraggable(isDraggable); widget.setShouldScale(shouldScale); return widget; } } - - } From 58ccff01c0c7eff59e715c27bf3886c6c3999860 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:58:26 +0530 Subject: [PATCH 26/40] Error fix --- .../dynamichud/IntegrationTest.java | 7 +++---- .../dynamichud/utils/Util.java | 1 - .../dynamichud/widgets/TextWidget.java | 18 ++++++++++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 28dacc6..17d396d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -4,7 +4,6 @@ import com.tanishisherewith.dynamichud.integration.DynamicHudIntegration; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widgets.TextWidget; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; @@ -18,7 +17,8 @@ public class IntegrationTest implements DynamicHudIntegration { @Override public void init() { //Global registry - DynamicValueRegistry.registerGlobal("FPS", () -> "FPS: " + DynamicHUD.MC.getCurrentFps()); + // We recommend using the syntax "modid:key_name" for easier debugging and to prevent data conflicts in global registries. + DynamicValueRegistry.registerGlobal("dynamichud:FPS", () -> "FPS: " + DynamicHUD.MC.getCurrentFps()); //Local registry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); @@ -30,7 +30,7 @@ public void init() { .setY(150) .setDraggable(true) .rainbow(false) - .withRegistryKey("FPS") + .withRegistryKey("dynamichud:FPS") .setModID(DynamicHUD.MOD_ID) .shouldScale(false) .build(); @@ -78,5 +78,4 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { public void registerCustomWidgets() { //WidgetManager.addWidgetData(MyWidget.DATA); } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java index b7f2ccc..94b384b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java @@ -25,5 +25,4 @@ public static Quadrant getQuadrant(int x, int y) { public enum Quadrant { UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index a7b1805..599c468 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud.widgets; +import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.internal.RegistrySource; @@ -32,7 +33,7 @@ public class TextWidget extends Widget implements ContextMenuProvider { Supplier textSupplier; private String registryKey; private RegistrySource registrySource; - private final DynamicValueRegistry valueRegistry; + private DynamicValueRegistry valueRegistry; public TextWidget() { this(null, null, false, false, Color.WHITE, "unknown"); @@ -219,7 +220,20 @@ public void readFromTag(NbtCompound tag) { rainbowBrightness = tag.getFloat("RainbowBrightness"); textColor = new Color(tag.getInt("TextColor")); registryKey = tag.getString("RegistryKey"); - registrySource = RegistrySource.valueOf(tag.getString("RegistrySource")); + registrySource = tag.contains("RegistrySource") ? RegistrySource.valueOf(tag.getString("RegistrySource")) : RegistrySource.LOCAL; + + if(registrySource == RegistrySource.LOCAL){ + //Search all instance of DVR to find if a value for the key is valid. + for(DynamicValueRegistry dvr: DynamicValueRegistry.getInstances(modId)) { + if (dvr.get(registryKey) != null) { + valueRegistry = dvr; + } + } + } + + if(valueRegistry == null){ + throw new RuntimeException("Local DynamicValueRegistry not found for: " + registryKey); + } initializeTextSupplier(); createMenu(); From 04daabe02c88d0fc963a9144674402b8808bd59a Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sun, 23 Feb 2025 19:37:10 +0530 Subject: [PATCH 27/40] wrong scope --- .../dynamichud/utils/contextmenu/ContextMenu.java | 1 + .../tanishisherewith/dynamichud/widgets/TextWidget.java | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index fb12b2f..bced000 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations; import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 599c468..ed7473d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -1,6 +1,5 @@ package com.tanishisherewith.dynamichud.widgets; -import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.internal.RegistrySource; @@ -229,10 +228,9 @@ public void readFromTag(NbtCompound tag) { valueRegistry = dvr; } } - } - - if(valueRegistry == null){ - throw new RuntimeException("Local DynamicValueRegistry not found for: " + registryKey); + if(valueRegistry == null){ + throw new RuntimeException("Local DynamicValueRegistry not found for: " + registryKey); + } } initializeTextSupplier(); From 263cf5750c4c9f3bed3408a4be39fd55aeaeb4d0 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 13 Mar 2025 22:17:20 +0530 Subject: [PATCH 28/40] Bit of improvements. --- .../dynamichud/config/GlobalConfig.java | 13 +++ .../integration/DynamicHudIntegration.java | 1 - .../integration/IntegrationManager.java | 1 + .../screens/AbstractMoveableScreen.java | 25 ++++- .../dynamichud/utils/Input.java | 2 +- .../utils/contextmenu/ContextMenu.java | 4 +- .../utils/contextmenu/ContextMenuManager.java | 4 +- .../utils/contextmenu/options/Option.java | 2 +- .../dynamichud/widget/UserManageable.java | 5 + .../dynamichud/widget/Widget.java | 29 +++++- .../dynamichud/widget/WidgetManager.java | 4 + .../dynamichud/widget/WidgetRenderer.java | 99 ++++++++++++------- .../dynamichud/widgets/TextWidget.java | 24 +---- 13 files changed, 141 insertions(+), 72 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index c771c26..1d21a5c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -34,6 +34,9 @@ public final class GlobalConfig { @SerialEntry private boolean showColorPickerPreview = true; + @SerialEntry + private boolean renderInDebugScreen = false; + @SerialEntry private boolean forceSameContextMenuSkin = true; @@ -69,6 +72,12 @@ public Screen createYACLGUI() { .binding(1.0f, () -> this.scale, newVal -> this.scale = newVal) .controller(floatOption -> FloatSliderControllerBuilder.create(floatOption).range(0.1f, 2.5f).step(0.1f)) .build()) + .option(Option.createBuilder() + .name(Text.literal("Render in debug screen")) + .description(OptionDescription.of(Text.literal("Renders widgets even when the debug screen is on"))) + .binding(true, () -> this.renderInDebugScreen, newVal -> this.renderInDebugScreen = newVal) + .controller(booleanOption -> BooleanControllerBuilder.create(booleanOption).yesNoFormatter()) + .build()) .option(Option.createBuilder() .name(Text.literal("Show Color picker preview")) .description(OptionDescription.of(Text.literal("Shows the preview below your mouse pointer on selecting color from the screen. Note: You may drop some frames with the preview on."))) @@ -127,6 +136,10 @@ public boolean shouldDisplayDescriptions() { return displayDescriptions; } + public boolean renderInDebugScreen() { + return renderInDebugScreen; + } + public int getSnapSize() { return snapSize; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java index e4b3f71..db4de32 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java @@ -3,7 +3,6 @@ import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.widget.WidgetData; import com.tanishisherewith.dynamichud.widget.WidgetManager; -import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.option.KeyBinding; diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java index 078a807..b068403 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java @@ -152,6 +152,7 @@ public static void integrate(){ printInfo("(DynamicHUD) Integration of supported mods was successful"); + // Sheesh if(!invalid_implementations.isEmpty()){ BooleanPool.put("WarningScreen", false); diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 49b49e5..d15cc75 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -11,23 +11,32 @@ public abstract class AbstractMoveableScreen extends Screen { public final WidgetRenderer widgetRenderer; + //TrayWidget trayWidget; /** * Constructs a AbstractMoveableScreen object. */ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { super(title); this.widgetRenderer = renderer; + // this.trayWidget = new TrayWidget(width - 210,height - 10); + } + + @Override + protected void init() { + super.init(); } @Override public void onDisplayed() { super.onDisplayed(); + // this.trayWidget.updatePosition(width, height); + // trayWidget.setFocused(true); widgetRenderer.isInEditor = true; } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - widgetRenderer.mouseDragged(mouseX, mouseY, button, GlobalConfig.get().getSnapSize()); + widgetRenderer.mouseDragged(mouseX, mouseY, button,deltaX,deltaY, GlobalConfig.get().getSnapSize()); ContextMenuManager.getInstance().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); } @@ -43,7 +52,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { @Override public boolean charTyped(char chr, int modifiers) { - ContextMenuManager.getInstance().charTyped(chr); + widgetRenderer.charTyped(chr,modifiers); + ContextMenuManager.getInstance().charTyped(chr,modifiers); return super.charTyped(chr, modifiers); } @@ -56,14 +66,20 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - widgetRenderer.keyPressed(keyCode); + widgetRenderer.keyPressed(keyCode, scanCode, modifiers); ContextMenuManager.getInstance().keyPressed(keyCode, scanCode, modifiers); + /* + if(widgetRenderer.selectedWidget != null && (keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE)){ + trayWidget.minimizeWidget(widgetRenderer.selectedWidget); + } + + */ return super.keyPressed(keyCode, scanCode, modifiers); } @Override public boolean keyReleased(int keyCode, int scanCode, int modifiers) { - widgetRenderer.keyReleased(keyCode); + widgetRenderer.keyReleased(keyCode, scanCode, modifiers); ContextMenuManager.getInstance().keyReleased(keyCode, scanCode, modifiers); return super.keyReleased(keyCode, scanCode, modifiers); } @@ -105,6 +121,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) } } } + // trayWidget.render(drawContext,mouseX,mouseY,delta); } public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) {} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java index cd2ad2e..2e621d7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Input.java @@ -18,5 +18,5 @@ default boolean isMouseOver(double mouseX, double mouseY, double x, double y, do return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } - void charTyped(char c); + void charTyped(char c, int modifiers); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index bced000..7944880 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -190,10 +190,10 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, } @Override - public void charTyped(char c) { + public void charTyped(char c, int modifiers) { if (!shouldDisplay) return; for (Option option : options) { - option.charTyped(c); + option.charTyped(c, modifiers); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java index 4aa8ae9..6197d4a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java @@ -99,11 +99,11 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, } @Override - public void charTyped(char c) { + public void charTyped(char c, int modifiers) { for (ContextMenuProvider provider : providers) { ContextMenu contextMenu = provider.getContextMenu(); if (contextMenu != null) { - contextMenu.charTyped(c); + contextMenu.charTyped(c, modifiers); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java index 0b73009..250e4f8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java @@ -89,7 +89,7 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, public void keyPressed(int key, int scanCode, int modifiers) {} @Override - public void charTyped(char c) {} + public void charTyped(char c, int modifiers) {} @Override public void keyReleased(int key, int scanCode, int modifiers) {} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java b/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java new file mode 100644 index 0000000..a6493ec --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java @@ -0,0 +1,5 @@ +package com.tanishisherewith.dynamichud.widget; + +public interface UserManageable { + // Marker interface that a widget is add-able and removable. +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 3f0f7c2..f0543dd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.internal.UID; +import com.tanishisherewith.dynamichud.utils.Input; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; @@ -10,7 +11,7 @@ import net.minecraft.util.math.MathHelper; import org.lwjgl.glfw.GLFW; -public abstract class Widget { +public abstract class Widget implements Input { public static MinecraftClient mc = MinecraftClient.getInstance(); public WidgetData DATA; /** @@ -161,6 +162,7 @@ public boolean isOverlapping(Widget other) { public final void render(DrawContext drawContext, int mouseX, int mouseY) { if (!isVisible()) return; + if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().getScale()); } @@ -214,6 +216,7 @@ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { renderWidget(context, mouseX, mouseY); } + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { toggle(); @@ -234,7 +237,12 @@ public void clampPosition() { this.y = (int) MathHelper.clamp(this.y, 0, mc.getWindow().getScaledHeight() - getHeight()); } - public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { + @Override + public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return false; + } + + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY, int snapSize) { if (!isDraggable) return false; if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { int newX = (int) (mouseX - startX); @@ -263,8 +271,10 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi return false; } - public void mouseReleased(double mouseX, double mouseY, int button) { + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { dragging = false; + return true; } /** @@ -273,8 +283,17 @@ public void mouseReleased(double mouseX, double mouseY, int button) { * @param vAmount vertical amount of scrolling * @param hAmount horizontal amount of scrolling */ - public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { - } + @Override + public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) {} + + @Override + public void keyPressed(int key, int scanCode, int modifiers) {} + + @Override + public void keyReleased(int key, int scanCode, int modifiers) {} + + @Override + public void charTyped(char c, int modifiers) {} public boolean toggle() { return this.isVisible = !this.isVisible; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index 9437b07..b761dcd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -230,4 +230,8 @@ public static List getWidgetsForMod(String modID) { .filter(widget -> modID.equalsIgnoreCase(widget.getModId())) .toList(); } + + public static Map> getWidgetDataMap() { + return widgetDataMap; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index 6389f97..30e0beb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -1,7 +1,9 @@ package com.tanishisherewith.dynamichud.widget; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreen; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.GameMenuScreen; @@ -11,13 +13,13 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -public class WidgetRenderer { +public class WidgetRenderer implements Input { public final List> allowedScreens = new CopyOnWriteArrayList<>(); public boolean isInEditor = false; public Widget selectedWidget = null; List widgets; private boolean renderInGameHud = true; - private int Z_Index = 10; + private int Z_Index = 100; /** * Add the list of widgets the widgetRenderer should render @@ -48,8 +50,15 @@ public void shouldRenderInGameHud(boolean renderInGameHud) { this.renderInGameHud = renderInGameHud; } + private boolean renderInDebugScreen(){ + if(GlobalConfig.get().renderInDebugScreen()){ + return true; + } + return !DynamicHUD.MC.getDebugHud().shouldShowDebugHud(); + } + public void renderWidgets(DrawContext context, int mouseX, int mouseY) { - if (WidgetManager.getWidgets().isEmpty() || DynamicHUD.MC.getDebugHud().shouldShowDebugHud()) return; + if (WidgetManager.getWidgets().isEmpty() || !renderInDebugScreen()) return; Screen currentScreen = DynamicHUD.MC.currentScreen; @@ -83,6 +92,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { context.getMatrices().pop(); } + @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { Screen currentScreen = DynamicHUD.MC.currentScreen; if (currentScreen == null) { @@ -102,77 +112,92 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return false; } - public void mouseDragged(double mouseX, double mouseY, int button, int snapSize) { + @Override + public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { Screen currentScreen = DynamicHUD.MC.currentScreen; if (currentScreen == null) { return; } if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - // This essentially acts as a Z - layer where the widget first in the list is moved and dragged - // if they are overlapped on each other. - if (widget.mouseDragged(mouseX, mouseY, button, snapSize)) { - selectedWidget = widget; - return; - } + widget.mouseScrolled(mouseX, mouseY, vAmount, hAmount); } - selectedWidget = null; } } - public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { - Screen currentScreen = DynamicHUD.MC.currentScreen; - if (currentScreen == null) { - return; - } - if (currentScreen instanceof AbstractMoveableScreen) { + @Override + public void charTyped(char c, int modifiers) {} + + public void onCloseScreen() { + if (DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - widget.mouseScrolled(mouseX, mouseY, vAmount, hAmount); + widget.onClose(); } } } - public void keyPressed(int keyCode) { + public List getWidgets() { + return widgets; + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { + if (currentScreen == null) { + return false; + } + if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - widget.isShiftDown = true; + widget.mouseReleased(mouseX, mouseY, button); } } + return false; } - public void keyReleased(int keyCode) { + @Override + public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + return false; + } + + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY, int snapSize) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { + if (currentScreen == null) { + return false; + } + if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - widget.isShiftDown = false; + // This essentially acts as a Z - layer where the widget first in the list is moved and dragged + // if they are overlapped on each other. + if (widget.mouseDragged(mouseX, mouseY, button, deltaX, deltaY, snapSize)) { + selectedWidget = widget; + return true; + } } + selectedWidget = null; } + return false; } - public void onCloseScreen() { - if (DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen) { + @Override + public void keyPressed(int key, int scanCode, int modifiers) { + Screen currentScreen = DynamicHUD.MC.currentScreen; + if (currentScreen instanceof AbstractMoveableScreen && (key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { - widget.onClose(); + widget.isShiftDown = true; } } } - public List getWidgets() { - return widgets; - } - - public void mouseReleased(double mouseX, double mouseY, int button) { + @Override + public void keyReleased(int key, int scanCode, int modifiers) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if (currentScreen == null) { - return; - } - if (currentScreen instanceof AbstractMoveableScreen) { + if (currentScreen instanceof AbstractMoveableScreen && (key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { - widget.mouseReleased(mouseX, mouseY, button); + widget.isShiftDown = false; } } } + public WidgetRenderer withZIndex(int z_Index){ this.Z_Index = z_Index; return this; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index ed7473d..40e8fc6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -68,14 +68,12 @@ public TextWidget(DynamicValueRegistry valueRegistry, String registryKey, boolea @SuppressWarnings("unchecked") private void initializeTextSupplier() { switch (registrySource) { - case GLOBAL: - this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(registryKey); - break; - case LOCAL: + case GLOBAL -> this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(registryKey); + case LOCAL -> { if (valueRegistry != null) { this.textSupplier = (Supplier) valueRegistry.get(registryKey); } - break; + } } } @@ -148,7 +146,6 @@ public void createMenu() { subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows3", () -> this.shadow, value -> this.shadow = value)); subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows4", () -> this.shadow, value -> this.shadow = value)); menu.addOption(subMenuOption); - */ } @@ -156,8 +153,8 @@ public void createMenu() { @Override public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { if(menu == null) return; - - int color = /*rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) :*/ textColor.getRGB(); + //int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) : textColor.getRGB(); + int color = textColor.getRGB(); if (textSupplier != null) { String text = textSupplier.get(); if(rainbow){ @@ -169,7 +166,6 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { } menu.set(getX(), getY(), (int) Math.ceil(getHeight())); } - @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) { @@ -178,16 +174,6 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { return super.mouseClicked(mouseX, mouseY, button); } - @Override - public void mouseReleased(double mouseX, double mouseY, int button) { - super.mouseReleased(mouseX, mouseY, button); - } - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { - return super.mouseDragged(mouseX, mouseY, button, snapSize); - } - @Override public void onClose() { super.onClose(); From d20247e97b922862b304c1c606289697453481a9 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 19 Mar 2025 00:14:02 +0530 Subject: [PATCH 29/40] Fixed soo many bugs. Polished but now its a bit bloated. --- .../dynamichud/IntegrationTest.java | 3 +- .../integration/DynamicHudConfigurator.java | 18 +++++- .../integration/DynamicHudIntegration.java | 6 ++ .../integration/IntegrationManager.java | 12 ++-- .../dynamichud/internal/System.java | 33 +++++----- .../screens/AbstractMoveableScreen.java | 10 +--- .../utils/DynamicValueRegistry.java | 6 +- .../utils/contextmenu/ContextMenu.java | 7 ++- .../ContextMenuScreenRegistry.java | 11 ++++ .../contextmenu/options/BooleanOption.java | 12 ++-- .../contextmenu/options/ColorOption.java | 3 +- .../contextmenu/options/DoubleOption.java | 3 +- .../utils/contextmenu/options/EnumOption.java | 4 +- .../utils/contextmenu/options/ListOption.java | 4 +- .../utils/contextmenu/options/Option.java | 17 +++--- .../contextmenu/options/OptionGroup.java | 3 +- .../contextmenu/options/RunnableOption.java | 9 +-- .../contextmenu/options/SubMenuOption.java | 13 ++-- .../contextmenu/skinsystem/MinecraftSkin.java | 18 +++--- .../contextmenu/skinsystem/ModernSkin.java | 22 +++---- .../dynamichud/widget/Widget.java | 39 +++++++----- .../dynamichud/widget/WidgetManager.java | 11 ++-- .../dynamichud/widget/WidgetRenderer.java | 60 +++++++++++++------ .../dynamichud/widgets/TextWidget.java | 59 +++++++++--------- 24 files changed, 231 insertions(+), 152 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 17d396d..6f53f22 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -66,7 +66,8 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { .addWidget(HelloWidget) .addWidget(DynamicHUDWidget) .configureRenderer(renderer -> { - renderer.shouldRenderInGameHud(true); + //Already true by default + //renderer.shouldRenderInGameHud(true); renderer.addScreen(TitleScreen.class); }) .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {}); diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java index 0ba2e2f..f8446c9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java @@ -32,8 +32,15 @@ public DynamicHudConfigurator addWidget(Widget widget){ return this; } + /** + * Configure the existing renderer object with this method + */ public DynamicHudConfigurator configureRenderer(Consumer wrConsumer) { - return configureRenderer(wrConsumer, widgets); + if(renderer == null){ + this.renderer = new WidgetRenderer(widgets); + } + wrConsumer.accept(renderer); + return this; } public DynamicHudConfigurator configureRenderer(Consumer wrConsumer, List widgets) { @@ -41,6 +48,15 @@ public DynamicHudConfigurator configureRenderer(Consumer wrConsu wrConsumer.accept(renderer); return this; } + + /** + * Override the present widget renderer with your own instance + */ + public DynamicHudConfigurator overrideRenderer(WidgetRenderer renderer) { + this.renderer = renderer; + return this; + } + /** * Called before saving these widgets */ diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java index db4de32..14dacdd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.widget.WidgetData; import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.option.KeyBinding; @@ -55,6 +56,11 @@ public interface DynamicHudIntegration { */ void init(); + /** + * This method is called after widgets from the widget file have been loaded successfully and added to the renderer. + */ + default void postWidgetLoading(WidgetRenderer renderer) {} + /** * To register custom widgets. This method can be overridden by implementations. *

diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java index b068403..832fea9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java @@ -110,20 +110,22 @@ public static void integrate(){ printInfo(String.format("Supported mod with id %s was found!", modId)); - //Gets the widget file to save and load the widgets from widgetsFile = DHIntegration.getWidgetsFile(); - // Get the instance of AbstractMoveableScreen - screen = Objects.requireNonNull(configurator.getMovableScreen(), "AbstractMovableScreen instance should not be null!"); - // Adds / loads widgets from file if (WidgetManager.doesWidgetFileExist(widgetsFile)) { - WidgetManager.loadWidgets(widgetsFile); + List widgets = WidgetManager.loadWidgets(widgetsFile); + configurator.configureRenderer(renderer -> renderer.clearAndAdd(widgets)); + DHIntegration.postWidgetLoading(configurator.getRenderer()); } else { configurator.registerWidgets(); } + + // Get the instance of AbstractMoveableScreen + screen = Objects.requireNonNull(configurator.getMovableScreen(), "AbstractMovableScreen instance should not be null!"); + // Get the keybind to open the screen instance binding = DHIntegration.getKeyBind(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java index 2d426d5..73fa8b0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java @@ -2,26 +2,31 @@ import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; public abstract class System { // A map to store all instances of DynamicValueRegistry by modId - protected static final Map> instances = new ConcurrentHashMap<>(); - protected final String modId; + private static final Map, Map>> instanceRegistry = new HashMap<>(); - public System(String modId) { - this.modId = modId; - instances.computeIfAbsent(modId, k -> new ArrayList<>()).add((DynamicValueRegistry) this); + public static void registerInstance(Object instance, String modId) { + Class cls = instance.getClass(); + Map> modMap = instanceRegistry.computeIfAbsent(cls, k -> new HashMap<>()); + Set list = modMap.computeIfAbsent(modId, k -> new HashSet<>()); + list.add(instance); } - public static List getInstances(String modId) { - return instances.get(modId); - } - - public String getModId() { - return modId; + public static List getInstances(Class cls, String modId) { + Map> modMap = instanceRegistry.get(cls); + if (modMap == null) return Collections.emptyList(); + Set list = modMap.get(modId); + if (list == null) return Collections.emptyList(); + List typedList = new ArrayList<>(); + for (Object obj : list) { + if (cls.isInstance(obj)) { + typedList.add(cls.cast(obj)); + } + } + return typedList; } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index d15cc75..8b2bae6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -7,18 +7,17 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; public abstract class AbstractMoveableScreen extends Screen { public final WidgetRenderer widgetRenderer; - //TrayWidget trayWidget; /** * Constructs a AbstractMoveableScreen object. */ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { super(title); this.widgetRenderer = renderer; - // this.trayWidget = new TrayWidget(width - 210,height - 10); } @Override @@ -29,8 +28,6 @@ protected void init() { @Override public void onDisplayed() { super.onDisplayed(); - // this.trayWidget.updatePosition(width, height); - // trayWidget.setFocused(true); widgetRenderer.isInEditor = true; } @@ -68,12 +65,10 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyPressed(keyCode, scanCode, modifiers); ContextMenuManager.getInstance().keyPressed(keyCode, scanCode, modifiers); - /* if(widgetRenderer.selectedWidget != null && (keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE)){ - trayWidget.minimizeWidget(widgetRenderer.selectedWidget); + // trayWidget.minimizeWidget(widgetRenderer.selectedWidget); } - */ return super.keyPressed(keyCode, scanCode, modifiers); } @@ -121,7 +116,6 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) } } } - // trayWidget.render(drawContext,mouseX,mouseY,delta); } public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) {} diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index c3d37b2..8291ddf 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -19,7 +19,7 @@ * *

*/ -public class DynamicValueRegistry extends System { +public class DynamicValueRegistry { /** * A map that holds the global registry of suppliers. * @@ -40,7 +40,7 @@ public class DynamicValueRegistry extends System { * @param modId The ID of the mod for which this registry is being created. Doesn't need to be modId, it can simply be used as a standard unique identifier string. */ public DynamicValueRegistry(String modId) { - super(modId); + System.registerInstance(this,modId); } /** @@ -99,7 +99,7 @@ public void setLocalRegistry(Map> map) { * @return A list of DynamicValueRegistry instances, or an empty list if none exist. */ public static List getInstances(String modId) { - return instances.getOrDefault(modId, Collections.emptyList()); + return System.getInstances(DynamicValueRegistry.class, modId); } /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 7944880..3d7b59a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -2,9 +2,10 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations; +import com.tanishisherewith.dynamichud.internal.System; import com.tanishisherewith.dynamichud.utils.Input; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; import net.minecraft.client.gui.DrawContext; @@ -19,6 +20,7 @@ import java.util.List; import java.util.Objects; +@SuppressWarnings({"rawtypes", "unchecked"}) public class ContextMenu implements Input { public final Color darkerBackgroundColor; //The properties of a context menu @@ -57,6 +59,9 @@ public ContextMenu(int x, int y, @NotNull T properties, ContextMenuScreenFactory this.darkerBackgroundColor = properties.getBackgroundColor().darker().darker().darker().darker().darker().darker(); this.parentMenu = parentMenu; this.properties.getSkin().setContextMenu(this); + + Screen dummy = screenFactory.create(this, properties); + System.registerInstance(new ContextMenuScreenRegistry(dummy.getClass()), DynamicHUD.MOD_ID); } public void addOption(Option option) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java new file mode 100644 index 0000000..5b06044 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java @@ -0,0 +1,11 @@ +package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen; + +import net.minecraft.client.gui.screen.Screen; + +public class ContextMenuScreenRegistry{ + public Class screenKlass; + + public ContextMenuScreenRegistry(Class screenKlass){ + this.screenKlass = screenKlass; + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index 93ff89c..1427b94 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -12,23 +12,23 @@ public class BooleanOption extends Option { private final BooleanType booleanType; - public BooleanOption(String name, Supplier getter, Consumer setter, BooleanType booleanType) { + public BooleanOption(Text name, Supplier getter, Consumer setter, BooleanType booleanType) { super(name,getter, setter); this.booleanType = booleanType; this.renderer.init(this); } - public BooleanOption(String name, Supplier getter, Consumer setter) { + public BooleanOption(Text name, Supplier getter, Consumer setter) { this(name, getter, setter, BooleanType.TRUE_FALSE); } - public BooleanOption(String name, boolean defaultValue) { + public BooleanOption(Text name, boolean defaultValue) { this(name, defaultValue, BooleanType.TRUE_FALSE); } - public BooleanOption(String name, boolean defaultValue, BooleanType type) { - this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), type); - BooleanPool.put(name, defaultValue); + public BooleanOption(Text name, boolean defaultValue, BooleanType type) { + this(name, () -> BooleanPool.get(name.getString()), value -> BooleanPool.put(name.getString(), value), type); + BooleanPool.put(name.getString(), defaultValue); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 6c6ad24..548d18f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorGradient; +import net.minecraft.text.Text; import java.awt.*; import java.util.function.Consumer; @@ -12,7 +13,7 @@ public class ColorOption extends Option { private ContextMenu parentMenu = null; private ColorGradient colorGradient = null; - public ColorOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + public ColorOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter) { super(name,getter, setter); this.parentMenu = parentMenu; this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index d4a55bd..9e8e17e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import org.apache.commons.lang3.Validate; import org.lwjgl.glfw.GLFW; @@ -19,7 +20,7 @@ public class DoubleOption extends Option { ContextMenu parentMenu; private boolean isDragging = false; - public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { + public DoubleOption(Text name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { super(name,getter, setter); this.value = get(); this.minValue = minValue; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index f28db96..e2bb820 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -1,5 +1,7 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; +import net.minecraft.text.Text; + import java.util.function.Consumer; import java.util.function.Supplier; @@ -7,7 +9,7 @@ public class EnumOption> extends Option { private final E[] values; private int currentIndex = 0; - public EnumOption(String name, Supplier getter, Consumer setter, E[] values) { + public EnumOption(Text name, Supplier getter, Consumer setter, E[] values) { super(name,getter, setter); this.values = values; this.value = get(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index 5622356..c2eadf1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -1,5 +1,7 @@ package com.tanishisherewith.dynamichud.utils.contextmenu.options; +import net.minecraft.text.Text; + import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; @@ -8,7 +10,7 @@ public class ListOption extends Option { private final List values; private int currentIndex = 0; - public ListOption(String name, Supplier getter, Consumer setter, List values) { + public ListOption(Text name, Supplier getter, Consumer setter, List values) { super(name,getter, setter); this.values = values; this.value = getter.get(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java index 250e4f8..009303c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java @@ -7,12 +7,13 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; import java.util.function.Consumer; import java.util.function.Supplier; public abstract class Option implements Input { - public String name = "Empty", description = ""; + public Text name, description = Text.empty(); public T value = null; protected int x, y; protected int width = 0; @@ -26,11 +27,11 @@ public abstract class Option implements Input { protected SkinRenderer> renderer; protected Complexity complexity = Complexity.Simple; - public Option(String name,Supplier getter, Consumer setter) { + public Option(Text name,Supplier getter, Consumer setter) { this(name,getter, setter, () -> true); } - public Option(String name,Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) { + public Option(Text name,Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) { this.name = name; this.getter = getter; this.setter = setter; @@ -40,7 +41,7 @@ public Option(String name,Supplier getter, Consumer setter, Supplier getter, Consumer setter, Supplier shouldRender) { + public Option(Text name,Supplier getter, Consumer setter, Supplier shouldRender) { this(name,getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified()); } @@ -103,7 +104,7 @@ public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } - public Option setShouldRender(Supplier shouldRender) { + public Option renderWhen(Supplier shouldRender) { this.shouldRender = shouldRender; return this; } @@ -155,7 +156,7 @@ public void setPosition(int x, int y) { this.x = x; this.y = y; } - public Option description(String description){ + public Option description(Text description){ this.description = description; return this; } @@ -168,11 +169,11 @@ public SkinRenderer> getRenderer() { return renderer; } - public String getName() { + public Text getName() { return name; } - public String getDescription() { + public Text getDescription() { return description; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java index 0e4b148..56e2ecc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; import java.util.ArrayList; import java.util.Collections; @@ -13,7 +14,7 @@ public class OptionGroup extends Option { private final List> groupOptions = new ArrayList<>(); protected boolean expanded; // Skins can choose to use this or ignore it - public OptionGroup(String name) { + public OptionGroup(Text name) { super(name, () -> null, (v) -> {}, () -> true); this.expanded = false; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index bff5e07..75c25fa 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -2,6 +2,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.utils.BooleanPool; +import net.minecraft.text.Text; import java.util.function.Consumer; import java.util.function.Supplier; @@ -18,16 +19,16 @@ public class RunnableOption extends Option { * @param setter Return a boolean based on if the task is running or not. * @param task The task to run */ - public RunnableOption(String name, Supplier getter, Consumer setter, Runnable task) { + public RunnableOption(Text name, Supplier getter, Consumer setter, Runnable task) { super(name,getter, setter); this.name = name; this.task = task; this.renderer.init(this); } - public RunnableOption(String name, boolean defaultValue, Runnable task) { - this(name, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), task); - BooleanPool.put(name, defaultValue); + public RunnableOption(Text name, boolean defaultValue, Runnable task) { + this(name, () -> BooleanPool.get(name.getString()), value -> BooleanPool.put(name.getString(), value), task); + BooleanPool.put(name.getString(), defaultValue); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index aed4a94..708c4a9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.utils.BooleanPool; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import net.minecraft.text.Text; import java.util.Objects; import java.util.function.Consumer; @@ -18,7 +19,7 @@ public class SubMenuOption extends Option { private final ContextMenu subMenu; - public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter, T properties) { + public SubMenuOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter, T properties) { super(name,getter, setter); Objects.requireNonNull(parentMenu, "Parent Context Menu cannot be null in [" + name + "] SubMenu option"); this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties); @@ -27,16 +28,16 @@ public SubMenuOption(String name, ContextMenu< this.renderer.init(this); } - public SubMenuOption(String name, ContextMenu parentMenu, T properties) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), properties); + public SubMenuOption(Text name, ContextMenu parentMenu, T properties) { + this(name, parentMenu, () -> BooleanPool.get(name.getString()), value -> BooleanPool.put(name.getString(), value), properties); } - public SubMenuOption(String name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + public SubMenuOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter) { this(name, parentMenu, getter, setter, parentMenu.getProperties().cloneWithSkin()); } - public SubMenuOption(String name, ContextMenu parentMenu) { - this(name, parentMenu, () -> BooleanPool.get(name), value -> BooleanPool.put(name, value), parentMenu.getProperties().cloneWithSkin()); + public SubMenuOption(Text name, ContextMenu parentMenu) { + this(name, parentMenu, () -> BooleanPool.get(name.getString()), value -> BooleanPool.put(name.getString(), value), parentMenu.getProperties().cloneWithSkin()); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index d4cef43..a779116 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -18,8 +18,6 @@ import org.lwjgl.glfw.GLFW; import java.awt.*; -import java.math.BigDecimal; -import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.function.IntSupplier; @@ -54,8 +52,8 @@ public class MinecraftSkin extends Skin implements GroupableSkin { private List optionGroups; private OptionGroup selectedGroup; private final ScrollHandler groupScrollHandler; - private int groupPanelWidth = 60; // Width for the group panel - private IntSupplier groupPanelX = ()-> imageX - groupPanelWidth - 15; + private final int groupPanelWidth = 60; // Width for the group panel + private final IntSupplier groupPanelX = () -> imageX - groupPanelWidth - 15; public MinecraftSkin(PanelColor color) { super(); @@ -78,11 +76,11 @@ public MinecraftSkin(PanelColor color) { } private void enableContextMenuScissor() { - DrawHelper.enableScissor(0, imageY + 3, mc.getWindow().getScaledWidth(), panelHeight - 6); + DrawHelper.enableScissor(0, imageY + 3, mc.getWindow().getScaledWidth(), panelHeight - 8); } private void createGroups() { - OptionGroup generalGroup = new OptionGroup("General"); + OptionGroup generalGroup = new OptionGroup(Text.of("General")); for(Option option: getOptions(contextMenu)){ if(option instanceof OptionGroup og){ optionGroups.add(og); @@ -104,8 +102,6 @@ private void initOptionGroups(){ } } - - @Override public void renderContextMenu(DrawContext drawContext, ContextMenu contextMenu, int mouseX, int mouseY) { this.contextMenu = contextMenu; @@ -188,7 +184,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) if (yOffset >= groupY + 12 && yOffset <= groupY + panelHeight - 15) { drawContext.drawGuiTexture(TEXTURES.get(!group.isExpanded(), isMouseOver(mouseX, mouseY, groupX, yOffset, groupPanelWidth, 20)), groupX, yOffset, groupPanelWidth, 20); - DrawHelper.drawScrollableText(drawContext,mc.textRenderer,Text.literal(group.getName()),groupX + groupPanelWidth/2,groupX + 2,yOffset,groupX + groupPanelWidth - 2, yOffset + 20,-1); + DrawHelper.drawScrollableText(drawContext,mc.textRenderer, group.getName(),groupX + groupPanelWidth/2,groupX + 2,yOffset,groupX + groupPanelWidth - 2, yOffset + 20,-1); //Scrollable text uses scissor, so we need to enable the context menu scissor again this.enableContextMenuScissor(); @@ -208,7 +204,9 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) private int renderSelectedGroupOptions(DrawContext drawContext, int mouseX, int mouseY) { int yOffset = imageY + 12 - scrollHandler.getScrollOffset(); for (Option option : selectedGroup.getGroupOptions()) { - if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight && option.shouldRender()) { + if(!option.shouldRender()) continue; + + if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight) { option.render(drawContext, imageX + 4, yOffset, mouseX, mouseY); } yOffset += option.getHeight() + 1; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java index c5f87bc..add7d0f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java @@ -17,8 +17,8 @@ import net.minecraft.sound.SoundEvents; import net.minecraft.text.OrderedText; import net.minecraft.text.StringVisitable; +import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec2f; import org.lwjgl.glfw.GLFW; import java.awt.*; @@ -29,21 +29,21 @@ public class ModernSkin extends Skin implements GroupableSkin { private final Color themeColor; private final float radius; - private final String defaultToolTipHeader; - private final String defaultToolTipText; + private final Text defaultToolTipHeader; + private final Text defaultToolTipText; Color DARK_GRAY = new Color(20, 20, 20, 229); Color DARKER_GRAY_2 = new Color(12,12,12,246); Color DARKER_GRAY = new Color(10, 10, 10, 243); private int contextMenuX = 0, contextMenuY = 0; private int width = 0, height = 0; private float scaledWidth = 0, scaledHeight = 0; - private String TOOLTIP_TEXT; - private String TOOLTIP_HEAD; + private Text TOOLTIP_TEXT; + private Text TOOLTIP_HEAD; private static int SCALE_FACTOR = 4; private final ScrollHandler scrollHandler; - public ModernSkin(Color themeColor, float radius, String defaultToolTipHeader, String defaultToolTipText) { + public ModernSkin(Color themeColor, float radius, Text defaultToolTipHeader, Text defaultToolTipText) { this.themeColor = themeColor; this.radius = radius; TOOLTIP_TEXT = defaultToolTipText; @@ -65,7 +65,7 @@ public ModernSkin(Color themeColor, float radius, String defaultToolTipHeader, S } public ModernSkin(Color themeColor, float radius) { - this(themeColor, radius, "Example Tip", "Hover over a setting to see its tool-tip (if present) here!"); + this(themeColor, radius, Text.of("Example Tip"), Text.of("Hover over a setting to see its tool-tip (if present) here!")); } public ModernSkin(Color themeColor) { @@ -213,7 +213,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) { int toolTipWidth = (int) (width * 0.2f) + 4; int toolTipHeight = (int) (height * 0.16f); - if (!TOOLTIP_TEXT.isEmpty()) { + if (!TOOLTIP_TEXT.getString().isEmpty()) { toolTipHeight = Math.max(toolTipHeight, mc.textRenderer.getWrappedLinesHeight(TOOLTIP_TEXT, toolTipWidth)) + 18; toolTipHeight = Math.min(height - 23, toolTipHeight); } @@ -239,7 +239,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) { ColorHelper.changeAlpha(Color.WHITE, 175).getRGB() ); - if (TOOLTIP_TEXT.isEmpty() || TOOLTIP_HEAD.isEmpty()) { + if (TOOLTIP_TEXT.getString().isEmpty() || TOOLTIP_HEAD.getString().isEmpty()) { setTooltipText(defaultToolTipHeader, defaultToolTipText); return; } @@ -254,7 +254,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) { true ); - List wrappedText = mc.textRenderer.wrapLines(StringVisitable.plain(TOOLTIP_TEXT), toolTipWidth); + List wrappedText = mc.textRenderer.wrapLines(StringVisitable.styled(TOOLTIP_TEXT.getString(),TOOLTIP_TEXT.getStyle()), toolTipWidth); DrawHelper.scaleAndPosition(drawContext.getMatrices(), contextMenuX + 4, tooltipY + 19, textScale); @@ -277,7 +277,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) { setTooltipText(defaultToolTipHeader, defaultToolTipText); } - public void setTooltipText(String head_text, String tooltip_text) { + public void setTooltipText(Text head_text, Text tooltip_text) { TOOLTIP_TEXT = tooltip_text; TOOLTIP_HEAD = head_text; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index f0543dd..cb5f209 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -40,20 +40,22 @@ public abstract class Widget implements Input { public String modId = "unknown"; public Text tooltipText; + // Boolean to know if the widget is currently being displayed in an instance of AbstractMoveableScreen protected boolean isInEditor = false; + // Absolute position of the widget on screen in pixels. protected int x, y; protected boolean shouldScale = true; - private final Anchor anchor; // The chosen anchor point + protected Anchor anchor; // The chosen anchor point //Dimensions of the widget protected WidgetBox widgetBox; - int startX, startY; - private int offsetX, offsetY; // Offset from the anchor point + private int startX, startY; + protected int offsetX, offsetY; // Offset from the anchor point public Widget(WidgetData DATA, String modId) { this(DATA, modId, Anchor.CENTER); @@ -111,7 +113,7 @@ private int getAnchorX(int screenWidth) { return switch (anchor) { case TOP_RIGHT, BOTTOM_RIGHT -> screenWidth; case CENTER -> screenWidth / 2; - default -> 0; // TOP_LEFT and BOTTOM_LEFT + default -> 0; // TOP_LEFT and BOTTOM_LEFT }; } @@ -119,21 +121,20 @@ private int getAnchorY(int screenHeight) { return switch (anchor) { case BOTTOM_LEFT, BOTTOM_RIGHT -> screenHeight; case CENTER -> screenHeight / 2; - default -> 0; // TOP_LEFT and TOP_RIGHT + default -> 0; // TOP_LEFT and TOP_RIGHT }; } // Update position based on anchor and offset void updatePosition(int screenWidth, int screenHeight) { - if (offsetX == 0 || offsetY == 0) { - calculateOffset(x, y, screenWidth, screenHeight); + if(offsetX == 0 || offsetY == 0){ + calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); } int anchorX = getAnchorX(screenWidth); int anchorY = getAnchorY(screenHeight); this.x = anchorX + offsetX; this.y = anchorY + offsetY; - clampPosition(); } @@ -141,9 +142,8 @@ public void setPosition(int x, int y) { this.x = x; this.y = y; if (mc.getWindow() != null) { - //updatePercentages(); - calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Set initial offset - updatePosition(mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Initial placement + calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); + updatePosition(mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); } } @@ -329,8 +329,11 @@ protected void setTooltipText(Text text){ public void readFromTag(NbtCompound tag) { modId = tag.getString("modId"); uid = new UID(tag.getString("UID")); - x = tag.getInt("x"); - y = tag.getInt("y"); + // x = tag.getInt("x"); + // y = tag.getInt("y"); + anchor = Anchor.valueOf(tag.getString("anchor")); + offsetX = tag.getInt("offsetX"); + offsetY = tag.getInt("offsetY"); isVisible = tag.getBoolean("isVisible"); isDraggable = tag.getBoolean("isDraggable"); shouldScale = tag.getBoolean("shouldScale"); @@ -347,10 +350,12 @@ public void writeToTag(NbtCompound tag) { tag.putString("UID", uid.getUniqueID()); tag.putBoolean("isDraggable", isDraggable); tag.putBoolean("shouldScale", shouldScale); - tag.putInt("x", x); - tag.putInt("y", y); + // tag.putInt("x", x); + // tag.putInt("y", y); + tag.putString("anchor", anchor.name()); + tag.putInt("offsetX", offsetX); + tag.putInt("offsetY", offsetY); tag.putBoolean("isVisible", isVisible); - } public boolean isVisible() { @@ -379,6 +384,8 @@ public String toString() { "uniqueId='" + uid.getUniqueID() + '\'' + ", x=" + x + ", y=" + y + + ", offsetX=" + offsetX + + ", offsetY=" + offsetY + ", isVisible=" + isVisible + ", isDraggable=" + isDraggable + ", shiftDown=" + isShiftDown + diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index b761dcd..788c5dc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -178,9 +178,7 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti * * @param file The file to load from */ - public static void loadWidgets(File file) throws IOException { - widgets.clear(); - + public static List loadWidgets(File file) throws IOException { if (!file.exists()) { DynamicHUD.logger.warn("Main file {} was not found... Loading from a found backup file", file.getAbsolutePath()); file = new File(file.getAbsolutePath() + ".backup"); @@ -190,21 +188,24 @@ public static void loadWidgets(File file) throws IOException { if (rootTag == null) { printWarn("RootTag is null. File is either empty or corrupted: " + file); - return; + return Collections.emptyList(); } NbtList widgetList = rootTag.getList("widgets", NbtElement.COMPOUND_TYPE); if (widgetList == null) { printWarn("WidgetList is null. File is empty: " + file); - return; + return Collections.emptyList(); } + List widgetsToAdd = new ArrayList<>(); for (int i = 0; i < widgetList.size(); i++) { NbtCompound widgetTag = widgetList.getCompound(i); WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); Widget widget = widgetData.createWidget(); widget.readFromTag(widgetTag); printInfo("Loaded Widget: " + widget); + widgetsToAdd.add(widget); widgets.add(widget); } + return widgetsToAdd; } public static boolean doesWidgetFileExist(File file) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index 30e0beb..03c4b74 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -2,19 +2,20 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.config.GlobalConfig; +import com.tanishisherewith.dynamichud.internal.System; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.utils.Input; -import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreen; +import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.Screen; import org.lwjgl.glfw.GLFW; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Predicate; public class WidgetRenderer implements Input { - public final List> allowedScreens = new CopyOnWriteArrayList<>(); + private Predicate allowedScreens; public boolean isInEditor = false; public Widget selectedWidget = null; List widgets; @@ -30,8 +31,9 @@ public class WidgetRenderer implements Input { */ public WidgetRenderer(List widgets) { this.widgets = widgets; - addScreen(GameMenuScreen.class); - addScreen(ContextMenuScreen.class); + // Render in GameMenuScreen + this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class || + System.getInstances(ContextMenuScreenRegistry.class, DynamicHUD.MOD_ID).stream().anyMatch(registry -> registry.screenKlass == screen.getClass()); } public WidgetRenderer(String modID) { @@ -39,11 +41,41 @@ public WidgetRenderer(String modID) { } public void addWidget(Widget widget) { - widgets.add(widget); + this.widgets.add(widget); + } + public void removeWidget(Widget widget){ + this.widgets.remove(widget); + } + + public void clearAndAdd(List widgets) { + this.widgets.clear(); + this.widgets.addAll(widgets); } + /** + * Use this when you want to simply add more screens + */ public void addScreen(Class screen) { - allowedScreens.add(screen); + this.allowedScreens = allowedScreens.or(screen1 -> screen1.getClass() == screen); + } + + /** + * Use this when you want a more complex approach to rendering your widgets + */ + public Predicate getAllowedScreens() { + return this.allowedScreens; + } + + public void updateAllowedScreens(Predicate newAllowedScreens) { + this.allowedScreens = newAllowedScreens; + } + + public void negateAllowedScreens() { + allowedScreens = allowedScreens.negate(); + } + + public boolean isScreenAllowed(Screen screen) { + return allowedScreens.test(screen); } public void shouldRenderInGameHud(boolean renderInGameHud) { @@ -65,15 +97,6 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { context.getMatrices().push(); context.getMatrices().translate(0,0, Z_Index); - //Render in game hud - if (currentScreen == null && renderInGameHud) { - for (Widget widget : widgets) { - widget.isInEditor = false; - widget.render(context, 0, 0); - } - return; - } - //Render in editing screen if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { @@ -82,8 +105,8 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { } return; } - //Render in any other screen - if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass())) { + //Render in any other screen and the inGameHud + if ((currentScreen == null && renderInGameHud) || allowedScreens.test(currentScreen)) { for (Widget widget : widgets) { widget.isInEditor = false; widget.render(context, 0, 0); @@ -202,4 +225,5 @@ public WidgetRenderer withZIndex(int z_Index){ this.Z_Index = z_Index; return this; } + } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 40e8fc6..902f0ee 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -14,6 +14,7 @@ import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; import java.awt.*; @@ -80,57 +81,55 @@ private void initializeTextSupplier() { public void createMenu() { boolean dark_mode = false; ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(dark_mode ? MinecraftSkin.PanelColor.DARK_PANEL : MinecraftSkin.PanelColor.CREAMY)).build(); - menu = new ContextMenu<>(getX(), getY(), properties); - menu.addOption(new BooleanOption("Shadow", + + menu.addOption(new BooleanOption(Text.of("Shadow"), () -> this.shadow, value -> this.shadow = value, - BooleanOption.BooleanType.ON_OFF - ).description("Adds shadow to your text") + BooleanOption.BooleanType.ON_OFF) + .description(Text.of("Adds shadow to your text")) ); - menu.addOption(new BooleanOption("Rainbow", - () -> this.rainbow, value -> this.rainbow = value, BooleanOption.BooleanType.ON_OFF) - .description("Adds rainbow effect to your text") + menu.addOption(new BooleanOption(Text.of("Rainbow"), + () -> this.rainbow, value -> this.rainbow = value, + BooleanOption.BooleanType.ON_OFF) + .description(Text.of("Adds rainbow effect to your text")) ); - menu.addOption(new ColorOption("TextColor", menu, + menu.addOption(new ColorOption(Text.of("Text Color"), menu, () -> this.textColor, value -> this.textColor = value) - .description("Specify the color you want to add to your text") + .description(Text.of("Specify the color you want to add to your text")) + .renderWhen(()-> !this.rainbow) ); - menu.addOption(new DoubleOption( - "RainbowSpeed", + menu.addOption(new DoubleOption(Text.of("Rainbow Speed"), 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu) - .setShouldRender(() -> this.rainbow) + .renderWhen(() -> this.rainbow) ); - menu.addOption(new DoubleOption( - "Rainbow Spread", + menu.addOption(new DoubleOption(Text.of("Rainbow Spread"), 0.001f, 0.15f, 0.001f, () -> (double) this.rainbowSpread, value -> this.rainbowSpread = value.floatValue(), menu) - .setShouldRender(() -> this.rainbow) + .renderWhen(() -> this.rainbow) .withComplexity(Option.Complexity.Enhanced) ); - menu.addOption(new DoubleOption( - "Rainbow Saturation", + menu.addOption(new DoubleOption(Text.of("Rainbow Saturation"), 0, 1.0f, 0.1f, () -> (double) this.rainbowSaturation, value -> this.rainbowSaturation = value.floatValue(), menu) - .setShouldRender(() -> this.rainbow) + .renderWhen(() -> this.rainbow) .withComplexity(Option.Complexity.Pro) ); - menu.addOption(new DoubleOption( - "Rainbow Brightness", + menu.addOption(new DoubleOption(Text.of("Rainbow Brightness"), 0, 1.0f, 0.01f, () -> (double) this.rainbowBrightness, value -> this.rainbowBrightness = value.floatValue(), menu) - .setShouldRender(() -> this.rainbow) + .renderWhen(() -> this.rainbow) .withComplexity(Option.Complexity.Pro) ); /* OptionGroup group = new OptionGroup("Color"); - group.addOption(new ColorOption("TextColor", menu, + group.addOption(new ColorOption(Text.of("TextColor"), menu, () -> this.textColor, value -> this.textColor = value) - .description("Specify the color you want to add to your text") + .description(Text.of("Specify the color you want to add to your text")) ); group.addOption(new DoubleOption( - "RainbowSpeed", + Text.of("RainbowSpeed"), 1, 5.0f, 1, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu) .setShouldRender(() -> this.rainbow) @@ -139,12 +138,12 @@ public void createMenu() { List options = Arrays.asList("List1", "LONGER LIST 2", "List3"); AtomicBoolean running = new AtomicBoolean(false); AtomicBoolean subMenu = new AtomicBoolean(false); - menu.addOption(new ListOption<>("List??? ", option::get, option::set, options)); - menu.addOption(new RunnableOption("Runnable Test", running::get, running::set, () -> System.out.println("Runnable ran"))); - SubMenuOption subMenuOption = new SubMenuOption("SubMenu", menu, subMenu::get, subMenu::set); - subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows2", () -> this.shadow, value -> this.shadow = value)); - subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows3", () -> this.shadow, value -> this.shadow = value)); - subMenuOption.getSubMenu().addOption(new BooleanOption("Shadows4", () -> this.shadow, value -> this.shadow = value)); + menu.addOption(new ListOption<>(Text.of("List??? "), option::get, option::set, options)); + menu.addOption(new RunnableOption(Text.of("Runnable Test"), running::get, running::set, () -> System.out.println("Runnable ran"))); + SubMenuOption subMenuOption = new SubMenuOption(Text.of("SubMenu"), menu, subMenu::get, subMenu::set); + subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows2"), () -> this.shadow, value -> this.shadow = value)); + subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows3"), () -> this.shadow, value -> this.shadow = value)); + subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows4"), () -> this.shadow, value -> this.shadow = value)); menu.addOption(subMenuOption); */ From aef38fde99f9ad7be4c479e49ec873e23dfe3c9b Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 21 Apr 2025 17:06:25 +0530 Subject: [PATCH 30/40] Totally unneeded but cool GraphWidget along with a change to DynamicValueRegistry and fixed option name rendering in ClassicSkin. --- .../dynamichud/IntegrationTest.java | 29 ++ .../integration/DefaultIntegrationImpl.java | 4 +- .../integration/DynamicHudConfigurator.java | 3 +- .../integration/IntegrationManager.java | 14 +- .../dynamichud/internal/WarningScreen.java | 2 +- .../utils/DynamicValueRegistry.java | 96 ++-- .../utils/contextmenu/ContextMenu.java | 8 + .../contextmenu/options/ColorOption.java | 2 +- .../contextmenu/skinsystem/ClassicSkin.java | 22 +- .../dynamichud/widget/WidgetManager.java | 3 + .../dynamichud/widgets/GraphWidget.java | 461 ++++++++++++++++++ .../dynamichud/widgets/TextWidget.java | 33 +- 12 files changed, 592 insertions(+), 85 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 6f53f22..8f5bad1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -4,14 +4,20 @@ import com.tanishisherewith.dynamichud.integration.DynamicHudIntegration; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widgets.GraphWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; +import java.awt.*; + public class IntegrationTest implements DynamicHudIntegration { TextWidget FPSWidget; TextWidget HelloWidget; TextWidget DynamicHUDWidget; + GraphWidget graphWidget; DynamicValueRegistry registry; @Override @@ -58,6 +64,28 @@ public void init() { .shouldScale(true) .build(); + graphWidget = new GraphWidget.GraphWidgetBuilder() + .setX(250) + .setY(100) + .setGraphColor(Color.CYAN) + .setAnchor(Widget.Anchor.CENTER) + .setHeight(100) + .setWidth(150) + .setGridLines(10) + .setBackgroundColor(Color.DARK_GRAY) + .setLineThickness(1f) + .setMaxDataPoints(100) + .setMaxValue(120) + .setMinValue(30) + .setModID(DynamicHUD.MOD_ID) + .setDraggable(true) + .setDisplay(true) + .setShowGrid(true) + .setLabel("FPS Chart") + .build(); + + + graphWidget.addDataPointEveryTick(()-> (float) MinecraftClient.getInstance().getCurrentFps()); } @Override @@ -65,6 +93,7 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { configurator.addWidget(FPSWidget) .addWidget(HelloWidget) .addWidget(DynamicHUDWidget) + .addWidget(graphWidget) .configureRenderer(renderer -> { //Already true by default //renderer.shouldRenderInGameHud(true); diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java index fda9425..ecbf8b2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.integration; import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widgets.GraphWidget; import com.tanishisherewith.dynamichud.widgets.ItemWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; @@ -21,7 +22,8 @@ public void init() {} public void registerCustomWidgets() { WidgetManager.registerCustomWidgets( TextWidget.DATA, - ItemWidget.DATA + ItemWidget.DATA, + GraphWidget.DATA ); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java index f8446c9..e5c100a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java @@ -97,7 +97,7 @@ public final AbstractMoveableScreen getMovableScreen() { } /** - * Internal method to save these widgets using fabric API events. + * Internal method to save these widgets using fabric API events. Should not be called anywhere else except when loading the DHIntegration on startup. */ @ApiStatus.Internal public void setupSaveEvents(File widgetsFile){ @@ -131,5 +131,4 @@ private void saveWidgetsSafely(File widgetsFile, List widgets) { throw new RuntimeException(e); } } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java index 832fea9..1e4851d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java @@ -80,7 +80,7 @@ public static void integrate(){ } } - List invalid_implementations = new ArrayList<>(); + List bad_implementations = new ArrayList<>(); integrations.forEach(container -> { //Register custom widget data's by WidgetManager.registerCustomWidgets() first for every entrypoint @@ -148,22 +148,22 @@ public static void integrate(){ } else { DynamicHUD.logger.error("Mod {} has improper implementation of DynamicHUD", modId, e); } - invalid_implementations.add(new ModError(modId, e.getLocalizedMessage().trim())); + bad_implementations.add(new ModError(modId, e.getLocalizedMessage().trim())); } } printInfo("(DynamicHUD) Integration of supported mods was successful"); // Sheesh - if(!invalid_implementations.isEmpty()){ - BooleanPool.put("WarningScreen", false); + if(!bad_implementations.isEmpty()){ + BooleanPool.put("WarningScreenFlag", false); ClientTickEvents.START_CLIENT_TICK.register((client)->{ - if(BooleanPool.get("WarningScreen")) return; + if(BooleanPool.get("WarningScreenFlag")) return; if(DynamicHUD.MC.currentScreen instanceof TitleScreen) { - DynamicHUD.MC.setScreen(new WarningScreen(invalid_implementations)); - BooleanPool.put("WarningScreen", true); + DynamicHUD.MC.setScreen(new WarningScreen(bad_implementations)); + BooleanPool.put("WarningScreenFlag", true); } }); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java index 329ade2..0c2ac60 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java @@ -50,7 +50,7 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 20, 0xFFFFFF); - context.drawCenteredTextWithShadow(this.textRenderer, "Mods with invalid implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB()); + context.drawCenteredTextWithShadow(this.textRenderer, "Mods with bad implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB()); int y = 60; for (ModError error : modErrors) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index 8291ddf..8081490 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -6,8 +6,8 @@ import java.util.function.Supplier; /** - * This class is responsible for managing dynamic values for widgets. - * It maintains a global and local registry of suppliers for these dynamic values. + * A type-safe registry for managing dynamic values for widgets. + * Supports both global and local registries with unique identifiers. *

* To use a local registry, simple create an object of the class. *

@@ -20,44 +20,45 @@
  * 

*/ public class DynamicValueRegistry { - /** - * A map that holds the global registry of suppliers. - * - * @see #localRegistry - */ + private static final Map REGISTRY_BY_ID = new HashMap<>(); private static final Map> GLOBAL_REGISTRY = new HashMap<>(); - /** - * A map that holds the local registry of suppliers. - * - * @see #GLOBAL_REGISTRY - */ + private final String id; // Unique identifier for this registry instance private final Map> localRegistry = new HashMap<>(); /** - * Constructor for the DynamicValueRegistry class. - * - * @param modId The ID of the mod for which this registry is being created. Doesn't need to be modId, it can simply be used as a standard unique identifier string. + * Constructor for a local registry with a unique ID. + * @param modId The mod ID or unique identifier for grouping registries. + * @param registryId A unique ID for this registry instance. + */ + public DynamicValueRegistry(String modId, String registryId) { + this.id = registryId; + System.registerInstance(this, modId); + REGISTRY_BY_ID.put(registryId, this); + } + /** + * Constructor for a local registry using with registryId as modID. + * @param modId The mod ID or unique identifier for grouping registries. */ public DynamicValueRegistry(String modId) { - System.registerInstance(this,modId); + this.id = modId; + System.registerInstance(this, modId); + REGISTRY_BY_ID.put(modId, this); } /** * Registers a supplier in the global registry. - * - * @param key The key under which the supplier is to be registered. - * @param supplier The supplier to be registered. + * @param key The key for the supplier. + * @param supplier The supplier providing values of type T. */ - public static void registerGlobal(String key, Supplier supplier) { + public static void registerGlobal(String key, Supplier supplier) { GLOBAL_REGISTRY.put(key, supplier); } /** * Retrieves a supplier from the global registry. - * - * @param key The key of the supplier to be retrieved. - * @return The supplier registered under the given key, or null if no such supplier exists. + * @param key The key of the supplier. + * @return The supplier, or null if not found. */ public static Supplier getGlobal(String key) { return GLOBAL_REGISTRY.get(key); @@ -65,38 +66,35 @@ public static Supplier getGlobal(String key) { /** * Registers a supplier in the local registry. - * - * @param key The key under which the supplier is to be registered. - * @param supplier The supplier to be registered. + * @param key The key for the supplier. + * @param supplier The supplier providing values of type T. */ public void registerLocal(String key, Supplier supplier) { localRegistry.put(key, supplier); } /** - * Retrieves a supplier from the local registry, falling back to the global registry if necessary. - * - * @param key The key of the supplier to be retrieved. - * @return The supplier registered under the given key, or null if no such supplier exists. + * Retrieves a supplier from the local or global registry. + * @param key The key of the supplier. + * @return The supplier, or null if not found. */ public Supplier get(String key) { - return localRegistry.getOrDefault(key, GLOBAL_REGISTRY.get(key)); + return localRegistry.getOrDefault(key, null); } /** - * Sets the local registry to the given map. - * - * @param map The map to be set as the local registry. + * Gets the registry instance by its unique ID. + * @param registryId The unique ID of the registry. + * @return The registry instance, or null if not found. */ - public void setLocalRegistry(Map> map) { - localRegistry.clear(); - localRegistry.putAll(map); + public static DynamicValueRegistry getById(String registryId) { + return REGISTRY_BY_ID.get(registryId); } + /** - * Retrieves all instances of DynamicValueRegistry for a specific mod ID. - * - * @param modId The mod ID to search for. - * @return A list of DynamicValueRegistry instances, or an empty list if none exist. + * Retrieves all registry instances for a mod ID. + * @param modId The mod ID. + * @return A list of registries for the mod. */ public static List getInstances(String modId) { return System.getInstances(DynamicValueRegistry.class, modId); @@ -104,8 +102,7 @@ public static List getInstances(String modId) { /** * Removes a supplier from the global registry. - * - * @param key The key of the supplier to remove. + * @param key The key of the supplier. */ public static void removeGlobal(String key) { GLOBAL_REGISTRY.remove(key); @@ -113,10 +110,17 @@ public static void removeGlobal(String key) { /** * Removes a supplier from the local registry. - * - * @param key The key of the supplier to remove. + * @param key The key of the supplier. */ public void removeLocal(String key) { localRegistry.remove(key); } -} + + /** + * Gets the unique ID of this registry. + * @return The registry ID. + */ + public String getId() { + return id; + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 3d7b59a..837afa0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -8,11 +8,13 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory; import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option; +import com.tanishisherewith.dynamichud.widget.WidgetBox; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.lwjgl.glfw.GLFW; import java.awt.*; import java.util.ArrayList; @@ -132,6 +134,12 @@ public void toggleDisplay() { } } + public void toggleDisplay(WidgetBox widgetBox,double mouseX, double mouseY, int button){ + if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) { + toggleDisplay(); + } + } + public void resetAllOptions(){ for(Option option: options){ option.reset(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 548d18f..c222c9a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -13,7 +13,7 @@ public class ColorOption extends Option { private ContextMenu parentMenu = null; private ColorGradient colorGradient = null; - public ColorOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter) { + public ColorOption(Text name, Supplier getter, Consumer setter,ContextMenu parentMenu) { super(name,getter, setter); this.parentMenu = parentMenu; this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100); diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java index 26f5710..6cc8e5a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java @@ -146,7 +146,7 @@ public static class ClassicBooleanRenderer implements SkinRenderer option, int x, int y, option.setHeight(mc.textRenderer.fontHeight + 1); option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1); - drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y, Color.WHITE.getRGB(), false); - drawContext.drawText(mc.textRenderer, Text.of(option.value.name()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); + drawContext.drawText(mc.textRenderer, option.name.copy().append( ": "), x, y, Color.WHITE.getRGB(), false); + drawContext.drawText(mc.textRenderer, option.value.name(), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false); } } @@ -191,7 +191,7 @@ public static class ClassicSubMenuRenderer implements SkinRenderer option, int x, int y, option.setHeight(mc.textRenderer.fontHeight + 1); option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.toString()) + 1); - drawContext.drawText(mc.textRenderer, Text.of(option.name + ": "), x, y + 1, Color.WHITE.getRGB(), false); - drawContext.drawText(mc.textRenderer, Text.of(option.value.toString()), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false); + drawContext.drawText(mc.textRenderer, option.name.copy().append( ": "), x, y + 1, Color.WHITE.getRGB(), false); + drawContext.drawText(mc.textRenderer, option.value.toString(), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false); } } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index 788c5dc..1877de5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -199,6 +199,9 @@ public static List loadWidgets(File file) throws IOException { for (int i = 0; i < widgetList.size(); i++) { NbtCompound widgetTag = widgetList.getCompound(i); WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); + if(widgetData == null){ + throw new IllegalStateException("Widget Data for: " + widgetTag.getString("name") +" could not be found"); + } Widget widget = widgetData.createWidget(); widget.readFromTag(widgetTag); printInfo("Loaded Widget: " + widget); diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java new file mode 100644 index 0000000..2ed69bb --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java @@ -0,0 +1,461 @@ +package com.tanishisherewith.dynamichud.widgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.BooleanOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; +import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.WidgetBox; +import com.tanishisherewith.dynamichud.widget.WidgetData; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; +import org.joml.Matrix4f; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import net.minecraft.client.render.*; + +public class GraphWidget extends Widget implements ContextMenuProvider{ + public static WidgetData DATA = new WidgetData<>("GraphWidget","Show graph",GraphWidget::new); + //private final List dataPoints; + + private ContextMenu menu; + + private final float[] dataPoints; + private int head = 0; + private int maxDataPoints; + private float minValue; + private float maxValue; + private Color graphColor; + private Color backgroundColor; + private float lineThickness; + private boolean showGrid; + private int gridLines; + private float width; + private float height; + private String label; + private Supplier valueSupplier = null; + + public GraphWidget(String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) { + super(DATA, modId, anchor); + dataPoints = new float[maxDataPoints]; + //this.dataPoints = new ArrayList<>(); + this.width = width; + this.height = height; + this.maxDataPoints = maxDataPoints; + this.minValue = minValue; + this.maxValue = maxValue; + this.graphColor = graphColor; + this.backgroundColor = backgroundColor; + this.lineThickness = lineThickness; + this.showGrid = showGrid; + this.gridLines = gridLines; + this.label = label.trim(); + this.widgetBox = new WidgetBox(x, y, (int) width, (int) height); + setTooltipText(Text.of("Graph displaying: " + label)); + + createMenu(); + ContextMenuManager.getInstance().registerProvider(this); + } + + public GraphWidget(){ + this("null",Anchor.CENTER,0,0,0,0,0,Color.RED,Color.GREEN,0,false,0,"empty"); + } + + @Override + public void init() { + // Initialize the buffer with minValue, mimicking ArrayList behavior + for (int i = 0; i < maxDataPoints; i++) { + dataPoints[i] = minValue; + } + } + + public void addDataPoint(float value) { + int index = (head) % maxDataPoints; + dataPoints[index] = MathHelper.clamp(value, minValue, maxValue); + head = (head + 1) % maxDataPoints; // Buffer full, overwrite oldest and move head + } + public void addDataPointEveryTick(Supplier valueSupplier) { + this.valueSupplier = valueSupplier; + } + + private List getInterpolatedPoints() { + List points = new ArrayList<>(); + if (maxDataPoints < 2) return points; + + float xStep = width / (maxDataPoints - 1); + for (int i = 0; i < maxDataPoints - 1; i++) { + int index1 = (head + i) % maxDataPoints; + int index2 = (head + i + 1) % maxDataPoints; + + float x1 = x + i * xStep; + float y1 = y + height - ((dataPoints[index1] - minValue) / (maxValue - minValue) * height); + float x2 = x + (i + 1) * xStep; + float y2 = y + height - ((dataPoints[index2] - minValue) / (maxValue - minValue) * height); + + // Add interpolated points using cubic spline (simplified) + for (float t = 0; t <= 1; t += 0.03f) { + float t2 = t * t; + float t3 = t2 * t; + float h00 = 2 * t3 - 3 * t2 + 1; + float h10 = t3 - 2 * t2 + t; + float h01 = -2 * t3 + 3 * t2; + + float px = h00 * x1 + h10 * xStep + h01 * x2; + float py = h00 * y1 + h10 * (y2 - y1) + h01 * y2; + points.add(new float[]{px, py}); + } + } + return points; + } + + // draw a continuous interpolated curve + private void drawInterpolatedCurve(Matrix4f matrix, List points, int color, float thickness) { + if (points.size() < 2) return; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + float alpha = (float) (color >> 24 & 255) / 255.0F; + + for (int i = 0; i < points.size(); i++) { + float[] point = points.get(i); + float x = point[0]; + float y = point[1]; + + // Create a thick line by offsetting vertices perpendicular to the curve + float dx = (i < points.size() - 1) ? points.get(i + 1)[0] - x : x - points.get(i - 1)[0]; + float dy = (i < points.size() - 1) ? points.get(i + 1)[1] - y : y - points.get(i - 1)[1]; + float length = (float) Math.sqrt(dx * dx + dy * dy); + if (length == 0) continue; + + float offsetX = (thickness * 0.5f * dy) / length; + float offsetY = (thickness * 0.5f * -dx) / length; + + bufferBuilder.vertex(matrix, x + offsetX, y + offsetY, 0).color(red, green, blue, alpha); + bufferBuilder.vertex(matrix, x - offsetX, y - offsetY, 0).color(red, green, blue, alpha); + } + + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableBlend(); + } + + // draw a gradient shadow under the curve + private void drawGradientShadow(Matrix4f matrix, List points, float bottomY, int startColor, int endColor) { + if (points.size() < 2) return; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + + for (float[] point : points) { + float x = point[0]; + float y = point[1]; + + bufferBuilder.vertex(matrix, x, y, 0).color(startColor); + bufferBuilder.vertex(matrix, x, bottomY, 0).color(endColor); + } + + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableBlend(); + } + + @Override + public void renderWidget(DrawContext context, int mouseX, int mouseY) { + Matrix4f matrix = context.getMatrices().peek().getPositionMatrix(); + + if(valueSupplier != null){ + addDataPoint(valueSupplier.get()); + } + + // Apply pulse1 animation to background alpha + float animatedAlpha = MathHelper.clamp(MathAnimations.pulse1(backgroundColor.getAlpha() / 255.0f, 0.2f, 0.001f),0f,1.0f); + Color animatedBackgroundColor = ColorHelper.changeAlpha(backgroundColor, (int) (animatedAlpha * 255)); + Color gradientColor = ColorHelper.changeAlpha(backgroundColor, (int) (animatedAlpha * 255 * 0.7f)); + + DrawHelper.enableScissor(x - 50, y, (int) width + 2 + 50, (int) height + 2); + + // Draw gradient background with rounded corners + if(!isInEditor) { + DrawHelper.drawRoundedGradientRectangle( + matrix, + animatedBackgroundColor, + gradientColor, + gradientColor, + animatedBackgroundColor, + x, y, width, height, 5, + false, true, false, false + ); + } + + // Draw grid lines and value markings + if (showGrid) { + float stepY = height / (gridLines + 1); + float valueStep = (maxValue - minValue) / (gridLines + 1); + + //TODO: The scale is too small for grid lines for than 21 (20 is the barely visible threshold) + float scale = (float) MathHelper.clamp((stepY/9.5),0.0f,1.0f); //~ sqrt of 95 + + for (int i = 1; i <= gridLines; i++) { + float yPos = y + stepY * i; + DrawHelper.drawHorizontalLine(matrix, x, width, yPos, 0.5f, 0x4DFFFFFF); // Semi-transparent white + + // Draw value labels on the left axis + float value = maxValue - (i * valueStep); + String valueText = formatValue(value); + + //Scale the text to its proper position and size with grid lines + DrawHelper.scaleAndPosition(context.getMatrices(), x - 2, yPos, scale); + context.drawText(mc.textRenderer, valueText, x - mc.textRenderer.getWidth(valueText), (int) (yPos - (mc.textRenderer.fontHeight * scale)/2.0f), 0xFFFFFFFF, true); + DrawHelper.stopScaling(context.getMatrices()); + } + + // Draw vertical grid lines (time axis) + float stepX = width / 5; // 5 vertical lines + for (int i = 1; i < 5; i++) { + float xPos = x + stepX * i; + DrawHelper.drawVerticalLine(matrix, xPos, y, height, 0.5f, 0x4DFFFFFF); + } + } + // Draw interpolated graph curve + List points = getInterpolatedPoints(); + drawInterpolatedCurve(matrix, points, graphColor.getRGB(), lineThickness); + + // Draw shadow effect under the graph + drawGradientShadow( + matrix, points, y + height, + ColorHelper.changeAlpha(graphColor,50).getRGB(), + 0x00000000 + ); + + DrawHelper.drawChromaText( + context, label, + x + 5, y + 5, + 1.0f, 0.8f, 1.0f, 0.05f, true + ); + + // Draw axes + DrawHelper.drawHorizontalLine(matrix, x, width, y + height, 1.0f, 0xFFFFFFFF); // X-axis + DrawHelper.drawVerticalLine(matrix, x, y, height, 1.0f, 0xFFFFFFFF); // Y-axis + + // Draw min and max value labels with formatted values + /* + DrawHelper.scaleAndPosition(context.getMatrices(),x - 5,y,0.5f); + String formattedMaxVal = formatValue(maxValue); + context.drawText(mc.textRenderer, formattedMaxVal, x - 5 - mc.textRenderer.getWidth(formattedMaxVal), y - 4, 0xFFFFFFFF, true); + DrawHelper.stopScaling(context.getMatrices()); + + */ + + DrawHelper.scaleAndPosition(context.getMatrices(),x - 5,y + height,0.5f); + String formattedMinVal = formatValue(minValue); + context.drawText(mc.textRenderer, formattedMinVal, x - mc.textRenderer.getWidth(formattedMinVal), (int) (y + height - 4), 0xFFFFFFFF, true); + DrawHelper.stopScaling(context.getMatrices()); + + this.widgetBox.setSizeAndPositionNoScale(x,y,width,height); + DrawHelper.disableScissor(); + + if(menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight())); + } + + // format large values (e.g., 1000 -> "1K", 1000000 -> "1M") + private String formatValue(float value) { + if (Math.abs(value) >= 1_000_000) { + return String.format("%.1fM", value / 1_000_000); + } else if (Math.abs(value) >= 1_000) { + return String.format("%.1fK", value / 1_000); + } else { + return String.format("%.0f", value); + } + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + menu.toggleDisplay(widgetBox,mouseX,mouseY,button); + return super.mouseClicked(mouseX, mouseY, button); + } + + public void createMenu() { + ContextMenuProperties properties = ContextMenuProperties.builder().build(); + menu = new ContextMenu<>(getX(), (int) (getY() + height), properties); + + menu.addOption(new BooleanOption(Text.of("Show Grid"), + () -> this.showGrid, value -> this.showGrid = value, + BooleanOption.BooleanType.YES_NO) + .description(Text.of("Shows a grid and Y axis values")) + ); + menu.addOption(new DoubleOption(Text.of("Number of Grid Lines"), + 1, 25, 1, + () -> (double) this.gridLines, value -> this.gridLines = value.intValue(), menu) + .renderWhen(()-> this.showGrid) + ); + menu.addOption(new ColorOption(Text.of("Graph Line Color"), + () -> this.graphColor, value -> this.graphColor = value, menu) + .description(Text.of("Specify the color you want for the graph's lines")) + ); + menu.addOption(new ColorOption(Text.of("Graph Background Color"), + () -> this.backgroundColor, value -> this.backgroundColor = value, menu) + .description(Text.of("Specify the color you want for the graph's background")) + ); + menu.addOption(new DoubleOption(Text.of("Line Thickness"), + 0.5f, 5.0f, 0.1f, + () -> (double) this.lineThickness, value -> this.lineThickness = value.floatValue(), menu) + ); + } + + @Override + public void readFromTag(NbtCompound tag) { + super.readFromTag(tag); + this.width = tag.getFloat("width"); + this.height = tag.getFloat("height"); + this.maxDataPoints = tag.getInt("maxDataPoints"); + this.minValue = tag.getFloat("minValue"); + this.maxValue = tag.getFloat("maxValue"); + this.graphColor = new Color(tag.getInt("graphColor")); + this.backgroundColor = new Color(tag.getInt("backgroundColor")); + this.lineThickness = tag.getFloat("lineThickness"); + this.showGrid = tag.getBoolean("showGrid"); + this.gridLines = tag.getInt("gridLines"); + this.label = tag.getString("label"); + this.widgetBox = new WidgetBox(x, y, (int) width, (int) height); + + createMenu(); + } + + @Override + public void onClose() { + super.onClose(); + menu.close(); + } + + @Override + public void writeToTag(NbtCompound tag) { + super.writeToTag(tag); + tag.putFloat("width", width); + tag.putFloat("height", height); + tag.putInt("maxDataPoints", maxDataPoints); + tag.putFloat("minValue", minValue); + tag.putFloat("maxValue", maxValue); + tag.putInt("graphColor", graphColor.getRGB()); + tag.putInt("backgroundColor", backgroundColor.getRGB()); + tag.putFloat("lineThickness", lineThickness); + tag.putBoolean("showGrid", showGrid); + tag.putInt("gridLines", gridLines); + tag.putString("label", label); + } + + @Override + public ContextMenu getContextMenu() { + return menu; + } + + public static class GraphWidgetBuilder extends WidgetBuilder { + private Anchor anchor = Anchor.CENTER; + private float width = 100; + private float height = 50; + private int maxDataPoints = 50; + private float minValue = 0; + private float maxValue = 100; + private Color graphColor = new Color(0xFF00FF00); + private Color backgroundColor = new Color(0x80000000); + private float lineThickness = 1.0f; + private boolean showGrid = true; + private int gridLines = 4; + private String label = "Graph"; + + public GraphWidgetBuilder() { + } + + public GraphWidgetBuilder setAnchor(Anchor anchor) { + this.anchor = anchor; + return this; + } + + public GraphWidgetBuilder setWidth(float width) { + this.width = width; + return this; + } + + public GraphWidgetBuilder setHeight(float height) { + this.height = height; + return this; + } + + public GraphWidgetBuilder setMaxDataPoints(int maxDataPoints) { + this.maxDataPoints = maxDataPoints; + return this; + } + + public GraphWidgetBuilder setMinValue(float minValue) { + this.minValue = minValue; + return this; + } + + public GraphWidgetBuilder setMaxValue(float maxValue) { + this.maxValue = maxValue; + return this; + } + + public GraphWidgetBuilder setGraphColor(Color graphColor) { + this.graphColor = graphColor; + return this; + } + + public GraphWidgetBuilder setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + return this; + } + + public GraphWidgetBuilder setLineThickness(float lineThickness) { + this.lineThickness = lineThickness; + return this; + } + + public GraphWidgetBuilder setShowGrid(boolean showGrid) { + this.showGrid = showGrid; + return this; + } + + public GraphWidgetBuilder setGridLines(int gridLines) { + this.gridLines = gridLines; + return this; + } + + public GraphWidgetBuilder setLabel(String label) { + this.label = label; + return this; + } + + @Override + protected GraphWidgetBuilder self() { + return this; + } + + @Override + public GraphWidget build() { + GraphWidget widget = new GraphWidget(modID, anchor, width, height, maxDataPoints, minValue, maxValue, graphColor, backgroundColor, lineThickness, showGrid, gridLines, label); + widget.setPosition(x, y); + widget.setDraggable(isDraggable); + widget.setShouldScale(shouldScale); + widget.isVisible = display; + return widget; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 902f0ee..6d01a5a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -24,7 +24,6 @@ public class TextWidget extends Widget implements ContextMenuProvider { public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); private ContextMenu menu; - public Color textColor; protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text @@ -68,14 +67,16 @@ public TextWidget(DynamicValueRegistry valueRegistry, String registryKey, boolea @SuppressWarnings("unchecked") private void initializeTextSupplier() { - switch (registrySource) { - case GLOBAL -> this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(registryKey); + this.textSupplier = switch (registrySource) { + case GLOBAL -> (Supplier) DynamicValueRegistry.getGlobal(registryKey); case LOCAL -> { if (valueRegistry != null) { - this.textSupplier = (Supplier) valueRegistry.get(registryKey); + yield (Supplier) valueRegistry.get(registryKey); } + throw new IllegalStateException("ValueRegistry is null while initialising text supplier"); } - } + case null -> throw new IllegalStateException("RegistrySource is null while initialising text supplier"); + }; } public void createMenu() { @@ -93,8 +94,8 @@ public void createMenu() { BooleanOption.BooleanType.ON_OFF) .description(Text.of("Adds rainbow effect to your text")) ); - menu.addOption(new ColorOption(Text.of("Text Color"), menu, - () -> this.textColor, value -> this.textColor = value) + menu.addOption(new ColorOption(Text.of("Text Color"), + () -> this.textColor, value -> this.textColor = value, menu) .description(Text.of("Specify the color you want to add to your text")) .renderWhen(()-> !this.rainbow) ); @@ -167,9 +168,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) { - menu.toggleDisplay(); - } + menu.toggleDisplay(widgetBox,mouseX,mouseY,button); return super.mouseClicked(mouseX, mouseY, button); } @@ -182,6 +181,7 @@ public void onClose() { @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); + tag.putString("RegistryID", registrySource == RegistrySource.LOCAL ? valueRegistry.getId() : "global"); tag.putString("RegistryKey", registryKey); tag.putBoolean("Shadow", shadow); tag.putBoolean("Rainbow", rainbow); @@ -207,12 +207,13 @@ public void readFromTag(NbtCompound tag) { registrySource = tag.contains("RegistrySource") ? RegistrySource.valueOf(tag.getString("RegistrySource")) : RegistrySource.LOCAL; if(registrySource == RegistrySource.LOCAL){ - //Search all instance of DVR to find if a value for the key is valid. - for(DynamicValueRegistry dvr: DynamicValueRegistry.getInstances(modId)) { - if (dvr.get(registryKey) != null) { - valueRegistry = dvr; - } - } + String registryID = tag.getString("RegistryID"); + + if(registryID.equalsIgnoreCase("global")) + throw new IllegalStateException("Registry ID found to be global for LOCAL registry source"); + + valueRegistry = DynamicValueRegistry.getById(registryID); + if(valueRegistry == null){ throw new RuntimeException("Local DynamicValueRegistry not found for: " + registryKey); } From 3f81f6cc48d6dde5754994d1551e1549e9deb749 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:13:30 +0530 Subject: [PATCH 31/40] Bump to 1.21.4 --- build.gradle | 2 +- gradle.properties | 11 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- .../dynamichud/helpers/DrawHelper.java | 37 ++++++------ .../dynamichud/helpers/TextureHelper.java | 40 ++++++------- .../contextmenu/skinsystem/MinecraftSkin.java | 59 ++++++++++--------- .../dynamichud/widgets/GraphWidget.java | 42 ++++++------- .../dynamichud/widgets/TextWidget.java | 2 +- 8 files changed, 99 insertions(+), 96 deletions(-) diff --git a/build.gradle b/build.gradle index 5bdb604..ac1ac6e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.7-SNAPSHOT' + id 'fabric-loom' version '1.9-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index b1efe41..25a8eb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,15 +4,16 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loader_version=0.16.2 +minecraft_version=1.21.4 +yarn_mappings=1.21.4+build.1 +loader_version=0.16.9 # Mod Properties +# need versioning system mod_version = 2.2.0 maven_group = com.tanishisherewith archives_base_name = dynamichud # Dependencies -fabric_version=0.102.1+1.21.1 -yacl_version=3.5.0+1.21-fabric \ No newline at end of file +fabric_version=0.111.0+1.21.4 +yacl_version=3.6.6+1.21.4-fabric \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2617362..4eaec46 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index eac55e0..5a6ea1f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -1,10 +1,12 @@ package com.tanishisherewith.dynamichud.helpers; import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.ProjectionType; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.VertexSorter; import com.tanishisherewith.dynamichud.DynamicHUD; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.ShaderProgramKeys; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.*; import net.minecraft.client.util.math.MatrixStack; @@ -24,7 +26,7 @@ * Credits: HeliosClient */ public class DrawHelper { - public static VertexSorter vertexSorter; + public static ProjectionType projectionType; /** * Draws a singular gradient rectangle on screen with the given parameters @@ -55,7 +57,7 @@ public static void drawGradient(Matrix4f matrix4f, float x, float y, float width RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); switch (direction) { case LEFT_RIGHT: @@ -127,7 +129,7 @@ public static void drawRectangle(Matrix4f matrix4f, float x, float y, float widt RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); tessellator.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); @@ -214,7 +216,7 @@ public static void drawRainbowGradientRectangle(Matrix4f matrix4f, float x, floa RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); for (int i = 0; i <= width; i++) { float hue = (float) i / width; @@ -285,7 +287,7 @@ public static void drawRainbowGradient(float x, float y, float width, float heig RenderSystem.enableBlend(); RenderSystem.colorMask(false, false, false, true); RenderSystem.clearColor(0.0F, 0.0F, 0.0F, 0.0F); - RenderSystem.clear(GL40C.GL_COLOR_BUFFER_BIT, false); + RenderSystem.clear(GL40C.GL_COLOR_BUFFER_BIT); RenderSystem.colorMask(true, true, true, true); drawRectangle(matrix4f, x, y, width, height, Color.BLACK.getRGB()); @@ -333,7 +335,7 @@ public static void drawOutlineCircle(Matrix4f matrix4f, float xCenter, float yCe Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); for (int i = 0; i <= 360; i++) { double x = xCenter + Math.sin(Math.toRadians(i)) * radius; @@ -366,7 +368,7 @@ public static void drawFilledCircle(Matrix4f matrix4f, float xCenter, float yCen Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); @@ -426,7 +428,7 @@ public static void drawFilledArc(Matrix4f matrix4f, float x, float y, float radi Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); RenderSystem.enableBlend(); for (float angle = startAngle; angle <= endAngle; angle += 1.0F) { @@ -469,7 +471,7 @@ public static void drawFilledGradientQuadrant(Matrix4f matrix4f, float xCenter, Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); RenderSystem.enableBlend(); bufferBuilder.vertex(matrix4f, xCenter, yCenter, 0).color(startRed, startGreen, startBlue, startAlpha); @@ -512,7 +514,7 @@ public static void drawArc(Matrix4f matrix4f, float xCenter, float yCenter, floa Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); RenderSystem.enableBlend(); for (int i = startAngle; i <= endAngle; i++) { @@ -549,7 +551,7 @@ public static void drawFilledQuadrant(Matrix4f matrix4f, float xCenter, float yC Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); RenderSystem.enableBlend(); bufferBuilder.vertex(matrix4f, xCenter, yCenter, 0).color(red, green, blue, alpha); @@ -782,7 +784,7 @@ public static void drawRoundedGradientRectangle(Matrix4f matrix, Color color1, C RenderSystem.enableBlend(); RenderSystem.colorMask(false, false, false, true); RenderSystem.clearColor(0.0F, 0.0F, 0.0F, 0.0F); - RenderSystem.clear(GL40C.GL_COLOR_BUFFER_BIT, false); + RenderSystem.clear(GL40C.GL_COLOR_BUFFER_BIT); RenderSystem.colorMask(true, true, true, true); drawRoundedRectangle(matrix, x, y, TL, TR, BL, BR, width, height, (int) radius, color1.getRGB()); @@ -832,20 +834,19 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int } public static void unscaledProjection() { - vertexSorter = RenderSystem.getVertexSorting(); - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth(), mc.getWindow().getFramebufferHeight(), 0, 1000, 21000), VertexSorter.BY_Z); + projectionType = RenderSystem.getProjectionType(); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth(), mc.getWindow().getFramebufferHeight(), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC); } public static void scaledProjection() { - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), vertexSorter); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), projectionType); } public static void customScaledProjection(float scale) { - vertexSorter = RenderSystem.getVertexSorting(); - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), VertexSorter.BY_Z); + projectionType = RenderSystem.getProjectionType(); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC); } - /** * This method assumes that the x, y coords are the origin of a widget. * diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java index 8939443..86dc379 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -35,7 +35,7 @@ public static NativeImage resizeTexture(NativeImage image, int newWidth, int new int srcX = x * oldWidth / newWidth; int srcY = y * oldHeight / newHeight; - result.setColor(x, y, image.getColor(srcX, srcY)); + result.setColorArgb(x, y, image.getColorArgb(srcX, srcY)); } } @@ -58,10 +58,10 @@ public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage im y_diff = (y_ratio * i) - y; // Indexes of the 4 surrounding pixels - a = image.getColor(x, y); - b = image.getColor(x + 1, y); - c = image.getColor(x, y + 1); - d = image.getColor(x + 1, y + 1); + a = image.getColorArgb(x, y); + b = image.getColorArgb(x + 1, y); + c = image.getColorArgb(x, y + 1); + d = image.getColorArgb(x + 1, y + 1); // Blue element blue = (a & 0xff) * (1 - x_diff) * (1 - y_diff) + (b & 0xff) * (x_diff) * (1 - y_diff) + @@ -75,7 +75,7 @@ public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage im red = ((a >> 16) & 0xff) * (1 - x_diff) * (1 - y_diff) + ((b >> 16) & 0xff) * (x_diff) * (1 - y_diff) + ((c >> 16) & 0xff) * (y_diff) * (1 - x_diff) + ((d >> 16) & 0xff) * (x_diff * y_diff); - result.setColor(j, i, + result.setColorArgb(j, i, ((((int) red) << 16) & 0xff0000) | ((((int) green) << 8) & 0xff00) | ((int) blue) & 0xff); @@ -92,7 +92,7 @@ public static NativeImage invertTexture(NativeImage image) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int argb = image.getColor(x, y); + int argb = image.getColorArgb(x, y); int alpha = (argb >> 24) & 0xFF; int red = 255 - ((argb >> 16) & 0xFF); @@ -101,7 +101,7 @@ public static NativeImage invertTexture(NativeImage image) { int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; - result.setColor(x, y, newArgb); + result.setColorArgb(x, y, newArgb); } } @@ -123,7 +123,7 @@ public static NativeImage rotateTexture(NativeImage image, int degrees) { int newY = (int) ((x - centerX) * Math.sin(angle) + (y - centerY) * Math.cos(angle) + centerY); if (newX >= 0 && newX < width && newY >= 0 && newY < height) { - result.setColor(newY, newX, image.getColor(x, y)); + result.setColorArgb(newY, newX, image.getColorArgb(x, y)); } } } @@ -138,7 +138,7 @@ private static NativeImage flipTextureHorizontally(NativeImage image) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - result.setColor(width - x - 1, y, image.getColor(x, y)); + result.setColorArgb(width - x - 1, y, image.getColorArgb(x, y)); } } @@ -152,7 +152,7 @@ private static NativeImage flipTextureVertically(NativeImage image) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - result.setColor(x, height - y - 1, image.getColor(x, y)); + result.setColorArgb(x, height - y - 1, image.getColorArgb(x, y)); } } @@ -174,7 +174,7 @@ public static NativeImage applyGrayScaleFilter(NativeImage image) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int argb = image.getColor(x, y); + int argb = image.getColorArgb(x, y); int alpha = (argb >> 24) & 0xFF; int red = (argb >> 16) & 0xFF; @@ -184,7 +184,7 @@ public static NativeImage applyGrayScaleFilter(NativeImage image) { int gray = (red + green + blue) / 3; int newArgb = (alpha << 24) | (gray << 16) | (gray << 8) | gray; - result.setColor(x, y, newArgb); + result.setColorArgb(x, y, newArgb); } } @@ -196,7 +196,7 @@ public static NativeImage cropTexture(NativeImage image, int x, int y, int width for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { - result.setColor(j, i, image.getColor(x + j, y + i)); + result.setColorArgb(j, i, image.getColorArgb(x + j, y + i)); } } @@ -210,7 +210,7 @@ public static NativeImage tintTexture(NativeImage image, int color) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int argb = image.getColor(x, y); + int argb = image.getColorArgb(x, y); int alpha = (argb >> 24) & 0xFF; int red = ((argb >> 16) & 0xFF) * ((color >> 16) & 0xFF) / 255; @@ -219,7 +219,7 @@ public static NativeImage tintTexture(NativeImage image, int color) { int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; - result.setColor(x, y, newArgb); + result.setColorArgb(x, y, newArgb); } } @@ -233,8 +233,8 @@ public static NativeImage overlayTexture(NativeImage image, NativeImage overlay) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - int argb1 = image.getColor(x, y); - int argb2 = overlay.getColor(x, y); + int argb1 = image.getColorArgb(x, y); + int argb2 = overlay.getColorArgb(x, y); int alpha = Math.max((argb1 >> 24) & 0xFF, (argb2 >> 24) & 0xFF); int red = Math.min(255, ((argb1 >> 16) & 0xFF) + ((argb2 >> 16) & 0xFF)); @@ -243,7 +243,7 @@ public static NativeImage overlayTexture(NativeImage image, NativeImage overlay) int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; - result.setColor(x, y, newArgb); + result.setColorArgb(x, y, newArgb); } } @@ -258,7 +258,7 @@ public static int getAverageColor(NativeImage image) { for (int y = 0; y < image.getHeight(); y++) { for (int x = 0; x < image.getWidth(); x++) { - int argb = image.getColor(x, y); + int argb = image.getColorArgb(x, y); redTotal += (argb >> 16) & 0xFF; greenTotal += (argb >> 8) & 0xFF; diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java index a779116..07b79af 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java @@ -11,6 +11,7 @@ import com.tanishisherewith.dynamichud.utils.handlers.ScrollHandler; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ButtonTextures; +import net.minecraft.client.render.RenderLayer; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; @@ -124,7 +125,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen RenderSystem.enableDepthTest(); panelColor.applyColor(); - drawContext.drawTexture(BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight, 256, 254); + drawContext.drawTexture(RenderLayer::getGuiTextured, BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight, 256, 254); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -135,7 +136,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen drawSingularButton(drawContext,"^",mouseX,mouseY,groupPanelX.getAsInt() + groupPanelWidth/2 - size/2,imageY - 14,size,14, groupScrollHandler.isOffsetWithinBounds(-10)); drawSingularButton(drawContext,"v",mouseX,mouseY,groupPanelX.getAsInt() + groupPanelWidth/2 - size/2,imageY + panelHeight - 2,size,14, groupScrollHandler.isOffsetWithinBounds(10)); -// drawContext.drawGuiTexture(TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14); +// drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14); // drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -162,7 +163,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height, boolean enabled){ RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - drawContext.drawGuiTexture(TEXTURES.get(enabled, isMouseOver(mouseX, mouseY, x, y, width, height)), x, y, width, height); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(enabled, isMouseOver(mouseX, mouseY, x, y, width, height)), x, y, width, height); drawContext.drawText(mc.textRenderer, text, x + width/2 - mc.textRenderer.getWidth(text) / 2, y + mc.textRenderer.fontHeight/2 - 1, -1, true); } public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height){ @@ -176,13 +177,13 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); - drawContext.drawTexture(GROUP_BACKGROUND, groupX - 10, groupY + 2,groupPanelWidth + 20, panelHeight,0,0, 147,165,147,165); + drawContext.drawTexture(RenderLayer::getGuiTextured,GROUP_BACKGROUND, groupX - 10, groupY + 2,groupPanelWidth + 20, panelHeight,0,0, 147,165,147,165); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); int yOffset = groupY + 12 - groupScrollHandler.getScrollOffset(); for (OptionGroup group : optionGroups) { if (yOffset >= groupY + 12 && yOffset <= groupY + panelHeight - 15) { - drawContext.drawGuiTexture(TEXTURES.get(!group.isExpanded(), isMouseOver(mouseX, mouseY, groupX, yOffset, groupPanelWidth, 20)), groupX, yOffset, groupPanelWidth, 20); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(!group.isExpanded(), isMouseOver(mouseX, mouseY, groupX, yOffset, groupPanelWidth, 20)), groupX, yOffset, groupPanelWidth, 20); DrawHelper.drawScrollableText(drawContext,mc.textRenderer, group.getName(),groupX + groupPanelWidth/2,groupX + 2,yOffset,groupX + groupPanelWidth - 2, yOffset + 20,-1); @@ -223,8 +224,8 @@ private void drawScrollbar(DrawContext drawContext) { int handleY = (int) (scrollbarY + (panelHeight - handleHeight) * ((double) scrollHandler.getScrollOffset() / getMaxScrollOffset())); RenderSystem.enableBlend(); - drawContext.drawGuiTexture(SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY,DEFAULT_SCROLLBAR_WIDTH, panelHeight); - drawContext.drawGuiTexture(SCROLLER_TEXTURE, scrollbarX, handleY,DEFAULT_SCROLLBAR_WIDTH, (int) handleHeight); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY,DEFAULT_SCROLLBAR_WIDTH, panelHeight); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLLER_TEXTURE, scrollbarX, handleY,DEFAULT_SCROLLBAR_WIDTH, (int) handleHeight); RenderSystem.disableBlend(); } } @@ -378,14 +379,14 @@ public void render(DrawContext drawContext, BooleanOption option, int x, int y, option.setPosition(x + panelWidth - 75, y); int width = 50; - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); Text text = option.getBooleanType().getText(option.value); int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB(); drawContext.drawText(mc.textRenderer, text, (int) (option.getX() + (width / 2.0f) - (mc.textRenderer.getWidth(text) / 2.0f)), y + 5, color, true); @@ -410,10 +411,10 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in option.setPosition(x + panelWidth - 45, y); int width = 20; - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); @@ -427,7 +428,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in shadowOpacity, 1, 1); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); option.setHeight(25); @@ -477,10 +478,10 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i RenderSystem.defaultBlendFunc(); RenderSystem.enableDepthTest(); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - drawContext.drawGuiTexture(option.isMouseOver(mouseX, mouseY) ? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20); - drawContext.drawGuiTexture(isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE, (int) Math.round(sliderX), y, 8, 20); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, option.isMouseOver(mouseX, mouseY) ? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE, (int) Math.round(sliderX), y, 8, 20); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); // Determine the number of decimal places in option.step @@ -519,11 +520,11 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y, option.setPosition(x + panelWidth - maxWidth - 25, y); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); @@ -553,11 +554,11 @@ public void render(DrawContext drawContext, ListOption option, int x, int y, option.setPosition(x + panelWidth - maxWidth - 25, y); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = option.get().toString(); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); @@ -575,10 +576,10 @@ public void render(DrawContext drawContext, SubMenuOption option, int x, int y, option.setPosition(x + panelWidth - 55, y); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); - drawContext.drawGuiTexture(TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); String text = "Open"; drawContext.drawText(mc.textRenderer, text, option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth(text) / 2, y + 5, Color.YELLOW.getRGB(), true); RenderSystem.disableBlend(); @@ -600,12 +601,12 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y, option.setPosition(x + panelWidth - 51, y); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.enableBlend(); RenderSystem.enableDepthTest(); - drawContext.drawGuiTexture(TEXTURES.get(!option.value, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); + drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(!option.value, option.isMouseOver(mouseX, mouseY)), option.getX(), y, option.getWidth(), 20); drawContext.drawText(mc.textRenderer, "Run", option.getX() + option.getWidth() / 2 - mc.textRenderer.getWidth("Run") / 2, y + 5, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true); - drawContext.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.disableBlend(); RenderSystem.disableDepthTest(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java index 2ed69bb..fca4106 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java @@ -14,6 +14,10 @@ import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetBox; import com.tanishisherewith.dynamichud.widget.WidgetData; +import com.twelvemonkeys.lang.Validate; +import net.minecraft.client.gl.ShaderProgram; +import net.minecraft.client.gl.ShaderProgramKey; +import net.minecraft.client.gl.ShaderProgramKeys; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -23,16 +27,17 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.function.Supplier; import net.minecraft.client.render.*; +import javax.xml.validation.Validator; + public class GraphWidget extends Widget implements ContextMenuProvider{ public static WidgetData DATA = new WidgetData<>("GraphWidget","Show graph",GraphWidget::new); - //private final List dataPoints; private ContextMenu menu; - private final float[] dataPoints; private int head = 0; private int maxDataPoints; @@ -50,8 +55,8 @@ public class GraphWidget extends Widget implements ContextMenuProvider{ public GraphWidget(String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) { super(DATA, modId, anchor); - dataPoints = new float[maxDataPoints]; - //this.dataPoints = new ArrayList<>(); + Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2."); + this.dataPoints = new float[maxDataPoints]; this.width = width; this.height = height; this.maxDataPoints = maxDataPoints; @@ -65,13 +70,12 @@ public GraphWidget(String modId, Anchor anchor, float width, float height, int m this.label = label.trim(); this.widgetBox = new WidgetBox(x, y, (int) width, (int) height); setTooltipText(Text.of("Graph displaying: " + label)); - createMenu(); ContextMenuManager.getInstance().registerProvider(this); } public GraphWidget(){ - this("null",Anchor.CENTER,0,0,0,0,0,Color.RED,Color.GREEN,0,false,0,"empty"); + this("null",Anchor.CENTER,0,0,10,0,10,Color.RED,Color.GREEN,0,false,0,"empty"); } @Override @@ -93,19 +97,19 @@ public void addDataPointEveryTick(Supplier valueSupplier) { private List getInterpolatedPoints() { List points = new ArrayList<>(); - if (maxDataPoints < 2) return points; + if (dataPoints.length < 2) return points; - float xStep = width / (maxDataPoints - 1); - for (int i = 0; i < maxDataPoints - 1; i++) { - int index1 = (head + i) % maxDataPoints; - int index2 = (head + i + 1) % maxDataPoints; + float xStep = width / (dataPoints.length - 1); + for (int i = 0; i < dataPoints.length - 1; i++) { + int index1 = (head + i) % dataPoints.length; + int index2 = (head + i + 1) % dataPoints.length; float x1 = x + i * xStep; float y1 = y + height - ((dataPoints[index1] - minValue) / (maxValue - minValue) * height); float x2 = x + (i + 1) * xStep; float y2 = y + height - ((dataPoints[index2] - minValue) / (maxValue - minValue) * height); - // Add interpolated points using cubic spline (simplified) + // Add interpolated points using hermite spline (simplified) for (float t = 0; t <= 1; t += 0.03f) { float t2 = t * t; float t3 = t2 * t; @@ -127,10 +131,6 @@ private void drawInterpolatedCurve(Matrix4f matrix, List points, int co Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferBuilder = tessellator.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); - float red = (float) (color >> 16 & 255) / 255.0F; - float green = (float) (color >> 8 & 255) / 255.0F; - float blue = (float) (color & 255) / 255.0F; - float alpha = (float) (color >> 24 & 255) / 255.0F; for (int i = 0; i < points.size(); i++) { float[] point = points.get(i); @@ -146,12 +146,12 @@ private void drawInterpolatedCurve(Matrix4f matrix, List points, int co float offsetX = (thickness * 0.5f * dy) / length; float offsetY = (thickness * 0.5f * -dx) / length; - bufferBuilder.vertex(matrix, x + offsetX, y + offsetY, 0).color(red, green, blue, alpha); - bufferBuilder.vertex(matrix, x - offsetX, y - offsetY, 0).color(red, green, blue, alpha); + bufferBuilder.vertex(matrix, x + offsetX, y + offsetY, 0).color(color); + bufferBuilder.vertex(matrix, x - offsetX, y - offsetY, 0).color(color); } RenderSystem.enableBlend(); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); RenderSystem.disableBlend(); } @@ -172,7 +172,7 @@ private void drawGradientShadow(Matrix4f matrix, List points, float bot } RenderSystem.enableBlend(); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); + RenderSystem.setShader(ShaderProgramKeys.POSITION_COLOR); BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); RenderSystem.disableBlend(); } @@ -211,7 +211,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) { float valueStep = (maxValue - minValue) / (gridLines + 1); //TODO: The scale is too small for grid lines for than 21 (20 is the barely visible threshold) - float scale = (float) MathHelper.clamp((stepY/9.5),0.0f,1.0f); //~ sqrt of 95 + float scale = (float) MathHelper.clamp((stepY/9.5),0.0f,1.0f); for (int i = 1; i <= gridLines; i++) { float yPos = y + stepY * i; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 6d01a5a..b0bee05 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -35,7 +35,7 @@ public class TextWidget extends Widget implements ContextMenuProvider { private DynamicValueRegistry valueRegistry; public TextWidget() { - this(null, null, false, false, Color.WHITE, "unknown"); + this("null", false, false, Color.WHITE, "unknown"); } public TextWidget(String registryKey, boolean shadow, boolean rainbow, Color color, String modID) { From 2aa5e446aafade874061127dfa600e635f934c29 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sun, 25 May 2025 19:40:21 +0530 Subject: [PATCH 32/40] Updated GraphWidget, created new DynamicValueRegistry with some bug fixes and refactoring --- .../dynamichud/IntegrationTest.java | 43 ++-- .../dynamichud/helpers/DrawHelper.java | 5 +- .../dynamichud/helpers/TextureHelper.java | 2 +- .../utils/DynamicValueRegistry.java | 43 +++- .../dynamichud/utils/Util.java | 10 + .../dynamichud/widget/DynamicValueWidget.java | 71 ++++++ .../dynamichud/widgets/GraphWidget.java | 202 ++++++++++++++---- .../dynamichud/widgets/ItemWidget.java | 2 +- .../dynamichud/widgets/TextWidget.java | 97 ++------- 9 files changed, 328 insertions(+), 147 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 8f5bad1..0643311 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -30,13 +30,14 @@ public void init() { registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); registry.registerLocal("Hello", () -> "Hello " + DynamicHUD.MC.getSession().getUsername() + "!"); registry.registerLocal("DynamicHUD", () -> "DynamicHUD"); + registry.registerLocal("FPS", () -> DynamicHUD.MC.getCurrentFps()); FPSWidget = new TextWidget.Builder() .setX(250) .setY(150) .setDraggable(true) .rainbow(false) - .withRegistryKey("dynamichud:FPS") + .registryKey("dynamichud:FPS") .setModID(DynamicHUD.MOD_ID) .shouldScale(false) .build(); @@ -46,8 +47,8 @@ public void init() { .setY(100) .setDraggable(true) .rainbow(false) - .withRegistryKey("Hello") - .withValueRegistry(registry) + .registryKey("Hello") + .registryID(registry.getId()) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) .shadow(true) @@ -58,8 +59,8 @@ public void init() { .setY(0) .setDraggable(false) .rainbow(true) - .withRegistryKey("DynamicHUD") - .withValueRegistry(registry) + .registryKey("DynamicHUD") + .registryID(registry.getId()) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) .build(); @@ -67,25 +68,25 @@ public void init() { graphWidget = new GraphWidget.GraphWidgetBuilder() .setX(250) .setY(100) - .setGraphColor(Color.CYAN) - .setAnchor(Widget.Anchor.CENTER) - .setHeight(100) - .setWidth(150) - .setGridLines(10) - .setBackgroundColor(Color.DARK_GRAY) - .setLineThickness(1f) - .setMaxDataPoints(100) - .setMaxValue(120) - .setMinValue(30) + .label("FPS Chart") + .graphColor(Color.CYAN) + .anchor(Widget.Anchor.CENTER) + .height(100) + .width(150) + .gridLines(10) + .backgroundColor(Color.DARK_GRAY) + .lineThickness(1f) + .maxDataPoints(100) + .maxValue(120) + .minValue(30) .setModID(DynamicHUD.MOD_ID) .setDraggable(true) .setDisplay(true) - .setShowGrid(true) - .setLabel("FPS Chart") - .build(); - - - graphWidget.addDataPointEveryTick(()-> (float) MinecraftClient.getInstance().getCurrentFps()); + .showGrid(true) + .registryKey("FPS") + .registryID(registry.getId()) + .build() + .autoUpdateRange(); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index 5a6ea1f..88a9ba9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -264,13 +264,12 @@ public static void drawRainbowGradientRectangle(Matrix4f matrix4f, float x, floa * @param shadow Whether to render the text as shadow. */ public static void drawChromaText(@NotNull DrawContext drawContext, String text, int x, int y, float speed, float saturation, float brightness, float spread, boolean shadow) { - long time = System.currentTimeMillis(); // Get the current time for animation + long time = System.currentTimeMillis(); int length = text.length(); for (int i = 0; i < length; i++) { - // Calculate the hue for the current character float hue = (time % (int) (5000 / speed)) / (5000f / speed) + (i * spread); // Adjust the hue based on time and character position - hue = MathHelper.floorMod(hue, 1.0f); // Ensure the hue stays within the range [0, 1] + hue = MathHelper.floorMod(hue, 1.0f); // hue should stay within the range [0, 1] // Convert the hue to an RGB color int color = Color.HSBtoRGB(hue, saturation, brightness); diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java index 86dc379..48b5779 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -48,7 +48,7 @@ public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage im float x_ratio = ((float) (image.getWidth() - 1)) / newWidth; float y_ratio = ((float) (image.getHeight() - 1)) / newHeight; float x_diff, y_diff, blue, red, green; - int offset, a, b, c, d, index; + int a, b, c, d; for (int i = 0; i < newHeight; i++) { for (int j = 0; j < newWidth; j++) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index 8081490..b590ff0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -22,6 +22,7 @@ public class DynamicValueRegistry { private static final Map REGISTRY_BY_ID = new HashMap<>(); private static final Map> GLOBAL_REGISTRY = new HashMap<>(); + public static final String GLOBAL_ID = "global"; private final String id; // Unique identifier for this registry instance private final Map> localRegistry = new HashMap<>(); @@ -32,9 +33,9 @@ public class DynamicValueRegistry { * @param registryId A unique ID for this registry instance. */ public DynamicValueRegistry(String modId, String registryId) { - this.id = registryId; + this.id = registryId.trim(); System.registerInstance(this, modId); - REGISTRY_BY_ID.put(registryId, this); + REGISTRY_BY_ID.put(this.id, this); } /** * Constructor for a local registry using with registryId as modID. @@ -87,10 +88,46 @@ public Supplier get(String key) { * @param registryId The unique ID of the registry. * @return The registry instance, or null if not found. */ - public static DynamicValueRegistry getById(String registryId) { + public static DynamicValueRegistry getById(String registryId) { return REGISTRY_BY_ID.get(registryId); } + /** + * Gets the registry instance by its unique ID but throws an error if the instance is not present + * @param registryId The unique ID of the registry. + * @return The registry instance, or null if not found. + * @throws IllegalStateException If a registry for the id was not found + */ + public static DynamicValueRegistry getByIdSafe(String registryId) { + if(!REGISTRY_BY_ID.containsKey(registryId)){ + throw new IllegalStateException("DynamicValueRegistry for id: " + registryId + " not found"); + } + return REGISTRY_BY_ID.get(registryId); + } + + /** + * @param registryID the registry id + * @return whether the given id matches the global registry id or not + */ + public static boolean isGlobal(String registryID){ + return registryID.equals(GLOBAL_ID); + } + + /** + * Directly get the supplier for a given key and registry id + * @param registryID The registry ID + * @param key the registry key + * @return supplier as returned by the registry with the given key + */ + public static Supplier getValue(String registryID, String key){ + if(registryID.isEmpty() || key.isEmpty()) throw new IllegalArgumentException(); + + if(registryID.equals(GLOBAL_ID)){ + return getGlobal(key); + } + return getByIdSafe(registryID).get(key); + } + /** * Retrieves all registry instances for a mod ID. * @param modId The mod ID. diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java index 94b384b..6fe1090 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java @@ -25,4 +25,14 @@ public static Quadrant getQuadrant(int x, int y) { public enum Quadrant { UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT } + + public static boolean errorIfTrue(boolean expression, String message, Object... objects){ + if(!expression) DynamicHUD.logger.error(message, objects); + return expression; + } + + public static boolean warnIfTrue(boolean expression, String message, Object... objects){ + if(expression) DynamicHUD.logger.warn(message, objects); + return expression; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java new file mode 100644 index 0000000..66b3de3 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java @@ -0,0 +1,71 @@ +package com.tanishisherewith.dynamichud.widget; + +import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.utils.Util; +import net.minecraft.nbt.NbtCompound; + +import java.util.function.Supplier; + +public abstract class DynamicValueWidget extends Widget { + protected String registryKey; + protected String registryID; + protected Supplier valueSupplier; + + public DynamicValueWidget(WidgetData data, String modID, String registryID, String registryKey) { + this(data,modID,Anchor.CENTER,registryID,registryKey); + } + + public DynamicValueWidget(WidgetData data, String modId, Anchor anchor, String registryID, String registryKey) { + super(data,modId,anchor); + boolean emptyCheck = Util.warnIfTrue(registryID == null || registryID.isEmpty(), "Empty registry ID, using global registry. Widget: {}", this.toString()); + this.registryID = emptyCheck ? DynamicValueRegistry.GLOBAL_ID : registryID; + this.registryKey = registryKey; + + initializeValueSupplier(); + } + + protected void initializeValueSupplier() { + this.valueSupplier = DynamicValueRegistry.getValue(registryID, registryKey); + } + + @Override + public void writeToTag(NbtCompound tag) { + super.writeToTag(tag); + tag.putString("RegistryID", registryID); + tag.putString("RegistryKey", registryKey); + } + + @Override + public void readFromTag(NbtCompound tag) { + super.readFromTag(tag); + registryID = tag.getString("RegistryID"); + registryKey = tag.getString("RegistryKey"); + + initializeValueSupplier(); + + if(valueSupplier == null) throw new IllegalStateException("Value supplier remains null"); + } + + // for subclasses to implement + public abstract Object getValue(); + + public abstract static class DynamicValueWidgetBuilder, W extends DynamicValueWidget> extends WidgetBuilder { + protected String registryKey = ""; + protected String registryID = null; + + @SuppressWarnings("unchecked") + protected T self() { + return (T) this; + } + + public T registryKey(String registryKey) { + this.registryKey = registryKey; + return self(); + } + + public T registryID(String registryID) { + this.registryID = registryID; + return self(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java index fca4106..9237574 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java @@ -1,9 +1,11 @@ package com.tanishisherewith.dynamichud.widgets; import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations; +import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties; @@ -11,12 +13,10 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.options.BooleanOption; import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption; import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; -import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.DynamicValueWidget; import com.tanishisherewith.dynamichud.widget.WidgetBox; import com.tanishisherewith.dynamichud.widget.WidgetData; import com.twelvemonkeys.lang.Validate; -import net.minecraft.client.gl.ShaderProgram; -import net.minecraft.client.gl.ShaderProgramKey; import net.minecraft.client.gl.ShaderProgramKeys; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; @@ -27,22 +27,23 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; import net.minecraft.client.render.*; -import javax.xml.validation.Validator; - -public class GraphWidget extends Widget implements ContextMenuProvider{ +/** + * Graph widget to draw a simple but detailed graph. + * You need to use DynamicValueRegistry to pass a value to the graph. + * You can use null values to signify the graph should update with a new value yet. + */ +public class GraphWidget extends DynamicValueWidget implements ContextMenuProvider{ public static WidgetData DATA = new WidgetData<>("GraphWidget","Show graph",GraphWidget::new); private ContextMenu menu; private final float[] dataPoints; private int head = 0; private int maxDataPoints; - private float minValue; - private float maxValue; + private float minValue, prevMinValue; + private float maxValue, prevMaxValue; private Color graphColor; private Color backgroundColor; private float lineThickness; @@ -51,17 +52,18 @@ public class GraphWidget extends Widget implements ContextMenuProvider{ private float width; private float height; private String label; - private Supplier valueSupplier = null; + /// Automatically update the min and max of the graph + private boolean autoUpdateRange = false; - public GraphWidget(String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) { - super(DATA, modId, anchor); + public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) { + super(DATA, modId, anchor,registryID, registryKey); Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2."); this.dataPoints = new float[maxDataPoints]; this.width = width; this.height = height; this.maxDataPoints = maxDataPoints; - this.minValue = minValue; - this.maxValue = maxValue; + this.setMinValue(minValue); + this.setMaxValue(maxValue); this.graphColor = graphColor; this.backgroundColor = backgroundColor; this.lineThickness = lineThickness; @@ -75,7 +77,7 @@ public GraphWidget(String modId, Anchor anchor, float width, float height, int m } public GraphWidget(){ - this("null",Anchor.CENTER,0,0,10,0,10,Color.RED,Color.GREEN,0,false,0,"empty"); + this(DynamicValueRegistry.GLOBAL_ID,"unknown","unknown",Anchor.CENTER,0,0,10,0,10,Color.RED,Color.GREEN,0,false,0,"empty"); } @Override @@ -86,14 +88,31 @@ public void init() { } } - public void addDataPoint(float value) { + /// Automatically update the min and max of the graph + public GraphWidget autoUpdateRange(){ + this.autoUpdateRange = true; + return this; + } + + public void addDataPoint(Float value) { + if(value == null) return; + if(autoUpdateRange) { + if (getMaxValue() < value) { + setMaxValue(value + 10); + float diff = getMaxValue() - getPrevMaxValue(); + setMinValue(getMinValue() + diff); + } + if (getMinValue() > value) { + setMinValue(value - 10); + float diff = getPrevMinValue() - getMinValue(); + setMaxValue(getMaxValue() - diff); + } + } + int index = (head) % maxDataPoints; dataPoints[index] = MathHelper.clamp(value, minValue, maxValue); head = (head + 1) % maxDataPoints; // Buffer full, overwrite oldest and move head } - public void addDataPointEveryTick(Supplier valueSupplier) { - this.valueSupplier = valueSupplier; - } private List getInterpolatedPoints() { List points = new ArrayList<>(); @@ -182,7 +201,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) { Matrix4f matrix = context.getMatrices().peek().getPositionMatrix(); if(valueSupplier != null){ - addDataPoint(valueSupplier.get()); + addDataPoint(getValue()); } // Apply pulse1 animation to background alpha @@ -275,7 +294,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) { if(menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight())); } - // format large values (e.g., 1000 -> "1K", 1000000 -> "1M") + // format large values (like: 1000 -> 1K, 1000000 -> 1M) private String formatValue(float value) { if (Math.abs(value) >= 1_000_000) { return String.format("%.1fM", value / 1_000_000); @@ -339,6 +358,106 @@ public void readFromTag(NbtCompound tag) { createMenu(); } + public float getMinValue() { + return minValue; + } + + public void setMinValue(float minValue) { + this.prevMinValue = this.minValue; + this.minValue = minValue; + } + + public float getPrevMinValue() { + return prevMinValue; + } + + public float getMaxValue() { + return maxValue; + } + + public void setMaxValue(float maxValue) { + this.prevMaxValue = this.maxValue; + this.maxValue = maxValue; + } + + public float getPrevMaxValue() { + return prevMaxValue; + } + + public float getLineThickness() { + return lineThickness; + } + + public void setLineThickness(float lineThickness) { + this.lineThickness = lineThickness; + } + + public Color getBackgroundColor() { + return backgroundColor; + } + + public void setBackgroundColor(Color backgroundColor) { + this.backgroundColor = backgroundColor; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + @Override + public float getHeight() { + return height; + } + + public void setHeight(float height) { + this.height = height; + } + + @Override + public float getWidth() { + return width; + } + + public void setWidth(float width) { + this.width = width; + } + + public int getGridLines() { + return gridLines; + } + + public void setGridLines(int gridLines) { + this.gridLines = gridLines; + } + + public boolean isShowGrid() { + return showGrid; + } + + public void setShowGrid(boolean showGrid) { + this.showGrid = showGrid; + } + + public Color getGraphColor() { + return graphColor; + } + + public void setGraphColor(Color graphColor) { + this.graphColor = graphColor; + } + + @Override + public Float getValue() { + if (valueSupplier.get() instanceof Number number) { + return number.floatValue(); + } + return null; + } + @Override public void onClose() { super.onClose(); @@ -366,7 +485,7 @@ public ContextMenu getContextMenu() { return menu; } - public static class GraphWidgetBuilder extends WidgetBuilder { + public static class GraphWidgetBuilder extends DynamicValueWidgetBuilder { private Anchor anchor = Anchor.CENTER; private float width = 100; private float height = 50; @@ -380,66 +499,65 @@ public static class GraphWidgetBuilder extends WidgetBuilder { ItemStack itemStack; - public Builder setItemStack(ItemStack itemStack) { + public Builder itemStack(ItemStack itemStack) { this.itemStack = itemStack; return self(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index b0bee05..b6ca7cc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -2,7 +2,6 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.internal.RegistrySource; import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager; @@ -10,17 +9,15 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider; import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin; -import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.DynamicValueWidget; import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; import java.awt.*; -import java.util.function.Supplier; -public class TextWidget extends Widget implements ContextMenuProvider { +public class TextWidget extends DynamicValueWidget implements ContextMenuProvider { public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); private ContextMenu menu; @@ -29,56 +26,27 @@ public class TextWidget extends Widget implements ContextMenuProvider { protected boolean rainbow; // Whether to apply a rainbow effect to the text protected int rainbowSpeed = 2; //Speed of the rainbow effect protected float rainbowSpread = 0.01f, rainbowSaturation = 1.0f, rainbowBrightness = 1.0f; - Supplier textSupplier; private String registryKey; - private RegistrySource registrySource; - private DynamicValueRegistry valueRegistry; + //private DynamicValueRegistry valueRegistry; + private String registryID; public TextWidget() { - this("null", false, false, Color.WHITE, "unknown"); + this(DynamicValueRegistry.GLOBAL_ID,"unknown", false, false, Color.WHITE, "unknown"); } - public TextWidget(String registryKey, boolean shadow, boolean rainbow, Color color, String modID) { - super(DATA, modID); - this.registrySource = RegistrySource.GLOBAL; - this.registryKey = registryKey; - this.shadow = shadow; - this.rainbow = rainbow; - this.textColor = color; - this.valueRegistry = null; - initializeTextSupplier(); - createMenu(); - ContextMenuManager.getInstance().registerProvider(this); + public TextWidget(DynamicValueRegistry valueRegistry, String registryKey, boolean shadow, boolean rainbow, Color color, String modID) { + this(valueRegistry.getId(),registryKey,shadow,rainbow,color,modID); } - public TextWidget(DynamicValueRegistry valueRegistry, String registryKey, boolean shadow, - boolean rainbow, Color color, String modID) { - super(DATA, modID); - this.registrySource = RegistrySource.LOCAL; - this.valueRegistry = valueRegistry; - this.registryKey = registryKey; + public TextWidget(String registryID, String registryKey, boolean shadow, boolean rainbow, Color color, String modID) { + super(DATA, modID,registryID,registryKey); this.shadow = shadow; this.rainbow = rainbow; this.textColor = color; - initializeTextSupplier(); createMenu(); ContextMenuManager.getInstance().registerProvider(this); } - @SuppressWarnings("unchecked") - private void initializeTextSupplier() { - this.textSupplier = switch (registrySource) { - case GLOBAL -> (Supplier) DynamicValueRegistry.getGlobal(registryKey); - case LOCAL -> { - if (valueRegistry != null) { - yield (Supplier) valueRegistry.get(registryKey); - } - throw new IllegalStateException("ValueRegistry is null while initialising text supplier"); - } - case null -> throw new IllegalStateException("RegistrySource is null while initialising text supplier"); - }; - } - public void createMenu() { boolean dark_mode = false; ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(dark_mode ? MinecraftSkin.PanelColor.DARK_PANEL : MinecraftSkin.PanelColor.CREAMY)).build(); @@ -155,8 +123,8 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { if(menu == null) return; //int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) : textColor.getRGB(); int color = textColor.getRGB(); - if (textSupplier != null) { - String text = textSupplier.get(); + if (valueSupplier != null) { + String text = getValue(); if(rainbow){ DrawHelper.drawChromaText(drawContext,text,getX() + 2, getY() + 2, rainbowSpeed/2f,rainbowSaturation,rainbowBrightness,rainbowSpread,shadow); } else { @@ -181,7 +149,7 @@ public void onClose() { @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); - tag.putString("RegistryID", registrySource == RegistrySource.LOCAL ? valueRegistry.getId() : "global"); + tag.putString("RegistryID", registryID); tag.putString("RegistryKey", registryKey); tag.putBoolean("Shadow", shadow); tag.putBoolean("Rainbow", rainbow); @@ -190,7 +158,6 @@ public void writeToTag(NbtCompound tag) { tag.putFloat("RainbowSpread", rainbowSpread); tag.putFloat("RainbowSaturation", rainbowSaturation); tag.putFloat("RainbowBrightness", rainbowBrightness); - tag.putString("RegistrySource", registrySource.name()); } @Override @@ -204,35 +171,25 @@ public void readFromTag(NbtCompound tag) { rainbowBrightness = tag.getFloat("RainbowBrightness"); textColor = new Color(tag.getInt("TextColor")); registryKey = tag.getString("RegistryKey"); - registrySource = tag.contains("RegistrySource") ? RegistrySource.valueOf(tag.getString("RegistrySource")) : RegistrySource.LOCAL; - - if(registrySource == RegistrySource.LOCAL){ - String registryID = tag.getString("RegistryID"); - - if(registryID.equalsIgnoreCase("global")) - throw new IllegalStateException("Registry ID found to be global for LOCAL registry source"); - - valueRegistry = DynamicValueRegistry.getById(registryID); - - if(valueRegistry == null){ - throw new RuntimeException("Local DynamicValueRegistry not found for: " + registryKey); - } - } + registryID = tag.getString("RegistryID"); - initializeTextSupplier(); createMenu(); } + @Override + public String getValue() { + return (String) valueSupplier.get(); + } + @Override public ContextMenu getContextMenu() { return menu; } - public static class Builder extends WidgetBuilder { + + public static class Builder extends DynamicValueWidgetBuilder { private boolean shadow = false; private boolean rainbow = false; - private String registryKey = ""; - private DynamicValueRegistry valueRegistry = null; private Color textColor = Color.WHITE; public Builder shadow(boolean shadow) { @@ -245,16 +202,6 @@ public Builder rainbow(boolean rainbow) { return this; } - public Builder withRegistryKey(String registryKey) { - this.registryKey = registryKey; - return this; - } - - public Builder withValueRegistry(DynamicValueRegistry valueRegistry) { - this.valueRegistry = valueRegistry; - return this; - } - public Builder textColor(Color textColor) { this.textColor = textColor; return this; @@ -267,9 +214,7 @@ protected Builder self() { @Override public TextWidget build() { - TextWidget widget = (valueRegistry == null) ? - new TextWidget(registryKey, shadow, rainbow, textColor, modID) : - new TextWidget(valueRegistry, registryKey, shadow, rainbow, textColor, modID); + TextWidget widget = new TextWidget(registryID, registryKey, shadow, rainbow, textColor, modID); widget.setPosition(x, y); widget.setDraggable(isDraggable); From 1c9bb699dc03ab526bcc2370bbc16b22aaed426e Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 26 May 2025 23:33:17 +0530 Subject: [PATCH 33/40] Final push before complete update --- gradle.properties | 2 +- src/main/resources/fabric.mod.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 25a8eb4..df1ba47 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ loader_version=0.16.9 # Mod Properties # need versioning system -mod_version = 2.2.0 +mod_version = 3.0.0 maven_group = com.tanishisherewith archives_base_name = dynamichud diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 60d60a6..5874a6c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -41,6 +41,6 @@ } }, "suggests": { - "yet_another_config_lib_v3": "3.5.0+1.21-fabric" + "yet_another_config_lib_v3": ">=3.6.6+1.21.4-fabric" } } From fd31029dd1949bf0e6e2ffbde07d4e5c4044d217 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 27 May 2025 22:42:54 +0530 Subject: [PATCH 34/40] Full Reformat along with some final changes in GraphWidget and such. --- .../dynamichud/DynamicHUD.java | 5 - .../dynamichud/IntegrationTest.java | 4 +- .../dynamichud/config/GlobalConfig.java | 43 +++-- .../dynamichud/helpers/ColorHelper.java | 2 - .../dynamichud/helpers/DrawHelper.java | 37 ++-- .../helpers/animationhelper/Animation.java | 4 +- .../animationhelper/AnimationProperty.java | 1 + .../helpers/animationhelper/Easing.java | 12 +- .../helpers/animationhelper/EasingType.java | 2 +- .../animations/MathAnimations.java | 5 +- .../animations/ValueAnimation.java | 4 +- .../integration/DefaultIntegrationImpl.java | 3 +- .../integration/DynamicHudConfigurator.java | 24 ++- .../integration/DynamicHudIntegration.java | 7 +- .../integration/IntegrationManager.java | 14 +- .../dynamichud/internal/ModError.java | 3 +- .../dynamichud/internal/RegistrySource.java | 6 - .../dynamichud/internal/System.java | 3 - .../dynamichud/internal/WarningScreen.java | 32 ++-- .../dynamichud/mixins/OptionsScreenMixin.java | 4 +- .../dynamichud/mixins/ScreenMixin.java | 1 - .../screens/AbstractMoveableScreen.java | 15 +- .../utils/DynamicValueRegistry.java | 38 ++-- .../dynamichud/utils/Util.java | 8 +- .../utils/contextmenu/ContextMenu.java | 23 +-- .../utils/contextmenu/ContextMenuManager.java | 3 +- .../contextmenu/ContextMenuProperties.java | 11 +- .../ContextMenuScreenRegistry.java | 4 +- .../contextmenu/options/BooleanOption.java | 2 +- .../contextmenu/options/ColorOption.java | 4 +- .../contextmenu/options/DoubleOption.java | 8 +- .../utils/contextmenu/options/EnumOption.java | 2 +- .../utils/contextmenu/options/ListOption.java | 2 +- .../utils/contextmenu/options/Option.java | 34 ++-- .../contextmenu/options/OptionGroup.java | 27 +-- .../contextmenu/options/RunnableOption.java | 9 +- .../contextmenu/options/SubMenuOption.java | 2 +- .../options/coloroption/ColorGradient.java | 14 +- .../options/coloroption/SaturationHueBox.java | 12 +- .../contextmenu/skinsystem/ClassicSkin.java | 7 +- .../contextmenu/skinsystem/MinecraftSkin.java | 73 +++---- .../contextmenu/skinsystem/ModernSkin.java | 180 +++++++++--------- .../utils/contextmenu/skinsystem/Skin.java | 5 +- .../skinsystem/interfaces/GroupableSkin.java | 3 +- .../skinsystem/interfaces/SkinRenderer.java | 14 +- .../utils/handlers/ScrollHandler.java | 9 +- .../dynamichud/widget/DynamicValueWidget.java | 19 +- .../dynamichud/widget/UserManageable.java | 1 + .../dynamichud/widget/Widget.java | 26 +-- .../dynamichud/widget/WidgetBox.java | 6 +- .../dynamichud/widget/WidgetManager.java | 9 +- .../dynamichud/widget/WidgetRenderer.java | 20 +- .../dynamichud/widgets/GraphWidget.java | 52 ++--- .../dynamichud/widgets/ItemWidget.java | 2 +- .../dynamichud/widgets/TextWidget.java | 32 ++-- src/main/resources/fabric.mod.json | 5 +- 56 files changed, 483 insertions(+), 414 deletions(-) delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 02d0ea6..c37f1b1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -2,9 +2,6 @@ import com.tanishisherewith.dynamichud.config.GlobalConfig; import com.tanishisherewith.dynamichud.integration.IntegrationManager; -import com.tanishisherewith.dynamichud.widget.WidgetManager; -import com.tanishisherewith.dynamichud.widgets.ItemWidget; -import com.tanishisherewith.dynamichud.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -19,7 +16,6 @@ public class DynamicHUD implements ClientModInitializer { public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); public static String MOD_ID = "dynamichud"; - public static void printInfo(String msg) { logger.info(msg); } @@ -40,5 +36,4 @@ public void onInitializeClient() { //In game screen render. HudRenderCallback.EVENT.register(new HudRender()); } - } diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java index 0643311..78636d0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java @@ -7,7 +7,6 @@ import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widgets.GraphWidget; import com.tanishisherewith.dynamichud.widgets.TextWidget; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.text.Text; @@ -100,7 +99,8 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { //renderer.shouldRenderInGameHud(true); renderer.addScreen(TitleScreen.class); }) - .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {}); + .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {} + ); return configurator; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index 1d21a5c..e832380 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -6,6 +6,7 @@ import dev.isxander.yacl3.config.v2.api.SerialEntry; import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -38,7 +39,7 @@ public final class GlobalConfig { private boolean renderInDebugScreen = false; @SerialEntry - private boolean forceSameContextMenuSkin = true; + private final boolean forceSameContextMenuSkin = true; //These package names are getting seriously long @SerialEntry @@ -97,31 +98,31 @@ public Screen createYACLGUI() { .controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10, 500)) .build()) .build()) - .option(Option.createBuilder() - .name(Text.literal("Widget HUD Active Background Color")) - .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will be rendered"))) - .binding(new Color(0, 0, 0, 128), () -> this.hudActiveColor, newVal -> this.hudActiveColor = newVal) - .controller(ColorControllerBuilder::create) + .option(Option.createBuilder() + .name(Text.literal("Widget HUD Active Background Color")) + .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will be rendered"))) + .binding(new Color(0, 0, 0, 128), () -> this.hudActiveColor, newVal -> this.hudActiveColor = newVal) + .controller(ColorControllerBuilder::create) .build()) - .option(Option.createBuilder() - .name(Text.literal("Widget HUD Inactive Background Color")) - .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered"))) - .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) - .controller(ColorControllerBuilder::create) + .option(Option.createBuilder() + .name(Text.literal("Widget HUD Inactive Background Color")) + .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered"))) + .binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal) + .controller(ColorControllerBuilder::create) .build()) - .option(Option.createBuilder() - .name(Text.literal("Settings Complexity")) - .description(OptionDescription.of(Text.literal("The level of options to display. Options equal to or below this level will be displayed"))) - .binding(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.Simple, () -> this.complexity, newVal -> this.complexity = newVal) - .controller((option) -> EnumControllerBuilder.create(option) - .enumClass(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.class) - .formatValue(value -> Text.of(value.name())) - ) + .option(Option.createBuilder() + .name(Text.literal("Settings Complexity")) + .description(OptionDescription.of(Text.literal("The level of options to display. Options equal to or below this level will be displayed"))) + .binding(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.Simple, () -> this.complexity, newVal -> this.complexity = newVal) + .controller((option) -> EnumControllerBuilder.create(option) + .enumClass(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.class) + .formatValue(value -> Text.of(value.name())) + ) .build()) .build()) .save(HANDLER::save) .build() - .generateScreen(null); + .generateScreen(MinecraftClient.getInstance().currentScreen); } public float getScale() { @@ -152,7 +153,7 @@ public Color getHudActiveColor() { return hudActiveColor; } - public com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity complexity(){ + public com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity complexity() { return complexity; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java index 32d75da..a564ad9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java @@ -5,11 +5,9 @@ import net.minecraft.client.util.Window; import net.minecraft.util.math.MathHelper; import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL30; import java.awt.*; -import java.math.BigInteger; import java.nio.ByteBuffer; /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index 88a9ba9..69de5ea 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -3,8 +3,8 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.ProjectionType; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.systems.VertexSorter; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.widget.WidgetBox; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gl.ShaderProgramKeys; import net.minecraft.client.gui.DrawContext; @@ -15,6 +15,7 @@ import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.NotNull; import org.joml.Matrix4f; +import org.lwjgl.opengl.GL40; import org.lwjgl.opengl.GL40C; import java.awt.*; @@ -26,7 +27,7 @@ * Credits: HeliosClient */ public class DrawHelper { - public static ProjectionType projectionType; + public static ProjectionType projectionType; /** * Draws a singular gradient rectangle on screen with the given parameters @@ -92,8 +93,13 @@ public static void drawGradient(Matrix4f matrix4f, float x, float y, float width } public static void enableScissor(int x, int y, int width, int height) { - enableScissor(x,y,width,height,mc.getWindow().getScaleFactor()); + enableScissor(x, y, width, height, mc.getWindow().getScaleFactor()); } + + public static void enableScissor(WidgetBox box) { + enableScissor((int) box.x, (int) box.y, (int) box.getWidth(), (int) box.getHeight(), mc.getWindow().getScaleFactor()); + } + public static void enableScissor(int x, int y, int width, int height, double scaleFactor) { int scissorX = (int) (x * scaleFactor); int scissorY = (int) (DynamicHUD.MC.getWindow().getHeight() - ((y + height) * scaleFactor)); @@ -253,15 +259,16 @@ public static void drawRainbowGradientRectangle(Matrix4f matrix4f, float x, floa /** * Draw chroma text (text with a nice rainbow effect) + * * @param drawContext A drawContext object - * @param text The text to display - * @param x X pos of text - * @param y Y pos of text - * @param speed Speed of rainbow - * @param saturation Saturation of the rainbow colors - * @param brightness Brightness of the rainbow colors - * @param spread How much the color difference should be between each character (ideally between 0.001 to 0.2) - * @param shadow Whether to render the text as shadow. + * @param text The text to display + * @param x X pos of text + * @param y Y pos of text + * @param speed Speed of rainbow + * @param saturation Saturation of the rainbow colors + * @param brightness Brightness of the rainbow colors + * @param spread How much the color difference should be between each character (ideally between 0.001 to 0.2) + * @param shadow Whether to render the text as shadow. */ public static void drawChromaText(@NotNull DrawContext drawContext, String text, int x, int y, float speed, float saturation, float brightness, float spread, boolean shadow) { long time = System.currentTimeMillis(); @@ -843,7 +850,7 @@ public static void scaledProjection() { public static void customScaledProjection(float scale) { projectionType = RenderSystem.getProjectionType(); - RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC); + RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC); } /** @@ -903,11 +910,11 @@ public static void drawScrollableText(DrawContext context, TextRenderer textRend if (i > k) { l = i - k; double d = (double) Util.getMeasuringTimeMs() / 1000.0; - double e = Math.max((double)l * 0.5, 3.0); + double e = Math.max((double) l * 0.5, 3.0); double f = Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * d / e)) / 2.0 + 0.5; - double g = MathHelper.lerp(f, 0.0, (double)l); + double g = MathHelper.lerp(f, 0.0, l); context.enableScissor(startX, startY, endX, endY); - context.drawTextWithShadow(textRenderer, text, startX - (int)g, j, color); + context.drawTextWithShadow(textRenderer, text, startX - (int) g, j, color); context.disableScissor(); } else { l = MathHelper.clamp(centerX, startX + i / 2, endX - i / 2); diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java index a600118..2ce05cc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Animation.java @@ -59,5 +59,7 @@ public void finish() { completionCallbacks.forEach(Runnable::run); } - public boolean isFinished() { return finished; } + public boolean isFinished() { + return finished; + } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java index 40a1b0b..20a80b0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java @@ -3,5 +3,6 @@ // AnimationProperty.java public interface AnimationProperty { T get(); + void set(T value); } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java index c917fa3..75998ea 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/Easing.java @@ -9,16 +9,20 @@ public static float apply(EasingType easingType, float progress) { case EASE_IN_OUT_SINE -> (float) (-(Math.cos(Math.PI * progress) - 1) / 2); case EASE_IN_QUAD -> progress * progress; case EASE_OUT_QUAD -> 1 - (1 - progress) * (1 - progress); - case EASE_IN_OUT_QUAD -> progress < 0.5 ? 2 * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 2) / 2); + case EASE_IN_OUT_QUAD -> + progress < 0.5 ? 2 * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 2) / 2); case EASE_IN_CUBIC -> progress * progress * progress; case EASE_OUT_CUBIC -> (float) (1 - Math.pow(1 - progress, 3)); - case EASE_IN_OUT_CUBIC -> progress < 0.5 ? 4 * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 3) / 2); + case EASE_IN_OUT_CUBIC -> + progress < 0.5 ? 4 * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 3) / 2); case EASE_IN_QUART -> progress * progress * progress * progress; case EASE_OUT_QUART -> (float) (1 - Math.pow(1 - progress, 4)); - case EASE_IN_OUT_QUART -> progress < 0.5 ? 8 * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 4) / 2); + case EASE_IN_OUT_QUART -> + progress < 0.5 ? 8 * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 4) / 2); case EASE_IN_QUINT -> progress * progress * progress * progress * progress; case EASE_OUT_QUINT -> (float) (1 - Math.pow(1 - progress, 5)); - case EASE_IN_OUT_QUINT -> progress < 0.5 ? 16 * progress * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 5) / 2); + case EASE_IN_OUT_QUINT -> + progress < 0.5 ? 16 * progress * progress * progress * progress * progress : (float) (1 - Math.pow(-2 * progress + 2, 5) / 2); case EASE_IN_EXPO -> (float) (progress == 0 ? 0 : Math.pow(2, 10 * progress - 10)); case EASE_OUT_EXPO -> (float) (progress == 1 ? 1 : 1 - Math.pow(2, -10 * progress)); case EASE_IN_OUT_EXPO -> { diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java index c91405a..8316475 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/EasingType.java @@ -31,5 +31,5 @@ public enum EasingType { EASE_IN_OUT_ELASTIC, EASE_IN_BOUNCE, EASE_OUT_BOUNCE, - EASE_IN_OUT_BOUNCE; + EASE_IN_OUT_BOUNCE } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java index d47d0ce..e34f137 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java @@ -83,12 +83,13 @@ public static float pulse2(float speed, float min, float max) { // Linear interpolation between values over time public static float lerp(float start, float end, long startTime, float duration) { - return lerp(start,end,startTime,duration,EasingType.LINEAR); + return lerp(start, end, startTime, duration, EasingType.LINEAR); } + public static float lerp(float start, float end, long startTime, float duration, EasingType easing) { float progress = (System.currentTimeMillis() - startTime) / duration; progress = Math.min(1, Math.max(0, progress)); // Clamp 0-1 - return start + (end - start) * Easing.apply(easing,progress); + return start + (end - start) * Easing.apply(easing, progress); } // Bouncing animation using quadratic ease-out diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java index af10979..9d19d3b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java @@ -20,12 +20,12 @@ public ValueAnimation(AnimationProperty property, float start, float end, } public ValueAnimation(AnimationProperty property, float start, float end) { - this(property,start,end,EasingType.LINEAR); + this(property, start, end, EasingType.LINEAR); } @Override protected void applyAnimation(float progress) { - this.value = startValue + (endValue - startValue) * Easing.apply(easing,progress); + this.value = startValue + (endValue - startValue) * Easing.apply(easing, progress); property.set(value); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java index ecbf8b2..33ae2b7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java @@ -16,7 +16,8 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) { } @Override - public void init() {} + public void init() { + } @Override public void registerCustomWidgets() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java index e5c100a..8b1695b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java @@ -27,7 +27,7 @@ public class DynamicHudConfigurator { private AbstractMoveableScreen screen = null; public boolean markAsUtility = false; // A.k.a we don't want this mod to display a hud. - public DynamicHudConfigurator addWidget(Widget widget){ + public DynamicHudConfigurator addWidget(Widget widget) { this.widgets.add(widget); return this; } @@ -36,7 +36,7 @@ public DynamicHudConfigurator addWidget(Widget widget){ * Configure the existing renderer object with this method */ public DynamicHudConfigurator configureRenderer(Consumer wrConsumer) { - if(renderer == null){ + if (renderer == null) { this.renderer = new WidgetRenderer(widgets); } wrConsumer.accept(renderer); @@ -60,7 +60,7 @@ public DynamicHudConfigurator overrideRenderer(WidgetRenderer renderer) { /** * Called before saving these widgets */ - public DynamicHudConfigurator onSave(Consumer> saveHandler){ + public DynamicHudConfigurator onSave(Consumer> saveHandler) { this.saveHandler = saveHandler; return this; } @@ -72,7 +72,7 @@ public DynamicHudConfigurator onSave(Consumer> saveHandler){ * !! Should never be null !! * *

- * */ + */ public DynamicHudConfigurator withMoveableScreen(Function screenProvider) { this.screen = screenProvider.apply(this); return this; @@ -86,11 +86,17 @@ public DynamicHudConfigurator modifyWidgets(Consumer operation) { return this; } - public List getWidgets() { return Collections.unmodifiableList(widgets); } + public List getWidgets() { + return Collections.unmodifiableList(widgets); + } - public WidgetRenderer getRenderer() { return renderer; } + public WidgetRenderer getRenderer() { + return renderer; + } - public final Consumer> getSaveHandler() { return saveHandler; } + public final Consumer> getSaveHandler() { + return saveHandler; + } public final AbstractMoveableScreen getMovableScreen() { return screen; @@ -100,7 +106,7 @@ public final AbstractMoveableScreen getMovableScreen() { * Internal method to save these widgets using fabric API events. Should not be called anywhere else except when loading the DHIntegration on startup. */ @ApiStatus.Internal - public void setupSaveEvents(File widgetsFile){ + public void setupSaveEvents(File widgetsFile) { /* === Saving === */ // Each mod is hooked to the fabric's event system to save its widget. @@ -118,7 +124,7 @@ public void setupSaveEvents(File widgetsFile){ } @ApiStatus.Internal - public final void registerWidgets(){ + public final void registerWidgets() { widgets.forEach(WidgetManager::addWidget); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java index 14dacdd..bcc32de 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud.integration; +import com.tanishisherewith.dynamichud.IntegrationTest; import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.widget.WidgetData; import com.tanishisherewith.dynamichud.widget.WidgetManager; @@ -14,6 +15,8 @@ /** * This interface provides methods for integrating DynamicHud into a mod. + * @see IntegrationTest + * @see DefaultIntegrationImpl */ public interface DynamicHudIntegration { /** @@ -44,6 +47,7 @@ public interface DynamicHudIntegration { /** * Entry point for configuring DynamicHUD integration. + * * @param configurator Configuration context */ DynamicHudConfigurator configure(DynamicHudConfigurator configurator); @@ -59,7 +63,8 @@ public interface DynamicHudIntegration { /** * This method is called after widgets from the widget file have been loaded successfully and added to the renderer. */ - default void postWidgetLoading(WidgetRenderer renderer) {} + default void postWidgetLoading(WidgetRenderer renderer) { + } /** * To register custom widgets. This method can be overridden by implementations. diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java index 1e4851d..a98d0fb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java @@ -55,7 +55,7 @@ public static void openScreen(KeyBinding key, AbstractMoveableScreen screen) { } } - private static void checkToEnableTestIntegration(){ + private static void checkToEnableTestIntegration() { String[] args = FabricLoader.getInstance().getLaunchArguments(true); for (int i = 0; i < args.length; i++) { if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) { @@ -65,7 +65,7 @@ private static void checkToEnableTestIntegration(){ } } - public static void integrate(){ + public static void integrate() { checkToEnableTestIntegration(); printInfo("Integrating mods..."); @@ -103,7 +103,7 @@ public static void integrate(){ DynamicHudConfigurator configurator = DHIntegration.configure(new DynamicHudConfigurator()); - if(configurator.markAsUtility) { + if (configurator.markAsUtility) { printInfo(String.format("Supported utility mod with id %s was found!", modId)); continue; } @@ -155,13 +155,13 @@ public static void integrate(){ // Sheesh - if(!bad_implementations.isEmpty()){ + if (!bad_implementations.isEmpty()) { BooleanPool.put("WarningScreenFlag", false); - ClientTickEvents.START_CLIENT_TICK.register((client)->{ - if(BooleanPool.get("WarningScreenFlag")) return; + ClientTickEvents.START_CLIENT_TICK.register((client) -> { + if (BooleanPool.get("WarningScreenFlag")) return; - if(DynamicHUD.MC.currentScreen instanceof TitleScreen) { + if (DynamicHUD.MC.currentScreen instanceof TitleScreen) { DynamicHUD.MC.setScreen(new WarningScreen(bad_implementations)); BooleanPool.put("WarningScreenFlag", true); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java index d81a04d..57ab93d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/ModError.java @@ -1,3 +1,4 @@ package com.tanishisherewith.dynamichud.internal; -public record ModError(String modName,String errorMessage) {} +public record ModError(String modName, String errorMessage) { +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java b/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java deleted file mode 100644 index f8dacea..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/RegistrySource.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.tanishisherewith.dynamichud.internal; - -public enum RegistrySource { - GLOBAL, - LOCAL; -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java index 73fa8b0..e3ab2ab 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/System.java @@ -1,9 +1,6 @@ package com.tanishisherewith.dynamichud.internal; -import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry; - import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public abstract class System { // A map to store all instances of DynamicValueRegistry by modId diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java index 0c2ac60..2b7ef4b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java @@ -1,17 +1,13 @@ package com.tanishisherewith.dynamichud.internal; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.ClickEvent; import net.minecraft.text.OrderedText; -import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Util; -import net.minecraft.util.crash.CrashReportSection; import java.awt.*; import java.io.File; @@ -28,16 +24,16 @@ public WarningScreen(List modErrors) { @Override protected void init() { ButtonWidget confirmButton = ButtonWidget.builder(Text.of("I Understand"), button -> MinecraftClient.getInstance().setScreen(null)) - .dimensions(this.width / 2 - 100, this.height - 40, 200, 20) - .narrationSupplier((e)-> Text.literal("I understand")) - .build(); + .dimensions(this.width / 2 - 100, this.height - 40, 200, 20) + .narrationSupplier((e) -> Text.literal("I understand")) + .build(); ButtonWidget logs_folder = ButtonWidget.builder(Text.of("Open logs"), button -> { - File logsFolder = new File(MinecraftClient.getInstance().runDirectory, "logs"); - Util.getOperatingSystem().open(logsFolder); + File logsFolder = new File(MinecraftClient.getInstance().runDirectory, "logs"); + Util.getOperatingSystem().open(logsFolder); }) .dimensions(this.width / 2 - 100, this.height - 70, 200, 20) - .narrationSupplier((e)-> Text.literal("Open logs")) + .narrationSupplier((e) -> Text.literal("Open logs")) .build(); // Add "I Understand" button @@ -49,24 +45,24 @@ protected void init() { public void render(DrawContext context, int mouseX, int mouseY, float delta) { super.render(context, mouseX, mouseY, delta); - context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 20, 0xFFFFFF); - context.drawCenteredTextWithShadow(this.textRenderer, "Mods with bad implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB()); + context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 20, 0xFFFFFF); + context.drawCenteredTextWithShadow(this.textRenderer, "Mods with bad implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB()); int y = 60; for (ModError error : modErrors) { - Text modName = Text.literal( "> \"" + error.modName() + "\"").formatted(Formatting.RED); + Text modName = Text.literal("> \"" + error.modName() + "\"").formatted(Formatting.RED); context.drawText(this.textRenderer, modName, this.width / 2 - 100, y, -1, false); - List errorMessage = this.textRenderer.wrapLines(Text.literal( "Error: " + error.errorMessage()), this.width/2); + List errorMessage = this.textRenderer.wrapLines(Text.literal("Error: " + error.errorMessage()), this.width / 2); - if(mouseX >= this.width/2 - 100 && mouseX <= this.width/2 - 100 + this.textRenderer.getWidth(modName) && mouseY >= y && mouseY <= y + this.textRenderer.fontHeight){ - context.drawOrderedTooltip(textRenderer,errorMessage,mouseX,mouseY); + if (mouseX >= this.width / 2 - 100 && mouseX <= this.width / 2 - 100 + this.textRenderer.getWidth(modName) && mouseY >= y && mouseY <= y + this.textRenderer.fontHeight) { + context.drawOrderedTooltip(textRenderer, errorMessage, mouseX, mouseY); } y += 11; // Space between mod errors } y += 5; context.drawCenteredTextWithShadow(this.textRenderer, Text.of("Please report this problem to the respective mod owners."), this.width / 2, y, -1); - context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Widgets of these mods won't work.").formatted(Formatting.YELLOW), this.width / 2, y + 10,-1); - context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Check latest.log for more details").formatted(Formatting.ITALIC), this.width / 2, y + 30,-1); + context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Widgets of these mods won't work.").formatted(Formatting.YELLOW), this.width / 2, y + 10, -1); + context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Check latest.log for more details").formatted(Formatting.ITALIC), this.width / 2, y + 30, -1); } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java index 772b49d..5b0367a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java @@ -17,11 +17,13 @@ @Mixin(OptionsScreen.class) public abstract class OptionsScreenMixin extends Screen { - @Shadow protected abstract ButtonWidget createButton(Text message, Supplier screenSupplier); + @Shadow + protected abstract ButtonWidget createButton(Text message, Supplier screenSupplier); protected OptionsScreenMixin(Text title) { super(title); } + @Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/GridWidget$Adder;add(Lnet/minecraft/client/gui/widget/Widget;)Lnet/minecraft/client/gui/widget/Widget;", ordinal = 0)) private void init(CallbackInfo ci, @Local(ordinal = 0) DirectionalLayoutWidget directionalLayoutWidget) { DirectionalLayoutWidget directionalLayoutWidget2 = directionalLayoutWidget.add(DirectionalLayoutWidget.horizontal()); diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index 60f368f..21446b4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -1,6 +1,5 @@ package com.tanishisherewith.dynamichud.mixins; -import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.integration.IntegrationManager; import com.tanishisherewith.dynamichud.widget.WidgetManager; import com.tanishisherewith.dynamichud.widget.WidgetRenderer; diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 8b2bae6..55ad285 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -33,9 +33,9 @@ public void onDisplayed() { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - widgetRenderer.mouseDragged(mouseX, mouseY, button,deltaX,deltaY, GlobalConfig.get().getSnapSize()); + widgetRenderer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY, GlobalConfig.get().getSnapSize()); ContextMenuManager.getInstance().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - return super.mouseDragged(mouseX, mouseY, button,deltaX,deltaY); + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } @Override @@ -49,8 +49,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { @Override public boolean charTyped(char chr, int modifiers) { - widgetRenderer.charTyped(chr,modifiers); - ContextMenuManager.getInstance().charTyped(chr,modifiers); + widgetRenderer.charTyped(chr, modifiers); + ContextMenuManager.getInstance().charTyped(chr, modifiers); return super.charTyped(chr, modifiers); } @@ -65,8 +65,8 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) { widgetRenderer.keyPressed(keyCode, scanCode, modifiers); ContextMenuManager.getInstance().keyPressed(keyCode, scanCode, modifiers); - if(widgetRenderer.selectedWidget != null && (keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE)){ - // trayWidget.minimizeWidget(widgetRenderer.selectedWidget); + if (widgetRenderer.selectedWidget != null && (keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE)) { + // trayWidget.minimizeWidget(widgetRenderer.selectedWidget); } return super.keyPressed(keyCode, scanCode, modifiers); @@ -118,7 +118,8 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) } } - public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) {} + public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int button) { + } @Override public void close() { diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index b590ff0..355a616 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -2,7 +2,9 @@ import com.tanishisherewith.dynamichud.internal.System; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.function.Supplier; /** @@ -12,7 +14,7 @@ * To use a local registry, simple create an object of the class. *
  *     {@code
- *     DynamicValueRegistry dvr = new DynamicValueRegistry("mod_id");
+ *     DynamicValueRegistry dvr = new DynamicValueRegistry("mod_id", "my_registry_id");
  *     dvr.registerLocal("ABC",//YourSupplier);
  *     Supplier result = dvr.get("ABC");
  *     }
@@ -29,7 +31,8 @@ public class DynamicValueRegistry {
 
     /**
      * Constructor for a local registry with a unique ID.
-     * @param modId The mod ID or unique identifier for grouping registries.
+     *
+     * @param modId      The mod ID or unique identifier for grouping registries.
      * @param registryId A unique ID for this registry instance.
      */
     public DynamicValueRegistry(String modId, String registryId) {
@@ -37,8 +40,10 @@ public DynamicValueRegistry(String modId, String registryId) {
         System.registerInstance(this, modId);
         REGISTRY_BY_ID.put(this.id, this);
     }
+
     /**
      * Constructor for a local registry using with registryId as modID.
+     *
      * @param modId The mod ID or unique identifier for grouping registries.
      */
     public DynamicValueRegistry(String modId) {
@@ -49,7 +54,8 @@ public DynamicValueRegistry(String modId) {
 
     /**
      * Registers a supplier in the global registry.
-     * @param key The key for the supplier.
+     *
+     * @param key      The key for the supplier.
      * @param supplier The supplier providing values of type T.
      */
     public static  void registerGlobal(String key, Supplier supplier) {
@@ -58,6 +64,7 @@ public static  void registerGlobal(String key, Supplier supplier) {
 
     /**
      * Retrieves a supplier from the global registry.
+     *
      * @param key The key of the supplier.
      * @return The supplier, or null if not found.
      */
@@ -67,7 +74,8 @@ public static Supplier getGlobal(String key) {
 
     /**
      * Registers a supplier in the local registry.
-     * @param key The key for the supplier.
+     *
+     * @param key      The key for the supplier.
      * @param supplier The supplier providing values of type T.
      */
     public void registerLocal(String key, Supplier supplier) {
@@ -76,6 +84,7 @@ public void registerLocal(String key, Supplier supplier) {
 
     /**
      * Retrieves a supplier from the local or global registry.
+     *
      * @param key The key of the supplier.
      * @return The supplier, or null if not found.
      */
@@ -85,6 +94,7 @@ public Supplier get(String key) {
 
     /**
      * Gets the registry instance by its unique ID.
+     *
      * @param registryId The unique ID of the registry.
      * @return The registry instance, or null if not found.
      */
@@ -94,12 +104,13 @@ public static DynamicValueRegistry getById(String registryId) {
 
     /**
      * Gets the registry instance by its unique ID but throws an error if the instance is not present
+     *
      * @param registryId The unique ID of the registry.
      * @return The registry instance, or null if not found.
      * @throws IllegalStateException If a registry for the id was not found
      */
     public static DynamicValueRegistry getByIdSafe(String registryId) {
-        if(!REGISTRY_BY_ID.containsKey(registryId)){
+        if (!REGISTRY_BY_ID.containsKey(registryId)) {
             throw new IllegalStateException("DynamicValueRegistry for id: " + registryId + " not found");
         }
         return REGISTRY_BY_ID.get(registryId);
@@ -109,20 +120,21 @@ public static DynamicValueRegistry getByIdSafe(String registryId) {
      * @param registryID the registry id
      * @return whether the given id matches the global registry id or not
      */
-    public static boolean isGlobal(String registryID){
+    public static boolean isGlobal(String registryID) {
         return registryID.equals(GLOBAL_ID);
     }
 
     /**
      * Directly get the supplier for a given key and registry id
+     *
      * @param registryID The registry ID
-     * @param key the registry key
+     * @param key        the registry key
      * @return supplier as returned by the registry with the given key
      */
-    public static Supplier getValue(String registryID, String key){
-        if(registryID.isEmpty() || key.isEmpty()) throw new IllegalArgumentException();
+    public static Supplier getValue(String registryID, String key) {
+        if (registryID.isEmpty() || key.isEmpty()) throw new IllegalArgumentException();
 
-        if(registryID.equals(GLOBAL_ID)){
+        if (registryID.equals(GLOBAL_ID)) {
             return getGlobal(key);
         }
         return getByIdSafe(registryID).get(key);
@@ -130,6 +142,7 @@ public static Supplier getValue(String registryID, String key){
 
     /**
      * Retrieves all registry instances for a mod ID.
+     *
      * @param modId The mod ID.
      * @return A list of registries for the mod.
      */
@@ -139,6 +152,7 @@ public static List getInstances(String modId) {
 
     /**
      * Removes a supplier from the global registry.
+     *
      * @param key The key of the supplier.
      */
     public static void removeGlobal(String key) {
@@ -147,6 +161,7 @@ public static void removeGlobal(String key) {
 
     /**
      * Removes a supplier from the local registry.
+     *
      * @param key The key of the supplier.
      */
     public void removeLocal(String key) {
@@ -155,6 +170,7 @@ public void removeLocal(String key) {
 
     /**
      * Gets the unique ID of this registry.
+     *
      * @return The registry ID.
      */
     public String getId() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
index 6fe1090..4210d61 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
@@ -26,13 +26,13 @@ public enum Quadrant {
         UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
     }
 
-    public static boolean errorIfTrue(boolean expression, String message, Object... objects){
-        if(!expression) DynamicHUD.logger.error(message, objects);
+    public static boolean errorIfTrue(boolean expression, String message, Object... objects) {
+        if (!expression) DynamicHUD.logger.error(message, objects);
         return expression;
     }
 
-    public static boolean warnIfTrue(boolean expression, String message, Object... objects){
-        if(expression) DynamicHUD.logger.warn(message, objects);
+    public static boolean warnIfTrue(boolean expression, String message, Object... objects) {
+        if (expression) DynamicHUD.logger.warn(message, objects);
         return expression;
     }
 }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
index 837afa0..48a2cf6 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -48,8 +48,9 @@ public ContextMenu(int x, int y, T properties) {
     }
 
     public ContextMenu(int x, int y, T properties, ContextMenuScreenFactory screenFactory) {
-        this(x, y, properties, screenFactory,null);
+        this(x, y, properties, screenFactory, null);
     }
+
     public ContextMenu(int x, int y, @NotNull T properties, ContextMenuScreenFactory screenFactory, @Nullable ContextMenu parentMenu) {
         Objects.requireNonNull(screenFactory, "ContextMenuScreenFactory cannot be null!");
         Objects.requireNonNull(properties, "ContextMenu Properties cannot be null!");
@@ -134,14 +135,14 @@ public void toggleDisplay() {
         }
     }
 
-    public void toggleDisplay(WidgetBox widgetBox,double mouseX, double mouseY, int button){
+    public void toggleDisplay(WidgetBox widgetBox, double mouseX, double mouseY, int button) {
         if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) {
             toggleDisplay();
         }
     }
 
-    public void resetAllOptions(){
-        for(Option option: options){
+    public void resetAllOptions() {
+        for (Option option : options) {
             option.reset();
         }
     }
@@ -159,7 +160,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
     public boolean mouseReleased(double mouseX, double mouseY, int button) {
         if (!shouldDisplay) return false;
         for (Option option : options) {
-            option.getRenderer().mouseReleased(option,mouseX, mouseY, button);
+            option.getRenderer().mouseReleased(option, mouseX, mouseY, button);
         }
         return properties.getSkin().mouseReleased(this, mouseX, mouseY, button);
     }
@@ -168,7 +169,7 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
     public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
         if (!shouldDisplay) return false;
         for (Option option : options) {
-            option.getRenderer().mouseDragged(option,mouseX, mouseY, button, deltaX, deltaY);
+            option.getRenderer().mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
         }
         return properties.getSkin().mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY);
     }
@@ -177,7 +178,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
     public void keyPressed(int key, int scanCode, int modifiers) {
         if (!shouldDisplay) return;
         for (Option option : options) {
-            option.getRenderer().keyPressed(option,key, scanCode, modifiers);
+            option.getRenderer().keyPressed(option, key, scanCode, modifiers);
         }
 
         properties.getSkin().keyPressed(this, key, scanCode, modifiers);
@@ -187,7 +188,7 @@ public void keyPressed(int key, int scanCode, int modifiers) {
     public void keyReleased(int key, int scanCode, int modifiers) {
         if (!shouldDisplay) return;
         for (Option option : options) {
-            option.getRenderer().keyReleased(option,key, scanCode, modifiers);
+            option.getRenderer().keyReleased(option, key, scanCode, modifiers);
         }
         properties.getSkin().keyReleased(this, key, scanCode, modifiers);
 
@@ -197,7 +198,7 @@ public void keyReleased(int key, int scanCode, int modifiers) {
     public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
         if (!shouldDisplay) return;
         for (Option option : options) {
-            option.getRenderer().mouseScrolled(option,mouseX, mouseY, horizontalAmount, verticalAmount);
+            option.getRenderer().mouseScrolled(option, mouseX, mouseY, horizontalAmount, verticalAmount);
         }
         properties.getSkin().mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount);
     }
@@ -257,8 +258,8 @@ public ContextMenu getParentMenu() {
         return parentMenu;
     }
 
-    public  ContextMenu createSubMenu(int x, int y, K properties){
-        return new ContextMenu<>(x,y,properties, screenFactory,this);
+    public  ContextMenu createSubMenu(int x, int y, K properties) {
+        return new ContextMenu<>(x, y, properties, screenFactory, this);
     }
 
     public float getScale() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
index 6197d4a..70edde9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
@@ -10,7 +10,8 @@ public class ContextMenuManager implements Input {
     private static final ContextMenuManager INSTANCE = new ContextMenuManager();
     private final List providers = new ArrayList<>();
 
-    private ContextMenuManager() {}
+    private ContextMenuManager() {
+    }
 
     public static ContextMenuManager getInstance() {
         return INSTANCE;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
index 43989b1..6cb0ead 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
@@ -23,7 +23,8 @@ public class ContextMenuProperties {
     protected boolean enableAnimations = true;
     protected Skin skin = new ClassicSkin();
 
-    protected ContextMenuProperties() {}
+    protected ContextMenuProperties() {
+    }
 
     public static Builder builder() {
         return new Builder<>(new ContextMenuProperties());
@@ -93,6 +94,7 @@ public Skin getSkin() {
     public ContextMenuProperties clone() {
         return cloneToBuilder().build();
     }
+
     public Builder cloneToBuilder() {
         return ContextMenuProperties.builder()
                 .backgroundColor(backgroundColor)
@@ -108,10 +110,11 @@ public Builder cloneToBuilder() {
                 .hoverColor(hoverColor)
                 .enableAnimations(enableAnimations);
     }
+
     public ContextMenuProperties cloneWithSkin() {
-            return this.cloneToBuilder()
-                    .skin(skin)
-                    .build();
+        return this.cloneToBuilder()
+                .skin(skin)
+                .build();
     }
 
     public static class Builder {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
index 5b06044..3bd3646 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
@@ -2,10 +2,10 @@
 
 import net.minecraft.client.gui.screen.Screen;
 
-public class ContextMenuScreenRegistry{
+public class ContextMenuScreenRegistry {
     public Class screenKlass;
 
-    public ContextMenuScreenRegistry(Class screenKlass){
+    public ContextMenuScreenRegistry(Class screenKlass) {
         this.screenKlass = screenKlass;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
index 1427b94..d5f3b55 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
@@ -13,7 +13,7 @@ public class BooleanOption extends Option {
     private final BooleanType booleanType;
 
     public BooleanOption(Text name, Supplier getter, Consumer setter, BooleanType booleanType) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         this.booleanType = booleanType;
         this.renderer.init(this);
     }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
index c222c9a..9471f7c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
@@ -13,8 +13,8 @@ public class ColorOption extends Option {
     private ContextMenu parentMenu = null;
     private ColorGradient colorGradient = null;
 
-    public ColorOption(Text name, Supplier getter, Consumer setter,ContextMenu parentMenu) {
-        super(name,getter, setter);
+    public ColorOption(Text name, Supplier getter, Consumer setter, ContextMenu parentMenu) {
+        super(name, getter, setter);
         this.parentMenu = parentMenu;
         this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100);
         this.renderer.init(this);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
index 9e8e17e..5f0e2ac 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
@@ -4,10 +4,8 @@
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
 import net.minecraft.client.gui.DrawContext;
 import net.minecraft.text.Text;
-import net.minecraft.util.math.MathHelper;
 import org.apache.commons.lang3.Validate;
 import org.lwjgl.glfw.GLFW;
-import org.lwjgl.system.MathUtil;
 
 import java.awt.*;
 import java.util.function.Consumer;
@@ -21,7 +19,7 @@ public class DoubleOption extends Option {
     private boolean isDragging = false;
 
     public DoubleOption(Text name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         this.value = get();
         this.minValue = minValue;
         this.maxValue = maxValue;
@@ -56,14 +54,14 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
     }
 
     private void step(double mouseX) {
-       this.step(mouseX,x);
+        this.step(mouseX, x);
     }
 
     public void step(double mouseX, double x) {
         double newValue = minValue + (float) (mouseX - x) / width * (maxValue - minValue);
         // Round the new value to the nearest step
         newValue = Math.round(newValue / step) * step;
-        newValue = Math.clamp(newValue,minValue,maxValue);
+        newValue = Math.clamp(newValue, minValue, maxValue);
         set(newValue);
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
index e2bb820..1eab358 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
@@ -10,7 +10,7 @@ public class EnumOption> extends Option {
     private int currentIndex = 0;
 
     public EnumOption(Text name, Supplier getter, Consumer setter, E[] values) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         this.values = values;
         this.value = get();
         for (int i = 0; i < values.length; i++) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
index c2eadf1..d407242 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
@@ -11,7 +11,7 @@ public class ListOption extends Option {
     private int currentIndex = 0;
 
     public ListOption(Text name, Supplier getter, Consumer setter, List values) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         this.values = values;
         this.value = getter.get();
         for (int i = 0; i < values.size(); i++) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
index 009303c..af9be9b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
@@ -27,11 +27,11 @@ public abstract class Option implements Input {
     protected SkinRenderer> renderer;
     protected Complexity complexity = Complexity.Simple;
 
-    public Option(Text name,Supplier getter, Consumer setter) {
-        this(name,getter, setter, () -> true);
+    public Option(Text name, Supplier getter, Consumer setter) {
+        this(name, getter, setter, () -> true);
     }
 
-    public Option(Text name,Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) {
+    public Option(Text name, Supplier getter, Consumer setter, Supplier shouldRender, ContextMenuProperties properties) {
         this.name = name;
         this.getter = getter;
         this.setter = setter;
@@ -41,8 +41,8 @@ public Option(Text name,Supplier getter, Consumer setter, Supplier getter, Consumer setter, Supplier shouldRender) {
-        this(name,getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified());
+    public Option(Text name, Supplier getter, Consumer setter, Supplier shouldRender) {
+        this(name, getter, setter, shouldRender, ContextMenuProperties.createGenericSimplified());
     }
 
     public T get() {
@@ -84,21 +84,26 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
         return isMouseOver(mouseX, mouseY);
     }
 
-    public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {}
+    public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
+    }
 
     @Override
-    public void keyPressed(int key, int scanCode, int modifiers) {}
+    public void keyPressed(int key, int scanCode, int modifiers) {
+    }
 
     @Override
-    public void charTyped(char c, int modifiers) {}
+    public void charTyped(char c, int modifiers) {
+    }
 
     @Override
-    public void keyReleased(int key, int scanCode, int modifiers) {}
+    public void keyReleased(int key, int scanCode, int modifiers) {
+    }
 
     /**
      * Called when the context menu closes
      */
-    public void onClose() {}
+    public void onClose() {
+    }
 
     public boolean isMouseOver(double mouseX, double mouseY) {
         return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
@@ -112,7 +117,8 @@ public Option renderWhen(Supplier shouldRender) {
     public boolean shouldRender() {
         return shouldRender.get() && GlobalConfig.get().complexity().ordinal() >= complexity.ordinal();
     }
-    public void reset(){
+
+    public void reset() {
         this.value = get();
     }
 
@@ -156,11 +162,13 @@ public void setPosition(int x, int y) {
         this.x = x;
         this.y = y;
     }
-    public Option description(Text description){
+
+    public Option description(Text description) {
         this.description = description;
         return this;
     }
-    public Option withComplexity(Complexity complexity){
+
+    public Option withComplexity(Complexity complexity) {
         this.complexity = complexity;
         return this;
     }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
index 56e2ecc..8a33767 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
@@ -31,15 +31,16 @@ public List> getGroupOptions() {
     public void updateProperties(ContextMenuProperties properties) {
         this.renderer = new OptionGroupRenderer(); // Set renderer as OptionGroupRenderer
 
-        if(groupOptions == null) return;
+        if (groupOptions == null) return;
 
-        for(Option option: groupOptions){
+        for (Option option : groupOptions) {
             option.updateProperties(properties);
         }
     }
 
     @Override
-    public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) {}
+    public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) {
+    }
 
     public boolean isExpanded() {
         return expanded;
@@ -51,27 +52,29 @@ public void setExpanded(boolean expanded) {
 
     public int getHeightOfOptions() {
         int height = 0;
-        for(Option option : getGroupOptions()){
+        for (Option option : getGroupOptions()) {
             height += option.getHeight() + 1;
         }
         return height;
     }
+
     @Override
     public int getHeight() {
-       return super.getHeight();
+        return super.getHeight();
     }
 
     public class OptionGroupRenderer implements SkinRenderer> {
 
         @Override
-        public void render(DrawContext drawContext, Option option, int x, int y, int mouseX, int mouseY) {}
+        public void render(DrawContext drawContext, Option option, int x, int y, int mouseX, int mouseY) {
+        }
 
         @Override
         public boolean mouseClicked(Option option2, double mouseX, double mouseY, int button) {
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().mouseClicked(subOption,mouseX, mouseY, button);
+                subOption.getRenderer().mouseClicked(subOption, mouseX, mouseY, button);
             }
             return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
         }
@@ -81,7 +84,7 @@ public boolean mouseReleased(Option option2, double mouseX, double
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().mouseReleased(subOption,mouseX, mouseY, button);
+                subOption.getRenderer().mouseReleased(subOption, mouseX, mouseY, button);
             }
             return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
         }
@@ -91,7 +94,7 @@ public boolean mouseDragged(Option option2, double mouseX, double m
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().mouseDragged(subOption,mouseX, mouseY, button, deltaX, deltaY);
+                subOption.getRenderer().mouseDragged(subOption, mouseX, mouseY, button, deltaX, deltaY);
             }
             return SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
         }
@@ -101,7 +104,7 @@ public void keyPressed(Option option2, int key, int scanCode, int m
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().keyPressed(subOption,key, scanCode, modifiers);
+                subOption.getRenderer().keyPressed(subOption, key, scanCode, modifiers);
             }
             SkinRenderer.super.keyPressed(option, key, scanCode, modifiers);
         }
@@ -111,7 +114,7 @@ public void keyReleased(Option option2, int key, int scanCode, int
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().keyReleased(subOption,key, scanCode, modifiers);
+                subOption.getRenderer().keyReleased(subOption, key, scanCode, modifiers);
             }
             SkinRenderer.super.keyReleased(option, key, scanCode, modifiers);
         }
@@ -121,7 +124,7 @@ public void mouseScrolled(Option option2, double mouseX, double mou
             OptionGroup option = (OptionGroup) option2;
 
             for (Option subOption : option.getGroupOptions()) {
-                subOption.getRenderer().mouseScrolled(subOption,mouseX, mouseY, horizontalAmount, verticalAmount);
+                subOption.getRenderer().mouseScrolled(subOption, mouseX, mouseY, horizontalAmount, verticalAmount);
             }
             SkinRenderer.super.mouseScrolled(option, mouseX, mouseY, horizontalAmount, verticalAmount);
         }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java
index 75c25fa..8bc80a1 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java
@@ -6,7 +6,6 @@
 
 import java.util.function.Consumer;
 import java.util.function.Supplier;
-import java.util.logging.Logger;
 
 public class RunnableOption extends Option {
     private final Runnable task;
@@ -20,7 +19,7 @@ public class RunnableOption extends Option {
      * @param task   The task to run
      */
     public RunnableOption(Text name, Supplier getter, Consumer setter, Runnable task) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         this.name = name;
         this.task = task;
         this.renderer.init(this);
@@ -35,10 +34,10 @@ public RunnableOption(Text name, boolean defaultValue, Runnable task) {
     public boolean mouseClicked(double mouseX, double mouseY, int button) {
         if (super.mouseClicked(mouseX, mouseY, button)) {
             set(true);
-            try{
+            try {
                 task.run();
-            } catch (Throwable e){
-                DynamicHUD.logger.error("Encountered error while running task for {}", this.name,e);
+            } catch (Throwable e) {
+                DynamicHUD.logger.error("Encountered error while running task for {}", this.name, e);
             }
             set(false);
             return true;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
index 708c4a9..25420dc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
@@ -20,7 +20,7 @@ public class SubMenuOption extends Option {
     private final ContextMenu subMenu;
 
     public  SubMenuOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter, T properties) {
-        super(name,getter, setter);
+        super(name, getter, setter);
         Objects.requireNonNull(parentMenu, "Parent Context Menu cannot be null in [" + name + "] SubMenu option");
         this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties);
         this.subMenu.getProperties().setHeightOffset(0);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
index 704d809..a035bdc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
@@ -1,16 +1,11 @@
 package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption;
 
-import com.tanishisherewith.dynamichud.DynamicHUD;
 import com.tanishisherewith.dynamichud.config.GlobalConfig;
 import com.tanishisherewith.dynamichud.helpers.ColorHelper;
 import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gl.Framebuffer;
 import net.minecraft.client.gui.DrawContext;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL12;
 
 import java.awt.*;
-import java.nio.ByteBuffer;
 import java.util.function.Consumer;
 
 public class ColorGradient {
@@ -63,12 +58,12 @@ public void render(DrawContext drawContext, int x1, int y1, int mouseX, int mous
         }
         gradientSlider.render(drawContext, x, y + client.textRenderer.fontHeight + 4);
         gradientBox.render(drawContext, x, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10);
-       // colorPickerButton.render(drawContext, x + 24 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8);
+        // colorPickerButton.render(drawContext, x + 24 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8);
         alphaSlider.render(drawContext, x + 10 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10);
 
         if (colorPickerButton.isPicking() && GlobalConfig.get().showColorPickerPreview()) {
-            int[] colors = ColorHelper.getMousePixelColor(mouseX,mouseY);
-            if(colors != null) {
+            int[] colors = ColorHelper.getMousePixelColor(mouseX, mouseY);
+            if (colors != null) {
                 int red = colors[0];
                 int green = colors[1];
                 int blue = colors[2];
@@ -89,7 +84,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
         }
         /*if (colorPickerButton.onClick(mouseX, mouseY, button)) {
             return true;
-        } else*/ if (gradientSlider.isMouseOver(mouseX, mouseY)) {
+        } else*/
+        if (gradientSlider.isMouseOver(mouseX, mouseY)) {
             gradientSlider.onClick(mouseX, mouseY, button);
             gradientBox.setHue(gradientSlider.getHue());
         } else if (gradientBox.isMouseOver(mouseX, mouseY)) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java
index 75c4081..e0eca23 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/SaturationHueBox.java
@@ -61,10 +61,10 @@ public void onClick(double mouseX, double mouseY, int button) {
                 this.isDragging = true;
             } else if (mouseX >= x && mouseX <= x + size && mouseY >= y && mouseY <= y + size) {
                 this.saturation = (float) (mouseX - x) / size;
-                this.value= 1.0f - (float) (mouseY - y) / size;
+                this.value = 1.0f - (float) (mouseY - y) / size;
 
-                this.saturation = Math.clamp(saturation,0.0f,1.0f);
-                this.value = Math.clamp(value,0.0f,1.0f);
+                this.saturation = Math.clamp(saturation, 0.0f, 1.0f);
+                this.value = Math.clamp(value, 0.0f, 1.0f);
                 this.isDragging = true;
             }
         }
@@ -83,10 +83,10 @@ public void onRelease(double mouseX, double mouseY, int button) {
     public void onDrag(double mouseX, double mouseY, int button) {
         if (isDragging) {
             this.saturation = (float) (mouseX - x) / size;
-            this.value= 1.0f - (float) (mouseY - y) / size;
+            this.value = 1.0f - (float) (mouseY - y) / size;
 
-            this.saturation = Math.clamp(saturation,0.0f,1.0f);
-            this.value = Math.clamp(value,0.0f,1.0f);
+            this.saturation = Math.clamp(saturation, 0.0f, 1.0f);
+            this.value = Math.clamp(value, 0.0f, 1.0f);
         }
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
index 6cc8e5a..93dc0e7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
@@ -3,7 +3,6 @@
 import com.tanishisherewith.dynamichud.helpers.DrawHelper;
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
 import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
 import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer;
 import net.minecraft.client.font.TextRenderer;
@@ -172,7 +171,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in
                     1,
                     1);
 
-            option.getColorGradient().render(drawContext, x + option.getParentMenu().getWidth() + 7, y - 10,mouseX,mouseY);
+            option.getColorGradient().render(drawContext, x + option.getParentMenu().getWidth() + 7, y - 10, mouseX, mouseY);
         }
     }
 
@@ -182,7 +181,7 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y,
             option.setHeight(mc.textRenderer.fontHeight + 1);
             option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.name()) + 1);
 
-            drawContext.drawText(mc.textRenderer, option.name.copy().append( ": "), x, y, Color.WHITE.getRGB(), false);
+            drawContext.drawText(mc.textRenderer, option.name.copy().append(": "), x, y, Color.WHITE.getRGB(), false);
             drawContext.drawText(mc.textRenderer, option.value.name(), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false);
         }
     }
@@ -258,7 +257,7 @@ public void render(DrawContext drawContext, ListOption option, int x, int y,
             option.setHeight(mc.textRenderer.fontHeight + 1);
             option.setWidth(mc.textRenderer.getWidth(option.name + ": " + option.value.toString()) + 1);
 
-            drawContext.drawText(mc.textRenderer, option.name.copy().append( ": "), x, y + 1, Color.WHITE.getRGB(), false);
+            drawContext.drawText(mc.textRenderer, option.name.copy().append(": "), x, y + 1, Color.WHITE.getRGB(), false);
             drawContext.drawText(mc.textRenderer, option.value.toString(), x + mc.textRenderer.getWidth(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false);
         }
     }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
index 07b79af..88b56d2 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
@@ -40,7 +40,7 @@ public class MinecraftSkin extends Skin implements GroupableSkin {
     private static final Identifier DEFAULT_BACKGROUND_PANEL = Identifier.ofVanilla("textures/gui/demo_background.png");
     private static final Identifier SCROLLER_TEXTURE = Identifier.ofVanilla("widget/scroller");
     private static final Identifier SCROLL_BAR_BACKGROUND = Identifier.ofVanilla("widget/scroller_background");
-    private static final Identifier GROUP_BACKGROUND = Identifier.of(DynamicHUD.MOD_ID,"textures/minecraftskin/group_panel.png");
+    private static final Identifier GROUP_BACKGROUND = Identifier.of(DynamicHUD.MOD_ID, "textures/minecraftskin/group_panel.png");
 
     private final Identifier BACKGROUND_PANEL;
     private final int panelWidth;
@@ -82,19 +82,19 @@ private void enableContextMenuScissor() {
 
     private void createGroups() {
         OptionGroup generalGroup = new OptionGroup(Text.of("General"));
-        for(Option option: getOptions(contextMenu)){
-            if(option instanceof OptionGroup og){
+        for (Option option : getOptions(contextMenu)) {
+            if (option instanceof OptionGroup og) {
                 optionGroups.add(og);
                 og.setExpanded(false);
-            } else{
+            } else {
                 generalGroup.addOption(option);
             }
         }
         optionGroups.addFirst(generalGroup);
     }
 
-    private void initOptionGroups(){
-        if(this.optionGroups == null) {
+    private void initOptionGroups() {
+        if (this.optionGroups == null) {
             this.optionGroups = new ArrayList<>();
             createGroups();
             selectedGroup = optionGroups.getFirst(); // Default to the first group
@@ -129,15 +129,15 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
 
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
 
-        drawSingularButton(drawContext,"X",mouseX,mouseY,imageX + 3,imageY + 3, 14,14);
+        drawSingularButton(drawContext, "X", mouseX, mouseY, imageX + 3, imageY + 3, 14, 14);
 
         //Up and down arrows near the group panel
         int size = (int) (groupPanelWidth * 0.5f);
-        drawSingularButton(drawContext,"^",mouseX,mouseY,groupPanelX.getAsInt() + groupPanelWidth/2 - size/2,imageY - 14,size,14, groupScrollHandler.isOffsetWithinBounds(-10));
-        drawSingularButton(drawContext,"v",mouseX,mouseY,groupPanelX.getAsInt() + groupPanelWidth/2 -  size/2,imageY + panelHeight - 2,size,14, groupScrollHandler.isOffsetWithinBounds(10));
+        drawSingularButton(drawContext, "^", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY - 14, size, 14, groupScrollHandler.isOffsetWithinBounds(-10));
+        drawSingularButton(drawContext, "v", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY + panelHeight - 2, size, 14, groupScrollHandler.isOffsetWithinBounds(10));
 
 //        drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14);
-  //      drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true);
+        //      drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true);
 
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
         RenderSystem.disableBlend();
@@ -148,8 +148,8 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
         contextMenu.setWidth(panelWidth - 4);
         contextMenu.y = imageY;
 
-        renderOptionGroups(drawContext,mouseX,mouseY);
-        renderSelectedGroupOptions(drawContext,mouseX,mouseY);
+        renderOptionGroups(drawContext, mouseX, mouseY);
+        renderSelectedGroupOptions(drawContext, mouseX, mouseY);
 
         contextMenu.setHeight(getContentHeight() + 15);
 
@@ -161,13 +161,14 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
         DrawHelper.disableScissor();
     }
 
-    public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height, boolean enabled){
+    public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height, boolean enabled) {
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
         drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(enabled, isMouseOver(mouseX, mouseY, x, y, width, height)), x, y, width, height);
-        drawContext.drawText(mc.textRenderer, text, x + width/2 - mc.textRenderer.getWidth(text) / 2, y + mc.textRenderer.fontHeight/2 - 1, -1, true);
+        drawContext.drawText(mc.textRenderer, text, x + width / 2 - mc.textRenderer.getWidth(text) / 2, y + mc.textRenderer.fontHeight / 2 - 1, -1, true);
     }
-    public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height){
-       this.drawSingularButton(drawContext,text,mouseX,mouseY,x,y,width,height,true);
+
+    public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height) {
+        this.drawSingularButton(drawContext, text, mouseX, mouseY, x, y, width, height, true);
     }
 
     private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY) {
@@ -177,7 +178,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY)
         RenderSystem.enableBlend();
         RenderSystem.enableDepthTest();
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
-        drawContext.drawTexture(RenderLayer::getGuiTextured,GROUP_BACKGROUND, groupX - 10, groupY + 2,groupPanelWidth + 20, panelHeight,0,0, 147,165,147,165);
+        drawContext.drawTexture(RenderLayer::getGuiTextured, GROUP_BACKGROUND, groupX - 10, groupY + 2, groupPanelWidth + 20, panelHeight, 0, 0, 147, 165, 147, 165);
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
 
         int yOffset = groupY + 12 - groupScrollHandler.getScrollOffset();
@@ -185,7 +186,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY)
             if (yOffset >= groupY + 12 && yOffset <= groupY + panelHeight - 15) {
                 drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(!group.isExpanded(), isMouseOver(mouseX, mouseY, groupX, yOffset, groupPanelWidth, 20)), groupX, yOffset, groupPanelWidth, 20);
 
-                DrawHelper.drawScrollableText(drawContext,mc.textRenderer, group.getName(),groupX + groupPanelWidth/2,groupX + 2,yOffset,groupX + groupPanelWidth - 2, yOffset + 20,-1);
+                DrawHelper.drawScrollableText(drawContext, mc.textRenderer, group.getName(), groupX + groupPanelWidth / 2, groupX + 2, yOffset, groupX + groupPanelWidth - 2, yOffset + 20, -1);
 
                 //Scrollable text uses scissor, so we need to enable the context menu scissor again
                 this.enableContextMenuScissor();
@@ -205,7 +206,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY)
     private int renderSelectedGroupOptions(DrawContext drawContext, int mouseX, int mouseY) {
         int yOffset = imageY + 12 - scrollHandler.getScrollOffset();
         for (Option option : selectedGroup.getGroupOptions()) {
-            if(!option.shouldRender()) continue;
+            if (!option.shouldRender()) continue;
 
             if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight) {
                 option.render(drawContext, imageX + 4, yOffset, mouseX, mouseY);
@@ -224,11 +225,12 @@ private void drawScrollbar(DrawContext drawContext) {
             int handleY = (int) (scrollbarY + (panelHeight - handleHeight) * ((double) scrollHandler.getScrollOffset() / getMaxScrollOffset()));
 
             RenderSystem.enableBlend();
-            drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY,DEFAULT_SCROLLBAR_WIDTH, panelHeight);
-            drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLLER_TEXTURE, scrollbarX, handleY,DEFAULT_SCROLLBAR_WIDTH, (int) handleHeight);
+            drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLL_BAR_BACKGROUND, scrollbarX, scrollbarY, DEFAULT_SCROLLBAR_WIDTH, panelHeight);
+            drawContext.drawGuiTexture(RenderLayer::getGuiTextured, SCROLLER_TEXTURE, scrollbarX, handleY, DEFAULT_SCROLLBAR_WIDTH, (int) handleHeight);
             RenderSystem.disableBlend();
         }
     }
+
     private int getMaxScrollOffset() {
         return getContentHeight() - panelHeight + 10;
     }
@@ -242,7 +244,7 @@ public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, dou
         if (isMouseOver(mouseX, mouseY, imageX, imageY, panelWidth, panelHeight)) {
             scrollHandler.mouseScrolled(verticalAmount);
         }
-        if (isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() - 10, imageY,groupPanelWidth + 10, panelHeight)) {
+        if (isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() - 10, imageY, groupPanelWidth + 10, panelHeight)) {
             groupScrollHandler.mouseScrolled(verticalAmount);
         }
     }
@@ -250,7 +252,7 @@ public void mouseScrolled(ContextMenu menu, double mouseX, double mouseY, dou
     @Override
     public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) {
         if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
-            if(isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)) {
+            if (isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)) {
                 mc.getSoundManager().play(PositionedSoundInstance.master(
                         SoundEvents.UI_BUTTON_CLICK, 1.0F));
 
@@ -258,14 +260,14 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, i
                 scrollHandler.stopDragging();
                 return true;
             }
-            int size = (int)(groupPanelWidth * 0.5f);
+            int size = (int) (groupPanelWidth * 0.5f);
             //Up and down button
-            if(groupScrollHandler.isOffsetWithinBounds(-10) && isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() + (double) groupPanelWidth /2 - size/2,imageY - 14,size,14)) {
+            if (groupScrollHandler.isOffsetWithinBounds(-10) && isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() + (double) groupPanelWidth / 2 - size / 2, imageY - 14, size, 14)) {
                 mc.getSoundManager().play(PositionedSoundInstance.master(
                         SoundEvents.UI_BUTTON_CLICK, 1.0F));
                 groupScrollHandler.addOffset(-10);
             }
-            if(groupScrollHandler.isOffsetWithinBounds(10) && isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() + (double) groupPanelWidth /2 - size/2,imageY + panelHeight - 2,size,14)) {
+            if (groupScrollHandler.isOffsetWithinBounds(10) && isMouseOver(mouseX, mouseY, groupPanelX.getAsInt() + (double) groupPanelWidth / 2 - size / 2, imageY + panelHeight - 2, size, 14)) {
                 mc.getSoundManager().play(PositionedSoundInstance.master(
                         SoundEvents.UI_BUTTON_CLICK, 1.0F));
                 groupScrollHandler.addOffset(10);
@@ -306,14 +308,14 @@ public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY,
     }
 
     @Override
-    public boolean mouseDragged(ContextMenu menu,double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+    public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
         if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
-            if(isMouseOver(mouseX,mouseY,imageX + panelWidth + 5,imageY - 5,DEFAULT_SCROLLBAR_WIDTH + 5,panelHeight + 10)) {
+            if (isMouseOver(mouseX, mouseY, imageX + panelWidth + 5, imageY - 5, DEFAULT_SCROLLBAR_WIDTH + 5, panelHeight + 10)) {
                 scrollHandler.updateScrollPosition(mouseY);
             }
             return true;
         }
-        return super.mouseDragged(menu,mouseX, mouseY, button, deltaX, deltaY);
+        return super.mouseDragged(menu, mouseX, mouseY, button, deltaX, deltaY);
     }
 
     @Override
@@ -325,7 +327,8 @@ public LayoutContext.Offset getGroupIndent() {
      * Group rendering handled already
      */
     @Override
-    public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY) {}
+    public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY) {
+    }
 
     public enum PanelColor {
         COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f),
@@ -434,19 +437,19 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in
             option.setHeight(25);
             option.setWidth(width);
 
-            if(option.getColorGradient().getColorPickerButton().isPicking()) {
+            if (option.getColorGradient().getColorPickerButton().isPicking()) {
                 DrawHelper.disableScissor(); // Disable scissor test for the colorpicker
             }
             //TODO: WHAT IS THISSSSS
             int colorGradientWidth = option.getColorGradient().getBoxSize() + option.getColorGradient().getAlphaSlider().getWidth() + option.getColorGradient().getColorPickerButton().getWidth();
-            option.getColorGradient().render(drawContext, x + panelWidth/2 - colorGradientWidth/2, y + 12,mouseX,mouseY);
+            option.getColorGradient().render(drawContext, x + panelWidth / 2 - colorGradientWidth / 2, y + 12, mouseX, mouseY);
 
-            if(option.getColorGradient().shouldDisplay()) {
+            if (option.getColorGradient().shouldDisplay()) {
                 int colorGradientHeight = option.getColorGradient().getBoxSize() + 10 + option.getColorGradient().getGradientSlider().getHeight();
                 option.setHeight(option.getHeight() + colorGradientHeight);
             }
 
-            if(option.getColorGradient().getColorPickerButton().isPicking()) {
+            if (option.getColorGradient().getColorPickerButton().isPicking()) {
                 DrawHelper.enableScissor(imageX, imageY + 2, panelWidth, panelHeight - 4);
             }
         }
@@ -471,7 +474,7 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i
             option.setHeight(25);
             option.setPosition(x + panelWidth - 122, y);
 
-            double sliderX = option.getX()  + ((option.value - option.minValue) / (option.maxValue - option.minValue)) * (option.getWidth() - 8);
+            double sliderX = option.getX() + ((option.value - option.minValue) / (option.maxValue - option.minValue)) * (option.getWidth() - 8);
             boolean isMouseOverHandle = isMouseOver(mouseX, mouseY, sliderX, y, 10, 20);
 
             RenderSystem.enableBlend();
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index add7d0f..3888f6a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -32,7 +32,7 @@ public class ModernSkin extends Skin implements GroupableSkin {
     private final Text defaultToolTipHeader;
     private final Text defaultToolTipText;
     Color DARK_GRAY = new Color(20, 20, 20, 229);
-    Color DARKER_GRAY_2 = new Color(12,12,12,246);
+    Color DARKER_GRAY_2 = new Color(12, 12, 12, 246);
     Color DARKER_GRAY = new Color(10, 10, 10, 243);
     private int contextMenuX = 0, contextMenuY = 0;
     private int width = 0, height = 0;
@@ -80,16 +80,17 @@ public ModernSkin() {
     public LayoutContext.Offset getGroupIndent() {
         return new LayoutContext.Offset(2, 2);
     }
-    public void enableSkinScissor(){
-        DrawHelper.enableScissor(contextMenuX + (int) (width * 0.2f) + 10,contextMenuY + 19,  (int) (width * 0.8f - 14),height - 23,SCALE_FACTOR);
+
+    public void enableSkinScissor() {
+        DrawHelper.enableScissor(contextMenuX + (int) (width * 0.2f) + 10, contextMenuY + 19, (int) (width * 0.8f - 14), height - 23, SCALE_FACTOR);
     }
 
     @Override
     public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY) {
-        mouseX = (int) (mc.mouse.getX()/SCALE_FACTOR);
-        mouseY = (int) (mc.mouse.getY()/SCALE_FACTOR);
+        mouseX = (int) (mc.mouse.getX() / SCALE_FACTOR);
+        mouseY = (int) (mc.mouse.getY() / SCALE_FACTOR);
 
-        if(group.isExpanded() && group.getHeight() > 20) {
+        if (group.isExpanded() && group.getHeight() > 20) {
             DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(),
                     groupX + 1, groupY + 14, width - groupX - 8 + contextMenuX, group.getHeight() - 16, radius, DARKER_GRAY_2.getRGB());
         }
@@ -97,11 +98,11 @@ public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX,
         String groupText = group.name + " " + (group.isExpanded() ? "-" : "+");
 
         DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(),
-                groupX + 1, groupY + 1,true,true, !group.isExpanded(),!group.isExpanded(), mc.textRenderer.getWidth(groupText) + 6, 16, radius, DARKER_GRAY_2.getRGB());
+                groupX + 1, groupY + 1, true, true, !group.isExpanded(), !group.isExpanded(), mc.textRenderer.getWidth(groupText) + 6, 16, radius, DARKER_GRAY_2.getRGB());
 
         drawContext.drawText(mc.textRenderer, groupText, groupX + 4, groupY + 4, -1, true);
 
-        if(group.isExpanded()) {
+        if (group.isExpanded()) {
             int yOffset = groupY + 16 + getGroupIndent().top;
             for (Option option : group.getGroupOptions()) {
                 if (!option.shouldRender()) continue;
@@ -111,19 +112,20 @@ public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX,
             }
 
             group.setHeight(yOffset - groupY);
-        } else{
+        } else {
             group.setHeight(20);
         }
     }
+
     private void drawScrollbar(DrawContext drawContext) {
         if (getMaxScrollOffset() > 0) {
             int scrollbarX = contextMenuX + width + 5; // Position at the right of the panel
             int scrollbarY = contextMenuY + 19; // Position below the header
-            int handleHeight = (int) ((float) (height- 23) * ( (height- 23) / (float) contextMenu.getHeight()));
-            int handleY = scrollbarY + (int) ((float) ((height- 23) - handleHeight) * ((float) scrollHandler.getScrollOffset() / getMaxScrollOffset()));
+            int handleHeight = (int) ((float) (height - 23) * ((height - 23) / (float) contextMenu.getHeight()));
+            int handleY = scrollbarY + (int) ((float) ((height - 23) - handleHeight) * ((float) scrollHandler.getScrollOffset() / getMaxScrollOffset()));
 
-            DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), scrollbarX,scrollbarY,2,height - 23,1,DARKER_GRAY.getRGB());
-            DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), scrollbarX,handleY,2,handleHeight,1,Color.LIGHT_GRAY.getRGB());
+            DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), scrollbarX, scrollbarY, 2, height - 23, 1, DARKER_GRAY.getRGB());
+            DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), scrollbarX, handleY, 2, handleHeight, 1, Color.LIGHT_GRAY.getRGB());
         }
     }
 
@@ -132,8 +134,8 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
         //This is equivalent to "Auto" GUI scale in minecraft options
         SCALE_FACTOR = mc.getWindow().calculateScaleFactor(0, mc.forcesUnicodeFont());
 
-        mouseX = (int) (mc.mouse.getX()/SCALE_FACTOR);
-        mouseY = (int) (mc.mouse.getY()/SCALE_FACTOR);
+        mouseX = (int) (mc.mouse.getX() / SCALE_FACTOR);
+        mouseY = (int) (mc.mouse.getY() / SCALE_FACTOR);
 
         // Apply custom scaling to counteract Minecraft's default scaling
         DrawHelper.customScaledProjection(SCALE_FACTOR);
@@ -254,7 +256,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) {
                 true
         );
 
-        List wrappedText = mc.textRenderer.wrapLines(StringVisitable.styled(TOOLTIP_TEXT.getString(),TOOLTIP_TEXT.getStyle()), toolTipWidth);
+        List wrappedText = mc.textRenderer.wrapLines(StringVisitable.styled(TOOLTIP_TEXT.getString(), TOOLTIP_TEXT.getStyle()), toolTipWidth);
 
         DrawHelper.scaleAndPosition(drawContext.getMatrices(), contextMenuX + 4, tooltipY + 19, textScale);
 
@@ -300,14 +302,14 @@ public boolean mouseReleased(ContextMenu menu, double mouseX, double mouseY,
 
     @Override
     public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, int button) {
-        mouseX = mc.mouse.getX()/SCALE_FACTOR;
-        mouseY = mc.mouse.getY()/SCALE_FACTOR;
+        mouseX = mc.mouse.getX() / SCALE_FACTOR;
+        mouseY = mc.mouse.getY() / SCALE_FACTOR;
 
-        if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX,mouseY, contextMenuX + width - 5,contextMenuY,7,height)) {
+        if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY, 7, height)) {
             scrollHandler.startDragging(mouseY);
         }
 
-        if(button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
+        if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
             int optionStartX = contextMenuX + (int) (width * 0.2f) + 10;
             int yOffset = contextMenu.y + 22 - scrollHandler.getScrollOffset();
             for (Option option : getOptions(contextMenu)) {
@@ -332,12 +334,13 @@ public boolean mouseClicked(ContextMenu menu, double mouseX, double mouseY, i
         }
         return super.mouseClicked(menu, mouseX, mouseY, button);
     }
+
     @Override
     public boolean mouseDragged(ContextMenu menu, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
-        mouseX = mc.mouse.getX()/SCALE_FACTOR;
-        mouseY = mc.mouse.getY()/SCALE_FACTOR;
+        mouseX = mc.mouse.getX() / SCALE_FACTOR;
+        mouseY = mc.mouse.getY() / SCALE_FACTOR;
 
-        if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX,mouseY, contextMenuX + width - 5,contextMenuY,7,height)) {
+        if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY, 7, height)) {
             scrollHandler.updateScrollPosition(mouseY);
         }
         return super.mouseDragged(menu, mouseX, mouseY, button, deltaX, deltaY);
@@ -417,15 +420,15 @@ public class ModernColorOptionRenderer implements SkinRenderer {
         private float scale = 0f;
         private boolean display = false;
 
-        public void update(ColorOption option){
-            if(option.getColorGradient().shouldDisplay() && display){
+        public void update(ColorOption option) {
+            if (option.getColorGradient().shouldDisplay() && display) {
                 scale += ANIMATION_SPEED;
             }
-            if(!display){
+            if (!display) {
                 scale -= ANIMATION_SPEED;
             }
-            scale = MathHelper.clamp(scale,0,1.0f);
-            if(scale <= 0){
+            scale = MathHelper.clamp(scale, 0, 1.0f);
+            if (scale <= 0) {
                 option.getColorGradient().close();
             }
         }
@@ -454,7 +457,7 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in
             int shadowOpacity = Math.min(option.value.getAlpha(), 45);
 
             //The shape behind the preview
-            Color behindColor = isMouseOver(mouseX,mouseY,x + backgroundWidth - width - 17, y + 1,width + 2,14) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color behindColor = isMouseOver(mouseX, mouseY, x + backgroundWidth - width - 17, y + 1, width + 2, 14) ? getThemeColor().darker().darker() : getThemeColor();
             DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(),
                     x + backgroundWidth - width - 17,
                     y + 1,
@@ -489,26 +492,26 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in
                     1);
 
             int targetHeight = (int) (option.getColorGradient().getBoxSize() + option.getColorGradient().getGradientBox().getSize() * scale);
-            option.setHeight(option.getColorGradient().shouldDisplay() ?  targetHeight : 20);
+            option.setHeight(option.getColorGradient().shouldDisplay() ? targetHeight : 20);
             option.setWidth(width);
 
-            if(option.getColorGradient().getColorPickerButton().isPicking()) {
+            if (option.getColorGradient().getColorPickerButton().isPicking()) {
                 RenderSystem.disableScissor(); //Disable scissor so the color picker preview works
             }
 
-            DrawHelper.scaleAndPosition(drawContext.getMatrices(),x + backgroundWidth/2.0f,y, scale);
-            option.getColorGradient().render(drawContext, x + backgroundWidth/2 - 50, y + 6,mouseX,mouseY);
+            DrawHelper.scaleAndPosition(drawContext.getMatrices(), x + backgroundWidth / 2.0f, y, scale);
+            option.getColorGradient().render(drawContext, x + backgroundWidth / 2 - 50, y + 6, mouseX, mouseY);
             DrawHelper.stopScaling(drawContext.getMatrices());
 
-            if(option.getColorGradient().getColorPickerButton().isPicking()) {
+            if (option.getColorGradient().getColorPickerButton().isPicking()) {
                 enableSkinScissor(); // re-enable the scissor
             }
         }
 
         @Override
         public boolean mouseClicked(ColorOption option, double mouseX, double mouseY, int button) {
-            mouseX = mc.mouse.getX()/SCALE_FACTOR;
-            mouseY = mc.mouse.getY()/SCALE_FACTOR;
+            mouseX = mc.mouse.getX() / SCALE_FACTOR;
+            mouseY = mc.mouse.getY() / SCALE_FACTOR;
             if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX() + (int) (width * 0.8f - 14) - 37, option.getY(), 22, 16)) {
                 option.isVisible = !option.isVisible;
                 if (option.isVisible) {
@@ -519,23 +522,23 @@ public boolean mouseClicked(ColorOption option, double mouseX, double mouseY, in
                 }
                 return true;
             }
-            option.getColorGradient().mouseClicked(mouseX,mouseY,button);
+            option.getColorGradient().mouseClicked(mouseX, mouseY, button);
             return false;
         }
 
         @Override
         public boolean mouseDragged(ColorOption option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
-            mouseX = mc.mouse.getX()/SCALE_FACTOR;
-            mouseY = mc.mouse.getY()/SCALE_FACTOR;
-            option.getColorGradient().mouseDragged(mouseX,mouseY,button);
+            mouseX = mc.mouse.getX() / SCALE_FACTOR;
+            mouseY = mc.mouse.getY() / SCALE_FACTOR;
+            option.getColorGradient().mouseDragged(mouseX, mouseY, button);
             return SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
         }
 
         @Override
         public boolean mouseReleased(ColorOption option, double mouseX, double mouseY, int button) {
-            mouseX = mc.mouse.getX()/SCALE_FACTOR;
-            mouseY = mc.mouse.getY()/SCALE_FACTOR;
-            option.getColorGradient().mouseReleased(mouseX,mouseY,button);
+            mouseX = mc.mouse.getX() / SCALE_FACTOR;
+            mouseY = mc.mouse.getY() / SCALE_FACTOR;
+            option.getColorGradient().mouseReleased(mouseX, mouseY, button);
 
             return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
         }
@@ -562,7 +565,7 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i
             int sliderBackgroundHeight = 2;
             int sliderX = x + backgroundWidth - sliderBackgroundWidth - 10;
 
-            option.setPosition(x,y);
+            option.setPosition(x, y);
             option.setWidth(sliderBackgroundWidth);
             option.setHeight(14);
 
@@ -572,15 +575,15 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i
             // Background
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
-                    sliderX, y, sliderBackgroundWidth, sliderBackgroundHeight,1, DARKER_GRAY.getRGB()
+                    sliderX, y, sliderBackgroundWidth, sliderBackgroundHeight, 1, DARKER_GRAY.getRGB()
             );
 
             // Active fill
             int activeFillWidth = (int) ((displayValue - option.minValue) / (option.maxValue - option.minValue) * option.getWidth());
-            Color fillColor = isMouseOver(mouseX,mouseY,sliderX, y,sliderBackgroundWidth,sliderBackgroundHeight + 4) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color fillColor = isMouseOver(mouseX, mouseY, sliderX, y, sliderBackgroundWidth, sliderBackgroundHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
-                    sliderX, y, activeFillWidth, sliderBackgroundHeight,1, fillColor.getRGB()
+                    sliderX, y, activeFillWidth, sliderBackgroundHeight, 1, fillColor.getRGB()
             );
 
             // Draw slider handle
@@ -589,7 +592,7 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i
 
             // Draw value text
             String text = String.format("%.2f", displayValue);
-            DrawHelper.scaleAndPosition(drawContext.getMatrices(),sliderX + 120 - mc.textRenderer.getWidth(text),y + 7,0.6f);
+            DrawHelper.scaleAndPosition(drawContext.getMatrices(), sliderX + 120 - mc.textRenderer.getWidth(text), y + 7, 0.6f);
             drawContext.drawText(
                     mc.textRenderer,
                     text,
@@ -603,8 +606,8 @@ public void render(DrawContext drawContext, DoubleOption option, int x, int y, i
 
         @Override
         public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) {
-            mouseX = mc.mouse.getX()/SCALE_FACTOR;
-            mouseY = mc.mouse.getY()/SCALE_FACTOR;
+            mouseX = mc.mouse.getX() / SCALE_FACTOR;
+            mouseY = mc.mouse.getY() / SCALE_FACTOR;
             if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX() + (int) (width * 0.8f - 14) - 125, option.getY() - 1, option.getWidth() + 2, option.getHeight() + 1)) {
                 option.setDragging(true);
                 return true;
@@ -615,7 +618,7 @@ public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, i
         @Override
         public boolean mouseDragged(DoubleOption option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
             if (option.isDragging()) {
-                mouseX = mc.mouse.getX()/SCALE_FACTOR;
+                mouseX = mc.mouse.getX() / SCALE_FACTOR;
                 int backgroundWidth = (int) (width * 0.8f - 14);
                 int sliderBackgroundWidth = 120;
                 int sliderX = option.getX() + backgroundWidth - sliderBackgroundWidth - 10;
@@ -645,36 +648,36 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y,
             String mainLabel = option.name + ": ";
             String selectedOption = option.get().toString();
             drawContext.drawText(mc.textRenderer, mainLabel, x + 4, y + 2, -1, false);
-            Color fillColor = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
-                    x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2,2,
+                    x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2, 2,
                     fillColor.getRGB()
             );
             // "<" and ">" buttons
-            int contextMenuWidth = (int)(width * 0.8f - 14);
+            int contextMenuWidth = (int) (width * 0.8f - 14);
             int leftX = x + contextMenuWidth - 30;
-            boolean hoveredOverLeft = isMouseOver(mouseX,mouseY,leftX,y,mc.textRenderer.getWidth("<") + 5,mc.textRenderer.fontHeight);
-            boolean hoveredOverRight = isMouseOver(mouseX,mouseY,leftX + mc.textRenderer.getWidth("<") + 6,y,mc.textRenderer.getWidth(">") + 5,mc.textRenderer.fontHeight);
+            boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight);
+            boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.textRenderer.getWidth("<") + 6, y, mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight);
             // Shadow
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX + 1, y + 3,
-                    (mc.textRenderer.getWidth("<") * 2) + 10, mc.textRenderer.fontHeight,2,
-                    ColorHelper.changeAlpha(Color.BLACK,128).getRGB()
+                    (mc.textRenderer.getWidth("<") * 2) + 10, mc.textRenderer.fontHeight, 2,
+                    ColorHelper.changeAlpha(Color.BLACK, 128).getRGB()
             );
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX, y + 2,
-                    true,false,true,false,
-                    mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight,2,
+                    true, false, true, false,
+                    mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight, 2,
                     hoveredOverLeft ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
             );
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX + mc.textRenderer.getWidth("<") + 6, y + 2,
-                    false,true,false,true,
-                    mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight,2,
+                    false, true, false, true,
+                    mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight, 2,
                     hoveredOverRight ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
             );
             DrawHelper.drawVerticalLine(
@@ -685,8 +688,8 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y,
                     0.7f,
                     Color.WHITE.getRGB()
             );
-            drawContext.drawText(mc.textRenderer, "<", leftX + mc.textRenderer.getWidth("<")/2 + 1, y + 3, -1, false);
-            drawContext.drawText(mc.textRenderer, ">", leftX + mc.textRenderer.getWidth("<") + 7 + mc.textRenderer.getWidth(">")/2, y + 3, -1, false);
+            drawContext.drawText(mc.textRenderer, "<", leftX + mc.textRenderer.getWidth("<") / 2 + 1, y + 3, -1, false);
+            drawContext.drawText(mc.textRenderer, ">", leftX + mc.textRenderer.getWidth("<") + 7 + mc.textRenderer.getWidth(">") / 2, y + 3, -1, false);
 
             drawContext.drawText(mc.textRenderer, selectedOption, x + 6 + mc.textRenderer.getWidth(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), false);
         }
@@ -705,11 +708,11 @@ public boolean mouseClicked(EnumOption option, double mouseX, double mouseY,
 
             // Check if the main label is clicked to cycle
             // "<" and ">" buttons
-            int contextMenuWidth = (int)(width * 0.8f - 14);
+            int contextMenuWidth = (int) (width * 0.8f - 14);
             int leftX = x + contextMenuWidth - 30;
-            boolean hoveredOverLeft = isMouseOver(mouseX,mouseY,leftX,y,mc.textRenderer.getWidth("<") + 5,mc.textRenderer.fontHeight);
-            boolean hoveredOverRight = isMouseOver(mouseX,mouseY,leftX + mc.textRenderer.getWidth("<") + 6,y,mc.textRenderer.getWidth(">") + 5,mc.textRenderer.fontHeight);
-            boolean hoveredOverMainLabel = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2);
+            boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight);
+            boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.textRenderer.getWidth("<") + 6, y, mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight);
+            boolean hoveredOverMainLabel = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2);
 
             if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) {
                 E[] values = option.getValues();
@@ -744,37 +747,37 @@ public void render(DrawContext drawContext, ListOption option, int x, int y,
             String mainLabel = option.name + ": ";
             String selectedOption = option.get().toString();
             drawContext.drawText(mc.textRenderer, mainLabel, x + 4, y + 2, -1, false);
-            Color fillColor = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
-                    x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2,2,
+                    x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2, 2,
                     fillColor.getRGB()
             );
 
             // "<" and ">" buttons
-            int contextMenuWidth = (int)(width * 0.8f - 14);
+            int contextMenuWidth = (int) (width * 0.8f - 14);
             int leftX = x + contextMenuWidth - 30;
-            boolean hoveredOverLeft = isMouseOver(mouseX,mouseY,leftX,y,mc.textRenderer.getWidth("<") + 5,mc.textRenderer.fontHeight);
-            boolean hoveredOverRight = isMouseOver(mouseX,mouseY,leftX + mc.textRenderer.getWidth("<") + 6,y,mc.textRenderer.getWidth(">") + 5,mc.textRenderer.fontHeight);
+            boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight);
+            boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.textRenderer.getWidth("<") + 6, y, mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight);
             // Shadow
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX + 1, y + 3,
-                    (mc.textRenderer.getWidth("<") * 2) + 10, mc.textRenderer.fontHeight,2,
-                    ColorHelper.changeAlpha(Color.BLACK,128).getRGB()
+                    (mc.textRenderer.getWidth("<") * 2) + 10, mc.textRenderer.fontHeight, 2,
+                    ColorHelper.changeAlpha(Color.BLACK, 128).getRGB()
             );
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX, y + 2,
-                    true,false,true,false,
-                    mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight,2,
+                    true, false, true, false,
+                    mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight, 2,
                     hoveredOverLeft ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
             );
             DrawHelper.drawRoundedRectangle(
                     drawContext.getMatrices().peek().getPositionMatrix(),
                     leftX + mc.textRenderer.getWidth("<") + 6, y + 2,
-                    false,true,false,true,
-                    mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight,2,
+                    false, true, false, true,
+                    mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight, 2,
                     hoveredOverRight ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
             );
             DrawHelper.drawVerticalLine(
@@ -785,8 +788,8 @@ public void render(DrawContext drawContext, ListOption option, int x, int y,
                     0.7f,
                     Color.WHITE.getRGB()
             );
-            drawContext.drawText(mc.textRenderer, "<", leftX + mc.textRenderer.getWidth("<")/2 + 1, y + 3, -1, false);
-            drawContext.drawText(mc.textRenderer, ">", leftX + mc.textRenderer.getWidth("<") + 7 + mc.textRenderer.getWidth(">")/2, y + 3, -1, false);
+            drawContext.drawText(mc.textRenderer, "<", leftX + mc.textRenderer.getWidth("<") / 2 + 1, y + 3, -1, false);
+            drawContext.drawText(mc.textRenderer, ">", leftX + mc.textRenderer.getWidth("<") + 7 + mc.textRenderer.getWidth(">") / 2, y + 3, -1, false);
 
             drawContext.drawText(mc.textRenderer, selectedOption, x + 6 + mc.textRenderer.getWidth(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), false);
         }
@@ -810,7 +813,7 @@ public boolean mouseClicked(ListOption option, double mouseX, double mouseY,
             // Check hover states
             boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.textRenderer.getWidth("<") + 5, mc.textRenderer.fontHeight);
             boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.textRenderer.getWidth("<") + 6, y, mc.textRenderer.getWidth(">") + 5, mc.textRenderer.fontHeight);
-            boolean hoveredOverMainLabel = isMouseOver(mouseX,mouseY,x + 4 + mc.textRenderer.getWidth(mainLabel), y,mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2);
+            boolean hoveredOverMainLabel = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2);
 
             // Check if any area is clicked
             if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) {
@@ -842,10 +845,10 @@ public void render(DrawContext drawContext, SubMenuOption option, int x, int y,
             mouseY = (int) (mc.mouse.getY() / SCALE_FACTOR);
 
             String text = "Open";
-            int contextMenuWidth = (int)(width * 0.8f - 14);
+            int contextMenuWidth = (int) (width * 0.8f - 14);
             int xPos = x + 4 + contextMenuWidth - 40;
 
-            option.setPosition( xPos - 1, y);
+            option.setPosition(xPos - 1, y);
             option.setWidth(mc.textRenderer.getWidth(text) + 5);
             option.setHeight(16);
 
@@ -853,7 +856,7 @@ public void render(DrawContext drawContext, SubMenuOption option, int x, int y,
 
             drawContext.drawText(mc.textRenderer, text, xPos + 2, y + 4, Color.WHITE.getRGB(), true);
 
-            Color fillColor = isMouseOver(mouseX,mouseY,xPos + 2, y + 4,mc.textRenderer.getWidth(text) + 5, mc.textRenderer.fontHeight + 4) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.textRenderer.getWidth(text) + 5, mc.textRenderer.fontHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
 
             DrawHelper.drawRoundedRectangleWithShadowBadWay(
                     drawContext.getMatrices().peek().getPositionMatrix(),
@@ -913,10 +916,10 @@ public class ModernRunnableRenderer implements SkinRenderer {
         @Override
         public void render(DrawContext drawContext, RunnableOption option, int x, int y, int mouseX, int mouseY) {
             String text = "Run â–¶";
-            int contextMenuWidth = (int)(width * 0.8f - 14);
+            int contextMenuWidth = (int) (width * 0.8f - 14);
             int xPos = x + 4 + contextMenuWidth - 45;
 
-            option.setPosition( xPos - 1, y);
+            option.setPosition(xPos - 1, y);
             option.setWidth(mc.textRenderer.getWidth(text) + 5);
             option.setHeight(mc.textRenderer.fontHeight + 6);
 
@@ -924,7 +927,7 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y,
 
             drawContext.drawText(mc.textRenderer, text, xPos + 2, y + 4, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true);
 
-            Color fillColor = isMouseOver(mouseX,mouseY,xPos + 2, y + 4,mc.textRenderer.getWidth(text) + 5, mc.textRenderer.fontHeight + 4) ?  getThemeColor().darker().darker() : getThemeColor();
+            Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.textRenderer.getWidth(text) + 5, mc.textRenderer.fontHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
 
             DrawHelper.drawRoundedRectangleWithShadowBadWay(
                     drawContext.getMatrices().peek().getPositionMatrix(),
@@ -937,6 +940,7 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y,
                     1
             );
         }
+
         @Override
         public boolean mouseClicked(RunnableOption option, double mouseX, double mouseY, int button) {
             mouseX = mc.mouse.getX() / SCALE_FACTOR;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
index 04fc50a..852366c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
@@ -24,7 +24,8 @@ public Skin(ContextMenu menu) {
         this.contextMenu = menu;
     }
 
-    public Skin() {}
+    public Skin() {
+    }
 
     public > void addRenderer(Class optionClass, Supplier> renderer) {
         renderers.put(optionClass, renderer);
@@ -67,7 +68,7 @@ protected List> flattenOptions(List> options) {
         return flattened;
     }
 
-    protected List> getOptions(ContextMenu menu){
+    protected List> getOptions(ContextMenu menu) {
         return supportsGroups() ? menu.getOptions() : flattenOptions(menu.getOptions());
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
index f41c5a0..c93dd52 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
@@ -6,6 +6,7 @@
 
 public interface GroupableSkin {
     LayoutContext.Offset getGroupIndent();
-    void renderGroup(DrawContext drawContext, OptionGroup group,int groupX, int groupY, int mouseX, int mouseY);
+
+    void renderGroup(DrawContext drawContext, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY);
 }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/SkinRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/SkinRenderer.java
index aeeab58..89fa741 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/SkinRenderer.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/SkinRenderer.java
@@ -3,31 +3,31 @@
 import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
 import net.minecraft.client.gui.DrawContext;
 
-public interface SkinRenderer>  {
+public interface SkinRenderer> {
     void render(DrawContext drawContext, T option, int x, int y, int mouseX, int mouseY);
 
     default boolean mouseClicked(T option, double mouseX, double mouseY, int button) {
-        return option.mouseClicked(mouseX, mouseY,button);
+        return option.mouseClicked(mouseX, mouseY, button);
     }
 
     default boolean mouseReleased(T option, double mouseX, double mouseY, int button) {
-        return option.mouseReleased(mouseX, mouseY,button);
+        return option.mouseReleased(mouseX, mouseY, button);
     }
 
     default boolean mouseDragged(T option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
-        return option.mouseDragged(mouseX, mouseY,button,deltaX,deltaY);
+        return option.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
     }
 
     default void keyPressed(T option, int key, int scanCode, int modifiers) {
-        option.keyPressed(key, scanCode,modifiers);
+        option.keyPressed(key, scanCode, modifiers);
     }
 
     default void keyReleased(T option, int key, int scanCode, int modifiers) {
-        option.keyReleased(key, scanCode,modifiers);
+        option.keyReleased(key, scanCode, modifiers);
     }
 
     default void mouseScrolled(T option, double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
-        option.mouseScrolled(mouseX, mouseY,horizontalAmount,verticalAmount);
+        option.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
     }
 
     default void init(T option) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
index ba7913e..2bd9d98 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
@@ -19,7 +19,7 @@ public ScrollHandler() {
     }
 
     public void updateScrollOffset(int maxYOffset) {
-        if(maxYOffset < 0) maxYOffset = 0;
+        if (maxYOffset < 0) maxYOffset = 0;
 
         this.maxScrollOffset = maxYOffset;
         applyMomentum();
@@ -40,7 +40,7 @@ public void stopDragging() {
         isDragging = false;
     }
 
-    public void addOffset(int offset){
+    public void addOffset(int offset) {
         this.scrollOffset = MathHelper.clamp(scrollOffset + offset, 0, maxScrollOffset);
     }
 
@@ -50,7 +50,7 @@ public void updateScrollPosition(double mouseY) {
             double deltaY = lastMouseY - mouseY;
 
             // Update the scroll offset based on the mouse movement
-            scrollOffset = MathHelper.clamp(scrollOffset - (int)(deltaY * SCROLL_SPEED), 0, maxScrollOffset);
+            scrollOffset = MathHelper.clamp(scrollOffset - (int) (deltaY * SCROLL_SPEED), 0, maxScrollOffset);
 
             // Update the last mouse position
             lastMouseY = mouseY;
@@ -68,7 +68,8 @@ private void applyMomentum() {
     public int getScrollOffset() {
         return Math.max(scrollOffset, 0);
     }
-    public boolean isOffsetWithinBounds(int offset){
+
+    public boolean isOffsetWithinBounds(int offset) {
         return scrollOffset + offset >= 0 && scrollOffset + offset <= maxScrollOffset;
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
index 66b3de3..506de8d 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
@@ -2,21 +2,28 @@
 
 import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
 import com.tanishisherewith.dynamichud.utils.Util;
+import com.tanishisherewith.dynamichud.widgets.GraphWidget;
+import com.tanishisherewith.dynamichud.widgets.TextWidget;
 import net.minecraft.nbt.NbtCompound;
 
 import java.util.function.Supplier;
 
+/**
+ * DynamicValueWidget is an abstract extension of Widget that automatically handles DynamicValueRegistry to retrieve supplier data.
+ * @see GraphWidget
+ * @see TextWidget
+ */
 public abstract class DynamicValueWidget extends Widget {
     protected String registryKey;
     protected String registryID;
     protected Supplier valueSupplier;
 
     public DynamicValueWidget(WidgetData data, String modID, String registryID, String registryKey) {
-        this(data,modID,Anchor.CENTER,registryID,registryKey);
+        this(data, modID, Anchor.CENTER, registryID, registryKey);
     }
 
     public DynamicValueWidget(WidgetData data, String modId, Anchor anchor, String registryID, String registryKey) {
-        super(data,modId,anchor);
+        super(data, modId, anchor);
         boolean emptyCheck = Util.warnIfTrue(registryID == null || registryID.isEmpty(), "Empty registry ID, using global registry. Widget: {}", this.toString());
         this.registryID = emptyCheck ? DynamicValueRegistry.GLOBAL_ID : registryID;
         this.registryKey = registryKey;
@@ -43,13 +50,15 @@ public void readFromTag(NbtCompound tag) {
 
         initializeValueSupplier();
 
-        if(valueSupplier == null) throw new IllegalStateException("Value supplier remains null");
+        if (valueSupplier == null) throw new IllegalStateException("Value supplier remains null");
     }
 
-    // for subclasses to implement
+    /**
+     * Subclasses should implement this to get value from the supplier.
+     */
     public abstract Object getValue();
 
-    public abstract static class DynamicValueWidgetBuilder, W extends DynamicValueWidget> extends WidgetBuilder {
+    public abstract static class DynamicValueWidgetBuilder, W extends DynamicValueWidget> extends WidgetBuilder {
         protected String registryKey = "";
         protected String registryID = null;
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java b/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java
index a6493ec..b719d15 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java
@@ -1,5 +1,6 @@
 package com.tanishisherewith.dynamichud.widget;
 
+//unused
 public interface UserManageable {
     // Marker interface that a widget is add-able and removable.
 }
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
index cb5f209..7838d34 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
@@ -127,7 +127,7 @@ private int getAnchorY(int screenHeight) {
 
     // Update position based on anchor and offset
     void updatePosition(int screenWidth, int screenHeight) {
-        if(offsetX == 0 || offsetY == 0){
+        if (offsetX == 0 || offsetY == 0) {
             calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight());
         }
 
@@ -242,7 +242,7 @@ public final boolean mouseDragged(double mouseX, double mouseY, int button, doub
         return false;
     }
 
-    public boolean mouseDragged(double mouseX, double mouseY, int button,  double deltaX, double deltaY, int snapSize) {
+    public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY, int snapSize) {
         if (!isDraggable) return false;
         if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
             int newX = (int) (mouseX - startX);
@@ -284,16 +284,20 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
      * @param hAmount horizontal amount of scrolling
      */
     @Override
-    public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) {}
+    public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) {
+    }
 
     @Override
-    public void keyPressed(int key, int scanCode, int modifiers) {}
+    public void keyPressed(int key, int scanCode, int modifiers) {
+    }
 
     @Override
-    public void keyReleased(int key, int scanCode, int modifiers) {}
+    public void keyReleased(int key, int scanCode, int modifiers) {
+    }
 
     @Override
-    public void charTyped(char c, int modifiers) {}
+    public void charTyped(char c, int modifiers) {
+    }
 
     public boolean toggle() {
         return this.isVisible = !this.isVisible;
@@ -322,15 +326,15 @@ protected void drawWidgetBackground(DrawContext context) {
     /**
      * Set the tooltip text of the widget
      */
-    protected void setTooltipText(Text text){
+    protected void setTooltipText(Text text) {
         this.tooltipText = text;
     }
 
     public void readFromTag(NbtCompound tag) {
         modId = tag.getString("modId");
         uid = new UID(tag.getString("UID"));
-   //     x = tag.getInt("x");
-   //     y = tag.getInt("y");
+        //     x = tag.getInt("x");
+        //     y = tag.getInt("y");
         anchor = Anchor.valueOf(tag.getString("anchor"));
         offsetX = tag.getInt("offsetX");
         offsetY = tag.getInt("offsetY");
@@ -350,8 +354,8 @@ public void writeToTag(NbtCompound tag) {
         tag.putString("UID", uid.getUniqueID());
         tag.putBoolean("isDraggable", isDraggable);
         tag.putBoolean("shouldScale", shouldScale);
-    //    tag.putInt("x", x);
-   //     tag.putInt("y", y);
+        //    tag.putInt("x", x);
+        //     tag.putInt("y", y);
         tag.putString("anchor", anchor.name());
         tag.putInt("offsetX", offsetX);
         tag.putInt("offsetY", offsetY);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
index aea7f75..e12da3f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
@@ -1,7 +1,7 @@
 package com.tanishisherewith.dynamichud.widget;
 
 public class WidgetBox {
-    public float x = 0, y = 0;
+    public float x, y;
     private float width;
     private float height;
 
@@ -45,14 +45,14 @@ public boolean intersects(WidgetBox other) {
         return !(this.y + this.height < other.y);
     }
 
-    public void setSizeAndPositionNoScale(float x, float y, float width, float height) {
+    public void setDimensionsNoScale(float x, float y, float width, float height) {
         this.x = x;
         this.y = y;
         this.height = height;
         this.width = width;
     }
 
-    public void setSizeAndPosition(float x, float y, float width, float height, boolean shouldScale, float scale) {
+    public void setDimensions(float x, float y, float width, float height, boolean shouldScale, float scale) {
         this.x = x;
         this.y = y;
         this.height = height * (shouldScale ? scale : 1.0f);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
index 1877de5..693cc30 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
@@ -2,7 +2,6 @@
 
 import com.tanishisherewith.dynamichud.DynamicHUD;
 import com.tanishisherewith.dynamichud.mixins.ScreenMixin;
-import net.fabricmc.fabric.api.util.NbtType;
 import net.minecraft.nbt.NbtCompound;
 import net.minecraft.nbt.NbtElement;
 import net.minecraft.nbt.NbtIo;
@@ -180,6 +179,7 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti
      */
     public static List loadWidgets(File file) throws IOException {
         if (!file.exists()) {
+            // The backup file check is done in the doesWidgetFileExist() function below this
             DynamicHUD.logger.warn("Main file {} was not found... Loading from a found backup file", file.getAbsolutePath());
             file = new File(file.getAbsolutePath() + ".backup");
         }
@@ -199,8 +199,8 @@ public static List loadWidgets(File file) throws IOException {
         for (int i = 0; i < widgetList.size(); i++) {
             NbtCompound widgetTag = widgetList.getCompound(i);
             WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name"));
-            if(widgetData == null){
-                throw new IllegalStateException("Widget Data for: " + widgetTag.getString("name") +" could not be found");
+            if (widgetData == null) {
+                throw new IllegalStateException("A Widget named '" + widgetTag.getString("name") + "' was found in the save file, but no matching WidgetData for its class could be located. This may indicate that the mod responsible for saving this widget has been removed or its implementation is incorrect.");
             }
             Widget widget = widgetData.createWidget();
             widget.readFromTag(widgetTag);
@@ -211,6 +211,9 @@ public static List loadWidgets(File file) throws IOException {
         return widgetsToAdd;
     }
 
+    /**
+     * Checks if the given file exists, or if a backup file exists.
+     */
     public static boolean doesWidgetFileExist(File file) {
         return file.exists() || new File(file.getAbsolutePath() + ".backup").exists();
     }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
index 03c4b74..223797b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
@@ -6,6 +6,7 @@
 import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen;
 import com.tanishisherewith.dynamichud.utils.Input;
 import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry;
+import dev.isxander.yacl3.gui.YACLScreen;
 import net.minecraft.client.gui.DrawContext;
 import net.minecraft.client.gui.screen.GameMenuScreen;
 import net.minecraft.client.gui.screen.Screen;
@@ -32,7 +33,7 @@ public class WidgetRenderer implements Input {
     public WidgetRenderer(List widgets) {
         this.widgets = widgets;
         // Render in GameMenuScreen
-        this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class ||
+        this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class || screen instanceof YACLScreen ||
                 System.getInstances(ContextMenuScreenRegistry.class, DynamicHUD.MOD_ID).stream().anyMatch(registry -> registry.screenKlass == screen.getClass());
     }
 
@@ -43,7 +44,8 @@ public WidgetRenderer(String modID) {
     public void addWidget(Widget widget) {
         this.widgets.add(widget);
     }
-    public void removeWidget(Widget widget){
+
+    public void removeWidget(Widget widget) {
         this.widgets.remove(widget);
     }
 
@@ -56,7 +58,7 @@ public void clearAndAdd(List widgets) {
      * Use this when you want to simply add more screens
      */
     public void addScreen(Class screen) {
-       this.allowedScreens = allowedScreens.or(screen1 -> screen1.getClass() == screen);
+        this.allowedScreens = allowedScreens.or(screen1 -> screen1.getClass() == screen);
     }
 
     /**
@@ -82,8 +84,8 @@ public void shouldRenderInGameHud(boolean renderInGameHud) {
         this.renderInGameHud = renderInGameHud;
     }
 
-    private boolean renderInDebugScreen(){
-        if(GlobalConfig.get().renderInDebugScreen()){
+    private boolean renderInDebugScreen() {
+        if (GlobalConfig.get().renderInDebugScreen()) {
             return true;
         }
         return !DynamicHUD.MC.getDebugHud().shouldShowDebugHud();
@@ -95,7 +97,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) {
         Screen currentScreen = DynamicHUD.MC.currentScreen;
 
         context.getMatrices().push();
-        context.getMatrices().translate(0,0, Z_Index);
+        context.getMatrices().translate(0, 0, Z_Index);
 
         //Render in editing screen
         if (currentScreen instanceof AbstractMoveableScreen) {
@@ -149,7 +151,8 @@ public void mouseScrolled(double mouseX, double mouseY, double vAmount, double h
     }
 
     @Override
-    public void charTyped(char c, int modifiers) {}
+    public void charTyped(char c, int modifiers) {
+    }
 
     public void onCloseScreen() {
         if (DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen) {
@@ -221,9 +224,8 @@ public void keyReleased(int key, int scanCode, int modifiers) {
         }
     }
 
-    public WidgetRenderer withZIndex(int z_Index){
+    public WidgetRenderer withZIndex(int z_Index) {
         this.Z_Index = z_Index;
         return this;
     }
-
 }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 9237574..64d47c7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -1,7 +1,7 @@
 package com.tanishisherewith.dynamichud.widgets;
 
 import com.mojang.blaze3d.systems.RenderSystem;
-import com.tanishisherewith.dynamichud.DynamicHUD;
+import com.tanishisherewith.dynamichud.config.GlobalConfig;
 import com.tanishisherewith.dynamichud.helpers.ColorHelper;
 import com.tanishisherewith.dynamichud.helpers.DrawHelper;
 import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations;
@@ -19,6 +19,7 @@
 import com.twelvemonkeys.lang.Validate;
 import net.minecraft.client.gl.ShaderProgramKeys;
 import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.render.*;
 import net.minecraft.nbt.NbtCompound;
 import net.minecraft.text.Text;
 import net.minecraft.util.math.MathHelper;
@@ -28,15 +29,13 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import net.minecraft.client.render.*;
-
 /**
  * Graph widget to draw a simple but detailed graph.
  * You need to use DynamicValueRegistry to pass a value to the graph.
  * You can use null values to signify the graph should update with a new value yet.
  */
-public class GraphWidget extends DynamicValueWidget implements ContextMenuProvider{
-    public static WidgetData DATA = new WidgetData<>("GraphWidget","Show graph",GraphWidget::new);
+public class GraphWidget extends DynamicValueWidget implements ContextMenuProvider {
+    public static WidgetData DATA = new WidgetData<>("GraphWidget", "Show graph", GraphWidget::new);
 
     private ContextMenu menu;
     private final float[] dataPoints;
@@ -56,7 +55,7 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
     private boolean autoUpdateRange = false;
 
     public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) {
-        super(DATA, modId, anchor,registryID, registryKey);
+        super(DATA, modId, anchor, registryID, registryKey);
         Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2.");
         this.dataPoints = new float[maxDataPoints];
         this.width = width;
@@ -76,8 +75,8 @@ public GraphWidget(String registryID, String registryKey, String modId, Anchor a
         ContextMenuManager.getInstance().registerProvider(this);
     }
 
-    public GraphWidget(){
-        this(DynamicValueRegistry.GLOBAL_ID,"unknown","unknown",Anchor.CENTER,0,0,10,0,10,Color.RED,Color.GREEN,0,false,0,"empty");
+    public GraphWidget() {
+        this(DynamicValueRegistry.GLOBAL_ID, "unknown", "unknown", Anchor.CENTER, 0, 0, 10, 0, 10, Color.RED, Color.GREEN, 0, false, 0, "empty");
     }
 
     @Override
@@ -89,14 +88,14 @@ public void init() {
     }
 
     /// Automatically update the min and max of the graph
-    public GraphWidget autoUpdateRange(){
+    public GraphWidget autoUpdateRange() {
         this.autoUpdateRange = true;
         return this;
     }
 
     public void addDataPoint(Float value) {
-        if(value == null) return;
-        if(autoUpdateRange) {
+        if (value == null) return;
+        if (autoUpdateRange) {
             if (getMaxValue() < value) {
                 setMaxValue(value + 10);
                 float diff = getMaxValue() - getPrevMaxValue();
@@ -200,19 +199,19 @@ private void drawGradientShadow(Matrix4f matrix, List points, float bot
     public void renderWidget(DrawContext context, int mouseX, int mouseY) {
         Matrix4f matrix = context.getMatrices().peek().getPositionMatrix();
 
-        if(valueSupplier != null){
+        if (valueSupplier != null) {
             addDataPoint(getValue());
         }
 
         // Apply pulse1 animation to background alpha
-        float animatedAlpha = MathHelper.clamp(MathAnimations.pulse1(backgroundColor.getAlpha() / 255.0f, 0.2f, 0.001f),0f,1.0f);
+        float animatedAlpha = MathHelper.clamp(MathAnimations.pulse1(backgroundColor.getAlpha() / 255.0f, 0.2f, 0.001f), 0f, 1.0f);
         Color animatedBackgroundColor = ColorHelper.changeAlpha(backgroundColor, (int) (animatedAlpha * 255));
         Color gradientColor = ColorHelper.changeAlpha(backgroundColor, (int) (animatedAlpha * 255 * 0.7f));
 
-        DrawHelper.enableScissor(x - 50, y, (int) width + 2 + 50, (int) height + 2);
+        DrawHelper.enableScissor(widgetBox);
 
         // Draw gradient background with rounded corners
-        if(!isInEditor) {
+        if (!isInEditor) {
             DrawHelper.drawRoundedGradientRectangle(
                     matrix,
                     animatedBackgroundColor,
@@ -230,7 +229,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
             float valueStep = (maxValue - minValue) / (gridLines + 1);
 
             //TODO: The scale is too small for grid lines for than 21 (20 is the barely visible threshold)
-            float scale = (float) MathHelper.clamp((stepY/9.5),0.0f,1.0f);
+            float scale = (float) MathHelper.clamp((stepY / 9.5), 0.0f, 1.0f);
 
             for (int i = 1; i <= gridLines; i++) {
                 float yPos = y + stepY * i;
@@ -242,7 +241,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
 
                 //Scale the text to its proper position and size with grid lines
                 DrawHelper.scaleAndPosition(context.getMatrices(), x - 2, yPos, scale);
-                context.drawText(mc.textRenderer, valueText, x - mc.textRenderer.getWidth(valueText), (int) (yPos - (mc.textRenderer.fontHeight * scale)/2.0f), 0xFFFFFFFF, true);
+                context.drawText(mc.textRenderer, valueText, x - mc.textRenderer.getWidth(valueText), (int) (yPos - (mc.textRenderer.fontHeight * scale) / 2.0f), 0xFFFFFFFF, true);
                 DrawHelper.stopScaling(context.getMatrices());
             }
 
@@ -260,7 +259,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
         // Draw shadow effect under the graph
         drawGradientShadow(
                 matrix, points, y + height,
-                ColorHelper.changeAlpha(graphColor,50).getRGB(),
+                ColorHelper.changeAlpha(graphColor, 50).getRGB(),
                 0x00000000
         );
 
@@ -283,15 +282,15 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
 
          */
 
-        DrawHelper.scaleAndPosition(context.getMatrices(),x - 5,y + height,0.5f);
+        DrawHelper.scaleAndPosition(context.getMatrices(), x - 5, y + height, 0.5f);
         String formattedMinVal = formatValue(minValue);
         context.drawText(mc.textRenderer, formattedMinVal, x - mc.textRenderer.getWidth(formattedMinVal), (int) (y + height - 4), 0xFFFFFFFF, true);
         DrawHelper.stopScaling(context.getMatrices());
 
-        this.widgetBox.setSizeAndPositionNoScale(x,y,width,height);
+        this.widgetBox.setDimensions(x, y, width, height,shouldScale, GlobalConfig.get().getScale());
         DrawHelper.disableScissor();
 
-        if(menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
+        if (menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
     }
 
     // format large values (like: 1000 -> 1K, 1000000 -> 1M)
@@ -307,13 +306,13 @@ private String formatValue(float value) {
 
     @Override
     public boolean mouseClicked(double mouseX, double mouseY, int button) {
-        menu.toggleDisplay(widgetBox,mouseX,mouseY,button);
+        menu.toggleDisplay(widgetBox, mouseX, mouseY, button);
         return super.mouseClicked(mouseX, mouseY, button);
     }
 
     public void createMenu() {
         ContextMenuProperties properties = ContextMenuProperties.builder().build();
-        menu = new ContextMenu<>(getX(), (int) (getY() + height), properties);
+        menu = new ContextMenu<>(getX(), (int) (getY() + widgetBox.getHeight()), properties);
 
         menu.addOption(new BooleanOption(Text.of("Show Grid"),
                 () -> this.showGrid, value -> this.showGrid = value,
@@ -323,7 +322,7 @@ public void createMenu() {
         menu.addOption(new DoubleOption(Text.of("Number of Grid Lines"),
                 1, 25, 1,
                 () -> (double) this.gridLines, value -> this.gridLines = value.intValue(), menu)
-                .renderWhen(()-> this.showGrid)
+                .renderWhen(() -> this.showGrid)
         );
         menu.addOption(new ColorOption(Text.of("Graph Line Color"),
                 () -> this.graphColor, value -> this.graphColor = value, menu)
@@ -499,7 +498,8 @@ public static class GraphWidgetBuilder extends DynamicValueWidgetBuilder(getX(), getY(), properties);
 
         menu.addOption(new BooleanOption(Text.of("Shadow"),
-                        () -> this.shadow, value -> this.shadow = value,
-                        BooleanOption.BooleanType.ON_OFF)
+                () -> this.shadow, value -> this.shadow = value,
+                BooleanOption.BooleanType.ON_OFF)
                 .description(Text.of("Adds shadow to your text"))
         );
         menu.addOption(new BooleanOption(Text.of("Rainbow"),
-                        () -> this.rainbow, value -> this.rainbow = value,
-                        BooleanOption.BooleanType.ON_OFF)
+                () -> this.rainbow, value -> this.rainbow = value,
+                BooleanOption.BooleanType.ON_OFF)
                 .description(Text.of("Adds rainbow effect to your text"))
         );
         menu.addOption(new ColorOption(Text.of("Text Color"),
                 () -> this.textColor, value -> this.textColor = value, menu)
                 .description(Text.of("Specify the color you want to add to your text"))
-                .renderWhen(()-> !this.rainbow)
+                .renderWhen(() -> !this.rainbow)
         );
         menu.addOption(new DoubleOption(Text.of("Rainbow Speed"),
                 1, 5.0f, 1,
@@ -120,23 +123,24 @@ public void createMenu() {
 
     @Override
     public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) {
-        if(menu == null) return;
+        if (menu == null) return;
         //int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) : textColor.getRGB();
         int color = textColor.getRGB();
         if (valueSupplier != null) {
             String text = getValue();
-            if(rainbow){
-                DrawHelper.drawChromaText(drawContext,text,getX() + 2, getY() + 2, rainbowSpeed/2f,rainbowSaturation,rainbowBrightness,rainbowSpread,shadow);
+            if (rainbow) {
+                DrawHelper.drawChromaText(drawContext, text, getX() + 2, getY() + 2, rainbowSpeed / 2f, rainbowSaturation, rainbowBrightness, rainbowSpread, shadow);
             } else {
                 drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow);
             }
-            widgetBox.setSizeAndPosition(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
+            widgetBox.setDimensions(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
         }
         menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
     }
+
     @Override
     public boolean mouseClicked(double mouseX, double mouseY, int button) {
-        menu.toggleDisplay(widgetBox,mouseX,mouseY,button);
+        menu.toggleDisplay(widgetBox, mouseX, mouseY, button);
         return super.mouseClicked(mouseX, mouseY, button);
     }
 
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 5874a6c..6ff31d0 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -21,7 +21,6 @@
     "dynamicHud": [
       "com.tanishisherewith.dynamichud.integration.DefaultIntegrationImpl"
     ],
-
     "client": [
       "com.tanishisherewith.dynamichud.DynamicHUD"
     ]
@@ -37,7 +36,9 @@
   },
   "custom": {
     "modmenu": {
-      "badges": ["library"]
+      "badges": [
+        "library"
+      ]
     }
   },
   "suggests": {

From 025c3f6644d40f980a9abd4880e0f371547414a5 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Thu, 29 May 2025 01:21:01 +0530
Subject: [PATCH 35/40] Fixed rendering issues and TextWidget not saving.

---
 .../dynamichud/DynamicHUD.java                |  1 +
 .../dynamichud/IntegrationTest.java           |  3 +--
 .../dynamichud/helpers/DrawHelper.java        |  5 +---
 .../integration/DynamicHudConfigurator.java   |  5 ++--
 .../contextmenu/skinsystem/MinecraftSkin.java | 23 +++++++++---------
 .../contextmenu/skinsystem/ModernSkin.java    |  3 ++-
 .../dynamichud/widget/WidgetManager.java      |  8 ++++++-
 .../dynamichud/widgets/GraphWidget.java       | 24 ++++++++++++-------
 .../dynamichud/widgets/TextWidget.java        |  6 ++---
 9 files changed, 44 insertions(+), 34 deletions(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
index c37f1b1..ef01878 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
@@ -5,6 +5,7 @@
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
 import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
 import net.minecraft.client.MinecraftClient;
 import org.slf4j.Logger;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
index 78636d0..e6c010c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
@@ -99,8 +99,7 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) {
                     //renderer.shouldRenderInGameHud(true);
                     renderer.addScreen(TitleScreen.class);
                 })
-                .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {}
-                );
+                .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {});
 
         return configurator;
     }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index 69de5ea..bbf0b4a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -27,7 +27,6 @@
  * Credits: HeliosClient
  */
 public class DrawHelper {
-    public static ProjectionType projectionType;
 
     /**
      * Draws a singular gradient rectangle  on screen with the given parameters
@@ -840,16 +839,14 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int
     }
 
     public static void unscaledProjection() {
-        projectionType = RenderSystem.getProjectionType();
         RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth(), mc.getWindow().getFramebufferHeight(), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
     }
 
     public static void scaledProjection() {
-        RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), projectionType);
+        RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
     }
 
     public static void customScaledProjection(float scale) {
-        projectionType = RenderSystem.getProjectionType();
         RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java
index 8b1695b..7340598 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudConfigurator.java
@@ -6,6 +6,7 @@
 import com.tanishisherewith.dynamichud.widget.WidgetManager;
 import com.tanishisherewith.dynamichud.widget.WidgetRenderer;
 import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.fabricmc.fabric.api.event.Event;
 import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
 import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
 import org.jetbrains.annotations.ApiStatus;
@@ -120,7 +121,7 @@ public void setupSaveEvents(File widgetsFile) {
         ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName())));
 
         //When minecraft closes
-        ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName())));
+       ClientLifecycleEvents.CLIENT_STOPPING.register((mc)-> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName())));
     }
 
     @ApiStatus.Internal
@@ -132,7 +133,7 @@ private void saveWidgetsSafely(File widgetsFile, List widgets) {
         try {
             this.saveHandler.accept(widgets);
             WidgetManager.saveWidgets(widgetsFile, widgets);
-        } catch (IOException e) {
+        } catch (Throwable e) {
             DynamicHUD.logger.error("Failed to save widgets. Widgets passed: {}", widgets);
             throw new RuntimeException(e);
         }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
index 88b56d2..d133339 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
@@ -9,6 +9,7 @@
 import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.GroupableSkin;
 import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer;
 import com.tanishisherewith.dynamichud.utils.handlers.ScrollHandler;
+import net.minecraft.client.gl.ShaderProgramKeys;
 import net.minecraft.client.gui.DrawContext;
 import net.minecraft.client.gui.screen.ButtonTextures;
 import net.minecraft.client.render.RenderLayer;
@@ -132,17 +133,17 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
         drawSingularButton(drawContext, "X", mouseX, mouseY, imageX + 3, imageY + 3, 14, 14);
 
         //Up and down arrows near the group panel
-        int size = (int) (groupPanelWidth * 0.5f);
-        drawSingularButton(drawContext, "^", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY - 14, size, 14, groupScrollHandler.isOffsetWithinBounds(-10));
-        drawSingularButton(drawContext, "v", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY + panelHeight - 2, size, 14, groupScrollHandler.isOffsetWithinBounds(10));
-
-//        drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14);
-        //      drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true);
-
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
         RenderSystem.disableBlend();
         RenderSystem.disableDepthTest();
 
+        int size = (int) (groupPanelWidth * 0.5f);
+        drawSingularButton(drawContext, "^", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY - 14, size, 14, groupScrollHandler.isOffsetWithinBounds(-10));
+        drawSingularButton(drawContext, "v", mouseX, mouseY, groupPanelX.getAsInt() + groupPanelWidth / 2 - size / 2, imageY + panelHeight - 2, size, 14, groupScrollHandler.isOffsetWithinBounds(10));
+        drawContext.draw();
+        // drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(true, isMouseOver(mouseX, mouseY, imageX + 3, imageY + 3, 14, 14)), imageX + 3, imageY + 3, 14, 14);
+        // drawContext.drawText(mc.textRenderer, "X", imageX + 10 - mc.textRenderer.getWidth("X") / 2, imageY + 6, -1, true);
+
         this.enableContextMenuScissor();
 
         contextMenu.setWidth(panelWidth - 4);
@@ -164,7 +165,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
     public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height, boolean enabled) {
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
         drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(enabled, isMouseOver(mouseX, mouseY, x, y, width, height)), x, y, width, height);
-        drawContext.drawText(mc.textRenderer, text, x + width / 2 - mc.textRenderer.getWidth(text) / 2, y + mc.textRenderer.fontHeight / 2 - 1, -1, true);
+        drawContext.drawText(mc.textRenderer, text, x + width / 2 - mc.textRenderer.getWidth(text) / 2, y + mc.textRenderer.fontHeight / 2 - 1, Color.WHITE.getRGB(), true);
     }
 
     public void drawSingularButton(DrawContext drawContext, String text, int mouseX, int mouseY, int x, int y, int width, int height) {
@@ -178,7 +179,7 @@ private void renderOptionGroups(DrawContext drawContext, int mouseX, int mouseY)
         RenderSystem.enableBlend();
         RenderSystem.enableDepthTest();
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
-        drawContext.drawTexture(RenderLayer::getGuiTextured, GROUP_BACKGROUND, groupX - 10, groupY + 2, groupPanelWidth + 20, panelHeight, 0, 0, 147, 165, 147, 165);
+        drawContext.drawTexture(RenderLayer::getGuiTextured, GROUP_BACKGROUND, groupX - 10, groupY + 2, 0,0,groupPanelWidth + 20, panelHeight,  80, 158);
         RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
 
         int yOffset = groupY + 12 - groupScrollHandler.getScrollOffset();
@@ -416,12 +417,12 @@ public void render(DrawContext drawContext, ColorOption option, int x, int y, in
             int width = 20;
             RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
             RenderSystem.enableBlend();
-            RenderSystem.enableDepthTest();
             drawContext.drawGuiTexture(RenderLayer::getGuiTextured, TEXTURES.get(!option.isVisible, option.isMouseOver(mouseX, mouseY)), option.getX(), y, width, 20);
             RenderSystem.disableBlend();
-            RenderSystem.disableDepthTest();
+            RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
 
             int shadowOpacity = Math.min(option.value.getAlpha(), 45);
+            drawContext.draw();
             DrawHelper.drawRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(),
                     option.getX() + 4,
                     y + 4,
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index 3888f6a..fae4d09 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -184,7 +184,8 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
 
         renderToolTipText(drawContext, mouseX, mouseY);
 
-        //Reset our scaling so minecraft runs normally
+        //Reset our scaling so minecraft runs normally\
+        drawContext.draw();
         DrawHelper.scaledProjection();
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
index 693cc30..f32809c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
@@ -141,7 +141,13 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti
         Set widgetSet = new HashSet<>();
         for (Widget widget : widgets) {
             NbtCompound widgetTag = new NbtCompound();
-            widget.writeToTag(widgetTag);
+            //I faced this exception once and had to spend 10 minutes trying to find it. P.S. It leaves 0 stacktrace message
+            try {
+                widget.writeToTag(widgetTag);
+            } catch (Throwable e){
+                DynamicHUD.logger.error("Widget [{}] occurred an exception while writing to NBT. This may be due to duplicate entries or invalid entry values", widget.toString());
+            }
+
             // Check for duplicates
             if (widgetSet.add(widgetTag.toString())) {
                 printInfo("Saving Widget: " + widget);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 64d47c7..78f8636 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -38,7 +38,7 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
     public static WidgetData DATA = new WidgetData<>("GraphWidget", "Show graph", GraphWidget::new);
 
     private ContextMenu menu;
-    private final float[] dataPoints;
+    private float[] dataPoints;
     private int head = 0;
     private int maxDataPoints;
     private float minValue, prevMinValue;
@@ -56,27 +56,33 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
 
     public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) {
         super(DATA, modId, anchor, registryID, registryKey);
-        Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2.");
-        this.dataPoints = new float[maxDataPoints];
         this.width = width;
         this.height = height;
         this.maxDataPoints = maxDataPoints;
-        this.setMinValue(minValue);
-        this.setMaxValue(maxValue);
         this.graphColor = graphColor;
         this.backgroundColor = backgroundColor;
         this.lineThickness = lineThickness;
         this.showGrid = showGrid;
         this.gridLines = gridLines;
-        this.label = label.trim();
-        this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
+        this.label = label;
+
+        internal_init();
+
         setTooltipText(Text.of("Graph displaying: " + label));
         createMenu();
         ContextMenuManager.getInstance().registerProvider(this);
     }
+    private void internal_init(){
+        Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2.");
+        this.dataPoints = new float[maxDataPoints];
+        this.setMinValue(minValue);
+        this.setMaxValue(maxValue);
+        this.label = label.trim();
+        this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
+    }
 
     public GraphWidget() {
-        this(DynamicValueRegistry.GLOBAL_ID, "unknown", "unknown", Anchor.CENTER, 0, 0, 10, 0, 10, Color.RED, Color.GREEN, 0, false, 0, "empty");
+        this(DynamicValueRegistry.GLOBAL_ID, "unknown", "unknown", Anchor.CENTER, 0, 0, 5, 0, 10, Color.RED, Color.GREEN, 0, false, 0, "empty");
     }
 
     @Override
@@ -352,8 +358,8 @@ public void readFromTag(NbtCompound tag) {
         this.showGrid = tag.getBoolean("showGrid");
         this.gridLines = tag.getInt("gridLines");
         this.label = tag.getString("label");
-        this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
 
+        internal_init();
         createMenu();
     }
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 6a052a7..4b315cc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -52,7 +52,7 @@ public TextWidget(String registryID, String registryKey, boolean shadow, boolean
 
     public void createMenu() {
         boolean dark_mode = false;
-        ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(dark_mode ? MinecraftSkin.PanelColor.DARK_PANEL : MinecraftSkin.PanelColor.CREAMY)).build();
+        ContextMenuProperties properties = ContextMenuProperties.builder().build();
         menu = new ContextMenu<>(getX(), getY(), properties);
 
         menu.addOption(new BooleanOption(Text.of("Shadow"),
@@ -153,8 +153,6 @@ public void onClose() {
     @Override
     public void writeToTag(NbtCompound tag) {
         super.writeToTag(tag);
-        tag.putString("RegistryID", registryID);
-        tag.putString("RegistryKey", registryKey);
         tag.putBoolean("Shadow", shadow);
         tag.putBoolean("Rainbow", rainbow);
         tag.putInt("TextColor", textColor.getRGB());
@@ -177,7 +175,7 @@ public void readFromTag(NbtCompound tag) {
         registryKey = tag.getString("RegistryKey");
         registryID = tag.getString("RegistryID");
 
-        createMenu();
+        //createMenu();
     }
 
     @Override

From 5c101818131ed608ad32073dac25bb97d590d626 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Fri, 30 May 2025 00:44:44 +0530
Subject: [PATCH 36/40] Changed to docs

---
 .../animations/MathAnimations.java            | 29 ++++++++++---------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
index e34f137..6850fff 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
@@ -6,14 +6,14 @@
 import net.minecraft.util.math.random.Random;
 
 public class MathAnimations {
-    // SHAKE: Random offset animation with smooth decay
+    /// SHAKE: Random offset animation with smooth decay
     public static float shake(float intensity, float frequency, float decay) {
         long time = System.currentTimeMillis();
         return (float) (Math.sin(time * frequency) *
                 Math.exp(-decay * time) * intensity);
     }
 
-    // 2D Shake with different X/Y frequencies
+    /// 2D Shake with different X/Y frequencies
     public static Vec2f shake2D(float intensity, float freqX, float freqY) {
         return new Vec2f(
                 (float) Math.sin(System.currentTimeMillis() * freqX) * intensity,
@@ -21,7 +21,7 @@ public static Vec2f shake2D(float intensity, float freqX, float freqY) {
         );
     }
 
-    // FLICKER: Random flashing effect
+    /// FLICKER: Random flashing effect
     public static float flicker(float min, float max, float chance) {
         Random rand = Random.create();
         return rand.nextFloat() < chance ?
@@ -29,7 +29,7 @@ public static float flicker(float min, float max, float chance) {
                 max;
     }
 
-    // CIRCULAR MOTION: Perfect for rotation/orbital animations
+    /// CIRCULAR MOTION: Perfect for rotation/orbital animations
     public static Vec2f circularMotion(float radius, float speed, float phase) {
         double angle = Math.toRadians((System.currentTimeMillis() * speed) % 360 + phase);
         return new Vec2f(
@@ -38,13 +38,13 @@ public static Vec2f circularMotion(float radius, float speed, float phase) {
         );
     }
 
-    // SAWTOOTH WAVE: Linear rise with sudden drop
+    /// SAWTOOTH WAVE: Linear rise with sudden drop
     public static float sawtooth(float period, float min, float max) {
         float phase = (System.currentTimeMillis() % period) / period;
         return min + (max - min) * phase;
     }
 
-    // TRIANGULAR WAVE: Linear rise and fall
+    /// TRIANGULAR WAVE: Linear rise and fall
     public static float triangleWave(float period, float min, float max) {
         float halfPeriod = period / 2;
         float phase = (System.currentTimeMillis() % period);
@@ -54,20 +54,20 @@ public static float triangleWave(float period, float min, float max) {
         return min + (max - min) * value;
     }
 
-    // BOUNCE: Simulates physical bouncing
+    /// BOUNCE: Simulates physical bouncing
     public static float bounce(float dropHeight, float gravity, float dampening) {
         float t = System.currentTimeMillis() / 1000f;
         return (float) (dropHeight * Math.abs(Math.sin(t * Math.sqrt(gravity))) *
                 Math.exp(-dampening * t));
     }
 
-    // PULSE: Smooth heartbeat-like effect
+    /// PULSE: Smooth heartbeat-like effect
     public static float pulse1(float base, float amplitude, float frequency) {
         return (float) (base + amplitude *
                 (0.5 + 0.5 * Math.sin(System.currentTimeMillis() * frequency)));
     }
 
-    // SPIRAL: Circular motion with expanding radius
+    /// SPIRAL: Circular motion with expanding radius
     public static Vec2f spiral(float baseRadius, float expansionRate, float speed) {
         float t = System.currentTimeMillis() / 1000f;
         return new Vec2f(
@@ -76,35 +76,36 @@ public static Vec2f spiral(float baseRadius, float expansionRate, float speed) {
         );
     }
 
-    // Continuous pulsating effect using sine wave
+    /// Continuous pulsating effect using sine wave
     public static float pulse2(float speed, float min, float max) {
         return (float) ((Math.sin(System.currentTimeMillis() * speed) + 1) / 2 * (max - min) + min);
     }
 
-    // Linear interpolation between values over time
+    /// Linear interpolation between values over time
     public static float lerp(float start, float end, long startTime, float duration) {
         return lerp(start, end, startTime, duration, EasingType.LINEAR);
     }
 
+    /// Linear interpolation between values over time with easing
     public static float lerp(float start, float end, long startTime, float duration, EasingType easing) {
         float progress = (System.currentTimeMillis() - startTime) / duration;
         progress = Math.min(1, Math.max(0, progress)); // Clamp 0-1
         return start + (end - start) * Easing.apply(easing, progress);
     }
 
-    // Bouncing animation using quadratic ease-out
+    /// Bouncing animation using quadratic ease-out
     public static float bounce(float start, float end, long startTime, float duration) {
         float time = System.currentTimeMillis() - startTime;
         time /= duration;
         return end * (1 - (time - 1) * (time - 1)) + start;
     }
 
-    // Continuous rotation using modulo
+    /// Continuous rotation using modulo
     public static float continuousRotation(float speed) {
         return (System.currentTimeMillis() % (360_000 / speed)) * (speed / 1000);
     }
 
-    // Elastic wobble effect
+    /// Elastic wobble effect
     public static float elasticWobble(float speed, float magnitude) {
         return (float) (Math.sin(System.currentTimeMillis() * speed) *
                 Math.exp(-0.001 * System.currentTimeMillis()) * magnitude);

From c12ce524f239cfdab0ee0953380958f7d8647197 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Fri, 30 May 2025 00:59:29 +0530
Subject: [PATCH 37/40] Remove YACLScreen

---
 .../com/tanishisherewith/dynamichud/widget/WidgetRenderer.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
index 223797b..167d8d9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
@@ -33,7 +33,7 @@ public class WidgetRenderer implements Input {
     public WidgetRenderer(List widgets) {
         this.widgets = widgets;
         // Render in GameMenuScreen
-        this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class || screen instanceof YACLScreen ||
+        this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class ||
                 System.getInstances(ContextMenuScreenRegistry.class, DynamicHUD.MOD_ID).stream().anyMatch(registry -> registry.screenKlass == screen.getClass());
     }
 

From 1dbee6d7d2082d370a51e3fc27656aef6450cbff Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Fri, 30 May 2025 01:06:48 +0530
Subject: [PATCH 38/40] GraphWidget tooltip fix

---
 .../com/tanishisherewith/dynamichud/widgets/GraphWidget.java   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 78f8636..f98b5c5 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -68,7 +68,6 @@ public GraphWidget(String registryID, String registryKey, String modId, Anchor a
 
         internal_init();
 
-        setTooltipText(Text.of("Graph displaying: " + label));
         createMenu();
         ContextMenuManager.getInstance().registerProvider(this);
     }
@@ -79,6 +78,8 @@ private void internal_init(){
         this.setMaxValue(maxValue);
         this.label = label.trim();
         this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
+
+        setTooltipText(Text.of("Graph displaying: " + label));
     }
 
     public GraphWidget() {

From 3c431b7511080bdd48a444e52ef89b488c9e162b Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sat, 31 May 2025 23:39:49 +0530
Subject: [PATCH 39/40] Fixing what I broke

---
 .../dynamichud/widgets/GraphWidget.java       | 50 +++++++++++--------
 .../dynamichud/widgets/TextWidget.java        |  1 -
 2 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index f98b5c5..83c4ce7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -65,6 +65,8 @@ public GraphWidget(String registryID, String registryKey, String modId, Anchor a
         this.showGrid = showGrid;
         this.gridLines = gridLines;
         this.label = label;
+        this.setMinValue(minValue);
+        this.setMaxValue(maxValue);
 
         internal_init();
 
@@ -74,8 +76,6 @@ public GraphWidget(String registryID, String registryKey, String modId, Anchor a
     private void internal_init(){
         Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2.");
         this.dataPoints = new float[maxDataPoints];
-        this.setMinValue(minValue);
-        this.setMaxValue(maxValue);
         this.label = label.trim();
         this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
 
@@ -259,6 +259,7 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
                 DrawHelper.drawVerticalLine(matrix, xPos, y, height, 0.5f, 0x4DFFFFFF);
             }
         }
+
         // Draw interpolated graph curve
         List points = getInterpolatedPoints();
         drawInterpolatedCurve(matrix, points, graphColor.getRGB(), lineThickness);
@@ -276,8 +277,9 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
                 1.0f, 0.8f, 1.0f, 0.05f, true
         );
 
+
         // Draw axes
-        DrawHelper.drawHorizontalLine(matrix, x, width, y + height, 1.0f, 0xFFFFFFFF); // X-axis
+        DrawHelper.drawHorizontalLine(matrix, x, width, y + height - 1, 1.0f, 0xFFFFFFFF); // X-axis
         DrawHelper.drawVerticalLine(matrix, x, y, height, 1.0f, 0xFFFFFFFF); // Y-axis
 
         // Draw min and max value labels with formatted values
@@ -345,25 +347,6 @@ public void createMenu() {
         );
     }
 
-    @Override
-    public void readFromTag(NbtCompound tag) {
-        super.readFromTag(tag);
-        this.width = tag.getFloat("width");
-        this.height = tag.getFloat("height");
-        this.maxDataPoints = tag.getInt("maxDataPoints");
-        this.minValue = tag.getFloat("minValue");
-        this.maxValue = tag.getFloat("maxValue");
-        this.graphColor = new Color(tag.getInt("graphColor"));
-        this.backgroundColor = new Color(tag.getInt("backgroundColor"));
-        this.lineThickness = tag.getFloat("lineThickness");
-        this.showGrid = tag.getBoolean("showGrid");
-        this.gridLines = tag.getInt("gridLines");
-        this.label = tag.getString("label");
-
-        internal_init();
-        createMenu();
-    }
-
     public float getMinValue() {
         return minValue;
     }
@@ -484,6 +467,29 @@ public void writeToTag(NbtCompound tag) {
         tag.putBoolean("showGrid", showGrid);
         tag.putInt("gridLines", gridLines);
         tag.putString("label", label);
+        tag.putBoolean("autoUpdateRange", autoUpdateRange);
+    }
+
+    @Override
+    public void readFromTag(NbtCompound tag) {
+        super.readFromTag(tag);
+        this.width = tag.getFloat("width");
+        this.height = tag.getFloat("height");
+        this.maxDataPoints = tag.getInt("maxDataPoints");
+        this.minValue = tag.getFloat("minValue");
+        this.maxValue = tag.getFloat("maxValue");
+        this.graphColor = new Color(tag.getInt("graphColor"));
+        this.backgroundColor = new Color(tag.getInt("backgroundColor"));
+        this.lineThickness = tag.getFloat("lineThickness");
+        this.showGrid = tag.getBoolean("showGrid");
+        this.gridLines = tag.getInt("gridLines");
+        this.label = tag.getString("label");
+        this.autoUpdateRange = tag.getBoolean("autoUpdateRange");
+        this.setMinValue(minValue);
+        this.setMaxValue(maxValue);
+
+        internal_init();
+        createMenu();
     }
 
     @Override
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 4b315cc..3a5ef2e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -51,7 +51,6 @@ public TextWidget(String registryID, String registryKey, boolean shadow, boolean
     }
 
     public void createMenu() {
-        boolean dark_mode = false;
         ContextMenuProperties properties = ContextMenuProperties.builder().build();
         menu = new ContextMenu<>(getX(), getY(), properties);
 

From 9fb56fb79fd017e1793fc64497249baffc6384c9 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Mon, 2 Jun 2025 00:33:03 +0530
Subject: [PATCH 40/40] Fix: SubMenuOption sharing same skin as ParentMenu
 leading to many problems. Final patches to all skins, widgets saving...

---
 .../integration/IntegrationManager.java       |   2 +-
 .../contextmenu/ContextMenuProperties.java    |  15 +++
 .../utils/contextmenu/options/Option.java     |   9 ++
 .../contextmenu/options/OptionGroup.java      |  10 +-
 .../contextmenu/options/SubMenuOption.java    |   2 +-
 .../options/coloroption/HueSlider.java        |   1 +
 .../contextmenu/skinsystem/ClassicSkin.java   |  13 +-
 .../contextmenu/skinsystem/MinecraftSkin.java |  93 ++++++++-----
 .../contextmenu/skinsystem/ModernSkin.java    |  24 ++--
 .../utils/contextmenu/skinsystem/Skin.java    |   9 ++
 .../dynamichud/widgets/TextWidget.java        | 125 +++++++++---------
 11 files changed, 186 insertions(+), 117 deletions(-)

diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
index a98d0fb..485a616 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
@@ -148,7 +148,7 @@ public static void integrate() {
                 } else {
                     DynamicHUD.logger.error("Mod {} has improper implementation of DynamicHUD", modId, e);
                 }
-                bad_implementations.add(new ModError(modId, e.getLocalizedMessage().trim()));
+                bad_implementations.add(new ModError(modId, e.getMessage().trim()));
             }
         }
         printInfo("(DynamicHUD) Integration of supported mods was successful");
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
index 6cb0ead..1b75f56 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
@@ -91,6 +91,9 @@ public Skin getSkin() {
         return skin;
     }
 
+    /**
+     * @return Cloned object of every property except skin
+     */
     public ContextMenuProperties clone() {
         return cloneToBuilder().build();
     }
@@ -111,12 +114,24 @@ public Builder cloneToBuilder() {
                 .enableAnimations(enableAnimations);
     }
 
+    /**
+     * @return Cloned object with same skin as the current ContextMenuProperties
+     */
     public ContextMenuProperties cloneWithSkin() {
         return this.cloneToBuilder()
                 .skin(skin)
                 .build();
     }
 
+    /**
+     * @return Cloned object with a clone of the skin as the current ContextMenuProperties
+     */
+    public ContextMenuProperties cloneSkin() {
+        return this.cloneToBuilder()
+                .skin(skin.clone())
+                .build();
+    }
+
     public static class Builder {
         protected final T properties;
 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
index af9be9b..be4bf94 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
@@ -185,6 +185,15 @@ public Text getDescription() {
         return description;
     }
 
+    @Override
+    public String toString() {
+        return this.getClass().getName() + "{" +
+                ", name=" + name +
+                ", x=" + x +
+                ", y=" + y +
+                '}';
+    }
+
     /**
      * How complex do you think this option is for a daily normal user.
      * For example, some options may be advanced and not needed for casual players but are helpful in customisation
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
index 8a33767..99097fd 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
@@ -29,8 +29,7 @@ public List> getGroupOptions() {
 
     @Override
     public void updateProperties(ContextMenuProperties properties) {
-        this.renderer = new OptionGroupRenderer(); // Set renderer as OptionGroupRenderer
-
+        super.updateProperties(properties);
         if (groupOptions == null) return;
 
         for (Option option : groupOptions) {
@@ -40,6 +39,7 @@ public void updateProperties(ContextMenuProperties properties) {
 
     @Override
     public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) {
+        super.render(drawContext,x,y,mouseX,mouseY);
     }
 
     public boolean isExpanded() {
@@ -63,11 +63,9 @@ public int getHeight() {
         return super.getHeight();
     }
 
-    public class OptionGroupRenderer implements SkinRenderer> {
-
+    public static class OptionGroupRenderer implements SkinRenderer> {
         @Override
-        public void render(DrawContext drawContext, Option option, int x, int y, int mouseX, int mouseY) {
-        }
+        public void render(DrawContext drawContext, Option option, int x, int y, int mouseX, int mouseY) {}
 
         @Override
         public boolean mouseClicked(Option option2, double mouseX, double mouseY, int button) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
index 25420dc..36f7f9b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java
@@ -22,7 +22,7 @@ public class SubMenuOption extends Option {
     public  SubMenuOption(Text name, ContextMenu parentMenu, Supplier getter, Consumer setter, T properties) {
         super(name, getter, setter);
         Objects.requireNonNull(parentMenu, "Parent Context Menu cannot be null in [" + name + "] SubMenu option");
-        this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties);
+        this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties.cloneSkin());
         this.subMenu.getProperties().setHeightOffset(0);
         this.subMenu.setVisible(get());
         this.renderer.init(this);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java
index ef05b2d..7f8298c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/HueSlider.java
@@ -44,6 +44,7 @@ public void render(DrawContext drawContext, int x, int y) {
             color = (color & 0x00FFFFFF) | (255 << 24);
             drawContext.fill(x + i, y, x + i + 1, y + height, color);
         }
+        drawContext.draw();
 
 
         // Draw the handle
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
index 93dc0e7..fec9a29 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
@@ -141,6 +141,11 @@ private void drawBorder(MatrixStack matrices, ContextMenu contextMenu, Contex
         }
     }
 
+    @Override
+    public Skin clone() {
+        return new ClassicSkin();
+    }
+
     public static class ClassicBooleanRenderer implements SkinRenderer {
         @Override
         public void render(DrawContext drawContext, BooleanOption option, int x, int y, int mouseX, int mouseY) {
@@ -191,10 +196,12 @@ public static class ClassicSubMenuRenderer implements SkinRenderer contextMen
 
         RenderSystem.enableBlend();
         RenderSystem.enableDepthTest();
-        panelColor.applyColor();
 
-        drawContext.drawTexture(RenderLayer::getGuiTextured, BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight, 256, 254);
-
-        RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
+        drawContext.drawTexture(RenderLayer::getGuiTextured, BACKGROUND_PANEL, imageX, imageY, 0, 0, panelWidth, panelHeight, 256, 254,panelColor.getColor());
 
         drawSingularButton(drawContext, "X", mouseX, mouseY, imageX + 3, imageY + 3, 14, 14);
 
         //Up and down arrows near the group panel
-        RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
         RenderSystem.disableBlend();
         RenderSystem.disableDepthTest();
 
@@ -324,6 +321,30 @@ public LayoutContext.Offset getGroupIndent() {
         return LayoutContext.Offset.zero();
     }
 
+    public void setPanelColor(PanelColor panelColor) {
+        this.panelColor = panelColor;
+    }
+
+    public PanelColor getPanelColor() {
+        return panelColor;
+    }
+
+    public int getPanelHeight() {
+        return panelHeight;
+    }
+
+    public int getPanelWidth() {
+        return panelWidth;
+    }
+
+    public int getImageX() {
+        return imageX;
+    }
+
+    public int getImageY() {
+        return imageY;
+    }
+
     /**
      * Group rendering handled already
      */
@@ -332,22 +353,22 @@ public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX,
     }
 
     public enum PanelColor {
-        COFFEE_BROWN(0.6f, 0.3f, 0.1f, 0.9f),
-        CREAMY(1.0f, 0.9f, 0.8f, 0.9f),
-        DARK_PANEL(0.2f, 0.2f, 0.2f, 0.9f),
-        FOREST_GREEN(0.0f, 0.6f, 0.2f, 0.9f),
-        GOLDEN_YELLOW(1.0f, 0.8f, 0.0f, 0.9f),
-        LAVENDER(0.8f, 0.6f, 1.0f, 0.9f),
-        LIGHT_BLUE(0.6f, 0.8f, 1.0f, 0.9f),
-        LIME_GREEN(0.7f, 1.0f, 0.3f, 0.9f),
-        MIDNIGHT_PURPLE(0.3f, 0.0f, 0.5f, 0.9f),
-        OCEAN_BLUE(0.0f, 0.5f, 1.0f, 0.9f),
-        ROSE_PINK(1.0f, 0.4f, 0.6f, 0.9f),
-        SKY_BLUE(0.5f, 0.8f, 1.0f, 0.9f),
-        SOFT_GREEN(0.6f, 1.0f, 0.6f, 0.9f),
-        SUNSET_ORANGE(1.0f, 0.5f, 0.0f, 0.9f),
-        WARM_YELLOW(1.0f, 1.0f, 0.6f, 0.9f),
-        CUSTOM(0.0f, 0.0f, 0.0f, 0.0f); // PlaceHolder for custom colors
+        COFFEE_BROWN(0.6f, 0.3f, 0.1f, 1.0f),
+        CREAMY(1.0f, 0.9f, 0.8f, 1.0f),
+        DARK_PANEL(0.2f, 0.2f, 0.2f, 1.0f),
+        FOREST_GREEN(0.0f, 0.6f, 0.2f, 1.0f),
+        GOLDEN_YELLOW(1.0f, 0.8f, 0.0f, 1.0f),
+        LAVENDER(0.8f, 0.6f, 1.0f, 1.0f),
+        LIGHT_BLUE(0.6f, 0.8f, 1.0f, 1.0f),
+        LIME_GREEN(0.7f, 1.0f, 0.3f, 1.0f),
+        MIDNIGHT_PURPLE(0.3f, 0.0f, 0.5f, 1.0f),
+        OCEAN_BLUE(0.0f, 0.5f, 1.0f, 1.0f),
+        ROSE_PINK(1.0f, 0.4f, 0.6f, 1.0f),
+        SKY_BLUE(0.5f, 0.8f, 1.0f, 1.0f),
+        SOFT_GREEN(0.6f, 1.0f, 0.6f, 1.0f),
+        SUNSET_ORANGE(1.0f, 0.5f, 0.0f, 1.0f),
+        WARM_YELLOW(1.0f, 1.0f, 0.6f, 1.0f),
+        CUSTOM(0.0f, 0.0f, 0.0f, 0.0f); /// PlaceHolder for custom colors
 
         private float red;
         private float green;
@@ -373,6 +394,9 @@ public static PanelColor custom(float red, float green, float blue, float alpha)
         public void applyColor() {
             RenderSystem.setShaderColor(red, green, blue, alpha);
         }
+        public int getColor() {
+            return new Color(red,green,blue,alpha).getRGB();
+        }
     }
 
     public class MinecraftBooleanRenderer implements SkinRenderer {
@@ -520,7 +544,7 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y,
             option.setHeight(25);
             option.setWidth(maxWidth);
 
-            drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25 / 2 - 5, -1, true);
+            drawContext.drawText(mc.textRenderer, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
 
             option.setPosition(x + panelWidth - maxWidth - 25, y);
 
@@ -554,7 +578,7 @@ public void render(DrawContext drawContext, ListOption option, int x, int y,
             option.setHeight(25);
             option.setWidth(maxWidth);
 
-            drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25 / 2 - 5, -1, true);
+            drawContext.drawText(mc.textRenderer, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
 
             option.setPosition(x + panelWidth - maxWidth - 25, y);
 
@@ -601,7 +625,7 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y,
             option.setHeight(25);
             option.setWidth(26);
 
-            drawContext.drawText(mc.textRenderer, option.name + ": ", x + 15, y + 25 / 2 - 5, -1, true);
+            drawContext.drawText(mc.textRenderer, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
 
             option.setPosition(x + panelWidth - 51, y);
 
@@ -615,4 +639,9 @@ public void render(DrawContext drawContext, RunnableOption option, int x, int y,
             RenderSystem.disableDepthTest();
         }
     }
+
+    @Override
+    public Skin clone() {
+        return new MinecraftSkin(panelColor);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index fae4d09..df1203e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -25,15 +25,15 @@
 import java.util.Arrays;
 import java.util.List;
 
-//TODO: Complete this
 public class ModernSkin extends Skin implements GroupableSkin {
+    static Color DARK_GRAY = new Color(20, 20, 20, 229);
+    static Color DARKER_GRAY = new Color(10, 10, 10, 243);
+    static Color DARKER_GRAY_2 = new Color(12, 12, 12, 246);
+
     private final Color themeColor;
     private final float radius;
     private final Text defaultToolTipHeader;
     private final Text defaultToolTipText;
-    Color DARK_GRAY = new Color(20, 20, 20, 229);
-    Color DARKER_GRAY_2 = new Color(12, 12, 12, 246);
-    Color DARKER_GRAY = new Color(10, 10, 10, 243);
     private int contextMenuX = 0, contextMenuY = 0;
     private int width = 0, height = 0;
     private float scaledWidth = 0, scaledHeight = 0;
@@ -95,7 +95,7 @@ public void renderGroup(DrawContext drawContext, OptionGroup group, int groupX,
                     groupX + 1, groupY + 14, width - groupX - 8 + contextMenuX, group.getHeight() - 16, radius, DARKER_GRAY_2.getRGB());
         }
 
-        String groupText = group.name + " " + (group.isExpanded() ? "-" : "+");
+        Text groupText = group.name.copy().append(" " + (group.isExpanded() ? "-" : "+"));
 
         DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(),
                 groupX + 1, groupY + 1, true, true, !group.isExpanded(), !group.isExpanded(), mc.textRenderer.getWidth(groupText) + 6, 16, radius, DARKER_GRAY_2.getRGB());
@@ -173,6 +173,7 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
 
             yOffset += option.getHeight() + 1;
         }
+        drawContext.draw();
         RenderSystem.disableScissor();
 
         contextMenu.setWidth(width);
@@ -185,7 +186,6 @@ public void renderContextMenu(DrawContext drawContext, ContextMenu contextMen
         renderToolTipText(drawContext, mouseX, mouseY);
 
         //Reset our scaling so minecraft runs normally\
-        drawContext.draw();
         DrawHelper.scaledProjection();
     }
 
@@ -209,6 +209,7 @@ public void drawBackButton(DrawContext drawContext, int mouseX, int mouseY) {
                 contextMenuX + 2, contextMenuY + 2, textWidth + 8, 14, radius, color, 125, 2, 2);
 
         drawContext.drawText(mc.textRenderer, backText, contextMenuX + 6, contextMenuY + 5, -1, true);
+        drawContext.draw();
     }
 
     public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) {
@@ -275,6 +276,7 @@ public void renderToolTipText(DrawContext drawContext, int mouseX, int mouseY) {
             textY += mc.textRenderer.fontHeight;
         }
 
+        drawContext.draw();
         DrawHelper.stopScaling(drawContext.getMatrices());
 
         setTooltipText(defaultToolTipHeader, defaultToolTipText);
@@ -646,7 +648,7 @@ public void render(DrawContext drawContext, EnumOption option, int x, int y,
             option.setHeight(mc.textRenderer.fontHeight + 2);
 
             // Draw main option name and selected option
-            String mainLabel = option.name + ": ";
+            Text mainLabel = option.name.copy().append(": ");
             String selectedOption = option.get().toString();
             drawContext.drawText(mc.textRenderer, mainLabel, x + 4, y + 2, -1, false);
             Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
@@ -745,7 +747,7 @@ public void render(DrawContext drawContext, ListOption option, int x, int y,
             option.setHeight(mc.textRenderer.fontHeight + 2);
 
             // Draw main option name and selected option
-            String mainLabel = option.name + ": ";
+            Text mainLabel = option.name.copy().append(": ");
             String selectedOption = option.get().toString();
             drawContext.drawText(mc.textRenderer, mainLabel, x + 4, y + 2, -1, false);
             Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.textRenderer.getWidth(mainLabel), y, mc.textRenderer.getWidth(selectedOption) + 5, mc.textRenderer.fontHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
@@ -804,7 +806,7 @@ public boolean mouseClicked(ListOption option, double mouseX, double mouseY,
 
             int x = option.getX();
             int y = option.getY();
-            String mainLabel = option.name + ": ";
+            Text mainLabel = option.name.copy().append(": ");
             String selectedOption = option.get().toString();
 
             // Calculate positions
@@ -949,4 +951,8 @@ public boolean mouseClicked(RunnableOption option, double mouseX, double mouseY,
             return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
         }
     }
+    @Override
+    public Skin clone() {
+        return new ModernSkin(themeColor,radius,defaultToolTipHeader,defaultToolTipText);
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
index 852366c..5c8e86b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
@@ -21,10 +21,12 @@ public abstract class Skin {
     private boolean createNewScreen;
 
     public Skin(ContextMenu menu) {
+        this();
         this.contextMenu = menu;
     }
 
     public Skin() {
+        addRenderer(OptionGroup.class, OptionGroup.OptionGroupRenderer::new);
     }
 
     public > void addRenderer(Class optionClass, Supplier> renderer) {
@@ -114,4 +116,11 @@ public void setCreateNewScreen(boolean createNewScreen) {
     protected boolean isMouseOver(double mouseX, double mouseY, double x, double y, double width, double height) {
         return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
     }
+
+    /**
+     * Create a new Skin object with the same parameters as this current screen. This is must for SubMenu options.
+     * If an object of same skin type is not returned then SubMenu options will not share the same skin with parent menu.
+     * @return new instance of this skin that need to be cloned to sub-menu option.
+     */
+    public abstract Skin clone();
 }
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 3a5ef2e..afab10a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -7,18 +7,22 @@
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager;
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
 import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider;
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.BooleanOption;
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption;
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption;
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
+import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ClassicSkin;
 import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ModernSkin;
 import com.tanishisherewith.dynamichud.widget.DynamicValueWidget;
 import com.tanishisherewith.dynamichud.widget.WidgetData;
 import net.minecraft.client.gui.DrawContext;
 import net.minecraft.nbt.NbtCompound;
 import net.minecraft.text.Text;
 
-import java.awt.*;
+import javax.swing.*;
+import java.awt.Color;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 public class TextWidget extends DynamicValueWidget implements ContextMenuProvider {
     public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new);
@@ -51,73 +55,63 @@ public TextWidget(String registryID, String registryKey, boolean shadow, boolean
     }
 
     public void createMenu() {
-        ContextMenuProperties properties = ContextMenuProperties.builder().build();
+        ContextMenuProperties properties = ContextMenuProperties.builder().skin(new ModernSkin(Color.YELLOW)).build();
         menu = new ContextMenu<>(getX(), getY(), properties);
 
-        menu.addOption(new BooleanOption(Text.of("Shadow"),
+        // Boolean Option
+        menu.addOption(new BooleanOption(Text.of("Toggle Shadow"),
                 () -> this.shadow, value -> this.shadow = value,
                 BooleanOption.BooleanType.ON_OFF)
-                .description(Text.of("Adds shadow to your text"))
-        );
-        menu.addOption(new BooleanOption(Text.of("Rainbow"),
-                () -> this.rainbow, value -> this.rainbow = value,
-                BooleanOption.BooleanType.ON_OFF)
-                .description(Text.of("Adds rainbow effect to your text"))
-        );
+                .description(Text.of("Enable or disable text shadow")));
+
+        // Color Option
         menu.addOption(new ColorOption(Text.of("Text Color"),
                 () -> this.textColor, value -> this.textColor = value, menu)
-                .description(Text.of("Specify the color you want to add to your text"))
-                .renderWhen(() -> !this.rainbow)
-        );
-        menu.addOption(new DoubleOption(Text.of("Rainbow Speed"),
-                1, 5.0f, 1,
-                () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu)
-                .renderWhen(() -> this.rainbow)
-        );
-        menu.addOption(new DoubleOption(Text.of("Rainbow Spread"),
-                0.001f, 0.15f, 0.001f,
-                () -> (double) this.rainbowSpread, value -> this.rainbowSpread = value.floatValue(), menu)
-                .renderWhen(() -> this.rainbow)
-                .withComplexity(Option.Complexity.Enhanced)
-        );
-        menu.addOption(new DoubleOption(Text.of("Rainbow Saturation"),
-                0, 1.0f, 0.1f,
-                () -> (double) this.rainbowSaturation, value -> this.rainbowSaturation = value.floatValue(), menu)
-                .renderWhen(() -> this.rainbow)
-                .withComplexity(Option.Complexity.Pro)
-        );
-        menu.addOption(new DoubleOption(Text.of("Rainbow Brightness"),
-                0, 1.0f, 0.01f,
-                () -> (double) this.rainbowBrightness, value -> this.rainbowBrightness = value.floatValue(), menu)
-                .renderWhen(() -> this.rainbow)
-                .withComplexity(Option.Complexity.Pro)
-        );
-
-        /*
-        OptionGroup group = new OptionGroup("Color");
-        group.addOption(new ColorOption(Text.of("TextColor"), menu,
-                () -> this.textColor, value -> this.textColor = value)
-                .description(Text.of("Specify the color you want to add to your text"))
-        );
-        group.addOption(new DoubleOption(
-                Text.of("RainbowSpeed"),
-                1, 5.0f, 1,
-                () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu)
-                .setShouldRender(() -> this.rainbow)
-        );
-        AtomicReference option = new AtomicReference<>("Enum1");
-        List options = Arrays.asList("List1", "LONGER LIST 2", "List3");
-        AtomicBoolean running = new AtomicBoolean(false);
-        AtomicBoolean subMenu = new AtomicBoolean(false);
-        menu.addOption(new ListOption<>(Text.of("List??? "), option::get, option::set, options));
-        menu.addOption(new RunnableOption(Text.of("Runnable Test"), running::get, running::set, () -> System.out.println("Runnable ran")));
-        SubMenuOption subMenuOption = new SubMenuOption(Text.of("SubMenu"), menu, subMenu::get, subMenu::set);
-        subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows2"), () -> this.shadow, value -> this.shadow = value));
-        subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows3"), () -> this.shadow, value -> this.shadow = value));
-        subMenuOption.getSubMenu().addOption(new BooleanOption(Text.of("Shadows4"), () -> this.shadow, value -> this.shadow = value));
-        menu.addOption(subMenuOption);
-         */
+                .description(Text.of("Change the text color")));
 
+        // Double Option
+        menu.addOption(new DoubleOption(Text.of("Opacity"),
+                0.0, 1.0, 0.1f,
+                () -> (double) this.rainbowBrightness, value -> this.rainbowBrightness = value.floatValue(), menu)
+                .description(Text.of("Adjust text opacity")));
+
+        // Runnable Option
+        AtomicBoolean ran = new AtomicBoolean(false);
+        menu.addOption(new RunnableOption(Text.of("Reset Position"),
+                ran::get, ran::set,
+                () -> this.setPosition(0, 0))
+                .description(Text.of("Reset widget to default position")));
+
+        // List Option
+        AtomicReference style = new AtomicReference<>("Style1");
+        List styles = Arrays.asList("Style1", "Style2", "Style3");
+        menu.addOption(new ListOption<>(Text.of("Text Style"),
+                style::get, style::set, styles)
+                .description(Text.of("Choose a text style")));
+
+        // Enum Option
+        menu.addOption(new EnumOption<>(Text.of("Alignment"),
+                () -> GroupLayout.Alignment.CENTER, value -> {}, GroupLayout.Alignment.values())
+                .description(Text.of("Set text alignment")));
+
+        // Option Group
+        OptionGroup group = new OptionGroup(Text.of("Display Options"));
+        group.addOption(new BooleanOption(Text.of("Bold Text"),
+                () -> false, value -> {}, BooleanOption.BooleanType.YES_NO)
+                .description(Text.of("Enable bold text")));
+        group.addOption(new DoubleOption(Text.of("Font Size"),
+                8.0, 24.0, 1.0f,
+                () -> 12.0, value -> {}, menu)
+                .description(Text.of("Adjust font size")));
+        menu.addOption(group);
+
+        // SubMenu Option
+        SubMenuOption subMenu = (SubMenuOption) new SubMenuOption(Text.of("Advanced Settings"), menu)
+                .description(Text.of("Open advanced settings"));
+        subMenu.getSubMenu().addOption(new BooleanOption(Text.of("Some Boolean"),
+                () -> false, value -> {}, BooleanOption.BooleanType.TRUE_FALSE)
+                .description(Text.of("True/False")));
+        menu.addOption(subMenu);
     }
 
     @Override
@@ -135,6 +129,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) {
             widgetBox.setDimensions(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
         }
         menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
+
     }
 
     @Override