From 9234b35eec82abe78aba344dd9544915007d80e8 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:25:45 +0530 Subject: [PATCH 01/33] Update README.md --- README.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 8108cd5..de919a7 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,15 @@ # DynamicHUD A library to create HUD elements and display them on the screen. **Fabric only**\ +### Version `1.3.0` -## Short introduction -Dynamic HUD is a library used to create and display "widgets" on the screen. - -Included widgets by the library are Armor Widget, Item Widget and Text Widget. - -The library also includes basic utility features like a menu, slider and a Color Picker. Overall, this mod contains all the features you will need for a Hud editor. - -## Note: This is a library meaning it does not do / display anything on its own, It is mainly to help other developers and ease of adding or displaying stuff on the screen +## This is a test branch for dynamichud 1.20.4. This branch will contain the majorly reworked version of dynamichud and all previous versions will be abandoned/not supported. +## The current version might be backported upto 1.16 fabric. +## Only fabric # Examples -- [_DynamicHUDtest.java_](src/main/java/com/tanishisherewith/dynamichud/DynamicHUDtest.java) # [Modrinth](https://modrinth.com/mod/dynamichud) -## A LIBRARY SIMILAR TO THIS WHICH SUPPORTS OLDER MINECRAFT VERSIONS: https://github.com/LaconicLizard/HudElements - # Demo: ### *May vary from version to version* ## New Version 1.2.0 From 8b8b7082c7947c4ef43f4516ed97dc64afdb697b Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:29:04 +0530 Subject: [PATCH 02/33] Update README.md --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index de919a7..cf61b52 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ # DynamicHUD -A library to create HUD elements and display them on the screen. **Fabric only**\ +A library to display stuff on the screen. **Fabric only** ### Version `1.3.0` -## This is a test branch for dynamichud 1.20.4. This branch will contain the majorly reworked version of dynamichud and all previous versions will be abandoned/not supported. -## The current version might be backported upto 1.16 fabric. -## Only fabric - -# Examples +# ⚠ IN PROGRESS ⚠ -# [Modrinth](https://modrinth.com/mod/dynamichud) +## This is a test branch for dynamichud 1.20.4. This branch will contain the majorly reworked version of dynamichud and all previous versions will be abandoned/not supported. +## The current version might be backported upto 1.16 fabric on demand. +## Only for fabric. +The reworked version could be found in the `newTrials` directory. # Demo: ### *May vary from version to version* -## New Version 1.2.0 +## Developed stage +> --- + +## Mid stage (1.2.0) https://github.com/V-Fast/DynamicHUD/assets/120117618/2abfcdf5-d786-4e58-acae-aefe51b77b4a -## Old Version +## Early stages https://github.com/V-Fast/DynamicHUD/assets/120117618/04de9319-69cd-4456-a555-c026c7e053a2 From c62cda62b5eee22c9b0b98d8a7b5ddb3ad69fde8 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 2 Apr 2024 23:30:49 +0530 Subject: [PATCH 03/33] Bug fixing (On trial) 2 --- build.gradle | 4 +- gradle.properties | 14 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../dynamichud/DynamicHUD.java | 22 +- .../dynamichud/DynamicHudIntegration.java | 48 ++++ .../dynamichud/helpers/DrawHelper.java | 22 ++ .../dynamichud/mixins/ScreenMixin.java | 22 ++ .../dynamichud/mixins/TitleScreenMixin.java | 104 -------- .../dynamichud/newTrial/DynamicHUD.java | 122 +++++++++ .../dynamichud/newTrial/DynamicHudTest.java | 60 +++++ .../newTrial/utils/DynamicValueRegistry.java | 32 +++ .../dynamichud/newTrial/utils/UID.java | 30 +++ .../dynamichud/newTrial/widget/Widget.java | 244 ++++++++++++++++++ .../newTrial/widget/WidgetData.java | 20 ++ .../newTrial/widget/WidgetManager.java | 149 +++++++++++ .../newTrial/widget/WidgetRenderer.java | 43 +++ .../newTrial/widgets/TextWidget.java | 129 +++++++++ .../dynamichud/util/DynamicUtil.java | 4 +- .../util/contextmenu/TextWidgetButtonExt.java | 4 - .../dynamichud/widget/WidgetBox.java | 12 + .../dynamichud/widget/WidgetManager.java | 8 +- src/main/resources/dynamichud.mixins.json | 2 +- src/main/resources/fabric.mod.json | 7 +- 23 files changed, 969 insertions(+), 135 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/TitleScreenMixin.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java diff --git a/build.gradle b/build.gradle index 8511df6..4f9c008 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.3-SNAPSHOT' id 'maven-publish' } @@ -28,7 +28,7 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modApi "com.terraformersmc:modmenu:7.1.0" + modApi "com.terraformersmc:modmenu:9.0.0" } processResources { diff --git a/gradle.properties b/gradle.properties index 3a255cd..27d3423 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,16 +1,16 @@ -# Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx3G +org.gradle.parallel=true # Fabric Properties - minecraft_version=1.20.1 - yarn_mappings=1.20.1+build.1 - loader_version=0.14.21 +# check these on https://fabricmc.net/develop + minecraft_version=1.20.4 + yarn_mappings=1.20.4+build.1 + loader_version=0.15.0 # Mod Properties - mod_version = 1.2.0 + mod_version = 1.3 maven_group = com.tanishisherewith archives_base_name = dynamichud # Dependencies - # check this on https://modmuss50.me/fabric.html - fabric_version=0.83.1+1.20.1 + fabric_version=0.91.1+1.20.4 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d..3499ded 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.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 6f43839..dd81dae 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -2,7 +2,9 @@ import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.interfaces.IWigdets; +import com.tanishisherewith.dynamichud.newTrial.utils.UID; import com.tanishisherewith.dynamichud.util.DynamicUtil; +import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -21,7 +23,9 @@ import java.io.File; -public class DynamicHUD implements ModInitializer { +public class DynamicHUD implements ClientModInitializer { + + public static MinecraftClient MC = MinecraftClient.getInstance(); private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); static AbstractMoveableScreen Screen; @@ -29,12 +33,12 @@ public class DynamicHUD implements ModInitializer { private static String TranslationKey = "DynamicHud Editor Screen"; private static InputUtil.Type inputType = InputUtil.Type.KEYSYM; private static int key = GLFW.GLFW_KEY_RIGHT_SHIFT; - public static final KeyBinding EditorScreenKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( - TranslationKey, - inputType, - key, - keybingCategory - )); + // public static final KeyBinding EditorScreenKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( +// TranslationKey, +// inputType, +// key, +// keybingCategory +// )); private static String filename = "widgets.nbt"; private static File fileDirectory = FabricLoader.getInstance().getConfigDir().toFile(); public static final File WIDGETS_FILE = new File(fileDirectory, filename); @@ -115,7 +119,7 @@ public static void printWarn(String msg) { } @Override - public void onInitialize() { + public void onInitializeClient() { dynamicutil = new DynamicUtil(mc); printInfo("DynamicHud Initialised"); @@ -138,7 +142,7 @@ public void onInitialize() { printInfo("Load file Directory: " + FileDirectory); } } - DynamicUtil.openDynamicScreen(EditorScreenKeyBinding, Screen); + // DynamicUtil.openDynamicScreen(EditorScreenKeyBinding, Screen); }); //RenderCallBack diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java new file mode 100644 index 0000000..d47d8a4 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java @@ -0,0 +1,48 @@ +package com.tanishisherewith.dynamichud; + +import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; +import org.lwjgl.glfw.GLFW; + +import java.io.File; + +public interface DynamicHudIntegration { + String KEYBIND_CATEGORY = "DynamicHud"; + String TRANSLATION_KEY = "DynamicHud Editor Screen"; + InputUtil.Type INPUT_TYPE = InputUtil.Type.KEYSYM; + int KEY = GLFW.GLFW_KEY_RIGHT_SHIFT; + KeyBinding EDITOR_SCREEN_KEY_BINDING = KeyBindingHelper.registerKeyBinding(new KeyBinding( + TRANSLATION_KEY, + INPUT_TYPE, + KEY, + KEYBIND_CATEGORY + )); + String FILENAME = "widgets.nbt"; + File FILE_DIRECTORY = FabricLoader.getInstance().getConfigDir().toFile(); + File WIDGETS_FILE = new File(FILE_DIRECTORY, FILENAME); + + void init(); + void addWidgets(); + default void registerWidgets(){} + + /** + * Returns the file where widgets are saved. + * + * @return The widgets file. + */ + default File getWidgetsFile() { + return WIDGETS_FILE; + } + + AbstractMoveableScreen getMovableScreen(); + + default WidgetRenderer getWidgetRenderer(){ + return new WidgetRenderer(WidgetManager.getWidgets()); + } +} + diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index 34f9115..75ac161 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -1,11 +1,13 @@ package com.tanishisherewith.dynamichud.helpers; import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; import com.tanishisherewith.dynamichud.util.CustomTextRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; import org.joml.Matrix4f; public class DrawHelper extends DrawContext { @@ -207,4 +209,24 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int drawContext.fill(x2 - 1, y1 + 1, x2, y2 - 1, color); } + /** + * This method assumes that the element is widget in the top-left corner (i.e. all drawing happens with respect to the top-left corner). + * @param matrices + * @param x X position of top-left corner of widget + * @param y Y position of top-left corner of widget + * @param scale Scale the matrices + */ + public static void scaleAndPosition(MatrixStack matrices, float x, float y,float z, float scale) { + matrices.push(); // Save the current transformation state + + // Translate to the desired position + matrices.translate(x, y, z); + + // Scale the matrix + matrices.scale(scale, scale, 1.0F); + } + public static void stopScaling(MatrixStack matrices){ + matrices.pop(); // Restore the previous transformation state + } + } diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java new file mode 100644 index 0000000..852887d --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -0,0 +1,22 @@ +package com.tanishisherewith.dynamichud.mixins; + +import com.tanishisherewith.dynamichud.DynamicHudIntegration; +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; +import com.tanishisherewith.dynamichud.newTrial.DynamicHudTest; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Screen.class) +public abstract class ScreenMixin { + @Inject(at = @At("TAIL"), method = "render") + private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ + widgetRenderer.renderWidgets(context); + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/TitleScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/TitleScreenMixin.java deleted file mode 100644 index 6abfe5e..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/TitleScreenMixin.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.tanishisherewith.dynamichud.mixins; - -import com.tanishisherewith.dynamichud.DynamicHUD; -import com.tanishisherewith.dynamichud.handlers.DefaultDragHandler; -import com.tanishisherewith.dynamichud.handlers.DefaultMouseHandler; -import com.tanishisherewith.dynamichud.handlers.DragHandler; -import com.tanishisherewith.dynamichud.handlers.MouseHandler; -import com.tanishisherewith.dynamichud.util.DynamicUtil; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(TitleScreen.class) -public abstract class TitleScreenMixin extends Screen { - protected MouseHandler mouseHandler = new DefaultMouseHandler(null, null, null); - protected DragHandler dragHandler = new DefaultDragHandler(); - protected Widget selectedWidget; - protected int dragStartX = 0, dragStartY = 0; // The starting position of a drag operation - protected int gridSize = 1; // The size of each grid cell in pixels - DynamicUtil dynamicUtil = DynamicHUD.getDynamicUtil(); - - protected TitleScreenMixin(Text title) { - super(title); - } - - public void setGridSize(int gridSize) { - this.gridSize = gridSize; - } - - @Inject(at = @At("TAIL"), method = "render") - private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - // Draw custom text on the title screen - if (dynamicUtil != null && (dynamicUtil.MainMenuWidgetAdded || dynamicUtil.WidgetLoaded)) { - dynamicUtil.render(context, delta); - } - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (mouseHandler.mouseClicked(mouseX, mouseY, button)) { - return true; - } - - for (Widget widget : dynamicUtil.getWidgetManager().getMainMenuWidgets()) { - if (widget.getWidgetBox().contains(widget, mouseX, mouseY,widget.getScale())) { - if (button == 1) { // Right-click - handleRightClickOnWidget(widget); - } else if (button == 0) { - widget.enabled = !widget.enabled; - } - if (dragHandler.startDragging(widget, mouseX, mouseY) && button == 0 && widget.isDraggable) { - selectedWidget = widget; - return true; - } - } - } - return super.mouseClicked(mouseX, mouseY, button); - } - - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (mouseHandler.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) { - return true; - } - if (selectedWidget != null && selectedWidget.isDraggable) { - // Update the position of the widget while dragging - int newX = (int) (mouseX - dragStartX); - int newY = (int) (mouseY - dragStartY); - - // Snap the widget to the grid - newX = (newX / gridSize) * gridSize; - newY = (newY / gridSize) * gridSize; - - selectedWidget.setX(newX); - selectedWidget.setY(newY); - return true; - } - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - } - - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (mouseHandler.mouseReleased(mouseX, mouseY, button)) { - return true; - } - if (selectedWidget != null) { - selectedWidget = null; - return true; - } - return super.mouseReleased(mouseX, mouseY, button); - } - - protected void handleRightClickOnWidget(Widget widget) { - - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java new file mode 100644 index 0000000..f2dda44 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -0,0 +1,122 @@ +package com.tanishisherewith.dynamichud.newTrial; + +import com.tanishisherewith.dynamichud.DynamicHudIntegration; +import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.util.DynamicUtil; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +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.metadata.ModMetadata; +import net.minecraft.client.MinecraftClient; +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.List; + +public class DynamicHUD implements ClientModInitializer { + + public static MinecraftClient MC = MinecraftClient.getInstance(); + private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); + private static final List widgetRenderers = new ArrayList<>(); + + public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { + widgetRenderers.add(widgetRenderer); + } + + public static List getWidgetRenderers() { + return widgetRenderers; + } + + public static void printInfo(String msg) { + logger.info(msg); + } + + public static void printWarn(String msg) { + logger.warn(msg); + } + + @Override + public void onInitializeClient() { + printInfo("DynamicHud Initialised"); + + //Save and Load + /* ClientTickEvents.START_CLIENT_TICK.register(server -> { + if (iWigdets != null) { + if (!WIDGETS_FILE.exists()) { + if (!dynamicutil.WidgetAdded) { + iWigdets.addWigdets(dynamicutil); + } + if (!dynamicutil.MainMenuWidgetAdded) { + iWigdets.addMainMenuWigdets(dynamicutil); + } + } + + if (WIDGETS_FILE.exists() && !dynamicutil.WidgetLoaded) { + iWigdets.loadWigdets(dynamicutil); + printInfo("Widgets loaded"); + File FileDirectory = new File(fileDirectory, filename); + printInfo("Load file Directory: " + FileDirectory); + } + } + DynamicUtil.openDynamicScreen(EditorScreenKeyBinding, Screen); + }); + + */ + FabricLoader.getInstance().getEntrypointContainers("dynamicHud", DynamicHudIntegration.class).forEach(entrypoint -> { + ModMetadata metadata = entrypoint.getProvider().getMetadata(); + String modId = metadata.getId(); + AbstractMoveableScreen screen; + try { + DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); + DHIntegration.init(); + + File widgetsFile = DHIntegration.getWidgetsFile(); + + if(widgetsFile.exists()) { + WidgetManager.loadWidgets(widgetsFile); + }else{ + DHIntegration.addWidgets(); + } + + screen = DHIntegration.getMovableScreen(); + KeyBinding binding =DHIntegration.EDITOR_SCREEN_KEY_BINDING; + WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); + addWidgetRenderer(widgetRenderer); + + //Register events for rendering, saving, loading, and opening the hudEditor + ClientTickEvents.START_CLIENT_TICK.register((client)->{ + DynamicUtil.openDynamicScreen(binding, screen); + }); + + // Save during exiting a world, server or Minecraft itself + ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile)); + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile)); + ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile)); + Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile))); + } catch (Throwable e) { + if(e instanceof IOException){ + logger.warn("An error has occured while loading widgets of mod {}", modId,e); + }else { + logger.warn("Mod {} has incorrect implementation of dynamicHud", modId, e); + } + } + }); + } + private void saveWidgetsSafely(File widgetsFile) { + try { + WidgetManager.saveWidgets(widgetsFile); + } catch (IOException e) { + logger.error("Failed to save widgets"); + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java new file mode 100644 index 0000000..78177ee --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -0,0 +1,60 @@ +package com.tanishisherewith.dynamichud.newTrial; + +import com.tanishisherewith.dynamichud.DynamicHudIntegration; +import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.huds.MoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; +import com.tanishisherewith.dynamichud.util.DynamicUtil; +import net.minecraft.client.gui.screen.GameMenuScreen; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.text.Text; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collections; + +public class DynamicHudTest implements DynamicHudIntegration { + TextWidget textWidget; + + DynamicValueRegistry registry = new DynamicValueRegistry(); + WidgetRenderer renderer; + @Override + public void init() { + DynamicValueRegistry.registerGlobal("FPS",() -> String.valueOf(DynamicHUD.MC.getCurrentFps())); + registry.registerLocal("FPS",()->String.valueOf(DynamicHUD.MC.getCurrentFps())); + } + + @Override + public void addWidgets() { + textWidget = new TextWidget.Builder() + .setX(0.6f) + .setY(0.6f) + .setDraggable(true) + .shouldScale(false) + .rainbow(false) + .setDHKey("FPS") + .build(); + + + WidgetManager.addWidget(textWidget); + } + + @Override + public AbstractMoveableScreen getMovableScreen() { + return new MoveableScreen(Text.of("Editor LOL"),new DynamicUtil(DynamicHUD.MC)); + } + + @Override + public WidgetRenderer getWidgetRenderer() { + renderer = new WidgetRenderer(Collections.singletonList(textWidget)); + renderer.shouldRenderInGameHud(true); + renderer.addScreen(TitleScreen.class); + renderer.addScreen(MultiplayerScreen.class); + return renderer; + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java new file mode 100644 index 0000000..2927a35 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java @@ -0,0 +1,32 @@ +package com.tanishisherewith.dynamichud.newTrial.utils; + +import java.util.*; +import java.util.function.Supplier; + +public class DynamicValueRegistry { + private static final Map> globalRegistry = new HashMap<>(); + private final Map> localRegistry = new HashMap<>(); + + public static void registerGlobal(String key, Supplier supplier) { + globalRegistry.put(key, supplier); + } + + public void registerLocal(String key, Supplier supplier) { + localRegistry.put(key, supplier); + } + public static Supplier getGlobal(String key) { + return globalRegistry.get(key); + } + + 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; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java new file mode 100644 index 0000000..cbe721b --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java @@ -0,0 +1,30 @@ +package com.tanishisherewith.dynamichud.newTrial.utils; + +import java.util.Random; + +public class UID { + private static final String ALPHANUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; + private static final int LENGTH = 6; + private static final Random RANDOM = new Random(); + public String uniqueID; + + public UID(String id) { + this.uniqueID = id; + } + + public static UID generate() { + StringBuilder sb = new StringBuilder(LENGTH); + for (int i = 0; i < LENGTH; i++) { + sb.append(ALPHANUMERIC.charAt(RANDOM.nextInt(ALPHANUMERIC.length()))); + } + return new UID(sb.toString()); + } + + public String getUniqueID() { + return uniqueID; + } + + public void setUniqueID(String uniqueID) { + this.uniqueID = uniqueID; + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java new file mode 100644 index 0000000..ce5950d --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -0,0 +1,244 @@ +package com.tanishisherewith.dynamichud.newTrial.widget; + +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.utils.UID; +import com.tanishisherewith.dynamichud.widget.WidgetBox; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.nbt.NbtCompound; + +import java.util.Set; + +public abstract class Widget { + + protected MinecraftClient mc = MinecraftClient.getInstance(); + + //This is the UID of the widget used to identify during loading and saving + public UID uid = UID.generate(); + public boolean display = true; // Whether the widget is enabled + public boolean isDraggable = true; + protected float xPercent; // The x position of the widget as a percentage of the screen width + protected float yPercent; // The y position of the widget as a percentage of the screen height + public boolean shouldScale = false; + protected WidgetBox widgetBox; + public static WidgetData DATA; + + public Widget(WidgetData DATA){ + Widget.DATA = DATA; + widgetBox = new WidgetBox(0,0,0,0,0); + init(); + } + + public void init(){ + + } + /** + * Returns the x position of the widget. + * + * @return The x position of the widget in pixels + */ + public float getX() { + return DynamicHUD.MC.getWindow().getScaledWidth() * xPercent; + } + + /** + * Returns the y position of the widget. + * + * @return The y position of the widget in pixels + */ + public float getY() { + return DynamicHUD.MC.getWindow().getScaledHeight() * yPercent; + } + + 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(); + } + + /** + * Renders the widget on the screen. + */ + public void render(DrawContext drawContext){ + if(shouldScale) { + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),0, 1.0f); + } + + renderWidget(drawContext); + + if(shouldScale){ + DrawHelper.stopScaling(drawContext.getMatrices()); + } + } + /** + * Renders the widget on the editor screen. + */ + public void renderInEditor(DrawContext drawContext){ + if(shouldScale) { + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),0, 1.0f); + } + + renderWidgetInEditor(drawContext); + + if(shouldScale){ + DrawHelper.stopScaling(drawContext.getMatrices()); + } + } + + + /** + * Renders the widget on the screen + * + * @param context + */ + public abstract void renderWidget(DrawContext context); + + + /** + * 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. + * + * @param context + */ + public void renderWidgetInEditor(DrawContext context){ + displayBg(context); + + renderWidget(context); + } + + /** + * Displays a faint grayish background if enabled or faint reddish background if disabled. + * Drawn with 2 pixel offset to all sides + * + * @param context + */ + protected void displayBg(DrawContext context){ + int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); + WidgetBox box = this.getWidgetBox(); + DrawHelper.fill(context, (int) (box.x1 - 2), (int) (box.y1 - 2), (int) (box.x2 + 2), (int) (box.y2 + 2), backgroundColor); + } + + + public void readFromTag(NbtCompound tag) { + uid = new UID(tag.getString("UID")); + xPercent = tag.getFloat("xPercent"); + yPercent = tag.getFloat("yPercent"); + display = tag.getBoolean("Display"); + isDraggable = tag.getBoolean("isDraggable"); + } + + /** + * Writes the state of this widget to the given tag. + * + * @param tag The tag to write to + */ + public void writeToTag(NbtCompound tag) { + tag.putString("UID", uid.getUniqueID()); + tag.putBoolean("isDraggable", isDraggable); + tag.putFloat("xPercent", xPercent); + tag.putFloat("yPercent", yPercent); + tag.putBoolean("Display", display); + } + + public boolean shouldDisplay() { + return display; + } + + 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; + } + + public void setShouldScale(boolean shouldScale) { + this.shouldScale = shouldScale; + } + + @Override + public String toString() { + return "Widget{" + + "uniqueId='" + uid.getUniqueID() + '\'' + + ", xPercent=" + xPercent + + ", yPercent=" + yPercent + + ", display=" + display + + '}'; + } + + public abstract static class WidgetBuilder { + protected float xPercent; + protected float yPercent; + protected boolean display = true; + protected boolean isDraggable = true; + protected boolean shouldScale = true; + + /** + * X Position of the widget relative to the screen. + * Should be between 0f - 1f + * + * @param xPercent + * @return + */ + public T setX(float xPercent) { + this.xPercent = xPercent; + return self(); + } + + /** + * Y Position of the widget relative to the screen. + * Should be between 0f - 1f + * + * @param yPercent + * @return + */ + public T setY(float yPercent) { + this.yPercent = yPercent; + return self(); + } + + public T setDisplay(boolean display) { + this.display = display; + return self(); + } + + public T setDraggable(boolean isDraggable) { + this.isDraggable = isDraggable; + return self(); + } + + public T shouldScale(boolean shouldScale) { + this.shouldScale = shouldScale; + return self(); + } + + // Method to be overridden in subclasses to return "this" correctly + protected abstract T self(); + + // Method to construct a Widget object + public abstract S build(); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java new file mode 100644 index 0000000..7939e21 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java @@ -0,0 +1,20 @@ +package com.tanishisherewith.dynamichud.newTrial.widget; + +import java.util.function.Supplier; + +public record WidgetData(String name, String description, Supplier widgetFactory) { + @Override + public String name() { + return name; + } + + @Override + public String description() { + return description; + } + + public Widget createWidget() { + return widgetFactory.get(); + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java new file mode 100644 index 0000000..14f8dfc --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -0,0 +1,149 @@ +package com.tanishisherewith.dynamichud.newTrial.widget; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.*; + +import net.fabricmc.fabric.api.util.NbtType; +import net.minecraft.nbt.*; + +import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; +import static com.tanishisherewith.dynamichud.DynamicHUD.printWarn; + +/** + * Manages a collection of widgets, providing methods to add, remove, save, and load widgets. + */ +public class WidgetManager { + /** + * The list of widgets managed by this manager. + */ + private static final List widgets = new ArrayList<>(); + + /** + * A map from widget names to WidgetData objects, used for creating new widgets. + */ + private static final Map> widgetDataMap = new TreeMap<>(); + + /** + * Adds a WidgetData object to the map. + * + * @param data The WidgetData object to add. + */ + public static void addWidgetData(WidgetData data){ + widgetDataMap.put(data.name(),data); + } + + /** + * Adds multiple WidgetData objects to the map. + * + * @param widgetDatas The WidgetData objects to add. + */ + public static void addWidgetDatas(WidgetData... widgetDatas){ + for(WidgetData data: widgetDatas) { + widgetDataMap.put(data.name(), data); + } + } + + /** + * Adds a widget to the list of managed widgets. + * + * @param widget The widget to add. + */ + public static void addWidget(Widget widget) { + widgets.add(widget); + } + + /** + * Adds multiple widgets to the list of managed widgets. + * + * @param widget The widgets to add. + */ + public static void addWidgets(Widget... widget) { + widgets.addAll(Arrays.stream(widget).toList()); + } + + /** + * Removes a widget from the list of managed widgets. + * + * @param widget The widget to remove. + */ + public static void removeWidget(Widget widget) { + widgets.remove(widget); + } + + /** + * Saves the state of all widgets to the given file. + * + * @param file The file to save to + */ + public static void saveWidgets(File file) throws IOException { + NbtCompound rootTag = new NbtCompound(); + NbtList widgetList = new NbtList(); + + printInfo("Saving widgets"); + + if (widgets.isEmpty()) { + printWarn("Widgets are empty.. Saving interrupted to prevent empty file"); + return; + } + + Set widgetSet = new HashSet<>(); + for (Widget widget : widgets) { + NbtCompound widgetTag = new NbtCompound(); + widget.writeToTag(widgetTag); + // Check for duplicates + if (widgetSet.add(widgetTag.toString())) { + widgetList.add(widgetTag); + } + } + + rootTag.put("widgets", widgetList); + + // Use a temporary file to write the data + File tempFile = new File(file.getAbsolutePath() + ".tmp"); + try (DataOutputStream out = new DataOutputStream(new FileOutputStream(tempFile))) { + NbtIo.write(rootTag, out); + // Check if the data has been written successfully + if (tempFile.length() > 0) { + // Check if the temporary file exists and can be renamed + Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + } else { + throw new IOException("Failed to write data to temporary file OR Empty data passed"); + } + } + } + + /** + * Loads the state of all widgets from the given file. + * + * @param file The file to load from + */ + public static void loadWidgets(File file) throws IOException { + widgets.clear(); + + if (file.exists()) { + NbtCompound rootTag = NbtIo.read(file.toPath()); + NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); + + 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); + widgets.add(widget); + } + }else{ + printWarn("Widget File does not exist. Try saving one first"); + } + } + + /** + * Returns the list of managed widgets. + * + * @return The list of managed widgets. + */ + public static List getWidgets() { + return widgets; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java new file mode 100644 index 0000000..6580509 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -0,0 +1,43 @@ +package com.tanishisherewith.dynamichud.newTrial.widget; + +import com.tanishisherewith.dynamichud.DynamicHUD; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class WidgetRenderer { + public final List> allowedScreens = new CopyOnWriteArrayList<>(); + private boolean renderInGameHud = true; + List widgets; + public WidgetRenderer(List widgets){ + this.widgets = widgets; + } + + public void addScreen(Class screen){ + allowedScreens.add(screen); + } + + public void shouldRenderInGameHud(boolean renderInGameHud) { + this.renderInGameHud = renderInGameHud; + } + + public void renderWidgets(DrawContext context) { + if(WidgetManager.getWidgets().isEmpty()) return; + + Screen currentScreen = DynamicHUD.MC.currentScreen; + if(currentScreen == null && renderInGameHud){ + for (Widget widget : widgets) { + widget.render(context); + } + return; + } + if (currentScreen!= null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass())) { + for (Widget widget : widgets) { + // System.out.println("Rendering Widget: " + widget); + widget.render(context); + } + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java new file mode 100644 index 0000000..5701b0b --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -0,0 +1,129 @@ +package com.tanishisherewith.dynamichud.newTrial.widgets; + +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.newTrial.widget.Widget; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.nbt.NbtCompound; + +import java.awt.*; +import java.util.function.Supplier; + +public class TextWidget extends Widget { + public static WidgetData DATA = new WidgetData<>("TextWidget","Display Text on screen",TextWidget::new); + Supplier textSupplier; + String dynamicRegistryKey; + protected boolean shadow; // Whether to draw a shadow behind the text + protected boolean rainbow; // Whether to apply a rainbow effect to the text + + public TextWidget() { + this(null,false,false); + } + + /** + * Searches for the supplier within the {@link DynamicValueRegistry#globalRegistry} using the given registryKey + * + * @param dynamicRegistryKey + * @param shadow + * @param rainbow + */ + public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow) { + super(DATA); + this.dynamicRegistryKey = dynamicRegistryKey; + textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); + this.shadow = shadow; + this.rainbow = rainbow; + } + + /** + * Searches for the supplier within the {@link DynamicValueRegistry#localRegistry} using the given registryKey and registryValue + * + * @param dynamicRegistryKey + * @param shadow + * @param rainbow + */ + public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, boolean shadow, boolean rainbow) { + super(DATA); + this.dynamicRegistryKey = dynamicRegistryKey; + textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); + this.shadow = shadow; + this.rainbow = rainbow; + } + + @Override + public void renderWidget(DrawContext drawContext) { + drawContext.getMatrices().push(); + drawContext.getMatrices().translate(0, 0, 420); + int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / (1 * 400f)) : Color.WHITE.getRGB(); + if(textSupplier != null) { + String text = textSupplier.get(); + drawContext.drawText(mc.textRenderer, text, (int) getX(), (int) getY(), color, shadow); + widgetBox.setSize(getX(),getY(),mc.textRenderer.getWidth(text),mc.textRenderer.fontHeight); + } + drawContext.getMatrices().pop(); + } + + @Override + public void writeToTag(NbtCompound tag) { + super.writeToTag(tag); + tag.putString("DRKey",dynamicRegistryKey); + tag.putBoolean("shadow",shadow); + tag.putBoolean("rainbow",rainbow); + } + + @Override + public void readFromTag(NbtCompound tag) { + super.readFromTag(tag); + shadow = tag.getBoolean("shadow"); + rainbow = tag.getBoolean("rainbow"); + dynamicRegistryKey = tag.getString("DRKey"); + } + public static class Builder extends WidgetBuilder { + + protected boolean shadow = false; + protected boolean rainbow = false; + protected String dynamicRegistryKey = ""; + DynamicValueRegistry dynamicValueRegistry = null; + + public Builder shadow(boolean shadow) { + this.shadow = shadow; + return self(); + } + + public Builder rainbow(boolean rainbow) { + this.rainbow = rainbow; + return self(); + } + public Builder setDHKey(String dynamicRegistryKey) { + this.dynamicRegistryKey = dynamicRegistryKey; + return self(); + } + public Builder setDH(DynamicValueRegistry dynamicValueRegistry) { + this.dynamicValueRegistry = dynamicValueRegistry; + return self(); + } + + @Override + protected Builder self() { + return this; + } + + @Override + public TextWidget build() { + TextWidget widget; + if(dynamicValueRegistry == null) { + widget = new TextWidget(dynamicRegistryKey, shadow, rainbow); + }else{ + widget = new TextWidget(dynamicValueRegistry,dynamicRegistryKey, shadow, rainbow); + } + widget.setxPercent(xPercent); + widget.setyPercent(yPercent); + widget.setDraggable(isDraggable); + widget.setShouldScale(shouldScale); + return widget; + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java b/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java index 742792b..b169aa4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java +++ b/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java @@ -39,7 +39,7 @@ public DynamicUtil(MinecraftClient client) { } /** - * Opens the MoveScreen when the specified key is pressed. + * 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 @@ -73,7 +73,7 @@ public void render(DrawContext context, float delta) { } // Draw each widget - if (!client.options.debugEnabled || client.currentScreen instanceof AbstractMoveableScreen) { + if (client.currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { if (client.currentScreen instanceof AbstractMoveableScreen) { widget.render(context); diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java index fa9b90c..60be115 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java +++ b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java @@ -10,8 +10,4 @@ public TextWidgetButtonExt(TextRenderer textRenderer, int x, int y, int width, i super(textRenderer, x, y, width, height, text); } - @Override - public void renderButton(DrawContext context, int mouseX, int mouseY, float delta) { - super.renderButton(context, mouseX, mouseY, delta); - } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index 067f6aa..6733d3f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -44,4 +44,16 @@ public float getWidth() { public float getHeight() { return height; } + public void setSize(float x,float y, float width, float height){ + this.x1 = x; + this.x2 = x + width; + this.y1 = y; + this.y2 = y + height; + } + public void setPosition(float x,float y, float x2, float y2){ + this.x1 = x; + this.x2 = x2; + this.y1 = y; + this.y2 = y2; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index c930768..a16c90a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -107,7 +107,7 @@ public void saveWidgets(File file) { printInfo("Saving widgets"); - if (widgets.size() < 1 && MainMenuWidgets.size() < 1) { + if (widgets.isEmpty() && MainMenuWidgets.isEmpty()) { printInfo("Widgets are empty.. Saving interrupted to prevent empty file"); return; } @@ -160,7 +160,8 @@ public Set loadWigdets(File file) { if (file.exists()) { printInfo("Widgets File exists"); try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { - NbtCompound rootTag = NbtIo.readCompressed(in); + DataInput input = new DataInputStream(in); + NbtCompound rootTag = NbtIo.readCompound(input); NbtList widgetList = rootTag.getList("Widgets", NbtType.COMPOUND); for (int i = 0; i < widgetList.size(); i++) { NbtCompound widgetTag = widgetList.getCompound(i); @@ -180,7 +181,8 @@ public Set loadMainMenuWigdets(File file) { Set MainMenuwidgets = new HashSet<>(); if (file.exists()) { try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { - NbtCompound rootTag = NbtIo.readCompressed(in); + DataInput input = new DataInputStream(in); + NbtCompound rootTag = NbtIo.readCompound(input); NbtList MainMenuwidgetList = rootTag.getList("MainMenuWidgets", NbtType.COMPOUND); for (int i = 0; i < MainMenuwidgetList.size(); i++) { NbtCompound widgetTag = MainMenuwidgetList.getCompound(i); diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json index f8d9096..2dc77ad 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -10,6 +10,6 @@ }, "client": [ "OptionsScreenMixin", - "TitleScreenMixin" + "ScreenMixin" ] } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 005e1b6..c694091 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -18,8 +18,11 @@ "license": "All-Rights-Reserved", "environment": "client", "entrypoints": { - "main": [ - "com.tanishisherewith.dynamichud.DynamicHUD" + "client": [ + "com.tanishisherewith.dynamichud.newTrial.DynamicHUD" + ], + "dynamicHud": [ + "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest" ], "modmenu": [ "com.tanishisherewith.dynamichud.ModMenuIntegration" From 55b21a8719cf057324c8d3a9c382f83f437f0963 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:36:17 +0530 Subject: [PATCH 04/33] Major new additions. --- build.gradle | 8 + gradle.properties | 3 +- .../dynamichud/DynamicHUD.java | 2 +- .../dynamichud/ModMenuIntegration.java | 6 +- .../dynamichud/helpers/DrawHelper.java | 8 +- .../dynamichud/mixins/OptionsScreenMixin.java | 2 - .../dynamichud/mixins/ScreenMixin.java | 17 ++ .../dynamichud/newTrial/DynamicHUD.java | 48 ++--- .../dynamichud/newTrial/DynamicHudTest.java | 33 ++-- .../newTrial/config/GlobalConfig.java | 51 ++++++ .../screens/AbstractMoveableScreen.java | 79 ++++++++ .../newTrial/utils/DynamicValueRegistry.java | 11 +- .../dynamichud/newTrial/utils/System.java | 24 +++ .../dynamichud/newTrial/widget/Widget.java | 169 ++++++++++++++---- .../newTrial/widget/WidgetManager.java | 100 +++++++++-- .../newTrial/widget/WidgetRenderer.java | 84 ++++++++- .../newTrial/widgets/TextWidget.java | 41 ++--- .../dynamichud/widget/WidgetBox.java | 4 +- .../assets/DynamicHUD/DynamicHud-logo.png | Bin 550679 -> 0 bytes src/main/resources/assets/DynamicHUD/logo.png | Bin 0 -> 192496 bytes src/main/resources/dynamichud.mixins.json | 2 + src/main/resources/fabric.mod.json | 2 +- 22 files changed, 577 insertions(+), 117 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java delete mode 100644 src/main/resources/assets/DynamicHUD/DynamicHud-logo.png create mode 100644 src/main/resources/assets/DynamicHUD/logo.png diff --git a/build.gradle b/build.gradle index 4f9c008..904421d 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,13 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + mavenCentral() + jcenter() maven { url "https://maven.terraformersmc.com/releases/" } + maven { + name 'Xander Maven' + url 'https://maven.isxander.dev/releases' + } } dependencies { @@ -28,6 +34,8 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "dev.isxander.yacl:yet-another-config-lib-fabric:${project.yacl_version}" + modApi "com.terraformersmc:modmenu:9.0.0" } diff --git a/gradle.properties b/gradle.properties index 27d3423..ba63423 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,4 +13,5 @@ org.gradle.parallel=true archives_base_name = dynamichud # Dependencies - fabric_version=0.91.1+1.20.4 \ No newline at end of file + fabric_version=0.91.1+1.20.4 + yacl_version=3.3.2+1.20.4 \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index dd81dae..18b14c4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -27,7 +27,7 @@ public class DynamicHUD implements ClientModInitializer { public static MinecraftClient MC = MinecraftClient.getInstance(); - private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); + public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); static AbstractMoveableScreen Screen; private static String keybingCategory = "DynamicHud"; private static String TranslationKey = "DynamicHud Editor Screen"; diff --git a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java index 07cb3aa..c9aec49 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java @@ -1,11 +1,15 @@ package com.tanishisherewith.dynamichud; +import com.tanishisherewith.dynamichud.newTrial.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 { + public static Screen YACL_CONFIG_SCREEN = GlobalConfig.get().createYACLGUI(); @Override public ConfigScreenFactory getModConfigScreenFactory() { - return parent -> DynamicHUD.getScreen(); + return parent -> YACL_CONFIG_SCREEN; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index 75ac161..b87dd3e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -211,20 +211,20 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int /** * This method assumes that the element is widget in the top-left corner (i.e. all drawing happens with respect to the top-left corner). - * @param matrices * @param x X position of top-left corner of widget * @param y Y position of top-left corner of widget * @param scale Scale the matrices */ - public static void scaleAndPosition(MatrixStack matrices, float x, float y,float z, float scale) { + public static void scaleAndPosition(MatrixStack matrices, float x, float y, float scale) { matrices.push(); // Save the current transformation state - // Translate to the desired position - matrices.translate(x, y, z); + // Translate the origin back to the desired position + matrices.translate(x, y, 0); // Scale the matrix matrices.scale(scale, scale, 1.0F); } + public static void stopScaling(MatrixStack matrices){ matrices.pop(); // Restore the previous transformation state } diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java index 345e818..a3f274a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java @@ -20,8 +20,6 @@ @Mixin(OptionsScreen.class) public class OptionsScreenMixin extends Screen { private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); - private final GameOptions settings = MinecraftClient.getInstance().options; - protected OptionsScreenMixin(Text title) { super(title); diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index 852887d..d1e4259 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -3,20 +3,37 @@ import com.tanishisherewith.dynamichud.DynamicHudIntegration; import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; import com.tanishisherewith.dynamichud.newTrial.DynamicHudTest; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; 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; @Mixin(Screen.class) public abstract class ScreenMixin { + @Shadow public int width; + + @Shadow public int height; + @Inject(at = @At("TAIL"), method = "render") private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ widgetRenderer.renderWidgets(context); } } + @Inject(at = @At("HEAD"), method = "resize") + private void onScreenResize(MinecraftClient client,int width, int height, CallbackInfo ci) { + WidgetManager.onScreenResized(width,height,this.width,this.height); + } + @Inject(at = @At("TAIL"), method = "close") + private void render(CallbackInfo ci) { + for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ + widgetRenderer.onCloseScreen(); + } + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index f2dda44..b73464d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -2,8 +2,10 @@ import com.tanishisherewith.dynamichud.DynamicHudIntegration; import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; import com.tanishisherewith.dynamichud.util.DynamicUtil; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; @@ -12,6 +14,7 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +27,7 @@ public class DynamicHUD implements ClientModInitializer { public static MinecraftClient MC = MinecraftClient.getInstance(); + public static String MOD_ID = "dynamichud"; private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); private static final List widgetRenderers = new ArrayList<>(); @@ -45,31 +49,16 @@ public static void printWarn(String msg) { @Override public void onInitializeClient() { - printInfo("DynamicHud Initialised"); - - //Save and Load - /* ClientTickEvents.START_CLIENT_TICK.register(server -> { - if (iWigdets != null) { - if (!WIDGETS_FILE.exists()) { - if (!dynamicutil.WidgetAdded) { - iWigdets.addWigdets(dynamicutil); - } - if (!dynamicutil.MainMenuWidgetAdded) { - iWigdets.addMainMenuWigdets(dynamicutil); - } - } + printInfo("Initialising DynamicHud"); - if (WIDGETS_FILE.exists() && !dynamicutil.WidgetLoaded) { - iWigdets.loadWigdets(dynamicutil); - printInfo("Widgets loaded"); - File FileDirectory = new File(fileDirectory, filename); - printInfo("Load file Directory: " + FileDirectory); - } - } - DynamicUtil.openDynamicScreen(EditorScreenKeyBinding, Screen); - }); + // Add WidgetData of included widgets + WidgetManager.addWidgetDatas( + TextWidget.DATA + ); + //YACL load + GlobalConfig.HANDLER.load(); - */ + printInfo("Integrating mods..."); FabricLoader.getInstance().getEntrypointContainers("dynamicHud", DynamicHudIntegration.class).forEach(entrypoint -> { ModMetadata metadata = entrypoint.getProvider().getMetadata(); String modId = metadata.getId(); @@ -88,11 +77,14 @@ public void onInitializeClient() { screen = DHIntegration.getMovableScreen(); KeyBinding binding =DHIntegration.EDITOR_SCREEN_KEY_BINDING; + WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); addWidgetRenderer(widgetRenderer); //Register events for rendering, saving, loading, and opening the hudEditor - ClientTickEvents.START_CLIENT_TICK.register((client)->{ + ClientTickEvents.START_CLIENT_TICK.register((client)-> { + System.out.println("TICK FOR : " + modId); + System.out.println(binding); DynamicUtil.openDynamicScreen(binding, screen); }); @@ -101,6 +93,9 @@ public void onInitializeClient() { ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile)); ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile)); Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile))); + + + printInfo(String.format("Integration of mod %s was successful",modId)); } catch (Throwable e) { if(e instanceof IOException){ logger.warn("An error has occured while loading widgets of mod {}", modId,e); @@ -109,6 +104,11 @@ public void onInitializeClient() { } } }); + + 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()); + Runtime.getRuntime().addShutdownHook(new Thread(() -> GlobalConfig.HANDLER.save())); } private void saveWidgetsSafely(File widgetsFile) { try { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index 78177ee..efad069 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -4,6 +4,7 @@ import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.huds.MoveableScreen; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; @@ -16,41 +17,45 @@ import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; public class DynamicHudTest implements DynamicHudIntegration { TextWidget textWidget; - - DynamicValueRegistry registry = new DynamicValueRegistry(); + DynamicValueRegistry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); WidgetRenderer renderer; @Override public void init() { - DynamicValueRegistry.registerGlobal("FPS",() -> String.valueOf(DynamicHUD.MC.getCurrentFps())); - registry.registerLocal("FPS",()->String.valueOf(DynamicHUD.MC.getCurrentFps())); - } + DynamicValueRegistry.registerGlobal("FPS",() -> "FPS: "+ DynamicHUD.MC.getCurrentFps()); + registry.registerLocal("FPS",()-> "FPS: "+ DynamicHUD.MC.getCurrentFps()); - @Override - public void addWidgets() { textWidget = new TextWidget.Builder() - .setX(0.6f) - .setY(0.6f) + .setX(300) + .setY(60) .setDraggable(true) - .shouldScale(false) .rainbow(false) - .setDHKey("FPS") + .setDRKey("FPS") + .setModID(DynamicHUD.MOD_ID) + .shouldScale(false) .build(); + } - + @Override + public void addWidgets() { WidgetManager.addWidget(textWidget); } @Override public AbstractMoveableScreen getMovableScreen() { - return new MoveableScreen(Text.of("Editor LOL"),new DynamicUtil(DynamicHUD.MC)); + return new MoveableScreen(Text.of("Editor"),new DynamicUtil(DynamicHUD.MC)); } @Override public WidgetRenderer getWidgetRenderer() { - renderer = new WidgetRenderer(Collections.singletonList(textWidget)); + // Get the widgets for this mod + List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); + + renderer = new WidgetRenderer(widgets); renderer.shouldRenderInGameHud(true); renderer.addScreen(TitleScreen.class); renderer.addScreen(MultiplayerScreen.class); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java new file mode 100644 index 0000000..22ae290 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java @@ -0,0 +1,51 @@ +package com.tanishisherewith.dynamichud.newTrial.config; + +import dev.isxander.yacl3.api.*; +import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; +import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder; +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.gui.controllers.slider.FloatSliderController; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class GlobalConfig { + private static GlobalConfig INSTANCE = new GlobalConfig(); + public static ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) + .id(new Identifier("dynamichud", "dynamichud_config")) + .serializer(config -> GsonConfigSerializerBuilder.create(config) + .setPath(FabricLoader.getInstance().getConfigDir().resolve("dynamichud.json5")) + .setJson5(true) + .build()) + .build(); + + @SerialEntry + public float scale = 1.0f; + + public Screen createYACLGUI() { + return YetAnotherConfigLib.createBuilder() + .title(Text.literal("DynamicHUD config screen.")) + .category(ConfigCategory.createBuilder() + .name(Text.literal("General")) + .tooltip(Text.literal("Set the general settings for all widgets.")) + .group(OptionGroup.createBuilder() + .name(Text.literal("Global")) + .description(OptionDescription.of(Text.literal("Global settings for all widgets."))) + .option(Option.createBuilder() + .name(Text.literal("Scale")) + .description(OptionDescription.of(Text.literal("Set scale for all widgets."))) + .binding(1.0f, () -> this.scale, newVal -> this.scale = newVal) + .controller(floatOption -> FloatSliderControllerBuilder.create(floatOption).range(0.1f,2.5f).step(0.1f)) + .build()) + .build()) + .build()) + .build() + .generateScreen(null); + } + public static GlobalConfig get(){ + return INSTANCE; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java new file mode 100644 index 0000000..4908b11 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -0,0 +1,79 @@ +package com.tanishisherewith.dynamichud.newTrial.screens; + +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.widget.Widget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +public abstract class AbstractMoveableScreen extends Screen { + protected boolean ShouldPause = false; // To pause if the screen is opened or not + public final WidgetRenderer widgetRenderer; + + + /** + * Constructs a AbstractMoveableScreen object. + * + */ + public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { + super(title); + this.widgetRenderer = renderer; + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + widgetRenderer.mouseDragged(mouseX,mouseY,button); + return false; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + widgetRenderer.mouseClicked(mouseX,mouseY,button); + return false; + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + widgetRenderer.mouseReleased(mouseX,mouseY,button); + return false; + } + + /** + * Renders this screen and its widgets on the screen. + * + * @param drawContext The matrix stack used for rendering + * @param mouseX The current x position of the mouse cursor + * @param mouseY The current y position of the mouse cursor + * @param delta The time elapsed since the last frame in seconds + */ + @Override + public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { + super.render(drawContext, mouseX, mouseY, delta); + + // Draw each widget + widgetRenderer.isInEditor = true; + widgetRenderer.renderWidgets(drawContext); + } + + @Override + public void close() { + super.close(); + widgetRenderer.isInEditor = false; + } + + public void setShouldPause(boolean shouldPause) { + this.ShouldPause = shouldPause; + } + + + @Override + public void resize(MinecraftClient client, int width, int height) { + super.resize(client, width, height); + } + + @Override + public boolean shouldPause() { + return ShouldPause; + } +} + diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java index 2927a35..43d62da 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java @@ -3,10 +3,13 @@ import java.util.*; import java.util.function.Supplier; -public class DynamicValueRegistry { +public class DynamicValueRegistry extends System { private static final Map> globalRegistry = new HashMap<>(); private final Map> localRegistry = new HashMap<>(); - + public DynamicValueRegistry(String modId) { + super(modId); + instances.computeIfAbsent(modId, k -> new ArrayList<>()).add(this); + } public static void registerGlobal(String key, Supplier supplier) { globalRegistry.put(key, supplier); } @@ -29,4 +32,8 @@ public Supplier get(String key) { return supplier; } + public void setLocalRegistry(Map> map){ + localRegistry.putAll(map); + } + } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java new file mode 100644 index 0000000..8022537 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java @@ -0,0 +1,24 @@ +package com.tanishisherewith.dynamichud.newTrial.utils; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class System { + protected final String modId; + + // A map to store all instances of DynamicValueRegistry by modId + protected static final Map> instances = new ConcurrentHashMap<>(); + + public System(String modId) { + this.modId = modId; + } + + public String getModId() { + return modId; + } + + public static List getInstances(String modId) { + return instances.get(modId); + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index ce5950d..4f1ea10 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -1,13 +1,14 @@ package com.tanishisherewith.dynamichud.newTrial.widget; -import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.utils.UID; import com.tanishisherewith.dynamichud.widget.WidgetBox; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; +import org.lwjgl.glfw.GLFW; import java.util.Set; @@ -17,20 +18,44 @@ public abstract class Widget { //This is the UID of the widget used to identify during loading and saving public UID uid = UID.generate(); - public boolean display = true; // Whether the widget is enabled + public boolean isInEditor = false; + // Whether the widget is enabled and should be displayed. + public boolean display = true; public boolean isDraggable = true; - protected float xPercent; // The x position of the widget as a percentage of the screen width - protected float yPercent; // The y position of the widget as a percentage of the screen height - public boolean shouldScale = false; + + //Boolean to check if the widget is being dragged + public boolean dragging; + + //To enable/disable snapping + public boolean shiftDown = false; + + // Used for dragging and snapping + int startX, startY, snapSize = 120; + + // Absolute position of the widget on screen in pixels. + public int x,y; + + // 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; + public boolean shouldScale = true; + public String modId = "unknown"; + + //Dimensions of the widget protected WidgetBox widgetBox; public static WidgetData DATA; - public Widget(WidgetData DATA){ + public Widget(WidgetData DATA, String modId){ Widget.DATA = DATA; - widgetBox = new WidgetBox(0,0,0,0,0); + widgetBox = new WidgetBox(0,0,0,0,1); + this.modId = modId; init(); } + /** + * This method is called at the end of the {@link Widget#Widget(WidgetData)} constructor. + */ public void init(){ } @@ -39,8 +64,8 @@ public void init(){ * * @return The x position of the widget in pixels */ - public float getX() { - return DynamicHUD.MC.getWindow().getScaledWidth() * xPercent; + public int getX() { + return x; } /** @@ -48,8 +73,20 @@ public float getX() { * * @return The y position of the widget in pixels */ - public float getY() { - return DynamicHUD.MC.getWindow().getScaledHeight() * yPercent; + public int getY() { + return y; + } + + public float getWidth(){ + return widgetBox.getWidth(); + } + public float getHeight(){ + return widgetBox.getHeight(); + } + + public void setPosition(int x, int y){ + this.x = x; + this.y = y; } public void setDraggable(boolean draggable) { @@ -74,13 +111,16 @@ public boolean isOverlapping(Widget other) { * Renders the widget on the screen. */ public void render(DrawContext drawContext){ + if(!shouldDisplay())return; + if(shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),0, 1.0f); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + scale(GlobalConfig.get().scale); } - renderWidget(drawContext); if(shouldScale){ + reverseScale(GlobalConfig.get().scale); DrawHelper.stopScaling(drawContext.getMatrices()); } } @@ -89,12 +129,14 @@ public void render(DrawContext drawContext){ */ public void renderInEditor(DrawContext drawContext){ if(shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),0, 1.0f); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + scale(GlobalConfig.get().scale); } renderWidgetInEditor(drawContext); if(shouldScale){ + reverseScale(GlobalConfig.get().scale); DrawHelper.stopScaling(drawContext.getMatrices()); } } @@ -115,12 +157,51 @@ public void renderInEditor(DrawContext drawContext){ * * @param context */ - public void renderWidgetInEditor(DrawContext context){ + private void renderWidgetInEditor(DrawContext context){ displayBg(context); renderWidget(context); } + public void mouseClicked(double mouseX, double mouseY, int button){ + if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT){ + toggle(); + } + } + public void mouseDragged(double mouseX, double mouseY, int button){ + if(this.isDraggable && button == GLFW.GLFW_MOUSE_BUTTON_LEFT){ + //Start dragging + startX = (int) (mouseX - x); + startY = (int) (mouseY - y); + dragging = true; + this.x = startX; + this.y = startY; + + // Divides the screen into several "grid boxes" which the elements snap to. Higher the snapSize, more the grid boxes + if (this.shiftDown) { + // Calculate the size of each snap box + int snapBoxWidth = (int) (widgetBox.getWidth() / this.snapSize); + int snapBoxHeight = (int) (widgetBox.getHeight() / this.snapSize); + + // Calculate the index of the snap box that the mouse is currently in + int snapBoxX = (int) (mouseX / snapBoxWidth); + int snapBoxY = (int) (mouseY / snapBoxHeight); + + // Snap the element to the top-left corner of the snap box + this.x = snapBoxX * snapBoxWidth; + this.y = snapBoxY * snapBoxHeight; + } + } + } + public void mouseReleased(double mouseX, double mouseY, int button) { + dragging = false; + } + + + public boolean toggle(){ + return this.display = !this.display; + } + /** * Displays a faint grayish background if enabled or faint reddish background if disabled. * Drawn with 2 pixel offset to all sides @@ -135,11 +216,13 @@ protected void displayBg(DrawContext context){ public void readFromTag(NbtCompound tag) { + modId = tag.getString("modId"); uid = new UID(tag.getString("UID")); - xPercent = tag.getFloat("xPercent"); - yPercent = tag.getFloat("yPercent"); + x = tag.getInt("x"); + y = tag.getInt("y"); display = tag.getBoolean("Display"); isDraggable = tag.getBoolean("isDraggable"); + shouldScale = tag.getBoolean("shouldScale"); } /** @@ -148,10 +231,13 @@ public void readFromTag(NbtCompound tag) { * @param tag The tag to write to */ public void writeToTag(NbtCompound tag) { + tag.putString("name", DATA.name()); + tag.putString("modId",modId); tag.putString("UID", uid.getUniqueID()); tag.putBoolean("isDraggable", isDraggable); - tag.putFloat("xPercent", xPercent); - tag.putFloat("yPercent", yPercent); + tag.putBoolean("shouldScale", shouldScale); + tag.putInt("x", x); + tag.putInt("y", y); tag.putBoolean("Display", display); } @@ -179,6 +265,18 @@ public void setShouldScale(boolean shouldScale) { this.shouldScale = shouldScale; } + public String getModId() { + return modId; + } + public void scale(float scale) { + this.xPercent *= scale; + this.yPercent *= scale; + } + public void reverseScale(float scale) { + this.xPercent /= scale; + this.yPercent /= scale; + } + @Override public String toString() { return "Widget{" + @@ -188,23 +286,24 @@ public String toString() { ", display=" + display + '}'; } - public abstract static class WidgetBuilder { - protected float xPercent; - protected float yPercent; + protected int x; + protected int y; protected boolean display = true; protected boolean isDraggable = true; protected boolean shouldScale = true; + protected String modID = "unknown"; + /** * X Position of the widget relative to the screen. * Should be between 0f - 1f * - * @param xPercent - * @return + * @param x + * @return Builder */ - public T setX(float xPercent) { - this.xPercent = xPercent; + public T setX(int x) { + this.x = x; return self(); } @@ -212,11 +311,11 @@ public T setX(float xPercent) { * Y Position of the widget relative to the screen. * Should be between 0f - 1f * - * @param yPercent + * @param y * @return */ - public T setY(float yPercent) { - this.yPercent = yPercent; + public T setY(int y) { + this.y = y; return self(); } @@ -234,11 +333,19 @@ public T shouldScale(boolean shouldScale) { this.shouldScale = shouldScale; return self(); } + public T setModID(String modID) { + this.modID = modID; + return self(); + } - // Method to be overridden in subclasses to return "this" correctly + /** + * Method to be overridden in subclasses to return "this" correctly + */ protected abstract T self(); - // Method to construct a Widget object + /** + * Method to construct a Widget object + */ public abstract S build(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 14f8dfc..02f384c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -5,11 +5,12 @@ import java.nio.file.StandardCopyOption; import java.util.*; +import com.tanishisherewith.dynamichud.DynamicHUD; import net.fabricmc.fabric.api.util.NbtType; import net.minecraft.nbt.*; +import net.minecraft.util.math.MathHelper; -import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; -import static com.tanishisherewith.dynamichud.DynamicHUD.printWarn; +import static com.tanishisherewith.dynamichud.DynamicHUD.*; /** * Manages a collection of widgets, providing methods to add, remove, save, and load widgets. @@ -71,6 +72,77 @@ public static void addWidgets(Widget... widget) { public static void removeWidget(Widget widget) { widgets.remove(widget); } + /* public static void onScreenResized(int newWidth, int newHeight) { + float scaleX = (float) newWidth / MC.getWindow().getScaledWidth(); + float scaleY = (float) newHeight / MC.getWindow().getScaledHeight(); + System.out.println("newWidth: " + newWidth); + System.out.println("newHeight: " + newHeight); + + System.out.println("scaleX: " + scaleX); + + for (Widget widget : widgets) { + float newX = widget.getX() * scaleX; + float newY = widget.getY() * scaleY; + System.out.println("newX: " + newX); + + // Ensure the widget is within the screen bounds + newX = MathHelper.clamp(newX,0,newWidth - widget.getWidth()); + newY = MathHelper.clamp(newY,0,newHeight - widget.getHeight()); + System.out.println("newX2: " + newX); + + widget.setPosition(newX, newY); + } + } + + */ + + /** + * Attempts to restore the widgets back to their place on screen resize. + *

+ * It works by storing the position of widgets as relative to the screen size before the resize + * and then using that percentage to restore the widget to their appropriate place. + *

+ * Widgets will move around on smaller GUI scales. + * Larger the GUI scale, more accurate is the position. + *

+ *

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

+ *

+ * + * @param newWidth Screen width after resize + * @param newHeight Screen height after resize + * @param previousWidth Screen width before resize + * @param previousHeight Screen height before resize + */ + public static void onScreenResized(int newWidth, int newHeight, int previousWidth, int previousHeight) { + for (Widget widget : widgets) { + + // To ensure that infinite coords is not returned + if(widget.xPercent <= 0f){ + widget.xPercent = (float) widget.getX()/previousWidth; + } + if(widget.yPercent <= 0f){ + widget.yPercent = (float) widget.getY()/previousHeight; + } + + // Use the stored percentages to calculate the new position + int newX = (int) (widget.xPercent * newWidth); + int newY = (int) (widget.yPercent * newHeight); + + // Ensure the widget is within the screen bounds + newX = (int) MathHelper.clamp(newX, 0, newWidth - widget.getWidth()); + newY = (int) MathHelper.clamp(newY, 0, newHeight - widget.getHeight()); + + // Update the widget's position + widget.setPosition(newX, newY); + + // Update the stored percentages with the new screen size (after resize). + widget.xPercent = (float) widget.getX() / newWidth; + widget.yPercent = (float) widget.getY() / newHeight; + } + } + /** * Saves the state of all widgets to the given file. @@ -100,17 +172,11 @@ public static void saveWidgets(File file) throws IOException { rootTag.put("widgets", widgetList); - // Use a temporary file to write the data - File tempFile = new File(file.getAbsolutePath() + ".tmp"); - try (DataOutputStream out = new DataOutputStream(new FileOutputStream(tempFile))) { + //Write the data to the file + try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) { NbtIo.write(rootTag, out); - // Check if the data has been written successfully - if (tempFile.length() > 0) { - // Check if the temporary file exists and can be renamed - Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - } else { - throw new IOException("Failed to write data to temporary file OR Empty data passed"); - } + }catch (IOException e){ + DynamicHUD.logger.warn("Error while saving",e); } } @@ -146,4 +212,14 @@ public static void loadWidgets(File file) throws IOException { public static List getWidgets() { return widgets; } + /** + * Returns the list of managed widgets with the same modID. + * + * @return The list of managed widgets with the same modID. + */ + public static List getWidgetsForMod(String modID) { + return getWidgets().stream() + .filter(widget -> modID.equalsIgnoreCase(widget.getModId())) + .toList(); + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index 6580509..fffdd2d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -1,8 +1,13 @@ package com.tanishisherewith.dynamichud.newTrial.widget; import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.widget.WidgetBox; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; +import org.lwjgl.glfw.GLFW; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -10,10 +15,14 @@ public class WidgetRenderer { public final List> allowedScreens = new CopyOnWriteArrayList<>(); private boolean renderInGameHud = true; + public boolean isInEditor = false; List widgets; public WidgetRenderer(List widgets){ this.widgets = widgets; } + public void addWidget(Widget widget){ + widgets.add(widget); + } public void addScreen(Class screen){ allowedScreens.add(screen); @@ -27,17 +36,88 @@ public void renderWidgets(DrawContext context) { if(WidgetManager.getWidgets().isEmpty()) return; Screen currentScreen = DynamicHUD.MC.currentScreen; + if(currentScreen == null && renderInGameHud){ for (Widget widget : widgets) { + widget.isInEditor = false; widget.render(context); } return; } - if (currentScreen!= null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass())) { + if(currentScreen instanceof AbstractMoveableScreen){ + for (Widget widget : widgets) { + widget.isInEditor = true; + widget.renderInEditor(context); + } + return; + } + if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass()) && !this.isInEditor) { for (Widget widget : widgets) { - // System.out.println("Rendering Widget: " + widget); + widget.isInEditor = false; widget.render(context); } } } + public void mouseClicked(double mouseX, double mouseY, int button){ + Screen currentScreen = DynamicHUD.MC.currentScreen; + if(currentScreen == null) { + return; + } + if(currentScreen instanceof AbstractMoveableScreen){ + for (Widget widget : widgets) { + widget.mouseClicked(mouseX,mouseY,button); + } + } + } + public void mouseDragged(double mouseX, double mouseY, int button){ + Screen currentScreen = DynamicHUD.MC.currentScreen; + if(currentScreen == null) { + return; + } + if(currentScreen instanceof AbstractMoveableScreen){ + for (Widget widget : widgets) { + widget.mouseDragged(mouseX,mouseY,button); + } + } + } + + 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; + } + } + } + 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; + } + } + } + public void onCloseScreen(){ + if(DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen){ + for (Widget widget : widgets) { + widget.shiftDown = false; + } + } + } + + public List getWidgets() { + return widgets; + } + + public void mouseReleased(double mouseX, double mouseY, int button){ + Screen currentScreen = DynamicHUD.MC.currentScreen; + if(currentScreen == null) { + return; + } + if(currentScreen instanceof AbstractMoveableScreen){ + for (Widget widget : widgets) { + widget.mouseReleased(mouseX,mouseY,button); + } + } + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 5701b0b..0c816a1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -1,8 +1,7 @@ package com.tanishisherewith.dynamichud.newTrial.widgets; -import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; @@ -16,11 +15,12 @@ public class TextWidget extends Widget { public static WidgetData DATA = new WidgetData<>("TextWidget","Display Text on screen",TextWidget::new); Supplier textSupplier; String dynamicRegistryKey; + DynamicValueRegistry dynamicValueRegistry; protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text public TextWidget() { - this(null,false,false); + this(null,false,false,"unknown"); } /** @@ -30,8 +30,8 @@ public TextWidget() { * @param shadow * @param rainbow */ - public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow) { - super(DATA); + public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,String modID) { + super(DATA,modID); this.dynamicRegistryKey = dynamicRegistryKey; textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; @@ -45,9 +45,10 @@ public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow) { * @param shadow * @param rainbow */ - public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, boolean shadow, boolean rainbow) { - super(DATA); + public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, boolean shadow, boolean rainbow,String modID) { + super(DATA,modID); this.dynamicRegistryKey = dynamicRegistryKey; + this.dynamicValueRegistry = dynamicValueRegistry; textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; @@ -55,15 +56,12 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist @Override public void renderWidget(DrawContext drawContext) { - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0, 0, 420); - int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / (1 * 400f)) : Color.WHITE.getRGB(); + int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / 10000f) : Color.WHITE.getRGB(); if(textSupplier != null) { String text = textSupplier.get(); - drawContext.drawText(mc.textRenderer, text, (int) getX(), (int) getY(), color, shadow); - widgetBox.setSize(getX(),getY(),mc.textRenderer.getWidth(text),mc.textRenderer.fontHeight); + drawContext.drawText(mc.textRenderer, text, (int) getX(), (int)getY(), color, shadow); + widgetBox.setSize(getX() - 2,getY() - 2,mc.textRenderer.getWidth(text) + 2,mc.textRenderer.fontHeight + 2); } - drawContext.getMatrices().pop(); } @Override @@ -80,9 +78,13 @@ public void readFromTag(NbtCompound tag) { shadow = tag.getBoolean("shadow"); rainbow = tag.getBoolean("rainbow"); dynamicRegistryKey = tag.getString("DRKey"); + + for(DynamicValueRegistry dvr: DynamicValueRegistry.getInstances(modId)){ + textSupplier = (Supplier) dvr.get(dynamicRegistryKey); + break; + } } public static class Builder extends WidgetBuilder { - protected boolean shadow = false; protected boolean rainbow = false; protected String dynamicRegistryKey = ""; @@ -97,11 +99,11 @@ public Builder rainbow(boolean rainbow) { this.rainbow = rainbow; return self(); } - public Builder setDHKey(String dynamicRegistryKey) { + public Builder setDRKey(String dynamicRegistryKey) { this.dynamicRegistryKey = dynamicRegistryKey; return self(); } - public Builder setDH(DynamicValueRegistry dynamicValueRegistry) { + public Builder setDVR(DynamicValueRegistry dynamicValueRegistry) { this.dynamicValueRegistry = dynamicValueRegistry; return self(); } @@ -115,12 +117,11 @@ protected Builder self() { public TextWidget build() { TextWidget widget; if(dynamicValueRegistry == null) { - widget = new TextWidget(dynamicRegistryKey, shadow, rainbow); + widget = new TextWidget(dynamicRegistryKey, shadow, rainbow,modID); }else{ - widget = new TextWidget(dynamicValueRegistry,dynamicRegistryKey, shadow, rainbow); + widget = new TextWidget(dynamicValueRegistry,dynamicRegistryKey, shadow, rainbow,modID); } - widget.setxPercent(xPercent); - widget.setyPercent(yPercent); + widget.setPosition(x,y); widget.setDraggable(isDraggable); widget.setShouldScale(shouldScale); return widget; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index 6733d3f..fd845fa 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -6,8 +6,8 @@ public class WidgetBox { public float x1 = 0, x2 = 0, y1 = 0, y2 = 0; public WidgetBox(float x1, float y1, float x2, float y2, float scale) { - this.width = (float) ((x2 - x1) * scale); - this.height = (float) ((y2 - y1) * scale); + this.width = (x2 - x1) * scale; + this.height = (y2 - y1) * scale; this.x1 = x1; this.x2 = x1 + width; this.y1 = y1; diff --git a/src/main/resources/assets/DynamicHUD/DynamicHud-logo.png b/src/main/resources/assets/DynamicHUD/DynamicHud-logo.png deleted file mode 100644 index e2848ae71f8f028597cd56737872c6b7f3f4cce2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 550679 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 C<-LpF+8 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

3SR-M_p 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 z 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�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
{&n`zMqWAxwl{~)PUHE)6i3Hz@U?sK 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 diff --git a/src/main/resources/assets/DynamicHUD/logo.png b/src/main/resources/assets/DynamicHUD/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bb4962c84c7bb6d1b532b68a58669a1a466cd2d3 GIT binary patch literal 192496 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%0A8-lJKQ$2$l({=vLZ;fbq{O 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ĬUEh;Lf(L@=o$H^WOHX`~ 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 bq6!?#> Date: Fri, 5 Apr 2024 16:20:41 +0530 Subject: [PATCH 05/33] Update README.md --- README.md | 66 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index cf61b52..d2b8b4a 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,37 @@ # DynamicHUD -A library to display stuff on the screen. **Fabric only** -### Version `1.3.0` - -# ⚠ IN PROGRESS ⚠ - -## This is a test branch for dynamichud 1.20.4. This branch will contain the majorly reworked version of dynamichud and all previous versions will be abandoned/not supported. -## The current version might be backported upto 1.16 fabric on demand. -## Only for fabric. -The reworked version could be found in the `newTrials` directory. - -# Demo: -### *May vary from version to version* -## Developed stage -> --- - -## Mid stage (1.2.0) -https://github.com/V-Fast/DynamicHUD/assets/120117618/2abfcdf5-d786-4e58-acae-aefe51b77b4a - - -## Early stages -https://github.com/V-Fast/DynamicHUD/assets/120117618/04de9319-69cd-4456-a555-c026c7e053a2 - - - - - - - - - - +**A library to display stuff on the screen. Fabric only** + +**Version:** `1.3.0` + +> ⚠ **IN PROGRESS** ⚠ +> +> This is a test branch for DynamicHUD 1.20.4. This branch will contain the majorly reworked version of DynamicHUD and all previous versions will be abandoned/not supported. +> +> The current version might be backported up to 1.16 fabric on demand. +> +> **Only for fabric.** +> +> The reworked version could be found in the `newTrials` directory. + +## Demo + +*May vary from version to version* + +### Developed stage +> In progress +--- + +### Mid stage (1.2.0) +
+ View Demo video + + [!Mid stage demo video](https://github.com/V-Fast/DynamicHUD/assets/120117618/2abfcdf5-d786-4e58-acae-aefe51b77b4a) +
+ +### Early stages +
+ View Demo video + + [!Early stage demo video](https://github.com/V-Fast/DynamicHUD/assets/120117618/04de9319-69cd-4456-a555-c026c7e053a2) +
From f4d09c985d53d8af0db1373c6b049f6ecbf20b21 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:27:50 +0530 Subject: [PATCH 06/33] version update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2b8b4a..9eb3d54 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ > In progress --- -### Mid stage (1.2.0) +### Mid stage (2.0.0)
View Demo video From 8b81bbae097fcefa9b166974dabe08c01da37b82 Mon Sep 17 00:00:00 2001 From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:28:19 +0530 Subject: [PATCH 07/33] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9eb3d54..474325a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **A library to display stuff on the screen. Fabric only** -**Version:** `1.3.0` +**Version:** `2.0.0` > ⚠ **IN PROGRESS** ⚠ > @@ -22,7 +22,7 @@ > In progress --- -### Mid stage (2.0.0) +### Mid stage (1.2.0)
View Demo video From 30ba53f27bbe217361e73f833f134248a23f2b30 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:40:55 +0530 Subject: [PATCH 08/33] New additions and version change --- gradle.properties | 2 +- .../dynamichud/DynamicHudIntegration.java | 74 +++++++++- .../dynamichud/mixins/ScreenMixin.java | 2 +- .../dynamichud/newTrial/DynamicHUD.java | 24 +++- .../dynamichud/newTrial/DynamicHudTest.java | 41 +++--- .../dynamichud/newTrial/HudRender.java | 14 ++ .../newTrial/config/GlobalConfig.java | 2 - .../screens/AbstractMoveableScreen.java | 25 +++- .../newTrial/utils/DynamicValueRegistry.java | 66 ++++++++- .../dynamichud/newTrial/widget/Widget.java | 133 ++++++++++-------- .../newTrial/widget/WidgetManager.java | 2 - .../newTrial/widget/WidgetRenderer.java | 33 +++-- .../newTrial/widgets/TextWidget.java | 22 ++- .../dynamichud/widget/WidgetBox.java | 13 +- src/main/resources/dynamichud.mixins.json | 2 - 15 files changed, 343 insertions(+), 112 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java diff --git a/gradle.properties b/gradle.properties index ba63423..6f22580 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.parallel=true loader_version=0.15.0 # Mod Properties - mod_version = 1.3 + mod_version = 2.0.0 maven_group = com.tanishisherewith archives_base_name = dynamichud diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java index d47d8a4..e92e3dc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud; -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -11,27 +11,83 @@ import java.io.File; +/** + * 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. + */ KeyBinding EDITOR_SCREEN_KEY_BINDING = KeyBindingHelper.registerKeyBinding(new KeyBinding( TRANSLATION_KEY, INPUT_TYPE, KEY, KEYBIND_CATEGORY )); + + /** + * The filename for the widgets file. + */ String FILENAME = "widgets.nbt"; + + /** + * The directory for the widgets file. + */ File FILE_DIRECTORY = FabricLoader.getInstance().getConfigDir().toFile(); + + /** + * The file where widgets are saved. + */ File WIDGETS_FILE = new File(FILE_DIRECTORY, FILENAME); + /** + * Initializes the DynamicHud integration. + *

+ * Suggested to be used to initialize {@link com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry} and widgets with their respective values + *

+ */ void init(); + + /** + * To be used to add widgets using {@link WidgetManager}. + */ void addWidgets(); - default void registerWidgets(){} /** - * Returns the file where widgets are saved. + * To register custom widgets. This method can be overridden by implementations. + */ + 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. * * @return The widgets file. */ @@ -39,10 +95,20 @@ default File getWidgetsFile() { return WIDGETS_FILE; } + /** + * Returns the movable screen for the DynamicHud. + * + * @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/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index d1e4259..023519c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -23,7 +23,7 @@ public abstract class ScreenMixin { @Inject(at = @At("TAIL"), method = "render") private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ - widgetRenderer.renderWidgets(context); + widgetRenderer.renderWidgets(context,mouseX,mouseY); } } @Inject(at = @At("HEAD"), method = "resize") diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index b73464d..0c3f85e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -1,14 +1,15 @@ package com.tanishisherewith.dynamichud.newTrial; import com.tanishisherewith.dynamichud.DynamicHudIntegration; -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; +import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; import com.tanishisherewith.dynamichud.util.DynamicUtil; import net.fabricmc.api.ClientModInitializer; 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; @@ -74,18 +75,20 @@ public void onInitializeClient() { }else{ DHIntegration.addWidgets(); } + DHIntegration.initAfter(); screen = DHIntegration.getMovableScreen(); + KeyBinding binding =DHIntegration.EDITOR_SCREEN_KEY_BINDING; + DHIntegration.registerCustomWidgets(); + WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); addWidgetRenderer(widgetRenderer); //Register events for rendering, saving, loading, and opening the hudEditor ClientTickEvents.START_CLIENT_TICK.register((client)-> { - System.out.println("TICK FOR : " + modId); - System.out.println(binding); - DynamicUtil.openDynamicScreen(binding, screen); + openDynamicScreen(binding, screen); }); // Save during exiting a world, server or Minecraft itself @@ -109,6 +112,8 @@ public void onInitializeClient() { ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> GlobalConfig.HANDLER.save()); ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> GlobalConfig.HANDLER.save()); Runtime.getRuntime().addShutdownHook(new Thread(() -> GlobalConfig.HANDLER.save())); + + HudRenderCallback.EVENT.register(new HudRender()); } private void saveWidgetsSafely(File widgetsFile) { try { @@ -118,5 +123,16 @@ private void saveWidgetsSafely(File widgetsFile) { throw new RuntimeException(e); } } + /** + * 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); + } + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index efad069..97b1582 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -1,64 +1,73 @@ package com.tanishisherewith.dynamichud.newTrial; import com.tanishisherewith.dynamichud.DynamicHudIntegration; -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.huds.MoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; import com.tanishisherewith.dynamichud.util.DynamicUtil; -import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.text.Text; -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; public class DynamicHudTest implements DynamicHudIntegration { TextWidget textWidget; + TextWidget Example2Widget; DynamicValueRegistry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); WidgetRenderer renderer; @Override public void init() { DynamicValueRegistry.registerGlobal("FPS",() -> "FPS: "+ DynamicHUD.MC.getCurrentFps()); - registry.registerLocal("FPS",()-> "FPS: "+ DynamicHUD.MC.getCurrentFps()); + registry.registerLocal("FPS",()-> "FPS C-DVR: "+ DynamicHUD.MC.getCurrentFps()); textWidget = new TextWidget.Builder() .setX(300) - .setY(60) + .setY(100) .setDraggable(true) .rainbow(false) .setDRKey("FPS") .setModID(DynamicHUD.MOD_ID) .shouldScale(false) .build(); + + Example2Widget = new TextWidget.Builder() + .setX(200) + .setY(100) + .setDraggable(true) + .rainbow(false) + .setDRKey("FPS") + .setDVR(registry) + .setModID(DynamicHUD.MOD_ID) + .shouldScale(false) + .build(); } @Override public void addWidgets() { WidgetManager.addWidget(textWidget); + WidgetManager.addWidget(Example2Widget); + } + public void initAfter(){ + List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); + + renderer = new WidgetRenderer(widgets); + renderer.shouldRenderInGameHud(true); + renderer.addScreen(TitleScreen.class); + renderer.addScreen(MultiplayerScreen.class); } @Override public AbstractMoveableScreen getMovableScreen() { - return new MoveableScreen(Text.of("Editor"),new DynamicUtil(DynamicHUD.MC)); + return new AbstractMoveableScreen(Text.literal("Editor"), renderer) {}; } @Override public WidgetRenderer getWidgetRenderer() { - // Get the widgets for this mod - List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); - - renderer = new WidgetRenderer(widgets); - renderer.shouldRenderInGameHud(true); - renderer.addScreen(TitleScreen.class); - renderer.addScreen(MultiplayerScreen.class); return renderer; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java new file mode 100644 index 0000000..bd842b0 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java @@ -0,0 +1,14 @@ +package com.tanishisherewith.dynamichud.newTrial; + +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; +import net.minecraft.client.gui.DrawContext; + +public class HudRender implements HudRenderCallback { + @Override + public void onHudRender(DrawContext drawContext, float tickDelta) { + for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ + widgetRenderer.renderWidgets(drawContext,-120,-120); + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java index 22ae290..a7a25cc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java @@ -2,11 +2,9 @@ import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; -import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder; 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.gui.controllers.slider.FloatSliderController; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index 4908b11..c42fd6c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -1,7 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.screens; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; -import com.tanishisherewith.dynamichud.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; @@ -9,7 +8,7 @@ public abstract class AbstractMoveableScreen extends Screen { protected boolean ShouldPause = false; // To pause if the screen is opened or not public final WidgetRenderer widgetRenderer; - + public int snapSize = 120; /** * Constructs a AbstractMoveableScreen object. @@ -22,7 +21,7 @@ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - widgetRenderer.mouseDragged(mouseX,mouseY,button); + widgetRenderer.mouseDragged(mouseX,mouseY,button, snapSize); return false; } @@ -38,6 +37,24 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { return false; } + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + widgetRenderer.keyPressed(keyCode); + return super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public boolean keyReleased(int keyCode, int scanCode, int modifiers) { + widgetRenderer.keyReleased(keyCode); + return super.keyReleased(keyCode, scanCode, modifiers); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + widgetRenderer.mouseScrolled(mouseX,mouseY,verticalAmount,horizontalAmount); + return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + } + /** * Renders this screen and its widgets on the screen. * @@ -52,7 +69,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) // Draw each widget widgetRenderer.isInEditor = true; - widgetRenderer.renderWidgets(drawContext); + widgetRenderer.renderWidgets(drawContext,mouseX,mouseY); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java index 43d62da..393a969 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java @@ -3,24 +3,79 @@ import java.util.*; 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. + *

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

+ *     {@code
+ *     DynamicValueRegistry dvr = new DynamicValueRegistry("mod_id");
+ *     dvr.registerGlobal("ABC",//YourSupplier);
+ *     Supplier result = dvr.get("ABC");
+ *     }
+ * 
+ *

+ */ public class DynamicValueRegistry extends System { + /** + * A map that holds the global registry of suppliers. + * @see #localRegistry + */ private static final Map> globalRegistry = new HashMap<>(); + + /** + * A map that holds the local registry of suppliers. + * @see #globalRegistry + */ 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. + */ public DynamicValueRegistry(String modId) { super(modId); instances.computeIfAbsent(modId, k -> new ArrayList<>()).add(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. + */ public static void registerGlobal(String key, Supplier supplier) { globalRegistry.put(key, supplier); } + /** + * 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. + */ public void registerLocal(String key, Supplier supplier) { localRegistry.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. + */ public static Supplier getGlobal(String key) { return globalRegistry.get(key); } + /** + * 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. + */ public Supplier get(String key) { // First, try to get the supplier from the local registry Supplier supplier = localRegistry.get(key); @@ -32,8 +87,13 @@ public Supplier get(String key) { return supplier; } - public void setLocalRegistry(Map> map){ - localRegistry.putAll(map); - } + /** + * Sets the local registry to the given map. + * + * @param map The map to be set as the local registry. + */ + public void setLocalRegistry(Map> map){ + localRegistry.putAll(map); + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 4f1ea10..7e99b82 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -8,6 +8,9 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.math.MathHelper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.lwjgl.glfw.GLFW; import java.util.Set; @@ -30,10 +33,10 @@ public abstract class Widget { public boolean shiftDown = false; // Used for dragging and snapping - int startX, startY, snapSize = 120; + int startX, startY; // Absolute position of the widget on screen in pixels. - public int x,y; + public int x, y; // 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; @@ -46,9 +49,9 @@ public abstract class Widget { protected WidgetBox widgetBox; public static WidgetData DATA; - public Widget(WidgetData DATA, String modId){ + public Widget(WidgetData DATA, String modId) { Widget.DATA = DATA; - widgetBox = new WidgetBox(0,0,0,0,1); + widgetBox = new WidgetBox(0, 0, 0, 0, 1); this.modId = modId; init(); } @@ -56,9 +59,10 @@ public Widget(WidgetData DATA, String modId){ /** * This method is called at the end of the {@link Widget#Widget(WidgetData)} constructor. */ - public void init(){ + public void init() { } + /** * Returns the x position of the widget. * @@ -77,14 +81,15 @@ public int getY() { return y; } - public float getWidth(){ + public float getWidth() { return widgetBox.getWidth(); } - public float getHeight(){ + + public float getHeight() { return widgetBox.getHeight(); } - public void setPosition(int x, int y){ + public void setPosition(int x, int y) { this.x = x; this.y = y; } @@ -92,6 +97,7 @@ public void setPosition(int x, int y){ 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() && @@ -110,36 +116,37 @@ public boolean isOverlapping(Widget other) { /** * Renders the widget on the screen. */ - public void render(DrawContext drawContext){ - if(!shouldDisplay())return; + public void render(DrawContext drawContext) { + if (!shouldDisplay()) return; - if(shouldScale) { + if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); - scale(GlobalConfig.get().scale); } renderWidget(drawContext); + updateWidgetBox(); - if(shouldScale){ - reverseScale(GlobalConfig.get().scale); + if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } } + /** * Renders the widget on the editor screen. */ - public void renderInEditor(DrawContext drawContext){ - if(shouldScale) { + public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { + if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); - scale(GlobalConfig.get().scale); } - renderWidgetInEditor(drawContext); + updateWidgetBox(); - if(shouldScale){ - reverseScale(GlobalConfig.get().scale); + if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } } + protected void updateWidgetBox(){ + widgetBox.setSizeAndPosition(x,y,getWidth(),getHeight()); + } /** @@ -157,49 +164,68 @@ public void renderInEditor(DrawContext drawContext){ * * @param context */ - private void renderWidgetInEditor(DrawContext context){ + private void renderWidgetInEditor(DrawContext context) { displayBg(context); renderWidget(context); } - public void mouseClicked(double mouseX, double mouseY, int button){ - if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT){ + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { toggle(); - } - } - public void mouseDragged(double mouseX, double mouseY, int button){ - if(this.isDraggable && button == GLFW.GLFW_MOUSE_BUTTON_LEFT){ - //Start dragging startX = (int) (mouseX - x); startY = (int) (mouseY - y); dragging = true; - this.x = startX; - this.y = startY; + return true; + } + return false; + } + + public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { + if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { + int newX = (int) (mouseX - startX); + int newY = (int) (mouseY - startY); - // Divides the screen into several "grid boxes" which the elements snap to. Higher the snapSize, more the grid boxes + // Divides the screen into several "grid boxes" which the elements snap to. + // Higher the snapSize, more the grid boxes if (this.shiftDown) { // Calculate the size of each snap box - int snapBoxWidth = (int) (widgetBox.getWidth() / this.snapSize); - int snapBoxHeight = (int) (widgetBox.getHeight() / this.snapSize); + int snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; + int snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; - // Calculate the index of the snap box that the mouse is currently in - int snapBoxX = (int) (mouseX / snapBoxWidth); - int snapBoxY = (int) (mouseY / snapBoxHeight); + // Calculate the index of the snap box that the new position would be in + int snapBoxX = newX / snapBoxWidth; + int snapBoxY = newY / snapBoxHeight; - // Snap the element to the top-left corner of the snap box - this.x = snapBoxX * snapBoxWidth; - this.y = snapBoxY * snapBoxHeight; + // Snap the new position to the top-left corner of the snap box + newX = snapBoxX * snapBoxWidth; + newY = snapBoxY * snapBoxHeight; } + + this.x = (int) MathHelper.clamp(newX, 0, mc.getWindow().getWidth() - getWidth()); + this.y = (int) MathHelper.clamp(newY, 0, mc.getWindow().getHeight() - getHeight()); + + return true; } + return false; } + public void mouseReleased(double mouseX, double mouseY, int button) { dragging = false; } + /** + * MouseScrolled event + * + * @param vAmount vertical amount of scrolling + * @param hAmount horizontal amount of scrolling + */ + public void mouseScrolled(double mouseX, double mouseY, double vAmount,double hAmount) { + } - public boolean toggle(){ - return this.display = !this.display; + + public boolean toggle() { + return this.display = !this.display; } /** @@ -208,7 +234,7 @@ public boolean toggle(){ * * @param context */ - protected void displayBg(DrawContext context){ + protected void displayBg(DrawContext context) { int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); WidgetBox box = this.getWidgetBox(); DrawHelper.fill(context, (int) (box.x1 - 2), (int) (box.y1 - 2), (int) (box.x2 + 2), (int) (box.y2 + 2), backgroundColor); @@ -232,7 +258,7 @@ public void readFromTag(NbtCompound tag) { */ public void writeToTag(NbtCompound tag) { tag.putString("name", DATA.name()); - tag.putString("modId",modId); + tag.putString("modId", modId); tag.putString("UID", uid.getUniqueID()); tag.putBoolean("isDraggable", isDraggable); tag.putBoolean("shouldScale", shouldScale); @@ -268,25 +294,21 @@ public void setShouldScale(boolean shouldScale) { public String getModId() { return modId; } - public void scale(float scale) { - this.xPercent *= scale; - this.yPercent *= scale; - } - public void reverseScale(float scale) { - this.xPercent /= scale; - this.yPercent /= scale; - } @Override public String toString() { return "Widget{" + "uniqueId='" + uid.getUniqueID() + '\'' + - ", xPercent=" + xPercent + - ", yPercent=" + yPercent + + ", x=" + x + + ", y=" + y + ", display=" + display + + ", isDraggable=" + isDraggable + + ", shiftDown=" + shiftDown + + ", shouldScale=" + shouldScale + '}'; } - public abstract static class WidgetBuilder { + + public abstract static class WidgetBuilder { protected int x; protected int y; protected boolean display = true; @@ -333,6 +355,7 @@ public T shouldScale(boolean shouldScale) { this.shouldScale = shouldScale; return self(); } + public T setModID(String modID) { this.modID = modID; return self(); @@ -340,7 +363,7 @@ public T setModID(String modID) { /** * Method to be overridden in subclasses to return "this" correctly - */ + */ protected abstract T self(); /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 02f384c..c419e74 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.widget; import java.io.*; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.*; import com.tanishisherewith.dynamichud.DynamicHUD; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index fffdd2d..0304a81 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -1,10 +1,7 @@ package com.tanishisherewith.dynamichud.newTrial.widget; import com.tanishisherewith.dynamichud.DynamicHUD; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.widget.WidgetBox; +import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import org.lwjgl.glfw.GLFW; @@ -17,6 +14,7 @@ public class WidgetRenderer { private boolean renderInGameHud = true; public boolean isInEditor = false; List widgets; + public Widget selectedWidget = null; public WidgetRenderer(List widgets){ this.widgets = widgets; } @@ -32,7 +30,7 @@ public void shouldRenderInGameHud(boolean renderInGameHud) { this.renderInGameHud = renderInGameHud; } - public void renderWidgets(DrawContext context) { + public void renderWidgets(DrawContext context, int mouseX, int mouseY) { if(WidgetManager.getWidgets().isEmpty()) return; Screen currentScreen = DynamicHUD.MC.currentScreen; @@ -47,7 +45,7 @@ public void renderWidgets(DrawContext context) { if(currentScreen instanceof AbstractMoveableScreen){ for (Widget widget : widgets) { widget.isInEditor = true; - widget.renderInEditor(context); + widget.renderInEditor(context,mouseX,mouseY); } return; } @@ -65,18 +63,35 @@ public void mouseClicked(double mouseX, double mouseY, int button){ } if(currentScreen instanceof AbstractMoveableScreen){ for (Widget widget : widgets) { - widget.mouseClicked(mouseX,mouseY,button); + if(widget.mouseClicked(mouseX,mouseY,button)){ + selectedWidget = widget; + return; + } } } } - public void mouseDragged(double mouseX, double mouseY, int button){ + public void mouseDragged(double mouseX, double mouseY, int button, int snapSize){ Screen currentScreen = DynamicHUD.MC.currentScreen; if(currentScreen == null) { return; } if(currentScreen instanceof AbstractMoveableScreen){ for (Widget widget : widgets) { - widget.mouseDragged(mouseX,mouseY,button); + if(widget.mouseDragged(mouseX,mouseY,button,snapSize)){ + selectedWidget = widget; + return; + } + } + } + } + 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) { + widget.mouseScrolled(mouseX,mouseY,vAmount,hAmount); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 0c816a1..0a08599 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -1,7 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.widgets; import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; @@ -14,8 +13,8 @@ public class TextWidget extends Widget { public static WidgetData DATA = new WidgetData<>("TextWidget","Display Text on screen",TextWidget::new); Supplier textSupplier; - String dynamicRegistryKey; - DynamicValueRegistry dynamicValueRegistry; + String dynamicRegistryKey = ""; + DynamicValueRegistry dynamicValueRegistry = null; protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text @@ -60,7 +59,7 @@ public void renderWidget(DrawContext drawContext) { if(textSupplier != null) { String text = textSupplier.get(); drawContext.drawText(mc.textRenderer, text, (int) getX(), (int)getY(), color, shadow); - widgetBox.setSize(getX() - 2,getY() - 2,mc.textRenderer.getWidth(text) + 2,mc.textRenderer.fontHeight + 2); + widgetBox.setSizeAndPosition(getX() - 2,getY() - 2,mc.textRenderer.getWidth(text) + 2,mc.textRenderer.fontHeight + 2); } } @@ -70,6 +69,9 @@ public void writeToTag(NbtCompound tag) { tag.putString("DRKey",dynamicRegistryKey); tag.putBoolean("shadow",shadow); tag.putBoolean("rainbow",rainbow); + + // If true then it means that we should use local registry and if false (i.e. null) then use global registry + tag.putBoolean("DVRObj", dynamicValueRegistry != null); } @Override @@ -79,9 +81,19 @@ public void readFromTag(NbtCompound tag) { rainbow = tag.getBoolean("rainbow"); dynamicRegistryKey = tag.getString("DRKey"); + // 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("DVRObj"); + + if(!dvrObj && dynamicRegistryKey != null){ + 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 textSupplier = (Supplier) dvr.get(dynamicRegistryKey); - break; + return; } } public static class Builder extends WidgetBuilder { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index fd845fa..578393f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -1,8 +1,8 @@ package com.tanishisherewith.dynamichud.widget; public class WidgetBox { - private final float width; - private final float height; + private float width; + private float height; public float x1 = 0, x2 = 0, y1 = 0, y2 = 0; public WidgetBox(float x1, float y1, float x2, float y2, float scale) { @@ -33,9 +33,12 @@ public boolean contains(Widget widget, double x, double y, float scale) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; } - public boolean intersects(float otherX1, float otherY1, float otherX2, float otherY2, float scale) { + public boolean intersects(float otherX1, float otherY1, float otherX2, float otherY2) { return !(otherX1 > x2 || otherX2 < x1 || otherY1 > y2 || otherY2 < y1); } + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseX >= x1 && mouseX <= x2 && mouseY >= y1 && mouseY <= y2; + } public float getWidth() { return width; @@ -44,11 +47,13 @@ public float getWidth() { public float getHeight() { return height; } - public void setSize(float x,float y, float width, float height){ + public void setSizeAndPosition(float x, float y, float width, float height){ this.x1 = x; this.x2 = x + width; this.y1 = y; this.y2 = y + height; + this.height = height; + this.width = width; } public void setPosition(float x,float y, float x2, float y2){ this.x1 = x; diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json index a6212c5..2dc77ad 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -9,8 +9,6 @@ "defaultRequire": 1 }, "client": [ - "KeyboardMixin", - "MouseMixin", "OptionsScreenMixin", "ScreenMixin" ] From 762d88ec90e1f8106294ec4203a1521dc8669bb8 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 6 Apr 2024 12:33:59 +0530 Subject: [PATCH 09/33] Better saving system and further ContextMenu layout --- .../dynamichud/newTrial/DynamicHUD.java | 12 ++++---- .../dynamichud/newTrial/utils/Util.java | 29 +++++++++++++++++++ .../utils/contextmenu/ContextMenu.java | 4 +++ .../newTrial/utils/contextmenu/Option.java | 4 +++ .../dynamichud/newTrial/widget/Widget.java | 19 +++++++----- .../newTrial/widget/WidgetManager.java | 25 +++++++++++++--- .../newTrial/widget/WidgetRenderer.java | 4 +-- .../newTrial/widgets/TextWidget.java | 10 +++---- 8 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 0c3f85e..f19e65f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -24,9 +24,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CountDownLatch; public class DynamicHUD implements ClientModInitializer { - public static MinecraftClient MC = MinecraftClient.getInstance(); public static String MOD_ID = "dynamichud"; private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); @@ -60,7 +60,9 @@ public void onInitializeClient() { GlobalConfig.HANDLER.load(); printInfo("Integrating mods..."); - FabricLoader.getInstance().getEntrypointContainers("dynamicHud", DynamicHudIntegration.class).forEach(entrypoint -> { + FabricLoader.getInstance() + .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class) + .forEach(entrypoint -> { ModMetadata metadata = entrypoint.getProvider().getMetadata(); String modId = metadata.getId(); AbstractMoveableScreen screen; @@ -92,18 +94,18 @@ public void onInitializeClient() { }); // Save during exiting a world, server or Minecraft itself + // Also saved when a resource pack is reloaded. ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile)); ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile)); ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile)); Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile))); - printInfo(String.format("Integration of mod %s was successful",modId)); } catch (Throwable e) { if(e instanceof IOException){ - logger.warn("An error has occured while loading widgets of mod {}", modId,e); + logger.warn("An error has occurred while loading widgets of mod {}", modId,e); }else { - logger.warn("Mod {} has incorrect implementation of dynamicHud", modId, e); + logger.warn("Mod {} has incorrect implementation of DynamicHUD", modId, e); } } }); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java new file mode 100644 index 0000000..0bfe69b --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java @@ -0,0 +1,29 @@ +package com.tanishisherewith.dynamichud.newTrial.utils; + +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; + +public class Util { + public enum Quadrant { + UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT + } + + public static Quadrant getQuadrant(int x, int y) { + int screenWidth = DynamicHUD.MC.getWindow().getScaledWidth(); + int screenHeight = DynamicHUD.MC.getWindow().getScaledHeight(); + + if (x < screenWidth / 2) { + if (y < screenHeight / 2) { + return Quadrant.UPPER_LEFT; + } else { + return Quadrant.BOTTOM_LEFT; + } + } else { + if (y < screenHeight / 2) { + return Quadrant.UPPER_RIGHT; + } else { + return Quadrant.BOTTOM_RIGHT; + } + } + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java new file mode 100644 index 0000000..3072fc9 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -0,0 +1,4 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; + +public class ContextMenu { +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java new file mode 100644 index 0000000..54d5c97 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -0,0 +1,4 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; + +public abstract class Option { +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 7e99b82..6c7061e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -116,14 +116,13 @@ public boolean isOverlapping(Widget other) { /** * Renders the widget on the screen. */ - public void render(DrawContext drawContext) { + public void render(DrawContext drawContext, int mouseX, int mouseY) { if (!shouldDisplay()) return; if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); } - renderWidget(drawContext); - updateWidgetBox(); + renderWidget(drawContext,mouseX,mouseY); if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); @@ -137,8 +136,7 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); } - renderWidgetInEditor(drawContext); - updateWidgetBox(); + renderWidgetInEditor(drawContext,mouseX,mouseY); if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); @@ -151,10 +149,15 @@ protected void updateWidgetBox(){ /** * Renders the widget on the screen + *

+ * The mouse position values are only passed when in a {@link com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen} screen. + *

* * @param context + * @param mouseX X position of mouse. + * @param mouseY Y position of mouse */ - public abstract void renderWidget(DrawContext context); + public abstract void renderWidget(DrawContext context,int mouseX, int mouseY); /** @@ -164,10 +167,10 @@ protected void updateWidgetBox(){ * * @param context */ - private void renderWidgetInEditor(DrawContext context) { + private void renderWidgetInEditor(DrawContext context,int mouseX, int mouseY) { displayBg(context); - renderWidget(context); + renderWidget(context,mouseX,mouseY); } public boolean mouseClicked(double mouseX, double mouseY, int button) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index c419e74..8fa8276 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -1,6 +1,8 @@ package com.tanishisherewith.dynamichud.newTrial.widget; import java.io.*; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.*; import com.tanishisherewith.dynamichud.DynamicHUD; @@ -164,18 +166,32 @@ public static void saveWidgets(File file) throws IOException { widget.writeToTag(widgetTag); // Check for duplicates if (widgetSet.add(widgetTag.toString())) { + printInfo("Saving Widget: " + widget); widgetList.add(widgetTag); } } rootTag.put("widgets", widgetList); - //Write the data to the file - try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) { + // Backup the old file + File backupFile = new File(file.getAbsolutePath() + ".bak"); + if (file.exists()) { + Files.copy(file.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + // Write the data to a temporary file + File tempFile = new File(file.getAbsolutePath() + ".tmp"); + try (DataOutputStream out = new DataOutputStream(new FileOutputStream(tempFile))) { NbtIo.write(rootTag, out); - }catch (IOException e){ - DynamicHUD.logger.warn("Error while saving",e); + } catch (IOException e) { + DynamicHUD.logger.warn("Error while saving", e); + // If save operation failed, restore the backup + Files.move(backupFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); + throw e; // rethrow the exception } + + // If save operation was successful, replace the old file with the new one + Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); } /** @@ -195,6 +211,7 @@ public static void loadWidgets(File file) throws IOException { WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); Widget widget = widgetData.createWidget(); widget.readFromTag(widgetTag); + printInfo("Loading Widget: " + widget); widgets.add(widget); } }else{ diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index 0304a81..581c0bc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -38,7 +38,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { if(currentScreen == null && renderInGameHud){ for (Widget widget : widgets) { widget.isInEditor = false; - widget.render(context); + widget.render(context,0,0); } return; } @@ -52,7 +52,7 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) { if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass()) && !this.isInEditor) { for (Widget widget : widgets) { widget.isInEditor = false; - widget.render(context); + widget.render(context,0,0); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 0a08599..dc8f2cf 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -54,7 +54,7 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist } @Override - public void renderWidget(DrawContext drawContext) { + public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / 10000f) : Color.WHITE.getRGB(); if(textSupplier != null) { String text = textSupplier.get(); @@ -66,12 +66,12 @@ public void renderWidget(DrawContext drawContext) { @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); - tag.putString("DRKey",dynamicRegistryKey); + tag.putString("DynamicRegistryKey",dynamicRegistryKey); tag.putBoolean("shadow",shadow); tag.putBoolean("rainbow",rainbow); // If true then it means that we should use local registry and if false (i.e. null) then use global registry - tag.putBoolean("DVRObj", dynamicValueRegistry != null); + tag.putBoolean("DynamicValueRegistry", dynamicValueRegistry != null); } @Override @@ -79,10 +79,10 @@ public void readFromTag(NbtCompound tag) { super.readFromTag(tag); shadow = tag.getBoolean("shadow"); rainbow = tag.getBoolean("rainbow"); - dynamicRegistryKey = tag.getString("DRKey"); + 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("DVRObj"); + boolean dvrObj = tag.getBoolean("DynamicValueRegistry"); if(!dvrObj && dynamicRegistryKey != null){ textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); From b338fd5aa0368b516c2f57023437cde98af450a1 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:01:11 +0530 Subject: [PATCH 10/33] Fixed scaling. ContextMenu and options. More stuff --- .../dynamichud/helpers/DrawHelper.java | 27 +++- .../dynamichud/newTrial/DynamicHudTest.java | 2 +- .../screens/AbstractMoveableScreen.java | 8 +- .../utils/contextmenu/ContextMenu.java | 135 ++++++++++++++++++ .../newTrial/utils/contextmenu/Option.java | 55 +++++++ .../contextmenu/options/BooleanOption.java | 39 +++++ .../dynamichud/newTrial/widget/Widget.java | 17 ++- .../newTrial/widget/WidgetManager.java | 4 +- .../newTrial/widget/WidgetRenderer.java | 2 +- .../newTrial/widgets/TextWidget.java | 43 ++++++ .../util/contextmenu/ContextMenu.java | 1 - .../dynamichud/widget/WidgetBox.java | 6 + 12 files changed, 321 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index b87dd3e..e925221 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -210,9 +210,9 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int } /** - * This method assumes that the element is widget in the top-left corner (i.e. all drawing happens with respect to the top-left corner). - * @param x X position of top-left corner of widget - * @param y Y position of top-left corner of widget + * This method assumes that the x, y coords are the origin of a widget. + * @param x X position of widget + * @param y Y position of widget * @param scale Scale the matrices */ public static void scaleAndPosition(MatrixStack matrices, float x, float y, float scale) { @@ -223,6 +223,27 @@ public static void scaleAndPosition(MatrixStack matrices, float x, float y, floa // Scale the matrix matrices.scale(scale, scale, 1.0F); + + matrices.translate(-x,-y,0); + } + /** + * This method scales the matrices by the centre of the widget + * @param x X position of widget + * @param y Y position of widget + * @param height height of widget + * @param width width of widget + * @param scale Scale the matrices + */ + public static void scaleAndPosition(MatrixStack matrices, float x, float y,float width, float height, float scale) { + matrices.push(); // Save the current transformation state + + // Translate the origin back to the desired position + matrices.translate(x + width / 2.0f, y + height / 2.0f, 0); + + // Scale the matrix + matrices.scale(scale, scale, 1.0F); + + matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f), 0); } public static void stopScaling(MatrixStack matrices){ diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index 97b1582..2cea9bd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -43,7 +43,7 @@ public void init() { .setDRKey("FPS") .setDVR(registry) .setModID(DynamicHUD.MOD_ID) - .shouldScale(false) + .shouldScale(true) .build(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index c42fd6c..433be03 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -8,7 +8,7 @@ public abstract class AbstractMoveableScreen extends Screen { protected boolean ShouldPause = false; // To pause if the screen is opened or not public final WidgetRenderer widgetRenderer; - public int snapSize = 120; + public int snapSize = 100; /** * Constructs a AbstractMoveableScreen object. @@ -65,8 +65,9 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou */ @Override public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { - super.render(drawContext, mouseX, mouseY, delta); - + if(this.client.world == null) { + this.renderBackgroundTexture(drawContext); + } // Draw each widget widgetRenderer.isInEditor = true; widgetRenderer.renderWidgets(drawContext,mouseX,mouseY); @@ -76,6 +77,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) public void close() { super.close(); widgetRenderer.isInEditor = false; + widgetRenderer.onCloseScreen(); } public void setShouldPause(boolean shouldPause) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index 3072fc9..b1702e5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -1,4 +1,139 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.widget.Widget; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + public class ContextMenu { + public int x,y; + protected float scale = 0.0f; + private final List> options = new ArrayList<>(); // The list of options in the context menu + private Widget selectedWidget; // The widget that this context menu is associated with + public int width = 0; + public int height = 0; + public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light grey color + 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 ContextMenu(int x,int y, int width, int height, Widget selectedWidget){ + this.x = x; + this.y = y + heightOffset; + this.width = width; + this.height = height; + this.selectedWidget = selectedWidget; + } + + public void addOption(Option option){ + options.add(option); + } + + public void render(DrawContext drawContext, int x, int y, int height){ + this.x = x; + this.y = y + heightOffset + height; + if(!shouldDisplay) return; + + update(); + DrawHelper.scaleAndPosition(drawContext.getMatrices(),x,y,scale); + + int x1 = this.x - 1; + int y1 = this.y; + int x2 = this.x + width; + int y2 = this.y + this.height; + + // Draw the background + DrawHelper.drawCutRectangle(drawContext, x1, y1, x2, y2, 0, backgroundColor, 1); + + int yOffset = y1 + 3; + this.width = 10; + for(Option option: options){ + option.render(drawContext,x + 2,yOffset); + this.width = Math.max(this.width, option.width + padding); + yOffset += option.height + 1; + } + this.width = this.width + 3; + this.height = (yOffset - y1); + + DrawHelper.stopScaling(drawContext.getMatrices()); + } + public void update() { + // Update the scale + float scaleSpeed = 0.1f; + scale += scaleSpeed; + if (scale > 1.0f) { + scale = 1.0f; + } + } + + public void close(){ + shouldDisplay = false; + scale = 0.0f; + } + public void open(){ + shouldDisplay = true; + update(); + } + public void toggleDisplay(){ + if(shouldDisplay){ + close(); + }else{ + open(); + } + } + + public void mouseClicked(double mouseX, double mouseY, int button){ + if(!shouldDisplay) return; + for(Option option: options){ + option.mouseClicked(mouseX, mouseY, button); + } + } + public void mouseReleased(double mouseX, double mouseY, int button){ + if(!shouldDisplay) return; + for(Option option: options){ + option.mouseReleased(mouseX, mouseY, button); + } + } + public void mouseDragged(double mouseX, double mouseY, int button){ + if(!shouldDisplay) return; + for(Option option: options){ + option.mouseDragged(mouseX, mouseY, button); + } + } + public void keyPressed(int key){ + if(!shouldDisplay) return; + for(Option option: options){ + option.keyPressed(key); + } + } + public void keyReleased(int key){ + if(!shouldDisplay) return; + for(Option option: options){ + option.keyReleased(key); + } + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getWidth() { + return width; + } + + public List> getOptions() { + return options; + } + + public int getHeight() { + return height; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java index 54d5c97..9c8772e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -1,4 +1,59 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; +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 int x,y; + protected float scale = 0.0f; + private Widget selectedWidget; // The widget that this context menu is associated with + public int width = 0; + public int height = 0; + protected Supplier getter; + protected Consumer setter; + public T value = null; + protected T defaultValue = null; + protected MinecraftClient mc = MinecraftClient.getInstance(); + + public Option(Supplier getter, Consumer setter){ + this.getter = getter; + this.setter = setter; + value = get(); + defaultValue = get(); + } + + protected T get(){ + return getter.get(); + } + protected void set(T value){ + setter.accept(value); + } + + public void render(DrawContext drawContext, int x, int y){ + this.x = x; + this.y = y; + } + + public boolean mouseClicked(double mouseX, double mouseY, int button){ + return isMouseOver(mouseX, mouseY); + } + public boolean mouseReleased(double mouseX, double mouseY, int button){ + return isMouseOver(mouseX, mouseY); + } + public boolean mouseDragged(double mouseX, double mouseY, int button){ + return isMouseOver(mouseX, mouseY); + } + public void keyPressed(int key){ + + } + public void keyReleased(int key){ + + } + 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/newTrial/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java new file mode 100644 index 0000000..d7f9fb6 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java @@ -0,0 +1,39 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.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; + +public class BooleanOption extends Option { + public String name = "Empty"; + + public BooleanOption(String name, Supplier getter, Consumer setter) { + super(getter, setter); + this.name = name; + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + value = get(); + 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)) { + value = !value; + set(value); + } + return true; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 6c7061e..04504ec 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -9,8 +9,6 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.MathHelper; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.lwjgl.glfw.GLFW; import java.util.Set; @@ -120,7 +118,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { if (!shouldDisplay()) return; if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); } renderWidget(drawContext,mouseX,mouseY); @@ -134,7 +132,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { */ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); } renderWidgetInEditor(drawContext,mouseX,mouseY); @@ -205,8 +203,12 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi newY = snapBoxY * snapBoxHeight; } - this.x = (int) MathHelper.clamp(newX, 0, mc.getWindow().getWidth() - getWidth()); - this.y = (int) MathHelper.clamp(newY, 0, mc.getWindow().getHeight() - getHeight()); + 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.getX() / mc.getWindow().getScaledWidth(); + this.yPercent = (float) this.getY() / mc.getWindow().getScaledHeight(); return true; } @@ -230,6 +232,9 @@ public void mouseScrolled(double mouseX, double mouseY, double vAmount,double hA public boolean toggle() { return this.display = !this.display; } + public void onClose(){ + this.shiftDown = false; + } /** * Displays a faint grayish background if enabled or faint reddish background if disabled. diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 8fa8276..37458bc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -117,7 +117,6 @@ 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 coords is not returned if(widget.xPercent <= 0f){ widget.xPercent = (float) widget.getX()/previousWidth; @@ -136,7 +135,6 @@ public static void onScreenResized(int newWidth, int newHeight, int previousWidt // Update the widget's position widget.setPosition(newX, newY); - // Update the stored percentages with the new screen size (after resize). widget.xPercent = (float) widget.getX() / newWidth; widget.yPercent = (float) widget.getY() / newHeight; @@ -174,7 +172,7 @@ public static void saveWidgets(File file) throws IOException { rootTag.put("widgets", widgetList); // Backup the old file - File backupFile = new File(file.getAbsolutePath() + ".bak"); + File backupFile = new File(file.getAbsolutePath() + ".backup"); if (file.exists()) { Files.copy(file.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index 581c0bc..3f0e2cd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -115,7 +115,7 @@ public void keyReleased(int keyCode){ public void onCloseScreen(){ if(DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen){ for (Widget widget : widgets) { - widget.shiftDown = false; + widget.onClose(); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index dc8f2cf..06796ab 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -2,10 +2,13 @@ import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; +import org.lwjgl.glfw.GLFW; import java.awt.*; import java.util.function.Supplier; @@ -17,6 +20,7 @@ public class TextWidget extends Widget { DynamicValueRegistry dynamicValueRegistry = null; protected boolean shadow; // Whether to draw a shadow behind the text protected boolean rainbow; // Whether to apply a rainbow effect to the text + private ContextMenu menu; public TextWidget() { this(null,false,false,"unknown"); @@ -35,6 +39,9 @@ public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,Str textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; + menu = new ContextMenu(getX(),getY(),20,20,null); + menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); + menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); } /** @@ -51,10 +58,14 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; + menu = new ContextMenu(getX(),getY(),20,20,null); + menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); + menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); } @Override public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { + menu.render(drawContext, getX() - 2,getY(), (int) Math.ceil(getHeight())); int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / 10000f) : Color.WHITE.getRGB(); if(textSupplier != null) { String text = textSupplier.get(); @@ -63,6 +74,33 @@ 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.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); + } + + @Override + public void onClose() { + super.onClose(); + menu.close(); + } + @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); @@ -93,8 +131,13 @@ public void readFromTag(NbtCompound tag) { //Unfortunately, this method takes the value from the first local registry with the key. //It returns to prevent overriding with other registries textSupplier = (Supplier) dvr.get(dynamicRegistryKey); + System.out.println(dvr); + System.out.println(DynamicValueRegistry.getInstances(modId)); return; } + menu = new ContextMenu(getX(),getY(),20,20,null); + menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); + menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); } public static class Builder extends WidgetBuilder { protected boolean shadow = false; diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java index e76e540..4b6275f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java @@ -287,7 +287,6 @@ private void drawOptions(DrawContext drawContext, TextRenderer textRenderer) { int boxWidth = valueTextWidth + 2; int boxHeight = textRenderer.fontHeight + 1; DrawHelper.fill(drawContext, boxX, boxY, boxX + boxWidth, boxY + boxHeight, 0x7F000000); - } } else if (option instanceof DoubleInputOption) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index 578393f..f44e8af 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -55,6 +55,12 @@ public void setSizeAndPosition(float x, float y, float width, float height){ this.height = height; this.width = width; } + public void setSize(double width, double height) { + if (width >= 0) + this.width = (int) Math.ceil(width); + if (height >= 0) + this.height = (int) Math.ceil(height); + } public void setPosition(float x,float y, float x2, float y2){ this.x1 = x; this.x2 = x2; From ea86f314befb2237ca8bebcad923b7e1e23aa356 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:12:58 +0530 Subject: [PATCH 11/33] More changes and fixes. Also DoubleOption. Enum option will be next and final. --- .../dynamichud/mixins/OptionsScreenMixin.java | 38 -------- .../dynamichud/mixins/ScreenMixin.java | 4 +- .../dynamichud/newTrial/DynamicHudTest.java | 6 +- .../screens/AbstractMoveableScreen.java | 2 +- .../utils/contextmenu/ContextMenu.java | 4 +- .../newTrial/utils/contextmenu/Option.java | 1 + .../contextmenu/options/DoubleOption.java | 91 +++++++++++++++++++ .../dynamichud/newTrial/widget/Widget.java | 15 ++- .../newTrial/widget/WidgetManager.java | 2 +- .../newTrial/widget/WidgetRenderer.java | 14 +++ .../newTrial/widgets/TextWidget.java | 28 +++--- src/main/resources/dynamichud.mixins.json | 1 - 12 files changed, 145 insertions(+), 61 deletions(-) delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java deleted file mode 100644 index a3f274a..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.tanishisherewith.dynamichud.mixins; - - -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.slider.ScaleSliderWidget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.option.OptionsScreen; -import net.minecraft.client.gui.widget.EmptyWidget; -import net.minecraft.client.gui.widget.GridWidget; -import net.minecraft.client.gui.widget.SimplePositioningWidget; -import net.minecraft.client.option.GameOptions; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.text.DecimalFormat; -@Mixin(OptionsScreen.class) -public class OptionsScreenMixin extends Screen { - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); - - protected OptionsScreenMixin(Text title) { - super(title); - } - - @Inject(at = @At("TAIL"), method = "init") - public void addButtons(CallbackInfo ci) { - int width = 100; - int height = 20; - int x = this.width - width - 10; - int y = this.height - height- 5; - String formattedValue = DECIMAL_FORMAT.format(Widget.getScale()); - ScaleSliderWidget scaleSlider = new ScaleSliderWidget(x, y, width, height, Text.of("Widgets Scale: " + formattedValue), Widget.getScale(), 0.5f, 3f); - this.addDrawableChild(scaleSlider); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index 023519c..a40ebd6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -30,8 +30,8 @@ private void render(DrawContext context, int mouseX, int mouseY, float delta, Ca private void onScreenResize(MinecraftClient client,int width, int height, CallbackInfo ci) { WidgetManager.onScreenResized(width,height,this.width,this.height); } - @Inject(at = @At("TAIL"), method = "close") - private void render(CallbackInfo ci) { + @Inject(at = @At("HEAD"), method = "close") + private void onClose(CallbackInfo ci) { for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ widgetRenderer.onCloseScreen(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index 2cea9bd..83f5bd9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -18,11 +18,15 @@ public class DynamicHudTest implements DynamicHudIntegration { TextWidget textWidget; TextWidget Example2Widget; - DynamicValueRegistry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); + DynamicValueRegistry registry; WidgetRenderer renderer; @Override public void init() { + //Global registry DynamicValueRegistry.registerGlobal("FPS",() -> "FPS: "+ DynamicHUD.MC.getCurrentFps()); + + //Local registry + registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); registry.registerLocal("FPS",()-> "FPS C-DVR: "+ DynamicHUD.MC.getCurrentFps()); textWidget = new TextWidget.Builder() diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index 433be03..df887e2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -75,9 +75,9 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) @Override public void close() { - super.close(); widgetRenderer.isInEditor = false; widgetRenderer.onCloseScreen(); + super.close(); } public void setShouldPause(boolean shouldPause) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index b1702e5..ad4a9de 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -21,11 +21,9 @@ public class ContextMenu { public int heightOffset = 4; // Height offset from the widget public boolean shouldDisplay = false; - public ContextMenu(int x,int y, int width, int height, Widget selectedWidget){ + public ContextMenu(int x,int y){ this.x = x; this.y = y + heightOffset; - this.width = width; - this.height = height; this.selectedWidget = selectedWidget; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java index 9c8772e..2c4907e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -30,6 +30,7 @@ protected T get(){ return getter.get(); } protected void set(T value){ + this.value = value; setter.accept(value); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java new file mode 100644 index 0000000..b084b56 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java @@ -0,0 +1,91 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import org.apache.commons.lang3.Validate; + +import javax.xml.validation.Validator; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class DoubleOption extends Option { + public String name = "Empty"; + private boolean isDragging = false; + private double minValue = 0.0,maxValue = 0.0; + float step = 0.1f; + public DoubleOption(String name,double minValue,double maxValue,float step,Supplier getter, Consumer setter) { + super(getter, setter); + this.name = name; + this.value = get(); + this.minValue = minValue; + this.maxValue = maxValue; + this.width = 30; + this.height = 16; + this.step = step; + Validate.isTrue(this.step>0.0f,"Step cannot be less than or equal to 0 (zero)"); + } + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + value = get(); + + this.width = 30; + 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()); + + // Draw the slider + drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, width); + + // Draw the handle + float handleWidth = 3; + float handleHeight = 8; + double handleX = x + (value - minValue) / (maxValue - minValue) * (width - handleWidth); + double handleY = y + textRenderer.fontHeight + 1 + ((2 - handleHeight) / 2); + + DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), 0xFFFFFFFF); + } + + private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth) { + DrawHelper.fill(drawContext, sliderX, sliderY, sliderX + sliderWidth, sliderY + 2, 0xFFFFFFFF); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + super.mouseClicked(mouseX, mouseY, button); + if(isMouseOver(mouseX, mouseY)) { + step(mouseX); + isDragging = true; + } + return true; + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + isDragging = false; + return super.mouseReleased(mouseX, mouseY, button); + } + private 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; + set(newValue); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button) { + if(isMouseOver(mouseX, mouseY) && isDragging) { + step(mouseX); + } + return super.mouseDragged(mouseX, mouseY, button); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 04504ec..7cc5c2f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -17,7 +17,12 @@ public abstract class Widget { protected MinecraftClient mc = MinecraftClient.getInstance(); - //This is the UID of the widget used to identify during loading and saving + /** + * This is the UID of the widget used to identify during loading and saving. + *

+ * It's different from modID because this is unique to each widget. + * @see #modId + */ public UID uid = UID.generate(); public boolean isInEditor = false; // Whether the widget is enabled and should be displayed. @@ -41,6 +46,14 @@ public abstract class Widget { // 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; public boolean shouldScale = true; + + /** + * An identifier for widgets to group them under one ID. + *

+ * Doesn't necessarily have to be the mod ID of mod, but it's preferred to use mod ID if you are only grouping widgets under one ID. + * Can be any string if wanted. + * @see #uid + */ public String modId = "unknown"; //Dimensions of the widget diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 37458bc..4af54ff 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -208,8 +208,8 @@ public static void loadWidgets(File file) throws IOException { NbtCompound widgetTag = widgetList.getCompound(i); WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); Widget widget = widgetData.createWidget(); - widget.readFromTag(widgetTag); printInfo("Loading Widget: " + widget); + widget.readFromTag(widgetTag); widgets.add(widget); } }else{ diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index 3f0e2cd..f299f26 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -3,6 +3,7 @@ import com.tanishisherewith.dynamichud.DynamicHUD; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; 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; @@ -15,8 +16,17 @@ public class WidgetRenderer { public boolean isInEditor = false; List widgets; public Widget selectedWidget = null; + + /** + * Add the list of widgets the widgetRenderer should render + *

+ * By default, it adds the {@link GameMenuScreen} to allow rendering of the widgets in the pause/main menu screen. + * + * @param widgets List of widgets to render + */ public WidgetRenderer(List widgets){ this.widgets = widgets; + addScreen(GameMenuScreen.class); } public void addWidget(Widget widget){ widgets.add(widget); @@ -63,6 +73,8 @@ public void mouseClicked(double mouseX, double mouseY, int button){ } 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.mouseClicked(mouseX,mouseY,button)){ selectedWidget = widget; return; @@ -77,6 +89,8 @@ public void mouseDragged(double mouseX, double mouseY, int button, int snapSize) } 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; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 06796ab..0d276a9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -4,6 +4,7 @@ import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.DoubleOption; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -20,6 +21,7 @@ public class TextWidget extends Widget { DynamicValueRegistry dynamicValueRegistry = null; 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 private ContextMenu menu; public TextWidget() { @@ -39,9 +41,13 @@ public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,Str textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; - menu = new ContextMenu(getX(),getY(),20,20,null); + createMenu(); + } + 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)); + menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); } /** @@ -58,19 +64,17 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; - menu = new ContextMenu(getX(),getY(),20,20,null); - menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); - menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); + createMenu(); } @Override public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { - menu.render(drawContext, getX() - 2,getY(), (int) Math.ceil(getHeight())); - int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / 10000f) : Color.WHITE.getRGB(); - if(textSupplier != null) { + menu.render(drawContext, getX() - 2, getY(), (int) Math.ceil(getHeight())); + int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (float) (5000f * rainbowSpeed))) : Color.WHITE.getRGB(); + if (textSupplier != null) { String text = textSupplier.get(); - drawContext.drawText(mc.textRenderer, text, (int) getX(), (int)getY(), color, shadow); - widgetBox.setSizeAndPosition(getX() - 2,getY() - 2,mc.textRenderer.getWidth(text) + 2,mc.textRenderer.fontHeight + 2); + drawContext.drawText(mc.textRenderer, text, (int) getX(), (int) getY(), color, shadow); + widgetBox.setSizeAndPosition(getX() - 2, getY() - 2, mc.textRenderer.getWidth(text) + 2, mc.textRenderer.fontHeight + 2); } } @@ -135,10 +139,8 @@ public void readFromTag(NbtCompound tag) { System.out.println(DynamicValueRegistry.getInstances(modId)); return; } - menu = new ContextMenu(getX(),getY(),20,20,null); - menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); - menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); - } + createMenu(); + } 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 2dc77ad..2cff290 100644 --- a/src/main/resources/dynamichud.mixins.json +++ b/src/main/resources/dynamichud.mixins.json @@ -9,7 +9,6 @@ "defaultRequire": 1 }, "client": [ - "OptionsScreenMixin", "ScreenMixin" ] } From 6822259f2da2d56307d31fbb0a76e3edd2b071d8 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 6 Apr 2024 17:54:52 +0530 Subject: [PATCH 12/33] Enum and List option. --- .../utils/contextmenu/options/EnumOption.java | 62 ++++++++++++++++++ .../utils/contextmenu/options/ListOption.java | 64 +++++++++++++++++++ .../newTrial/widgets/TextWidget.java | 27 ++++++-- 3 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java new file mode 100644 index 0000000..7c49a8f --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java @@ -0,0 +1,62 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +import java.awt.Color; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class EnumOption> extends Option { + private final E[] values; + private int currentIndex = 0; + public String name = "Empty"; + + public EnumOption(String name, Supplier getter, Consumer setter, E[] values) { + super(getter, setter); + this.name = name; + this.values = values; + this.value = get(); + for (int i = 0; i < values.length; i++) { + if (values[i] == value) { + currentIndex = i; + break; + } + } + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + value = get(); + this.height = mc.textRenderer.fontHeight + 1; + this.width = mc.textRenderer.getWidth(name + ": " + value.name()) + 1; + + int color = Color.WHITE.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(name + ": " + value.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(button == 0) { + currentIndex = (currentIndex + 1) % values.length; + if(currentIndex > values.length - 1){ + currentIndex = 0; + } + value = values[currentIndex]; + }else if(button == 1){ + currentIndex = (currentIndex - 1) % values.length; + if(currentIndex < 0){ + currentIndex = values.length - 1; + } + value = values[currentIndex]; + } + set(value); + } + return true; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java new file mode 100644 index 0000000..80f605a --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java @@ -0,0 +1,64 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ListOption extends Option { + private final List values; + private int currentIndex = 0; + public String name = "Empty"; + + public ListOption(String name, Supplier getter, Consumer setter, List values) { + super(getter, setter); + this.name = name; + this.values = values; + this.value = getter.get(); + for (int i = 0; i < values.size(); i++) { + if (values.get(i).toString().equals(value)) { + currentIndex = i; + break; + } + } + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + value = get(); + this.height = mc.textRenderer.fontHeight; + this.width = mc.textRenderer.getWidth(name + ": " + value.toString()) + 1; + + int color = Color.WHITE.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(name + ": " + value.toString()), x, y, color, false); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + super.mouseClicked(mouseX, mouseY, button); + if (isMouseOver(mouseX, mouseY)) { + if(button == 0) { + currentIndex = (currentIndex + 1) % values.size(); + if(currentIndex > values.size() - 1){ + currentIndex = 0; + } + value = values.get(currentIndex); + }else if(button == 1){ + currentIndex = (currentIndex - 1) % values.size(); + if(currentIndex < 0){ + currentIndex = values.size() - 1; + } + value = values.get(currentIndex); + } + set(value); + } + return true; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 0d276a9..ef6f1b2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -5,13 +5,17 @@ import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.DoubleOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.EnumOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.ListOption; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; import org.lwjgl.glfw.GLFW; -import java.awt.*; +import java.awt.Color; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; public class TextWidget extends Widget { @@ -48,6 +52,16 @@ public void createMenu(){ menu.addOption(new BooleanOption("Shadow",()->this.shadow,value-> this.shadow = value)); menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); + AtomicReference testss = new AtomicReference<>(test.TEST); + List options = Arrays.asList("TEST","TEST2","TEST23"); + AtomicReference option = new AtomicReference<>("TEST"); + menu.addOption(new EnumOption("Test", testss::get, testss::set,test.values())); + menu.addOption(new ListOption("New", option::get, option::set,options )); + } + public enum test{ + TEST, + TEST_2, + TEST_3 } /** @@ -109,8 +123,9 @@ public void onClose() { public void writeToTag(NbtCompound tag) { super.writeToTag(tag); tag.putString("DynamicRegistryKey",dynamicRegistryKey); - tag.putBoolean("shadow",shadow); - tag.putBoolean("rainbow",rainbow); + tag.putBoolean("Shadow",shadow); + tag.putBoolean("Rainbow",rainbow); + tag.putInt("RainbowSpeed",rainbowSpeed); // 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); @@ -119,8 +134,10 @@ public void writeToTag(NbtCompound tag) { @Override public void readFromTag(NbtCompound tag) { super.readFromTag(tag); - shadow = tag.getBoolean("shadow"); - rainbow = tag.getBoolean("rainbow"); + shadow = tag.getBoolean("Shadow"); + rainbow = tag.getBoolean("Rainbow"); + rainbowSpeed = tag.getInt("RainbowSpeed"); + 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 From 64bfc2920a4bca9eda7081accf1ccdaf4767e3bf Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sun, 7 Apr 2024 12:04:15 +0530 Subject: [PATCH 13/33] Fixes --- .../dynamichud/helpers/DrawHelper.java | 6 +-- .../dynamichud/newTrial/DynamicHUD.java | 1 + .../contextmenu/options/DoubleOption.java | 13 +++-- .../utils/contextmenu/options/EnumOption.java | 5 +- .../utils/contextmenu/options/ListOption.java | 6 ++- .../contextmenu/options/RunnableOption.java | 51 +++++++++++++++++++ .../dynamichud/newTrial/widget/Widget.java | 2 +- .../newTrial/widgets/TextWidget.java | 12 ++--- 8 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index e925221..f997e28 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -28,11 +28,7 @@ public DrawHelper(MinecraftClient client, VertexConsumerProvider.Immediate verte * @param color The color to fill the rectangle with */ public static void drawBox(DrawContext drawContext, int x, int y, int width, int height, int color) { - int x1 = x - width / 2 - 2; - int y1 = y - height / 2 - 2; - int x2 = x + width / 2 + 2; - int y2 = y + height / 2 + 2; - drawContext.fill(x1, y1, x2, y2, color); + drawContext.fill(x, y, x + width, y + height, color); } /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index f19e65f..92c3277 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -114,6 +114,7 @@ public void onInitializeClient() { ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> GlobalConfig.HANDLER.save()); ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> GlobalConfig.HANDLER.save()); Runtime.getRuntime().addShutdownHook(new Thread(() -> GlobalConfig.HANDLER.save())); + GlobalConfig.HANDLER.save(); HudRenderCallback.EVENT.register(new HudRender()); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java index b084b56..be23c90 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java @@ -7,6 +7,7 @@ import org.apache.commons.lang3.Validate; import javax.xml.validation.Validator; +import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -43,20 +44,22 @@ public void render(DrawContext drawContext, int x, int y) { drawContext.drawTextWithShadow(textRenderer, labelText, x, y + 1, 0xFFFFFFFF); DrawHelper.stopScaling(drawContext.getMatrices()); - // Draw the slider - drawSlider(drawContext, x, y + textRenderer.fontHeight + 1, width); - - // Draw the handle 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.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), 0xFFFFFFFF); } - private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth) { + private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) { DrawHelper.fill(drawContext, sliderX, sliderY, sliderX + sliderWidth, sliderY + 2, 0xFFFFFFFF); + DrawHelper.fill(drawContext, sliderX, sliderY, (int) Math.round(handleX), sliderY + 2, Color.ORANGE.getRGB()); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java index 7c49a8f..dde3f95 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -34,8 +35,8 @@ public void render(DrawContext drawContext, int x, int y) { this.height = mc.textRenderer.fontHeight + 1; this.width = mc.textRenderer.getWidth(name + ": " + value.name()) + 1; - int color = Color.WHITE.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(name + ": " + value.name()), x, y, color, false); + 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 diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java index 80f605a..3e69407 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java @@ -1,5 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -36,8 +37,9 @@ public void render(DrawContext drawContext, int x, int y) { this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name + ": " + value.toString()) + 1; - int color = Color.WHITE.getRGB(); - drawContext.drawText(mc.textRenderer, Text.of(name + ": " + value.toString()), x, y, color, false); + 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 diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java new file mode 100644 index 0000000..4663609 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java @@ -0,0 +1,51 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.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; + +public class RunnableOption extends Option { + public String name = "Empty"; + private Runnable task; + + /** + * Runnable option which runs a task when clicked on it. + * @param name The name to be displayed + * @param getter Get a default value to run the task by default + * @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) { + super(getter, setter); + this.name = "Run: " + name; // prepend the "run" symbol to the name + this.task = task; + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + value = get(); + int color = value ? Color.BLUE.getRGB() : Color.GRAY.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)) { + value = !value; + set(value); + if(value){ + task.run(); + } + } + return true; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 7cc5c2f..4b8b1ae 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -258,7 +258,7 @@ public void onClose(){ protected void displayBg(DrawContext context) { int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); WidgetBox box = this.getWidgetBox(); - DrawHelper.fill(context, (int) (box.x1 - 2), (int) (box.y1 - 2), (int) (box.x2 + 2), (int) (box.y2 + 2), backgroundColor); + DrawHelper.fill(context, (int) box.x1, (int) box.y1, (int) box.x2, (int) box.y2, backgroundColor); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index ef6f1b2..c88e184 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -29,7 +29,7 @@ public class TextWidget extends Widget { private ContextMenu menu; public TextWidget() { - this(null,false,false,"unknown"); + this(null,null,false,false,"unknown"); } /** @@ -75,7 +75,9 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist super(DATA,modID); this.dynamicRegistryKey = dynamicRegistryKey; this.dynamicValueRegistry = dynamicValueRegistry; - textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); + if(dynamicValueRegistry != null) { + textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); + } this.shadow = shadow; this.rainbow = rainbow; createMenu(); @@ -88,7 +90,7 @@ public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { if (textSupplier != null) { String text = textSupplier.get(); drawContext.drawText(mc.textRenderer, text, (int) getX(), (int) getY(), color, shadow); - widgetBox.setSizeAndPosition(getX() - 2, getY() - 2, mc.textRenderer.getWidth(text) + 2, mc.textRenderer.fontHeight + 2); + widgetBox.setSizeAndPosition(getX() - 2, getY() - 2, mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2); } } @@ -143,7 +145,7 @@ public void readFromTag(NbtCompound tag) { // 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 && dynamicRegistryKey != null){ + if(!dvrObj){ textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); return; } @@ -152,8 +154,6 @@ public void readFromTag(NbtCompound tag) { //Unfortunately, this method takes the value from the first local registry with the key. //It returns to prevent overriding with other registries textSupplier = (Supplier) dvr.get(dynamicRegistryKey); - System.out.println(dvr); - System.out.println(DynamicValueRegistry.getInstances(modId)); return; } createMenu(); From 11441eab07ff538127bf5c844d3d7b8008ea0f91 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sun, 7 Apr 2024 23:21:52 +0530 Subject: [PATCH 14/33] tiny change --- .../newTrial/utils/contextmenu/options/RunnableOption.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java index 4663609..c62fc3b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java @@ -30,10 +30,10 @@ public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); value = get(); + this.height = mc.textRenderer.fontHeight; + this.width = mc.textRenderer.getWidth("Run: " + name) + 1; int color = value ? Color.BLUE.getRGB() : Color.GRAY.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 From 4eb6360fc68d3a0849145cf65eefd48d0878b612 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:19:16 +0530 Subject: [PATCH 15/33] ColorOption and some changes --- .../dynamichud/helpers/ColorHelper.java | 26 + .../dynamichud/huds/MoveableScreen.java | 2 +- .../newTrial/helpers/DrawHelper.java | 847 ++++++++++++++++++ .../screens/AbstractMoveableScreen.java | 3 + .../contextmenu/options/ColorOption.java | 73 ++ .../contextmenu/options/DoubleOption.java | 21 +- .../coloroption/ColorGradientPicker.java | 140 +++ .../coloroption/ColorPickerButton.java | 52 ++ .../options/coloroption/GradientBox.java | 132 +++ .../options/coloroption/GradientSlider.java | 132 +++ .../newTrial/widgets/TextWidget.java | 77 +- .../util/contextmenu/ContextMenu.java | 4 +- 12 files changed, 1466 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java index 2194e4b..9e3884f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java @@ -94,6 +94,32 @@ public static float[] getRainbowColor() rainbow[2] = 0.5F + 0.5F * MathHelper.sin((x + 8F / 3F) * pi); return rainbow; } + + /** + * Rainbow color with custom speed. + * + * @param speed + * @return Current rainbow color. + */ + public static Color getRainbowColor(int speed) { + float hue = (System.currentTimeMillis() % (speed * 100)) / (speed * 100.0f); + return Color.getHSBColor(hue, 1.0f, 1.0f); + } + + + /** + * Changes alpha on color. + * + * @param color Target color. + * @param alpha Target alpha. + * @return Color with changed alpha. + */ + public static Color changeAlpha(Color color, int alpha) { + if (color != null) + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + else + return new Color(0); + } 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/huds/MoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java index 58c7a07..fd5085d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java @@ -106,7 +106,7 @@ protected void TextWidgetMenu(TextWidget textWidget, int x, int y) { textWidget.toggleTextColorOption(); if (textWidget.isTextcolorOptionEnabled()) - colorPicker = new ColorGradientPicker(mc, widgetX + 110, widgetY + textWidget.getHeight() + 5, textWidget.getTextcolor(), textWidget::setTextColor, 50, 100, selectedWidget); + colorPicker = new ColorGradientPicker(mc, widgetX +110, widgetY + textWidget.getHeight() + 5, textWidget.getTextcolor(), textWidget::setTextColor, 50, 100, selectedWidget); else colorPicker = null; }); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java new file mode 100644 index 0000000..d036afd --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java @@ -0,0 +1,847 @@ +package com.tanishisherewith.dynamichud.newTrial.helpers; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.MathHelper; +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL40C; + +import java.awt.*; + +/** + * Credits: HeliosClient + */ +public class DrawHelper { + + /** + * Draws a singular gradient rectangle on screen with the given parameters + * + * @param matrix4f Matrix4f object to draw the gradient + * @param x X position of the gradient + * @param y Y position of the gradient + * @param width Width of the gradient + * @param height Height of the gradient + * @param startColor start color of the gradient + * @param endColor end color of the gradient + * @param direction Draws the gradient in the given direction + */ + public static void drawGradient(Matrix4f matrix4f, float x, float y, float width, float height, int startColor, int endColor, Direction direction) { + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + + switch (direction) { + case LEFT_RIGHT: + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + break; + case TOP_BOTTOM: + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + break; + case RIGHT_LEFT: + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + break; + case BOTTOM_TOP: + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(startRed, startGreen, startBlue, startAlpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(endRed, endGreen, endBlue, endAlpha).next(); + break; + } + + tessellator.draw(); + + RenderSystem.disableBlend(); + } + + public static void enableScissor(int x, int y, int width, int height) { + double scaleFactor = DynamicHUD.MC.getWindow().getScaleFactor(); + + int scissorX = (int) (x * scaleFactor); + int scissorY = (int) (DynamicHUD.MC.getWindow().getHeight() - ((y + height) * scaleFactor)); + int scissorWidth = (int) (width * scaleFactor); + int scissorHeight = (int) (height * scaleFactor); + + RenderSystem.enableScissor(scissorX, scissorY, scissorWidth, scissorHeight); + } + + public static void disableScissor() { + RenderSystem.disableScissor(); + } + + /** + * Draws a singular rectangle on screen with the given parameters + * + * @param matrix4f Matrix4f object to draw the rectangle + * @param x X position of the rectangle + * @param y Y position of the rectangle + * @param width Width of the rectangle + * @param height Height of the rectangle + * @param color Color of the rectangle + */ + public static void drawRectangle(Matrix4f matrix4f, float x, float y, float width, float height, int 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + + bufferBuilder.vertex(matrix4f, x, y + height, 0.0F).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y + height, 0.0F).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x + width, y, 0.0F).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x, y, 0.0F).color(red, green, blue, alpha).next(); + + tessellator.draw(); + + RenderSystem.disableBlend(); + } + + /* ==== Drawing Rectangles ==== */ + + /** + * Draws a singular outline rectangle on screen with the given parameters + * + * @param matrix4f Matrix4f object to draw the rectangle + * @param x X position of the rectangle + * @param y Y position of the rectangle + * @param width Width of the rectangle + * @param height Height of the rectangle + * @param color Color of the rectangle + */ + public static void drawOutlineBox(Matrix4f matrix4f, float x, float y, float width, float height, float thickness, int color) { + drawRectangle(matrix4f, x, y, width, thickness, color); + drawRectangle(matrix4f, x, y + height - thickness, width, thickness, color); + drawRectangle(matrix4f, x, y + thickness, thickness, height - thickness * 2, color); + drawRectangle(matrix4f, x + width - thickness, y + thickness, thickness, height - thickness * 2, color); + } + + /** + * Draws a singular rectangle with a dark shadow on screen with the given parameters + * Bad way because there is a better way + * + * @param matrix4f Matrix4f object to draw the rectangle and shadow + * @param x X position of the rectangle + * @param y Y position of the rectangle + * @param width Width of the rectangle + * @param height Height of the rectangle + * @param color Color of the rectangle + * @param shadowOpacity Opacity of the shadow (Dark --> Lighter) + * @param shadowOffsetX X position Offset of the shadow from the main rectangle X pos + * @param shadowOffsetY Y position Offset of the shadow from the main rectangle Y pos + */ + public static void drawRectangleWithShadowBadWay(Matrix4f matrix4f, float x, float y, float width, float height, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) { + // First, render the shadow + drawRectangle(matrix4f, x + shadowOffsetX, y + shadowOffsetY, width, height, ColorHelper.getColor(0, 0, 0, shadowOpacity)); + + // Then, render the rectangle + drawRectangle(matrix4f, x, y, width, height, color); + } + + /** + * Draws an outline rounded rectangle by drawing 4 side rectangles, and 4 arcs + * + * @param matrix4f Matrix4f object to draw the rounded rectangle + * @param x X pos + * @param y Y pos + * @param width Width of rounded rectangle + * @param height Height of rounded rectangle + * @param radius Radius of the quadrants / the rounded rectangle + * @param color Color of the rounded rectangle + * @param thickness thickness of the outline + */ + public static void drawOutlineRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, float thickness, int color) { + // Draw the rectangles for the outline + drawRectangle(matrix4f, x + radius, y, width - radius * 2, thickness, color); // Top rectangle + drawRectangle(matrix4f, x + radius, y + height - thickness, width - radius * 2, thickness, color); // Bottom rectangle + drawRectangle(matrix4f, x, y + radius, thickness, height - radius * 2, color); // Left rectangle + drawRectangle(matrix4f, x + width - thickness, y + radius, thickness, height - radius * 2, color); // Right rectangle + + // Draw the arcs at the corners for the outline + drawArc(matrix4f, x + radius, y + radius, radius, thickness, color, 180, 270); // Top-left arc + drawArc(matrix4f, x + width - radius, y + radius, radius, thickness, color, 90, 180); // Top-right arc + drawArc(matrix4f, x + width - radius, y + height - radius, radius, thickness, color, 0, 90); // Bottom-right arc + drawArc(matrix4f, x + radius, y + height - radius, radius, thickness, color, 270, 360); // Bottom-left arc + } + + public static void drawRainbowGradientRectangle(Matrix4f matrix4f, float x, float y, float width, float height, float alpha) { + BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); + + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + + for (int i = 0; i <= width; i++) { + float hue = (float) i / width; + int color = Color.HSBtoRGB(hue, 1.0f, 1.0f); + color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); + + float red = (color >> 16 & 255) / 255.0F; + float green = (color >> 8 & 255) / 255.0F; + float blue = (color & 255) / 255.0F; + float alphaVal = (color >> 24 & 255) / 255.0F; + + bufferBuilder.vertex(matrix4f, x + i, y, 0.0f).color(red, green, blue, alphaVal).next(); + bufferBuilder.vertex(matrix4f, x + i, y + height, 0.0f).color(red, green, blue, alphaVal).next(); + } + + for (int i = (int) width; i >= 0; i--) { + float hue = (float) i / width; + int color = Color.HSBtoRGB(hue, 1.0f, 1.0f); + color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); + + float red = (color >> 16 & 255) / 255.0F; + float green = (color >> 8 & 255) / 255.0F; + float blue = (color & 255) / 255.0F; + float alphaVal = (color >> 24 & 255) / 255.0F; + + bufferBuilder.vertex(matrix4f, x + i, y + height, 0.0f).color(red, green, blue, alphaVal).next(); + bufferBuilder.vertex(matrix4f, x + i, y, 0.0f).color(red, green, blue, alphaVal).next(); + } + + Tessellator.getInstance().draw(); + + RenderSystem.disableBlend(); + } + + + public static void drawRainbowGradient(Matrix4f matrix, float x, float y, float width, float height) { + Matrix4f matrix4f = RenderSystem.getModelViewMatrix(); + + 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.colorMask(true, true, true, true); + + drawRectangle(matrix4f, x, y, width, height, Color.BLACK.getRGB()); + + RenderSystem.blendFunc(GL40C.GL_DST_ALPHA, GL40C.GL_ONE_MINUS_DST_ALPHA); + + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + + BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + for (float i = 0; i < width; i += 1.0f) { + float hue = (i / width); // Multiply by 1 to go through the whole color spectrum once (red to red) + Color color = Color.getHSBColor(hue, 1.0f, 1.0f); // Full saturation and brightness + + bufferBuilder.vertex(matrix4f, x + i, y, 0.0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).next(); + bufferBuilder.vertex(matrix4f, x + i + 1.0f, y, 0.0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).next(); + bufferBuilder.vertex(matrix4f, x + i + 1.0f, y + height, 0.0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).next(); + bufferBuilder.vertex(matrix4f, x + i, y + height, 0.0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).next(); + } + + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableBlend(); + + RenderSystem.defaultBlendFunc(); + } + + + /* ==== Drawing filled and outline circles ==== */ + /** + * Draws an outline of a circle + * + * @param matrix4f Matrix4f object to draw the circle outline + * @param xCenter X position of the circle outline + * @param yCenter Y position of the circle outline + * @param radius radius of the circle outline + * @param color color of the circle outline + */ + public static void drawOutlineCircle(Matrix4f matrix4f, float xCenter, float yCenter, float radius, float lineWidth, int 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); + + for (int i = 0; i <= 360; i++) { + double x = xCenter + Math.sin(Math.toRadians(i)) * radius; + double y = yCenter + Math.cos(Math.toRadians(i)) * radius; + double x2 = xCenter + Math.sin(Math.toRadians(i)) * (radius + lineWidth); + double y2 = yCenter + Math.cos(Math.toRadians(i)) * (radius + lineWidth); + bufferBuilder.vertex(matrix4f, (float) x, (float) y, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, (float) x2, (float) y2, 0).color(red, green, blue, alpha).next(); + } + + + tessellator.draw(); + } + + /** + * Draws a filled circle + * + * @param matrix4f Matrix4f object to draw the circle outline + * @param xCenter X position of the circle outline + * @param yCenter Y position of the circle outline + * @param radius radius of the circle outline + * @param color color of the circle outline + */ + public static void drawFilledCircle(Matrix4f matrix4f, float xCenter, float yCenter, float radius, int 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.blendFunc(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA); + + + bufferBuilder.vertex(matrix4f, xCenter, yCenter, 0).color(red, green, blue, alpha).next(); + + for (int i = 0; i <= 360; i++) { + double x = xCenter + Math.sin(Math.toRadians(i)) * radius; + double y = yCenter + Math.cos(Math.toRadians(i)) * radius; + bufferBuilder.vertex(matrix4f, (float) x, (float) y, 0).color(red, green, blue, alpha).next(); + } + + tessellator.draw(); + RenderSystem.disableBlend(); + } + + /** + * Draws a filled circle with a shadow bad way + * + * @param matrix4f Matrix4f object to draw the circle + * @param xCenter X position of the circle + * @param yCenter Y position of the circle + * @param radius Radius of the circle + * @param color Color of the circle + * @param shadowOffsetX X position of the circle shadow offset from main circle + * @param shadowOffsetY X position of the circle shadow offset from main circle + * @param shadowOpacity Opacity of the circle shadow offset from main circle + */ + public static void drawCircleWithShadow(Matrix4f matrix4f, float xCenter, float yCenter, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) { + // First, render the shadow + drawFilledCircle(matrix4f, xCenter + shadowOffsetX, yCenter + shadowOffsetY, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity)); + + // Then, render the circle + drawFilledCircle(matrix4f, xCenter, yCenter, radius, color); + } + + /** + * Not Tested + * + * @param matrix4f + * @param x + * @param y + * @param radius + * @param startAngle + * @param endAngle + * @param color + */ + @Deprecated + public static void drawFilledArc(Matrix4f matrix4f, float x, float y, float radius, float startAngle, float endAngle, int 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; + + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); + RenderSystem.enableBlend(); + + for (float angle = startAngle; angle <= endAngle; angle += 1.0F) { + float x1 = x + MathHelper.cos(angle * 0.017453292F) * radius; + float y1 = y + MathHelper.sin(angle * 0.017453292F) * radius; + float x2 = x + MathHelper.cos((angle + 1.0F) * 0.017453292F) * radius; + float y2 = y + MathHelper.sin((angle + 1.0F) * 0.017453292F) * radius; + + bufferBuilder.vertex(matrix4f, x, y, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x1, y1, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x2, y2, 0).color(red, green, blue, alpha).next(); + } + tessellator.draw(); + RenderSystem.disableBlend(); + } + /* ==== Drawing Quadrants, Arcs, and Triangles ==== */ + + /** + * Draws a filled Gradient quadrant + * + * @param matrix4f Matrix4f object to draw the quadrant + * @param xCenter X position of the quadrant + * @param yCenter Y position of the quadrant + * @param radius Radius of the quadrant + * @param startColor start color of the gradient + * @param endColor end color of the gradient + * @param quadrant Integer value of the quadrant of the circle. 1 == Top Right, 2 == Top Left, 3 == Bottom Right, 4 == Bottom Left + */ + public static void drawFilledGradientQuadrant(Matrix4f matrix4f, float xCenter, float yCenter, float radius, int startColor, int endColor, int quadrant) { + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + RenderSystem.enableBlend(); + + bufferBuilder.vertex(matrix4f, xCenter, yCenter, 0).color(startRed, startGreen, startBlue, startAlpha).next(); + + for (int i = quadrant * 90; i <= quadrant * 90 + 90; i++) { + double x = xCenter + Math.sin(Math.toRadians(i)) * radius; + double y = yCenter + Math.cos(Math.toRadians(i)) * radius; + + // Interpolate the color based on the angle + float t = (float) (i - quadrant * 90) / 90.0f; + float red = startRed * (1 - t) + endRed * t; + float green = startGreen * (1 - t) + endGreen * t; + float blue = startBlue * (1 - t) + endBlue * t; + float alpha = startAlpha * (1 - t) + endAlpha * t; + + bufferBuilder.vertex(matrix4f, (float) x, (float) y, 0).color(red, green, blue, alpha).next(); + } + + tessellator.draw(); + RenderSystem.disableBlend(); + } + + /** + * Draws an arc + * + * @param matrix4f Matrix4f object to draw the arc + * @param xCenter X position of the arc's center + * @param yCenter Y position of the arc's center + * @param radius Radius of the arc's center circle + * @param startAngle start Angle of the arc + * @param endAngle end Angle of the arc + * @param thickness Thickness of the arc (width of the arc) + */ + public static void drawArc(Matrix4f matrix4f, float xCenter, float yCenter, float radius, float thickness, int color, int startAngle, int endAngle) { + 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); + RenderSystem.enableBlend(); + + for (int i = startAngle; i <= endAngle; i++) { + double innerX = xCenter + Math.sin(Math.toRadians(i)) * (radius - thickness); + double innerY = yCenter + Math.cos(Math.toRadians(i)) * (radius - thickness); + double outerX = xCenter + Math.sin(Math.toRadians(i)) * radius; + double outerY = yCenter + Math.cos(Math.toRadians(i)) * radius; + + bufferBuilder.vertex(matrix4f, (float) innerX, (float) innerY, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, (float) outerX, (float) outerY, 0).color(red, green, blue, alpha).next(); + } + + tessellator.draw(); + + RenderSystem.disableBlend(); + } + + /** + * Draws a filled quadrant + * + * @param matrix4f Matrix4f object to draw the quadrant + * @param xCenter X position of the quadrant + * @param yCenter Y position of the quadrant + * @param radius Radius of the quadrant + * @param color color of the quadrant + * @param quadrant Integer value of the quadrant of the circle. 1 == Top Right, 2 == Top Left, 3 == Bottom Right, 4 == Bottom Left + */ + public static void drawFilledQuadrant(Matrix4f matrix4f, float xCenter, float yCenter, float radius, int color, int quadrant) { + 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + RenderSystem.setShader(GameRenderer::getPositionColorProgram); + bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + RenderSystem.enableBlend(); + + bufferBuilder.vertex(matrix4f, xCenter, yCenter, 0).color(red, green, blue, alpha).next(); + + for (int i = quadrant * 90; i <= quadrant * 90 + 90; i++) { + double x = xCenter + Math.sin(Math.toRadians(i)) * radius; + double y = yCenter + Math.cos(Math.toRadians(i)) * radius; + bufferBuilder.vertex(matrix4f, (float) x, (float) y, 0).color(red, green, blue, alpha).next(); + } + + tessellator.draw(); + RenderSystem.disableBlend(); + + } + + /** + * Draws a Triangle with the given coordinates + * + * @param matrix4f + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @param x3 + * @param y3 + * @param color + */ + public static void drawOutlineTriangle(Matrix4f matrix4f, int x1, int y1, int x2, int y2, int x3, int y3, int 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; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR); + + bufferBuilder.vertex(matrix4f, x1, y1, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x2, y2, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x3, y3, 0).color(red, green, blue, alpha).next(); + bufferBuilder.vertex(matrix4f, x1, y1, 0).color(red, green, blue, alpha).next(); + + tessellator.draw(); + } + + /** + * Draws a outline quadrant + * + * @param matrix4f Matrix4f object to draw the quadrant + * @param xCenter X position of the quadrant + * @param yCenter Y position of the quadrant + * @param radius Radius of the quadrant + * @param color color of the quadrant + * @param quadrant Integer value of the quadrant of the circle. 1 == Top Right, 2 == Top Left, 3 == Bottom Right, 4 == Bottom Left + */ + public static void drawOutlineQuadrant(Matrix4f matrix4f, float xCenter, float yCenter, float radius, int quadrant, int color) { + int startAngle = 0; + int endAngle = 0; + + if (quadrant == 1) { + startAngle = 270; + endAngle = 360; + } else if (quadrant == 2) { + startAngle = 180; + endAngle = 270; + } else if (quadrant == 3) { + startAngle = 90; + endAngle = 180; + } else if (quadrant == 4) { + endAngle = 90; + } + + drawArc(matrix4f, xCenter, yCenter, radius, 1f, color, startAngle, endAngle); + } + + /** + * Draws a filled rounded rectangle by drawing 1 main rectangle, 4 side rectangles, and 4 filled quadrants + * + * @param matrix4f Matrix4f object to draw the rounded rectangle + * @param x X pos + * @param y Y pos + * @param width Width of rounded rectangle + * @param height Height of rounded rectangle + * @param radius Radius of the quadrants / the rounded rectangle + * @param color Color of the rounded rectangle + */ + public static void drawRoundedRectangle(Matrix4f matrix4f, float x, float y, float width, float height, float radius, int color) { + drawRoundedRectangle(matrix4f, x, y, true, true, true, true, width, height, radius, color); + } + + /* ==== Drawing Rounded Rectangles ==== */ + + /** + * Draws a filled rounded rectangle by drawing 1 main rectangle, 4 side rectangles, and specified filled quadrants + * + * @param matrix4f Matrix4f object to draw the rounded rectangle + * @param x X pos + * @param y Y pos + * @param TL Whether to draw the top left quadrant + * @param TR Whether to draw the top right quadrant + * @param BL Whether to draw the bottom left quadrant + * @param BR Whether to draw the bottom right quadrant + * @param width Width of rounded rectangle + * @param height Height of rounded rectangle + * @param radius Radius of the quadrants / the rounded rectangle + * @param color Color of the rounded rectangle + */ + public static void drawRoundedRectangle(Matrix4f matrix4f, float x, float y, boolean TL, boolean TR, boolean BL, boolean BR, float width, float height, float radius, int color) { + // Draw the main rectangle + drawRectangle(matrix4f, x + radius, y + radius, width - 2 * radius, height - 2 * radius, color); + + // Draw rectangles at the sides + drawRectangle(matrix4f, x + radius, y, width - 2 * radius, radius, color); // top + drawRectangle(matrix4f, x + radius, y + height - radius, width - 2 * radius, radius, color); // bottom + drawRectangle(matrix4f, x, y + radius, radius, height - 2 * radius, color); // left + drawRectangle(matrix4f, x + width - radius, y + radius, radius, height - 2 * radius, color); // right + + if (TL) { + drawFilledQuadrant(matrix4f, x + radius, y + radius, radius, color, 2); + } else { + drawRectangle(matrix4f, x, y, radius, radius, color); + } + if (TR) { + drawFilledQuadrant(matrix4f, x + width - radius, y + radius, radius, color, 1); + } else { + drawRectangle(matrix4f, x + width - radius, y, radius, radius, color); + } + if (BL) { + drawFilledQuadrant(matrix4f, x + radius, y + height - radius, radius, color, 3); + } else { + drawRectangle(matrix4f, x, y + height - radius, radius, radius, color); + } + if (BR) { + drawFilledQuadrant(matrix4f, x + width - radius, y + height - radius, radius, color, 4); + } else { + drawRectangle(matrix4f, x + width - radius, y + height - radius, radius, radius, color); + } + } + + /** + * Draws a outline rounded gradient rectangle + * + * @param matrix4f Matrix4f object to draw the rounded gradient rectangle + * @param color1 is applied to the bottom-left vertex (x, y + height). + * @param color2 is applied to the bottom-right vertex (x + width, y + height). + * @param color3 is applied to the top-right vertex (x + width, y). + * @param color4 is applied to the top-left vertex (x, y). + * @param x X pos + * @param y Y pos + * @param width Width of rounded gradient rectangle + * @param height Height of rounded gradient rectangle + * @param radius Radius of the quadrants / the rounded gradient rectangle + */ + public static void drawOutlineGradientRoundedBox(Matrix4f matrix4f, float x, float y, float width, float height, float radius, float thickness, Color color1, Color color2, Color color3, Color color4) { + // Draw the rectangles for the outline with gradient + drawGradient(matrix4f, x + radius, y, width - radius * 2, thickness, color1.getRGB(), color2.getRGB(), Direction.LEFT_RIGHT); // Top rectangle + drawGradient(matrix4f, x + radius, y + height - thickness, width - radius * 2, thickness, color3.getRGB(), color4.getRGB(), Direction.RIGHT_LEFT); // Bottom rectangle + + drawGradient(matrix4f, x, y + radius, thickness, height - radius * 2, color4.getRGB(), color1.getRGB(), Direction.BOTTOM_TOP); // Left rectangle + drawGradient(matrix4f, x + width - thickness, y + radius, thickness, height - radius * 2, color2.getRGB(), color3.getRGB(), Direction.TOP_BOTTOM); // Right rectangle + + // Draw the arcs at the corners for the outline with gradient + drawArc(matrix4f, x + radius, y + radius, radius, thickness, color1.getRGB(), 180, 270); // Top-left arc + drawArc(matrix4f, x + width - radius, y + radius, radius, thickness, color2.getRGB(), 90, 180); // Top-right arc + drawArc(matrix4f, x + width - radius, y + height - radius, radius, thickness, color3.getRGB(), 0, 90); // Bottom-right arc + drawArc(matrix4f, x + radius, y + height - radius, radius, thickness, color4.getRGB(), 270, 360); // Bottom-left arc + } + + public static void drawCutRectangle(DrawContext drawContext, int x1, int y1, int x2, int y2, int z, int color, int cornerRadius) { + // Draw the rectangles + drawContext.fill(x1 + cornerRadius, y1, x2 - cornerRadius, y1 + cornerRadius, z, color); + drawContext.fill(x1 + cornerRadius, y2 - cornerRadius, x2 - cornerRadius, y2, z, color); + drawContext.fill(x1, y1 + cornerRadius, x2, y2 - cornerRadius, z, color); + } + + /** + * Draws a rounded rectangle with a shadow in a bad way + * + * @param matrix4f Matrix4f object to draw the rounded rectangle + * @param x X pos + * @param y Y pos + * @param width Width of rounded rectangle + * @param height Height of rounded rectangle + * @param radius Radius of the quadrants / the rounded rectangle + * @param color Color of the rounded rectangle + * @param shadowOpacity opacity of the shadow + * @param shadowOffsetX X offset of the shadow + * @param shadowOffsetY Y offset of the shadow + */ + public static void drawRoundedRectangleWithShadowBadWay(Matrix4f matrix4f, float x, float y, float width, float height, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) { + // First, render the shadow + drawRoundedRectangle(matrix4f, x + shadowOffsetX, y + shadowOffsetY, width, height, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity)); + + // Then, render the rounded rectangle + drawRoundedRectangle(matrix4f, x, y, width, height, radius, color); + } + + /** + * Draws a rounded gradient rectangle + * + * @param matrix Matrix4f object to draw the rounded gradient rectangle + * @param color1 is applied to the bottom-left vertex (x, y + height). + * @param color2 is applied to the bottom-right vertex (x + width, y + height). + * @param color3 is applied to the top-right vertex (x + width, y). + * @param color4 is applied to the top-left vertex (x, y). + * @param x X pos + * @param y Y pos + * @param width Width of rounded gradient rectangle + * @param height Height of rounded gradient rectangle + * @param radius Radius of the quadrants / the rounded gradient rectangle + */ + public static void drawRoundedGradientRectangle(Matrix4f matrix, Color color1, Color color2, Color color3, Color color4, float x, float y, float width, float height, float radius) { + drawRoundedGradientRectangle(matrix, color1, color2, color3, color4, x, y, width, height, radius, true, true, true, true); + } + + /** + * Draws a rounded gradient rectangle + * + * @param matrix Matrix4f object to draw the rounded gradient rectangle + * @param color1 is applied to the bottom-left vertex (x, y + height). + * @param color2 is applied to the bottom-right vertex (x + width, y + height). + * @param color3 is applied to the top-right vertex (x + width, y). + * @param color4 is applied to the top-left vertex (x, y). + * @param x X pos + * @param y Y pos + * @param width Width of rounded gradient rectangle + * @param height Height of rounded gradient rectangle + * @param radius Radius of the quadrants / the rounded gradient rectangle + */ + public static void drawRoundedGradientRectangle(Matrix4f matrix, Color color1, Color color2, Color color3, Color color4, float x, float y, float width, float height, float radius, boolean TL, boolean TR, boolean BL, boolean BR) { + 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.colorMask(true, true, true, true); + + drawRoundedRectangle(matrix, x, y, TL, TR, BL, BR, width, height, (int) radius, color1.getRGB()); + + RenderSystem.blendFunc(GL40C.GL_DST_ALPHA, GL40C.GL_ONE_MINUS_DST_ALPHA); + + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + + BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); + bufferBuilder.begin(VertexFormat.DrawMode.TRIANGLE_FAN, VertexFormats.POSITION_COLOR); + + bufferBuilder.vertex(matrix, x, y + height, 0.0F).color(color1.getRGB()).next(); + bufferBuilder.vertex(matrix, x + width, y + height, 0.0F).color(color2.getRGB()).next(); + bufferBuilder.vertex(matrix, x + width, y, 0.0F).color(color3.getRGB()).next(); + bufferBuilder.vertex(matrix, x, y, 0.0F).color(color4.getRGB()).next(); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); + RenderSystem.disableBlend(); + + RenderSystem.defaultBlendFunc(); + } + + /* ==== Drawing Lines ==== */ + public static void drawVerticalLine(Matrix4f matrix4f, float x, float y1, float height, float thickness, int color) { + drawRectangle(matrix4f, x, y1, thickness, height, color); + } + + public static void drawHorizontalLine(Matrix4f matrix4f, float x1, float width, float y, float thickness, int color) { + drawRectangle(matrix4f, x1, y, width, thickness, color); + } + + public enum Direction { + /* LEFT_RIGHT means from left to right. Same for others */ + LEFT_RIGHT, TOP_BOTTOM, RIGHT_LEFT, BOTTOM_TOP + } + /** + * Draws an outlined box on the screen. + * + * @param x1 The x position of the top left corner of the box + * @param y1 The y position of the top left corner of the box + * @param x2 The x position of the bottom right corner of the box + * @param y2 The y position of the bottom right corner of the box + * @param color The color to draw the box with + */ + public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int x2, int y2, int color) { + drawContext.fill(x1, y1, x2, y1 + 1, color); + drawContext.fill(x1, y2 - 1, x2, y2, color); + drawContext.fill(x1, y1 + 1, x1 + 1, y2 - 1, color); + drawContext.fill(x2 - 1, y1 + 1, x2, y2 - 1, color); + } + + /** + * This method assumes that the x, y coords are the origin of a widget. + * @param x X position of widget + * @param y Y position of widget + * @param scale Scale the matrices + */ + public static void scaleAndPosition(MatrixStack matrices, float x, float y, float scale) { + matrices.push(); // Save the current transformation state + + // Translate the origin back to the desired position + matrices.translate(x, y, 0); + + // Scale the matrix + matrices.scale(scale, scale, 1.0F); + + matrices.translate(-x,-y,0); + } + /** + * This method scales the matrices by the centre of the widget + * @param x X position of widget + * @param y Y position of widget + * @param height height of widget + * @param width width of widget + * @param scale Scale the matrices + */ + public static void scaleAndPosition(MatrixStack matrices, float x, float y,float width, float height, float scale) { + matrices.push(); // Save the current transformation state + + // Translate the origin back to the desired position + matrices.translate(x + width / 2.0f, y + height / 2.0f, 0); + + // Scale the matrix + matrices.scale(scale, scale, 1.0F); + + matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f), 0); + } + + public static void stopScaling(MatrixStack matrices){ + matrices.pop(); // Restore the previous transformation state + } + +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index df887e2..bc4a43d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -94,5 +94,8 @@ public void resize(MinecraftClient client, int width, int height) { public boolean shouldPause() { return ShouldPause; } + public void setSnapSize(int size){ + this.snapSize = size; + } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java new file mode 100644 index 0000000..e5a09af --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java @@ -0,0 +1,73 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption.ColorGradientPicker; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +import java.awt.*; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ColorOption extends Option { + public String name = "Empty"; + public boolean isVisible = false; + private ColorGradientPicker colorPicker = null; + public ColorOption(String name, Supplier getter, Consumer setter) { + super(getter, setter); + this.name = name; + colorPicker = new ColorGradientPicker(x + this.width + 50,y,value,color-> set(new Color(color)),50,100 ); + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + value = get(); + + int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); + this.height = mc.textRenderer.fontHeight; + this.width = mc.textRenderer.getWidth(name) + 12; + drawContext.drawText(mc.textRenderer, Text.of(name),x,y, color,false); + DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), + x + width - 8, + y, + 8, + 8, + 2, + value.getRGB(), + 90, + 1, + 1 ); + + colorPicker.render(drawContext,x + this.width + 50,y); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if(isMouseOver(mouseX, mouseY)) { + isVisible = !isVisible; + if(isVisible) + { + colorPicker.setPos(x + this.width + 50,y); + colorPicker.display(); + }else{ + colorPicker.close(); + } + } + colorPicker.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); + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button) { + colorPicker.mouseDragged(mouseX, mouseY, button); + return super.mouseDragged(mouseX, mouseY, button); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java index be23c90..644f2ed 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java @@ -1,12 +1,11 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import org.apache.commons.lang3.Validate; -import javax.xml.validation.Validator; import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; @@ -30,7 +29,6 @@ public DoubleOption(String name,double minValue,double maxValue,float step,Suppl @Override public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); - value = get(); this.width = 30; @@ -54,12 +52,23 @@ public void render(DrawContext drawContext, int x, int y) { // Draw the handle - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), 0xFFFFFFFF); + DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), + (float)handleX, + (float)handleY, + handleWidth, + handleHeight, + 1, + 0xFFFFFFFF, + 90, + 0.6f, + 0.6f); } private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) { - DrawHelper.fill(drawContext, sliderX, sliderY, sliderX + sliderWidth, sliderY + 2, 0xFFFFFFFF); - DrawHelper.fill(drawContext, sliderX, sliderY, (int) Math.round(handleX), sliderY + 2, Color.ORANGE.getRGB()); + 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()); + } } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java new file mode 100644 index 0000000..5f3d0b0 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -0,0 +1,140 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; + +import com.tanishisherewith.dynamichud.widget.Widget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.GlAllocationUtils; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.function.Consumer; + +public class ColorGradientPicker { + 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 ColorPickerButton colorPickerButton; + private int x,y; + private final int boxSize; + private boolean display = false; + + public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { + this.x = x; + this.y = y; + this.onColorSelected = onColorSelected; + float[] hsv = new float[3]; + Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), hsv); + this.boxSize = boxSize; + this.gradientSlider = new GradientSlider(x, y, colors, 10); + this.gradientSlider.setHue(hsv[0]); + + this.gradientBox = new GradientBox(x, y + 20, boxSize); + this.gradientBox.setHue(hsv[0]); + this.gradientBox.setSaturation(hsv[1]); + this.gradientBox.setValue(hsv[2]); + this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 35, 20); + } + public void setPos(int x, int y){ + this.x = x; + this.y = y; + } + public void display() { + display = true; + } + public void close() { + display = false; + } + public void tick() { + gradientSlider.tick(); + gradientBox.tick(); + } + public void defaultValues(){ + gradientSlider.defaultValues(); + gradientBox.defaultValues(); + } + + public void render(DrawContext drawContext, int x1, int y1) { + setPos(x1,y1); + if(!display){ + defaultValues(); + return; + } + tick(); + gradientSlider.render(drawContext,x + 30, y +client.textRenderer.fontHeight + 4); + gradientBox.render(drawContext,x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); + colorPickerButton.render(drawContext,x+ 40 + boxSize,y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 7); + + if (colorPickerButton.isPicking()) { + // Draw the cursor + 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()); + + ByteBuffer buffer = GlAllocationUtils.allocateByteBuffer(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.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); + } + } + + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if(!display){ + return false; + } + if (colorPickerButton.onClick(mouseX, mouseY, button)) { + return true; + } 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()) { + 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 = GlAllocationUtils.allocateByteBuffer(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); + } + onColorSelected.accept(gradientBox.getColor()); + return true; + } + + public void mouseReleased(double mouseX, double mouseY, int button) { + gradientSlider.onRelease(mouseX, mouseY, button); + gradientBox.onRelease(mouseX, mouseY, button); + } + + public void mouseDragged(double mouseX, double mouseY, int button) { + if(!display){ + return; + } + gradientSlider.onDrag(mouseX, mouseY, button); + gradientBox.setHue(gradientSlider.getHue()); + gradientBox.onDrag(mouseX, mouseY, button); + onColorSelected.accept(gradientBox.getColor()); + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java new file mode 100644 index 0000000..149c595 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -0,0 +1,52 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +public class ColorPickerButton { + private int x; + private int y; + private final int width; + private final int height; + private boolean isPicking = false; + + public ColorPickerButton(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public void render(DrawContext drawContext, int x, int y) { + this.x = x; + this.y = 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.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, "Pick", x + width / 2, y + (height - 8) / 2, 0xFFFFFFFF); + drawContext.getMatrices().pop(); + } + + public int getHeight() { + return height; + } + + public boolean onClick(double mouseX, double mouseY, int button) { + if (button == 0) { + if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { + isPicking = true; + return true; + } + } + return false; + } + + public boolean isPicking() { + return isPicking; + } + + public void setPicking(boolean picking) { + isPicking = picking; + } +} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java new file mode 100644 index 0000000..844be56 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java @@ -0,0 +1,132 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; + +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.widget.Widget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +import java.awt.*; + +public class GradientBox { + private final int size; + private final float alphaSpeed = 0.05f; + private int x; + private int y; + private float hue = 0.0f; + private float saturation = 1.0f; + private float value = 1.0f; + private boolean isDragging = false; + private float alpha = 0.0f; + + + public GradientBox(int x, int y, int size) { + this.x = x; + this.y = y; + this.size = size; + } + + public void tick() { + // Update the alpha + alpha += alphaSpeed; + if (alpha > 1.0f) { + alpha = 1.0f; + } + } + + public void render(DrawContext drawContext, int x, int y) { + setPosition(x,y); + drawContext.getMatrices().push(); + drawContext.getMatrices().translate(0,0,406); + DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + size + 2, y + size + 2, -1); + + // Draw the gradient + com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size,2); + /* for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + float saturation = (float) i / size; + float value = 1.0f - (float) j / size; + int color = Color.HSBtoRGB(hue, saturation, value); + color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); + drawContext.fill(x + i, y + j, x + i + 1, y + j + 1, color); + } + } + */ + + // Draw the handle + float handleSize = 3; + float handleX = x + saturation * size - handleSize / 2.0f; + float handleY = y + (1.0f - value) * size - handleSize / 2.0f; + + DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleSize), (int) (handleY + handleSize), -1); + drawContext.getMatrices().pop(); + } + public void defaultValues(){ + alpha = 0.0f; + } + + + /** + * Sets position. + * + * @param x - X position to set. + * @param y - Y position to set. + */ + public void setPosition(int x, int y) { + this.x = x; + this.y = y; + } + + public void onClick(double mouseX, double mouseY, int button) { + if (button == 0) { + float handleSize = 5; + float handleX = x + saturation * size - handleSize / 2.0f; + float handleY = y + (1.0f - value) * size - handleSize / 2.0f; + + 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.isDragging = true; + } + } + } + + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseX >= x && mouseX <= x + size && mouseY >= y && mouseY <= y + size; + } + + public void onRelease(double mouseX, double mouseY, int button) { + if (button == 0) { + isDragging = false; + } + } + + 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); + + value = 1.0f - (float) (mouseY - y) / size; + value = Math.max(0, value); + value = Math.min(1, value); + } + } + + public void setHue(float hue) { + this.hue = hue; + } + + public void setSaturation(float saturation) { + this.saturation = saturation; + } + + public void setValue(float value) { + this.value = value; + } + + public int getColor() { + return Color.HSBtoRGB(hue, saturation, value); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java new file mode 100644 index 0000000..b0e396b --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java @@ -0,0 +1,132 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; + +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.widget.Widget; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +import java.awt.*; + +public class GradientSlider { + private final int width; + private final int height; + private final float progressSpeed = 0.1f; + private final float alphaSpeed = 0.05f; + private int x; + private int y; + private float hue = 0.0f; + private float progress = 0.0f; + private boolean isDragging = false; + private float alpha = 0.0f; + + public GradientSlider(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public void tick() { + // Update the progress + progress += progressSpeed; + if (progress > 1.0f) { + progress = 1.0f; + } + + // Update the alpha + alpha += alphaSpeed; + if (alpha > 1.0f) { + alpha = 1.0f; + } + } + public void defaultValues(){ + progress = 0.0f; + alpha = 0.0f; + } + + /** + * Sets position. + * + * @param x - X position to set. + * @param y - Y position to set. + */ + public void setPosition(int x, int y) { + this.x = x; + this.y = y; + } + + public void render(DrawContext drawContext, int x, int y) { + setPosition(x,y); + drawContext.getMatrices().push(); + drawContext.getMatrices().translate(0,0,401); + DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + width + 2, y + height + 2, -1); + + // Draw the gradient + + for (int i = 0; i < width; i++) { + float hue = (float) i / width; + int color = Color.HSBtoRGB(hue, 1.0f, 1.0f); + color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); + drawContext.fill(x + i, y, x + i + 1, y + height, color); + } + + + // Draw the handle + if (progress >= 1.0f) { + float handleWidth = 3; + float handleHeight = height + 4; + float handleX = x + hue * width - handleWidth / 2.0f; + float handleY = y - (handleHeight - height) / 2.0f; + + DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); + } + drawContext.getMatrices().pop(); + } + + public int getHeight() { + return height; + } + + public void onClick(double mouseX, double mouseY, int button) { + if (button == 0) { + float handleWidth = 3; + float handleHeight = height + 4; + float handleX = x + hue * width - handleWidth / 2.0f; + float handleY = y - (handleHeight - height) / 2.0f; + + 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.isDragging = true; + } + } + } + + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + + public void onRelease(double mouseX, double mouseY, int button) { + if (button == 0) { + isDragging = false; + } + } + + 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); + } + } + + public float getHue() { + return hue; + } + + public void setHue(float hue) { + this.hue = hue; + } +} + diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index c88e184..f972f24 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -3,10 +3,7 @@ import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.DoubleOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.EnumOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.ListOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.*; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -27,9 +24,10 @@ public class TextWidget extends Widget { protected boolean rainbow; // Whether to apply a rainbow effect to the text protected int rainbowSpeed = 2; //Speed of the rainbow effect private ContextMenu menu; + public Color textColor; public TextWidget() { - this(null,null,false,false,"unknown"); + this(null,null,false,false,Color.WHITE,"unknown"); } /** @@ -39,30 +37,15 @@ public TextWidget() { * @param shadow * @param rainbow */ - public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,String modID) { + public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,Color color,String modID) { super(DATA,modID); this.dynamicRegistryKey = dynamicRegistryKey; textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; this.rainbow = rainbow; + this.textColor = color; createMenu(); } - 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)); - menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); - AtomicReference testss = new AtomicReference<>(test.TEST); - List options = Arrays.asList("TEST","TEST2","TEST23"); - AtomicReference option = new AtomicReference<>("TEST"); - menu.addOption(new EnumOption("Test", testss::get, testss::set,test.values())); - menu.addOption(new ListOption("New", option::get, option::set,options )); - } - public enum test{ - TEST, - TEST_2, - TEST_3 - } /** * Searches for the supplier within the {@link DynamicValueRegistry#localRegistry} using the given registryKey and registryValue @@ -71,25 +54,45 @@ public enum test{ * @param shadow * @param rainbow */ - public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, boolean shadow, boolean rainbow,String modID) { + public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, 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.shadow = shadow; this.rainbow = rainbow; createMenu(); } + public void createMenu(){ + System.out.println("TextColor: " + this.textColor); + 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)); + menu.addOption(new ColorOption("TextColor",()-> textColor, value -> textColor = value)); + menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); + AtomicReference testss = new AtomicReference<>(test.TEST); + List options = Arrays.asList("TEST","TEST2","TEST23"); + AtomicReference option = new AtomicReference<>("TEST"); + AtomicReference testColor = new AtomicReference<>(new Color(102)); + menu.addOption(new EnumOption("Test", testss::get, testss::set,test.values())); + menu.addOption(new ListOption("New", option::get, option::set,options )); + } + public enum test{ + TEST, + TEST_2, + TEST_3 + } @Override public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { menu.render(drawContext, getX() - 2, getY(), (int) Math.ceil(getHeight())); - int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (float) (5000f * rainbowSpeed))) : Color.WHITE.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, (int) getX(), (int) getY(), color, shadow); + drawContext.drawText(mc.textRenderer, text,getX(), getY(), color, shadow); widgetBox.setSizeAndPosition(getX() - 2, getY() - 2, mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2); } } @@ -127,6 +130,7 @@ public void writeToTag(NbtCompound tag) { tag.putString("DynamicRegistryKey",dynamicRegistryKey); tag.putBoolean("Shadow",shadow); tag.putBoolean("Rainbow",rainbow); + tag.putInt("TextColor",textColor.getRGB()); tag.putInt("RainbowSpeed",rainbowSpeed); // If true then it means that we should use local registry and if false (i.e. null) then use global registry @@ -136,24 +140,24 @@ public void writeToTag(NbtCompound tag) { @Override public void readFromTag(NbtCompound tag) { super.readFromTag(tag); - shadow = tag.getBoolean("Shadow"); - rainbow = tag.getBoolean("Rainbow"); - rainbowSpeed = tag.getInt("RainbowSpeed"); - - dynamicRegistryKey = tag.getString("DynamicRegistryKey"); + this.shadow = tag.getBoolean("Shadow"); + this.rainbow = tag.getBoolean("Rainbow"); + this.rainbowSpeed = tag.getInt("RainbowSpeed"); + 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){ - textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); + 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 - textSupplier = (Supplier) dvr.get(dynamicRegistryKey); + this.textSupplier = (Supplier) dvr.get(dynamicRegistryKey); return; } createMenu(); @@ -163,6 +167,7 @@ public static class Builder extends WidgetBuilder { protected boolean rainbow = false; protected String dynamicRegistryKey = ""; DynamicValueRegistry dynamicValueRegistry = null; + Color textColor = Color.WHITE; public Builder shadow(boolean shadow) { this.shadow = shadow; @@ -181,6 +186,10 @@ public Builder setDVR(DynamicValueRegistry dynamicValueRegistry) { this.dynamicValueRegistry = dynamicValueRegistry; return self(); } + public Builder setTextColor(Color textColor) { + this.textColor = textColor; + return self(); + } @Override protected Builder self() { @@ -191,9 +200,9 @@ protected Builder self() { public TextWidget build() { TextWidget widget; if(dynamicValueRegistry == null) { - widget = new TextWidget(dynamicRegistryKey, shadow, rainbow,modID); + widget = new TextWidget(dynamicRegistryKey, shadow, rainbow,textColor,modID); }else{ - widget = new TextWidget(dynamicValueRegistry,dynamicRegistryKey, shadow, rainbow,modID); + widget = new TextWidget(dynamicValueRegistry,dynamicRegistryKey, shadow, rainbow,textColor,modID); } widget.setPosition(x,y); widget.setDraggable(isDraggable); diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java index 4b6275f..2d533aa 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java @@ -272,9 +272,9 @@ private void drawOptions(DrawContext drawContext, TextRenderer textRenderer) { for (ContextMenuOption option : options) { if (option instanceof EnumCycleContextMenuOption enumOption) { enumOption.updateLabel(); - labelTextcolor = ColorHelper.ColorToInt(Color.WHITE); + labelTextcolor = Color.WHITE.getRGB(); } else if (option instanceof DataInputOption) { - labelTextcolor = ColorHelper.ColorToInt(Color.YELLOW); + labelTextcolor = Color.YELLOW.getRGB(); // Draw a black box around the value text String[] splitLabel = option.label.split(":"); From ac25bf7d05b061b91b33580c7991a4ff11307176 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:06:18 +0530 Subject: [PATCH 16/33] Working on API --- .../newTrial/config/GlobalConfig.java | 3 + .../newTrial/helpers/ColorHelper.java | 145 +++++++++++ .../newTrial/helpers/TextureHelper.java | 233 ++++++++++++++++++ .../{ => coloroption}/ColorOption.java | 14 +- .../dynamichud/newTrial/widget/Widget.java | 6 + .../newTrial/widgets/TextWidget.java | 3 +- 6 files changed, 397 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java rename src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/{ => coloroption}/ColorOption.java (82%) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java index a7a25cc..e59ad0c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java @@ -20,6 +20,9 @@ public class GlobalConfig { .build()) .build(); + /** + * Common scale for all widgets. Set by the user using YACL. + */ @SerialEntry public float scale = 1.0f; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java new file mode 100644 index 0000000..8a35f38 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java @@ -0,0 +1,145 @@ +package com.tanishisherewith.dynamichud.newTrial.helpers; + +import net.minecraft.util.math.MathHelper; + +import java.awt.*; + +/** + * This class provides helper methods for working with colors. + */ +public class ColorHelper { + public static int r, g, b, a; + public ColorHelper(int r, int g, int b) { + this.r = r; + this.g = g; + this.b = b; + this.a = 255; + validate(); + } + public ColorHelper() { + } + public void validate() { + if (r < 0) r = 0; + else if (r > 255) r = 255; + + if (g < 0) g = 0; + else if (g > 255) g = 255; + + if (b < 0) b = 0; + else if (b > 255) b = 255; + + if (a < 0) a = 0; + else if (a > 255) a = 255; + } + /** + * Returns a color as an integer value given its red, green and blue components. + * + * @param red The red component of the color + * @param green The green component of the color + * @param blue The blue component of the color + * @return The color as an integer value + */ + public static int getColor(int red, int green, int blue) { + return getColor(red, green, blue, 255); + } + + /** + * Returns a color as an integer value given its red, green, blue and alpha components. + * + * @param red The red component of the color + * @param green The green component of the color + * @param blue The blue component of the color + * @param alpha The alpha component of the color + * @return The color as an integer value + */ + public static int getColor(int red, int green, int blue, int alpha) { + return (alpha << 24) | (red << 16) | (green << 8) | blue; + } + + public static Color getColorFromInt(int color) { + int red = (color >> 16) & 0xFF; + int green = (color >> 8) & 0xFF; + int blue = color & 0xFF; + return new Color(red, green, blue); + } + + /** + * Returns a color as an integer value given its hue. + * + * @param hue The hue of the color + * @return The color as an integer value + */ + public static int getColorFromHue(float hue) { + return Color.HSBtoRGB(hue, 1.0f, 1.0f); + } + + /** + * Converts a color to an integer. + * + * @param color The color to convert + * @return The integer representation of the JWT color + */ + public static int ColorToInt(Color color) { + return color.getRGB(); + } + public static float[] getRainbowColor() + { + float x = System.currentTimeMillis() % 2000 / 1000F; + float pi = (float)Math.PI; + + float[] rainbow = new float[3]; + rainbow[0] = 0.5F + 0.5F * MathHelper.sin(x * pi); + rainbow[1] = 0.5F + 0.5F * MathHelper.sin((x + 4F / 3F) * pi); + rainbow[2] = 0.5F + 0.5F * MathHelper.sin((x + 8F / 3F) * pi); + return rainbow; + } + + /** + * Rainbow color with custom speed. + * + * @param speed + * @return Current rainbow color. + */ + public static Color getRainbowColor(int speed) { + float hue = (System.currentTimeMillis() % (speed * 100)) / (speed * 100.0f); + return Color.getHSBColor(hue, 1.0f, 1.0f); + } + + + /** + * Changes alpha on color. + * + * @param color Target color. + * @param alpha Target alpha. + * @return Color with changed alpha. + */ + public static Color changeAlpha(Color color, int alpha) { + if (color != null) + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + else + return new Color(0); + } + public static int fromRGBA(int r, int g, int b, int a) { + return (r << 16) + (g << 8) + (b) + (a << 24); + } + + public static int toRGBAR(int color) { + return (color >> 16) & 0x000000FF; + } + + public static int toRGBAG(int color) { + return (color >> 8) & 0x000000FF; + } + + public static int toRGBAB(int color) { + return (color) & 0x000000FF; + } + + public static int toRGBAA(int color) { + return (color >> 24) & 0x000000FF; + } + public int toInt() + { + return new Color(r,b,g,a).getRGB(); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java new file mode 100644 index 0000000..37c36c6 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java @@ -0,0 +1,233 @@ +package com.tanishisherewith.dynamichud.newTrial.helpers; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.tanishisherewith.dynamichud.util.CustomItemRenderer; +import com.tanishisherewith.dynamichud.util.CustomTextRenderer; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; + +/** + * This class provides helper methods for drawing textures on the screen. + */ +public class TextureHelper extends DrawContext { + public static CustomTextRenderer customTextRenderer; + public static CustomItemRenderer customItemRenderer; + + + public TextureHelper(MinecraftClient client, VertexConsumerProvider.Immediate vertexConsumers) { + super(client, vertexConsumers); + } + + /** + * Draws an item texture on the screen. + * + * @param itemStack The item stack to render the texture for + * @param x The x position to draw the texture at + * @param y The y position to draw the texture at + */ + public static void drawItemTexture(DrawContext drawContext, + ItemStack itemStack, + int x, + int y) { + drawContext.drawItem(itemStack, x, y); + } + + /** + * Draws the texture of the item in the player's main hand on the screen. + * + * @param client The Minecraft client instance + * @param x The x position to draw the texture at + * @param y The y position to draw the texture at + */ + public static void drawMainHandTexture(DrawContext drawContext, + MinecraftClient client, + int x, + int y) { + assert client.player != null; + ItemStack mainHandItem = client.player.getMainHandStack(); + drawItemTexture(drawContext, mainHandItem, x, y); + } + + /** + * Draws a textured rectangle on the screen. + * + * @param x The x position of the top left corner of the rectangle + * @param y The y position of the top left corner of the rectangle + * @param u The x position of the texture within the texture image + * @param v The y position of the texture within the texture image + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param textureWidth The width of the texture image + * @param textureHeight The height of the texture image + */ + public static void drawTexture(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + drawContext.drawTexture(texture, x, y, u, v, width, height, textureWidth, textureHeight); + } + + /** + * Draws a textured rectangle on the screen with a specified color. + * + * @param x The x position of the top left corner of the rectangle + * @param y The y position of the top left corner of the rectangle + * @param u The x position of the texture within the texture image + * @param v The y position of the texture within the texture image + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param color The color to draw the rectangle with + */ + public static void drawTexturedRect(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int color) { + RenderSystem.setShaderColor((color >> 16 & 255) / 255.0F, + (color >> 8 & 255) / 255.0F, + (color & 255) / 255.0F, + (color >> 24 & 255) / 255.0F); + drawContext.drawTexture(texture, x, y, u, v, width, height); + } + + /** + * Draws an item texture on the screen with text at a specified position relative to it. + * + * @param textRenderer The text renderer instance used for rendering the text + * @param itemStack The item stack to render the texture for + * @param x The x position to draw the texture at + * @param y The y position to draw the texture at + * @param text The text to draw relative to the texture + * @param color The color to draw the text with + * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) + * @param scale The scale factor to apply to the text (1.0 is normal size) + */ + public static void drawItemTextureWithText(DrawContext drawContext, + TextRenderer textRenderer, + ItemStack itemStack, + int x, + int y, + String text, + int color, + Position position, + float scale, + boolean textBackground + ) { + // Calculate the position of the text based on its size and the specified position + int textWidth = (int) (textRenderer.getWidth(text) * scale); + int textHeight = (int) (textRenderer.fontHeight * scale); + int textX = 0; + int textY = 0; + switch (position) { + case ABOVE -> { + textX = x + (16 - textWidth) / 2; + textY = y - textHeight; + } + case BELOW -> { + textX = x + (17 - textWidth) / 2; + textY = y + 16; + } + case LEFT -> { + textX = x - textWidth - 2; + textY = y + (16 - textHeight) / 2; + } + case RIGHT -> { + textX = x + 18; + textY = y + (16 - textHeight) / 2; + } + } + + // Draw semi-opaque black rectangle + if (text != null) { + if (textBackground && !text.trim().isEmpty()) { + int backgroundColor = 0x40000000; // ARGB format: 50% opaque black + drawContext.fill(textX - 1, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); + } + // Draw the scaled text at the calculated position + drawContext.getMatrices().push(); + drawContext.getMatrices().scale(scale, scale, 1.0f); + float scaledX = textX / scale; + float scaledY = textY / scale; + drawContext.drawText(textRenderer, text, (int) scaledX, (int) scaledY, color, false); + drawContext.getMatrices().pop(); + } + // Draw the item texture + drawContext.drawItem(itemStack, x, y); + } + + /** + * Draws an item texture on the screen with text at a specified position relative to it. + * + * @param itemScale The scale for the item to be rendered at + * @param textRenderer The text renderer instance used for rendering the text + * @param itemStack The item stack to render the texture for + * @param x The x position to draw the texture at + * @param y The y position to draw the texture at + * @param text The text to draw relative to the texture + * @param color The color to draw the text with + * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) + * @param textScale The scale factor to apply to the text (1.0 is normal size) + */ + public static void drawItemTextureWithTextAndScale(DrawContext drawContext, + float itemScale, + TextRenderer textRenderer, + ItemStack itemStack, + int x, + int y, + String text, + int color, + Position position, + float textScale, + boolean textBackground) { + if (text != null && !text.trim().isEmpty()) { + // Calculate the position of the text based on its size and the specified position + int textWidth = (int) (textRenderer.getWidth(text) * textScale); + int textHeight = (int) (textRenderer.fontHeight * textScale); + int textX = switch (position) { + case ABOVE, BELOW -> x + (int) ((16 * itemScale - textWidth) / 2); + case LEFT -> x - textWidth - 2; + case RIGHT -> x + (int) (16 * itemScale + 2); + }; + int textY = switch (position) { + case ABOVE -> y - textHeight - 2; + case BELOW -> y + (int) (16 * itemScale + 2); + case LEFT, RIGHT -> y + (int) ((16 * itemScale - textHeight) / 2); + }; + + // Draw semi-opaque black rectangle + if (textBackground) { + int backgroundColor = 0x40000000; // ARGB format: 50% opaque black + drawContext.fill(textX, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); + } + + // Draw the scaled text at the calculated position + drawContext.getMatrices().push(); + drawContext.getMatrices().scale(textScale, textScale, 11.0f); + float scaledX = textX / textScale; + float scaledY = textY / textScale; + drawContext.drawText(textRenderer, text, (int) scaledX + 1, (int) scaledY +1, color, false); + drawContext.getMatrices().pop(); + } + customItemRenderer = new CustomItemRenderer(itemStack, itemScale); + customItemRenderer.draw(drawContext, x, y, color); + } + + public enum Position { + ABOVE("Above"), + RIGHT("Right"), + BELOW("Below"), + LEFT("Left"); + private final String name; + + Position(String name) { + this.name = name; + } + + public static Position getByUpperCaseName(String name) { + if (name == null || name.isEmpty()) { + return null; + } + + return Position.valueOf(name.toUpperCase()); + } + } + + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java similarity index 82% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java rename to src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java index e5a09af..05a3fa2 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java @@ -1,8 +1,8 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption.ColorGradientPicker; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -14,10 +14,12 @@ public class ColorOption extends Option { public String name = "Empty"; public boolean isVisible = false; private ColorGradientPicker colorPicker = null; - public ColorOption(String name, Supplier getter, Consumer setter) { + public ContextMenu parentMenu = null; + public ColorOption(String name,ContextMenu parentMenu, Supplier getter, Consumer setter) { super(getter, setter); this.name = name; - colorPicker = new ColorGradientPicker(x + this.width + 50,y,value,color-> set(new Color(color)),50,100 ); + this.parentMenu = parentMenu; + colorPicker = new ColorGradientPicker(x + parentMenu.width + 2,y,value,color-> set(new Color(color)),50,100 ); } @Override @@ -40,7 +42,7 @@ public void render(DrawContext drawContext, int x, int y) { 1, 1 ); - colorPicker.render(drawContext,x + this.width + 50,y); + colorPicker.render(drawContext,x + parentMenu.width + 2,y); } @Override @@ -49,7 +51,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { isVisible = !isVisible; if(isVisible) { - colorPicker.setPos(x + this.width + 50,y); + colorPicker.setPos(x + parentMenu.width + 2,y); colorPicker.display(); }else{ colorPicker.close(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 4b8b1ae..7661e71 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -47,6 +47,12 @@ public abstract class Widget { protected float yPercent; public boolean shouldScale = true; + /** + * Scale of the current widget. + * @see GlobalConfig#scale + */ + protected float scale = 1.0f; + /** * An identifier for widgets to group them under one ID. *

diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index f972f24..f25a1f7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -4,6 +4,7 @@ import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.*; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption.ColorOption; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -71,7 +72,7 @@ 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)); - menu.addOption(new ColorOption("TextColor",()-> textColor, value -> textColor = value)); + menu.addOption(new ColorOption("TextColor",menu,()-> textColor, value -> textColor = value)); menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); AtomicReference testss = new AtomicReference<>(test.TEST); List options = Arrays.asList("TEST","TEST2","TEST23"); From a350075db1ea4f967b929e78ec7249d29e3e5557 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Wed, 10 Apr 2024 23:00:00 +0530 Subject: [PATCH 17/33] More changes and some fixes for multi - widget renderers of same mod. AlphaSlider as well. --- .../dynamichud/mixins/ScreenMixin.java | 2 - .../dynamichud/newTrial/DynamicHUD.java | 37 +++++--- .../{ => newTrial}/DynamicHudIntegration.java | 10 ++- .../dynamichud/newTrial/DynamicHudTest.java | 3 - .../newTrial/DynamicHudTestTWO.java | 80 +++++++++++++++++ .../utils/contextmenu/ContextMenu.java | 4 - .../options/coloroption/AlphaSlider.java | 86 +++++++++++++++++++ .../coloroption/ColorGradientPicker.java | 22 +++-- .../options/coloroption/ColorOption.java | 8 +- .../dynamichud/newTrial/widget/Widget.java | 13 +-- .../newTrial/widget/WidgetManager.java | 2 +- .../newTrial/widgets/TextWidget.java | 1 - src/main/resources/fabric.mod.json | 3 +- 13 files changed, 230 insertions(+), 41 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/{ => newTrial}/DynamicHudIntegration.java (92%) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index a40ebd6..226f3ad 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.mixins; -import com.tanishisherewith.dynamichud.DynamicHudIntegration; import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; -import com.tanishisherewith.dynamichud.newTrial.DynamicHudTest; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import net.minecraft.client.MinecraftClient; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 92c3277..53028db 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -1,12 +1,11 @@ package com.tanishisherewith.dynamichud.newTrial; -import com.tanishisherewith.dynamichud.DynamicHudIntegration; import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; -import com.tanishisherewith.dynamichud.util.DynamicUtil; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; @@ -15,7 +14,6 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.ModMetadata; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.option.KeyBinding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,14 +21,20 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.concurrent.CountDownLatch; public class DynamicHUD implements ClientModInitializer { public static MinecraftClient MC = MinecraftClient.getInstance(); public static String MOD_ID = "dynamichud"; private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); private static final List widgetRenderers = new ArrayList<>(); + /** + * 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> fileMap = new HashMap<>(); public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { widgetRenderers.add(widgetRenderer); @@ -81,13 +85,22 @@ public void onInitializeClient() { screen = DHIntegration.getMovableScreen(); - KeyBinding binding =DHIntegration.EDITOR_SCREEN_KEY_BINDING; + KeyBinding binding = DHIntegration.getKeyBind(); DHIntegration.registerCustomWidgets(); WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); addWidgetRenderer(widgetRenderer); + List widgets = fileMap.get(widgetsFile.getName()); + + if(widgets == null) { + fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + }else{ + widgetRenderer.getWidgets().addAll(widgets); + fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + } + //Register events for rendering, saving, loading, and opening the hudEditor ClientTickEvents.START_CLIENT_TICK.register((client)-> { openDynamicScreen(binding, screen); @@ -95,10 +108,10 @@ public void onInitializeClient() { // Save during exiting a world, server or Minecraft itself // Also saved when a resource pack is reloaded. - ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile)); - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile)); - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile)); - Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile))); + ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); + ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); + Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName())))); printInfo(String.format("Integration of mod %s was successful",modId)); } catch (Throwable e) { @@ -118,11 +131,11 @@ public void onInitializeClient() { HudRenderCallback.EVENT.register(new HudRender()); } - private void saveWidgetsSafely(File widgetsFile) { + private void saveWidgetsSafely(File widgetsFile, List widgets) { try { - WidgetManager.saveWidgets(widgetsFile); + WidgetManager.saveWidgets(widgetsFile,widgets); } catch (IOException e) { - logger.error("Failed to save widgets"); + 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/newTrial/DynamicHudIntegration.java similarity index 92% rename from src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java rename to src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java index e92e3dc..6e76760 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud; +package com.tanishisherewith.dynamichud.newTrial; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; @@ -94,6 +94,14 @@ default void initAfter(){} default File getWidgetsFile() { return WIDGETS_FILE; } + /** + * Returns the keybind to open the {@link AbstractMoveableScreen} instance. + * + * @return The keybind. + */ + default KeyBinding getKeyBind() { + return EDITOR_SCREEN_KEY_BINDING; + } /** * Returns the movable screen for the DynamicHud. diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index 83f5bd9..ff97576 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -1,14 +1,11 @@ package com.tanishisherewith.dynamichud.newTrial; -import com.tanishisherewith.dynamichud.DynamicHudIntegration; -import com.tanishisherewith.dynamichud.huds.MoveableScreen; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; -import com.tanishisherewith.dynamichud.util.DynamicUtil; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java new file mode 100644 index 0000000..59f0b34 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java @@ -0,0 +1,80 @@ +package com.tanishisherewith.dynamichud.newTrial; + +import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.newTrial.widget.Widget; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; +import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.minecraft.client.gui.screen.TitleScreen; +import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; +import net.minecraft.client.gui.screen.option.OptionsScreen; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL; + +import java.io.File; +import java.util.List; + +public class DynamicHudTestTWO implements DynamicHudIntegration { + TextWidget textWidget; + WidgetRenderer renderer; + @Override + public void init() { + //Global registry + DynamicValueRegistry.registerGlobal("CPS",() -> "NOT FPS"); + + + textWidget = new TextWidget.Builder() + .setX(150) + .setY(100) + .setDraggable(true) + .rainbow(true) + .setDRKey("CPS") + .setModID("CustomMod") + .shouldScale(true) + .build(); + } + + @Override + public KeyBinding getKeyBind() { + return KeyBindingHelper.registerKeyBinding(new KeyBinding( + "DynamicHUD editor screenn", + INPUT_TYPE, + GLFW.GLFW_KEY_RIGHT_CONTROL, + "CATEGORY 2" + )); + } + + @Override + public File getWidgetsFile() { + return new File(FILE_DIRECTORY,"widgets_new.nbt"); + } + + @Override + public void addWidgets() { + WidgetManager.addWidget(textWidget); + } + public void initAfter(){ + List widgets = WidgetManager.getWidgetsForMod("CustomMod"); + + renderer = new WidgetRenderer(widgets); + renderer.shouldRenderInGameHud(true); + renderer.addScreen(OptionsScreen.class); + renderer.addScreen(TitleScreen.class); + } + + @Override + public AbstractMoveableScreen getMovableScreen() { + return new AbstractMoveableScreen(Text.literal("Editor 2"), renderer) {}; + } + + @Override + public WidgetRenderer getWidgetRenderer() { + return renderer; + } + +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index ad4a9de..398037c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -13,7 +11,6 @@ public class ContextMenu { public int x,y; protected float scale = 0.0f; private final List> options = new ArrayList<>(); // The list of options in the context menu - private Widget selectedWidget; // The widget that this context menu is associated with public int width = 0; public int height = 0; public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light grey color @@ -24,7 +21,6 @@ public class ContextMenu { public ContextMenu(int x,int y){ this.x = x; this.y = y + heightOffset; - this.selectedWidget = selectedWidget; } public void addOption(Option option){ diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java new file mode 100644 index 0000000..4193f9e --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java @@ -0,0 +1,86 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; + +import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.math.MathHelper; + +import java.awt.*; + +public class AlphaSlider { + private final int width; + private final int height; + private int x; + private int y; + private boolean isDragging = false; + private Color color; + private int alphaHandleY = 0; + private float alpha; + public AlphaSlider(int x,int y,int width, int height, Color color) { + this.width = width; + this.height = height; + this.color = color; + this.x = x; + this.y = y; + alpha = color.getAlpha() / 255f; + } + + public void setColor(Color color) { + this.color = color; + } + public void render(DrawContext drawContext, int x, int y) { + this.x = x; + this.y = y; + + DrawHelper.drawOutlinedBox(drawContext,x - 2,y - 2,x + width + 2,y + height + 2,Color.WHITE.getRGB()); + DrawHelper.drawGradient(drawContext.getMatrices().peek().getPositionMatrix(),x,y,width,height,color.getRGB(), ColorHelper.changeAlpha(color,0).getRGB(), DrawHelper.Direction.TOP_BOTTOM); + drawContext.fill(x-2, y + alphaHandleY-1,x+width+2, y +alphaHandleY+1,Color.WHITE.getRGB()); + } + + public Color getColor() { + return ColorHelper.changeAlpha(color, (int) (alpha*255f)); + } + + public void onClick(double mouseX, double mouseY, int button) { + if (button == 0 && isMouseOver(mouseX, mouseY)) { + alphaHandleY = (int) mouseY-y; + alpha = 1.0f - (alphaHandleY / (float) height); + if(alpha < 0.0f){ + alpha = 0.0f; + }else if(alpha > 1.0f){ + alpha = 1.0f; + } + this.isDragging = true; + } + } + + public void setY(int y) { + this.y = y; + } + + public void setX(int x) { + this.x = x; + } + + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + + public void onRelease(double mouseX, double mouseY, int button) { + if (button == 0) { + isDragging = false; + } + } + + public void onDrag(double mouseX, double mouseY, int button) { + if (isDragging && isMouseOver(mouseX, mouseY)) { + alphaHandleY = (int) mouseY-y; + alpha = 1.0f - (alphaHandleY / (float) height); + if(alpha < 0.0f){ + alpha = 0.0f; + }else if(alpha > 1.0f){ + alpha = 1.0f; + } + } + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 5f3d0b0..379060e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -14,20 +14,20 @@ public class ColorGradientPicker { MinecraftClient client = MinecraftClient.getInstance(); - private final Consumer onColorSelected; // The callback to call when a color is selected + private final Consumer onColorSelected; // The callback to call when a color is selected private final GradientSlider gradientSlider; private final GradientBox gradientBox; private final ColorPickerButton colorPickerButton; + private final AlphaSlider alphaSlider; private int x,y; private final int boxSize; private boolean display = false; - public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { + public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { this.x = x; this.y = y; this.onColorSelected = onColorSelected; - 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 = new GradientSlider(x, y, colors, 10); this.gradientSlider.setHue(hsv[0]); @@ -36,6 +36,8 @@ public ColorGradientPicker(int x, int y, Color initialColor, Consumer o this.gradientBox.setHue(hsv[0]); this.gradientBox.setSaturation(hsv[1]); this.gradientBox.setValue(hsv[2]); + + this.alphaSlider = new AlphaSlider(x,y,10,boxSize,initialColor); this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 35, 20); } public void setPos(int x, int y){ @@ -66,7 +68,8 @@ public void render(DrawContext drawContext, int x1, int y1) { tick(); gradientSlider.render(drawContext,x + 30, y +client.textRenderer.fontHeight + 4); gradientBox.render(drawContext,x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); - colorPickerButton.render(drawContext,x+ 40 + boxSize,y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 7); + colorPickerButton.render(drawContext,x+ 55 + boxSize,y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); + alphaSlider.render(drawContext,x + 40 + boxSize,y + client.textRenderer.fontHeight +gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking()) { // Draw the cursor @@ -118,13 +121,16 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { colorPickerButton.setPicking(false); } - onColorSelected.accept(gradientBox.getColor()); + alphaSlider.setColor(new Color(gradientBox.getColor())); + alphaSlider.onClick(mouseX, mouseY, button); + onColorSelected.accept(alphaSlider.getColor()); return true; } public void mouseReleased(double mouseX, double mouseY, int button) { gradientSlider.onRelease(mouseX, mouseY, button); gradientBox.onRelease(mouseX, mouseY, button); + alphaSlider.onRelease(mouseX, mouseY, button); } public void mouseDragged(double mouseX, double mouseY, int button) { @@ -134,7 +140,9 @@ public void mouseDragged(double mouseX, double mouseY, int button) { gradientSlider.onDrag(mouseX, mouseY, button); gradientBox.setHue(gradientSlider.getHue()); gradientBox.onDrag(mouseX, mouseY, button); - onColorSelected.accept(gradientBox.getColor()); + alphaSlider.setColor(new Color(gradientBox.getColor())); + alphaSlider.onDrag(mouseX, mouseY, button); + onColorSelected.accept(alphaSlider.getColor()); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java index 05a3fa2..f32c4e5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java @@ -19,13 +19,13 @@ public ColorOption(String name,ContextMenu parentMenu, Supplier getter, C super(getter, setter); this.name = name; this.parentMenu = parentMenu; - colorPicker = new ColorGradientPicker(x + parentMenu.width + 2,y,value,color-> set(new Color(color)),50,100 ); + colorPicker = new ColorGradientPicker(x + this.parentMenu.width + 10,y - 10,value, this::set,50,100 ); } @Override public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); - value = get(); + System.out.println(value.getAlpha()); int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); this.height = mc.textRenderer.fontHeight; @@ -42,7 +42,7 @@ public void render(DrawContext drawContext, int x, int y) { 1, 1 ); - colorPicker.render(drawContext,x + parentMenu.width + 2,y); + colorPicker.render(drawContext,this.x + parentMenu.width + 10,y - 10); } @Override @@ -51,7 +51,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { isVisible = !isVisible; if(isVisible) { - colorPicker.setPos(x + parentMenu.width + 2,y); + colorPicker.setPos(x + parentMenu.width + 10,y - 10); colorPicker.display(); }else{ colorPicker.close(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 7661e71..6b97669 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -34,7 +34,8 @@ public abstract class Widget { //To enable/disable snapping public boolean shiftDown = false; - + public int snapBoxWidth,snapBoxHeight; + public static int snapSize = 1; // Used for dragging and snapping int startX, startY; @@ -144,6 +145,7 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } + } /** @@ -153,6 +155,10 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); } + // Calculate the size of each snap box + snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; + snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; + renderWidgetInEditor(drawContext,mouseX,mouseY); if (shouldScale) { @@ -202,6 +208,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { + Widget.snapSize = snapSize; if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { int newX = (int) (mouseX - startX); int newY = (int) (mouseY - startY); @@ -209,10 +216,6 @@ 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) { - // Calculate the size of each snap box - int snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; - int snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; - // Calculate the index of the snap box that the new position would be in int snapBoxX = newX / snapBoxWidth; int snapBoxY = newY / snapBoxHeight; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 4af54ff..6feb340 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -147,7 +147,7 @@ public static void onScreenResized(int newWidth, int newHeight, int previousWidt * * @param file The file to save to */ - public static void saveWidgets(File file) throws IOException { + public static void saveWidgets(File file,List widgets) throws IOException { NbtCompound rootTag = new NbtCompound(); NbtList widgetList = new NbtList(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index f25a1f7..df53480 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -68,7 +68,6 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist createMenu(); } public void createMenu(){ - System.out.println("TextColor: " + this.textColor); 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)); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cb56d52..616fb5f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -22,7 +22,8 @@ "com.tanishisherewith.dynamichud.newTrial.DynamicHUD" ], "dynamicHud": [ - "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest" + "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest", + "com.tanishisherewith.dynamichud.newTrial.DynamicHudTestTWO" ], "modmenu": [ "com.tanishisherewith.dynamichud.ModMenuIntegration" From 031c8af902aec49f5aff4a7b8f907bd4266f3434 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:13:49 +0530 Subject: [PATCH 18/33] More changes and fixes. Scaling improved. --- .../newTrial/DynamicHudTestTWO.java | 6 +- .../screens/AbstractMoveableScreen.java | 14 ++-- .../coloroption/ColorGradientPicker.java | 12 +--- .../options/coloroption/ColorOption.java | 3 +- .../options/coloroption/GradientBox.java | 24 ------- .../options/coloroption/GradientSlider.java | 25 +------ .../dynamichud/newTrial/widget/Widget.java | 53 +++++++-------- .../dynamichud/newTrial/widget/WidgetBox.java | 66 +++++++++++++++++++ .../newTrial/widget/WidgetManager.java | 15 +++-- .../newTrial/widgets/TextWidget.java | 31 +++++---- .../dynamichud/widget/Widget.java | 2 +- .../dynamichud/widget/WidgetBox.java | 11 +++- src/main/resources/fabric.mod.json | 3 +- 13 files changed, 135 insertions(+), 130 deletions(-) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java index 59f0b34..a449c5e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java @@ -20,7 +20,7 @@ import java.util.List; public class DynamicHudTestTWO implements DynamicHudIntegration { - TextWidget textWidget; + TextWidget exampleWidget; WidgetRenderer renderer; @Override public void init() { @@ -28,7 +28,7 @@ public void init() { DynamicValueRegistry.registerGlobal("CPS",() -> "NOT FPS"); - textWidget = new TextWidget.Builder() + exampleWidget = new TextWidget.Builder() .setX(150) .setY(100) .setDraggable(true) @@ -56,7 +56,7 @@ public File getWidgetsFile() { @Override public void addWidgets() { - WidgetManager.addWidget(textWidget); + WidgetManager.addWidget(exampleWidget); } public void initAfter(){ List widgets = WidgetManager.getWidgetsForMod("CustomMod"); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index bc4a43d..ef22c98 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -1,12 +1,12 @@ package com.tanishisherewith.dynamichud.newTrial.screens; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; + public abstract class AbstractMoveableScreen extends Screen { - protected boolean ShouldPause = false; // To pause if the screen is opened or not + protected boolean shouldPause = false; // To pause if the screen is opened or not public final WidgetRenderer widgetRenderer; public int snapSize = 100; @@ -81,18 +81,12 @@ public void close() { } public void setShouldPause(boolean shouldPause) { - this.ShouldPause = shouldPause; - } - - - @Override - public void resize(MinecraftClient client, int width, int height) { - super.resize(client, width, height); + this.shouldPause = shouldPause; } @Override public boolean shouldPause() { - return ShouldPause; + return shouldPause; } public void setSnapSize(int size){ this.snapSize = size; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 379060e..afc4880 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -38,7 +38,7 @@ public ColorGradientPicker(int x, int y, Color initialColor, Consumer onC this.gradientBox.setValue(hsv[2]); this.alphaSlider = new AlphaSlider(x,y,10,boxSize,initialColor); - this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 35, 20); + this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 30, 18); } public void setPos(int x, int y){ this.x = x; @@ -50,22 +50,12 @@ public void display() { public void close() { display = false; } - public void tick() { - gradientSlider.tick(); - gradientBox.tick(); - } - public void defaultValues(){ - gradientSlider.defaultValues(); - gradientBox.defaultValues(); - } public void render(DrawContext drawContext, int x1, int y1) { setPos(x1,y1); if(!display){ - defaultValues(); return; } - tick(); gradientSlider.render(drawContext,x + 30, y +client.textRenderer.fontHeight + 4); gradientBox.render(drawContext,x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); colorPickerButton.render(drawContext,x+ 55 + boxSize,y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java index f32c4e5..bf870c6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java @@ -25,7 +25,6 @@ public ColorOption(String name,ContextMenu parentMenu, Supplier getter, C @Override public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); - System.out.println(value.getAlpha()); int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); this.height = mc.textRenderer.fontHeight; @@ -42,7 +41,7 @@ public void render(DrawContext drawContext, int x, int y) { 1, 1 ); - colorPicker.render(drawContext,this.x + parentMenu.width + 10,y - 10); + colorPicker.render(drawContext,this.x + width/3 + parentMenu.width + 10,y - 10); } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java index 844be56..e1b5fc8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java @@ -9,14 +9,12 @@ public class GradientBox { private final int size; - private final float alphaSpeed = 0.05f; private int x; private int y; private float hue = 0.0f; private float saturation = 1.0f; private float value = 1.0f; private boolean isDragging = false; - private float alpha = 0.0f; public GradientBox(int x, int y, int size) { @@ -24,15 +22,6 @@ public GradientBox(int x, int y, int size) { this.y = y; this.size = size; } - - public void tick() { - // Update the alpha - alpha += alphaSpeed; - if (alpha > 1.0f) { - alpha = 1.0f; - } - } - public void render(DrawContext drawContext, int x, int y) { setPosition(x,y); drawContext.getMatrices().push(); @@ -41,16 +30,6 @@ public void render(DrawContext drawContext, int x, int y) { // Draw the gradient com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size,2); - /* for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - float saturation = (float) i / size; - float value = 1.0f - (float) j / size; - int color = Color.HSBtoRGB(hue, saturation, value); - color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); - drawContext.fill(x + i, y + j, x + i + 1, y + j + 1, color); - } - } - */ // Draw the handle float handleSize = 3; @@ -60,9 +39,6 @@ public void render(DrawContext drawContext, int x, int y) { DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleSize), (int) (handleY + handleSize), -1); drawContext.getMatrices().pop(); } - public void defaultValues(){ - alpha = 0.0f; - } /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java index b0e396b..8aa7e32 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java @@ -10,14 +10,10 @@ public class GradientSlider { private final int width; private final int height; - private final float progressSpeed = 0.1f; - private final float alphaSpeed = 0.05f; private int x; private int y; private float hue = 0.0f; - private float progress = 0.0f; private boolean isDragging = false; - private float alpha = 0.0f; public GradientSlider(int x, int y, int width, int height) { this.x = x; @@ -26,23 +22,6 @@ public GradientSlider(int x, int y, int width, int height) { this.height = height; } - public void tick() { - // Update the progress - progress += progressSpeed; - if (progress > 1.0f) { - progress = 1.0f; - } - - // Update the alpha - alpha += alphaSpeed; - if (alpha > 1.0f) { - alpha = 1.0f; - } - } - public void defaultValues(){ - progress = 0.0f; - alpha = 0.0f; - } /** * Sets position. @@ -66,20 +45,18 @@ public void render(DrawContext drawContext, int x, int y) { for (int i = 0; i < width; i++) { float hue = (float) i / width; int color = Color.HSBtoRGB(hue, 1.0f, 1.0f); - color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); + color = (color & 0x00FFFFFF) | (255 << 24); drawContext.fill(x + i, y, x + i + 1, y + height, color); } // Draw the handle - if (progress >= 1.0f) { float handleWidth = 3; float handleHeight = height + 4; float handleX = x + hue * width - handleWidth / 2.0f; float handleY = y - (handleHeight - height) / 2.0f; DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); - } drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 6b97669..a5abc47 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -1,10 +1,9 @@ package com.tanishisherewith.dynamichud.newTrial.widget; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; +import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.UID; -import com.tanishisherewith.dynamichud.widget.WidgetBox; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; @@ -34,9 +33,6 @@ public abstract class Widget { //To enable/disable snapping public boolean shiftDown = false; - public int snapBoxWidth,snapBoxHeight; - public static int snapSize = 1; - // Used for dragging and snapping int startX, startY; // Absolute position of the widget on screen in pixels. @@ -69,7 +65,7 @@ public abstract class Widget { public Widget(WidgetData DATA, String modId) { Widget.DATA = DATA; - widgetBox = new WidgetBox(0, 0, 0, 0, 1); + widgetBox = new WidgetBox(0, 0, 0, 0); this.modId = modId; init(); } @@ -108,8 +104,8 @@ public float getHeight() { } public void setPosition(int x, int y) { - this.x = x; - this.y = y; + this.x = x; + this.y = y; } public void setDraggable(boolean draggable) { @@ -152,22 +148,17 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { * Renders the widget on the editor screen. */ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { + displayBg(drawContext); + if (shouldScale) { DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); } - // Calculate the size of each snap box - snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; - snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; - renderWidgetInEditor(drawContext,mouseX,mouseY); if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); } } - protected void updateWidgetBox(){ - widgetBox.setSizeAndPosition(x,y,getWidth(),getHeight()); - } /** @@ -191,7 +182,7 @@ protected void updateWidgetBox(){ * @param context */ private void renderWidgetInEditor(DrawContext context,int mouseX, int mouseY) { - displayBg(context); + //displayBg(context); renderWidget(context,mouseX,mouseY); } @@ -208,7 +199,6 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { - Widget.snapSize = snapSize; if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { int newX = (int) (mouseX - startX); int newY = (int) (mouseY - startY); @@ -216,21 +206,21 @@ 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) { - // Calculate the index of the snap box that the new position would be in - int snapBoxX = newX / snapBoxWidth; - int snapBoxY = newY / snapBoxHeight; - - // Snap the new position to the top-left corner of the snap box - newX = snapBoxX * snapBoxWidth; - newY = snapBoxY * snapBoxHeight; + // Calculate the size of each snap box + int snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize; + int snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize; + + // Calculate the index of the snap box that the new position would be in and + // snap the new position to the top-left corner of the snap box + newX = (newX / snapBoxWidth) * snapBoxWidth; + newY = (newY / snapBoxHeight) * snapBoxHeight; } 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.getX() / mc.getWindow().getScaledWidth(); - this.yPercent = (float) this.getY() / mc.getWindow().getScaledHeight(); + this.xPercent = (float) this.x / mc.getWindow().getScaledWidth(); + this.yPercent = (float) this.y / mc.getWindow().getScaledHeight(); return true; } @@ -267,7 +257,12 @@ public void onClose(){ protected void displayBg(DrawContext context) { int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); WidgetBox box = this.getWidgetBox(); - DrawHelper.fill(context, (int) box.x1, (int) box.y1, (int) box.x2, (int) box.y2, backgroundColor); + DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), + box.x, + box.y, + box.getWidth(), + box.getHeight(), + backgroundColor); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java new file mode 100644 index 0000000..4ac9f25 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java @@ -0,0 +1,66 @@ +package com.tanishisherewith.dynamichud.newTrial.widget; + +public class WidgetBox { + private float width; + private float height; + public float x = 0, y = 0; + + public WidgetBox(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public boolean isMouseOver(double mouseX, double mouseY) { + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } + + public float getWidth() { + return width; + } + + public float getHeight() { + return height; + } + + public boolean intersects(WidgetBox other) { + // Check if this box is to the right of the other box + if (this.x > other.x + other.width) { + return false; + } + + // Check if this box is to the left of the other box + if (this.x + this.width < other.x) { + return false; + } + + // Check if this box is below the other box + if (this.y > other.y + other.height) { + return false; + } + + // Check if this box is above the other box + // If none of the above conditions are met, the boxes must intersect + return !(this.y + this.height < other.y); + } + + public void setSizeAndPosition(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){ + this.x = x; + this.y = y; + this.height = height * (shouldScale? scale : 1.0f); + this.width = width * (shouldScale? scale : 1.0f); + } + public void setSize(double width, double height,boolean shouldScale, float scale) { + if (width >= 0) + this.width = (int) Math.ceil(width * (shouldScale? scale : 1.0f)); + if (height >= 0) + this.height = (int) Math.ceil(height * (shouldScale? scale : 1.0f)); + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 6feb340..08758df 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -118,23 +118,24 @@ 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 coords is not returned - if(widget.xPercent <= 0f){ + if(widget.xPercent <= 0.0f){ widget.xPercent = (float) widget.getX()/previousWidth; } - if(widget.yPercent <= 0f){ + if(widget.yPercent <= 0.0f){ widget.yPercent = (float) widget.getY()/previousHeight; } // Use the stored percentages to calculate the new position - int newX = (int) (widget.xPercent * newWidth); - int newY = (int) (widget.yPercent * newHeight); + float newX = widget.xPercent * newWidth; + float newY = widget.yPercent * newHeight; // Ensure the widget is within the screen bounds - newX = (int) MathHelper.clamp(newX, 0, newWidth - widget.getWidth()); - newY = (int) MathHelper.clamp(newY, 0, newHeight - widget.getHeight()); + newX = MathHelper.clamp(newX, 0, newWidth - widget.getWidth()); + newY = MathHelper.clamp(newY, 0, newHeight - widget.getHeight()); // Update the widget's position - widget.setPosition(newX, newY); + 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; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index df53480..a75269f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.newTrial.widgets; import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.*; @@ -8,6 +9,7 @@ import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.nbt.NbtCompound; import org.lwjgl.glfw.GLFW; @@ -73,28 +75,29 @@ public void createMenu(){ menu.addOption(new BooleanOption("Rainbow",()->this.rainbow,value-> this.rainbow = value)); menu.addOption(new ColorOption("TextColor",menu,()-> textColor, value -> textColor = value)); menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); - AtomicReference testss = new AtomicReference<>(test.TEST); - List options = Arrays.asList("TEST","TEST2","TEST23"); - AtomicReference option = new AtomicReference<>("TEST"); - AtomicReference testColor = new AtomicReference<>(new Color(102)); - menu.addOption(new EnumOption("Test", testss::get, testss::set,test.values())); - menu.addOption(new ListOption("New", option::get, option::set,options )); + /* TEST */ + AtomicReference enums = new AtomicReference<>(Enum.Enum1); + AtomicReference option = new AtomicReference<>("Enum1"); + menu.addOption(new EnumOption<>("Enum", enums::get, enums::set, Enum.values())); + + List options = Arrays.asList("List1","List2","List3"); + menu.addOption(new ListOption<>("List", option::get, option::set, options)); } - public enum test{ - TEST, - TEST_2, - TEST_3 + public enum Enum{ + Enum1, + Enum2, + Enum3 } @Override public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { - menu.render(drawContext, getX() - 2, getY(), (int) Math.ceil(getHeight())); 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(), getY(), color, shadow); - widgetBox.setSizeAndPosition(getX() - 2, getY() - 2, mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2); + 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().scale); } + menu.render(drawContext, getX() - 2, getY(), (int) Math.ceil(getHeight())); } @Override @@ -114,7 +117,7 @@ public void mouseReleased(double mouseX, double mouseY, int button) { @Override public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { - menu.mouseDragged(mouseX,mouseY,button); + menu.mouseDragged(mouseX, mouseY, button); return super.mouseDragged(mouseX, mouseY, button, snapSize); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 6633a4e..30927be 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -117,7 +117,7 @@ public static void setScale(float scale) { public void setX(float x) { int screenWidth = client.getWindow().getScaledWidth(); if (x < 0) { - x = (0); + x = 0; } else if (x + getWidgetBox().getWidth() > screenWidth) { x = screenWidth - getWidgetBox().getWidth(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index f44e8af..a61db70 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -37,7 +37,7 @@ public boolean intersects(float otherX1, float otherY1, float otherX2, float oth return !(otherX1 > x2 || otherX2 < x1 || otherY1 > y2 || otherY2 < y1); } public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= x1 && mouseX <= x2 && mouseY >= y1 && mouseY <= y2; + return mouseX >= x1 && mouseX <= x1 + width && mouseY >= y1 && mouseY <= y2 + height; } public float getWidth() { @@ -47,14 +47,19 @@ public float getWidth() { public float getHeight() { return height; } + public void setSizeAndPosition(float x, float y, float width, float height){ this.x1 = x; - this.x2 = x + width; this.y1 = y; - this.y2 = y + height; this.height = height; this.width = width; } + public void setSizeAndPosition(float x, float y, float width, float height,boolean shouldScale, float scale){ + this.x1 = x; + this.y1 = y; + this.height = height * (shouldScale? scale : 1.0f); + this.width = width * (shouldScale? scale : 1.0f); + } public void setSize(double width, double height) { if (width >= 0) this.width = (int) Math.ceil(width); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 616fb5f..cb56d52 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -22,8 +22,7 @@ "com.tanishisherewith.dynamichud.newTrial.DynamicHUD" ], "dynamicHud": [ - "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest", - "com.tanishisherewith.dynamichud.newTrial.DynamicHudTestTWO" + "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest" ], "modmenu": [ "com.tanishisherewith.dynamichud.ModMenuIntegration" From 3ed5a375f803debc98c653cb1f0f8464cabef1c4 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:15:18 +0530 Subject: [PATCH 19/33] Cleanup --- .../dynamichud/newTrial/DynamicHUD.java | 144 +++++++++--------- .../newTrial/DynamicHudIntegration.java | 13 +- .../dynamichud/newTrial/DynamicHudTest.java | 15 +- .../newTrial/DynamicHudTestTWO.java | 14 +- .../dynamichud/newTrial/HudRender.java | 4 +- .../newTrial/config/GlobalConfig.java | 14 +- .../newTrial/helpers/ColorHelper.java | 50 +++--- .../newTrial/helpers/DrawHelper.java | 31 ++-- .../newTrial/helpers/TextureHelper.java | 2 +- .../screens/AbstractMoveableScreen.java | 18 +-- .../newTrial/utils/DynamicValueRegistry.java | 30 ++-- .../dynamichud/newTrial/utils/System.java | 11 +- .../dynamichud/newTrial/utils/Util.java | 8 +- .../utils/contextmenu/ContextMenu.java | 65 ++++---- .../newTrial/utils/contextmenu/Option.java | 34 +++-- .../contextmenu/options/BooleanOption.java | 4 +- .../contextmenu/options/DoubleOption.java | 33 ++-- .../utils/contextmenu/options/EnumOption.java | 13 +- .../utils/contextmenu/options/ListOption.java | 12 +- .../contextmenu/options/RunnableOption.java | 15 +- .../options/coloroption/AlphaSlider.java | 31 ++-- .../coloroption/ColorGradientPicker.java | 29 ++-- .../options/coloroption/ColorOption.java | 28 ++-- .../coloroption/ColorPickerButton.java | 6 +- .../options/coloroption/GradientBox.java | 9 +- .../options/coloroption/GradientSlider.java | 16 +- .../dynamichud/newTrial/widget/Widget.java | 64 ++++---- .../dynamichud/newTrial/widget/WidgetBox.java | 18 ++- .../newTrial/widget/WidgetManager.java | 115 +++++++------- .../newTrial/widget/WidgetRenderer.java | 72 +++++---- .../newTrial/widgets/TextWidget.java | 106 +++++++------ 31 files changed, 540 insertions(+), 484 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 53028db..8ac82e1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -25,16 +25,16 @@ import java.util.List; public class DynamicHUD implements ClientModInitializer { - public static MinecraftClient MC = MinecraftClient.getInstance(); - public static String MOD_ID = "dynamichud"; - private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); - private static final List widgetRenderers = new ArrayList<>(); /** * 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> fileMap = new HashMap<>(); + public static final HashMap> fileMap = new HashMap<>(); + private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); + private static final List widgetRenderers = new ArrayList<>(); + public static MinecraftClient MC = MinecraftClient.getInstance(); + public static String MOD_ID = "dynamichud"; public static void addWidgetRenderer(WidgetRenderer widgetRenderer) { widgetRenderers.add(widgetRenderer); @@ -52,6 +52,18 @@ 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); + } + } + @Override public void onInitializeClient() { printInfo("Initialising DynamicHud"); @@ -67,62 +79,62 @@ public void onInitializeClient() { FabricLoader.getInstance() .getEntrypointContainers("dynamicHud", DynamicHudIntegration.class) .forEach(entrypoint -> { - ModMetadata metadata = entrypoint.getProvider().getMetadata(); - String modId = metadata.getId(); - AbstractMoveableScreen screen; - try { - DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); - DHIntegration.init(); - - File widgetsFile = DHIntegration.getWidgetsFile(); - - if(widgetsFile.exists()) { - WidgetManager.loadWidgets(widgetsFile); - }else{ - DHIntegration.addWidgets(); - } - DHIntegration.initAfter(); - - screen = DHIntegration.getMovableScreen(); - - KeyBinding binding = DHIntegration.getKeyBind(); - - DHIntegration.registerCustomWidgets(); - - WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); - addWidgetRenderer(widgetRenderer); - - List widgets = fileMap.get(widgetsFile.getName()); - - if(widgets == null) { - fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); - }else{ - widgetRenderer.getWidgets().addAll(widgets); - fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); - } - - //Register events for rendering, saving, loading, and opening the hudEditor - ClientTickEvents.START_CLIENT_TICK.register((client)-> { - openDynamicScreen(binding, screen); + ModMetadata metadata = entrypoint.getProvider().getMetadata(); + String modId = metadata.getId(); + AbstractMoveableScreen screen; + try { + DynamicHudIntegration DHIntegration = entrypoint.getEntrypoint(); + DHIntegration.init(); + + File widgetsFile = DHIntegration.getWidgetsFile(); + + if (widgetsFile.exists()) { + WidgetManager.loadWidgets(widgetsFile); + } else { + DHIntegration.addWidgets(); + } + DHIntegration.initAfter(); + + screen = DHIntegration.getMovableScreen(); + + KeyBinding binding = DHIntegration.getKeyBind(); + + DHIntegration.registerCustomWidgets(); + + WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); + addWidgetRenderer(widgetRenderer); + + List widgets = fileMap.get(widgetsFile.getName()); + + if (widgets == null) { + fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + } else { + widgetRenderer.getWidgets().addAll(widgets); + fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + } + + //Register events for rendering, saving, loading, and opening the hudEditor + ClientTickEvents.START_CLIENT_TICK.register((client) -> { + openDynamicScreen(binding, screen); + }); + + // Save during exiting a world, server or Minecraft itself + // Also saved when a resource pack is reloaded. + ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); + ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); + Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile, fileMap.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.warn("Mod {} has incorrect implementation of DynamicHUD", modId, e); + } + } }); - // Save during exiting a world, server or Minecraft itself - // Also saved when a resource pack is reloaded. - ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile,fileMap.get(widgetsFile.getName()))); - Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile,fileMap.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.warn("Mod {} has incorrect implementation of DynamicHUD", modId, e); - } - } - }); - 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()); @@ -131,24 +143,14 @@ public void onInitializeClient() { HudRenderCallback.EVENT.register(new HudRender()); } + private void saveWidgetsSafely(File widgetsFile, List widgets) { try { - WidgetManager.saveWidgets(widgetsFile,widgets); + WidgetManager.saveWidgets(widgetsFile, widgets); } catch (IOException e) { logger.error("Failed to save widgets. Widgets passed: {}", widgets); throw new RuntimeException(e); } } - /** - * 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); - } - } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java index 6e76760..1a7ef92 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java @@ -63,7 +63,7 @@ public interface DynamicHudIntegration { /** * Initializes the DynamicHud integration. *

- * Suggested to be used to initialize {@link com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry} and widgets with their respective values + * Suggested to be used to initialize {@link com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry} and widgets with their respective values *

*/ void init(); @@ -76,15 +76,17 @@ public interface DynamicHudIntegration { /** * To register custom widgets. This method can be overridden by implementations. */ - default void registerCustomWidgets(){} + 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. + * Suggested to be used to initialize a {@link WidgetRenderer} object with the added widgets. *

*/ - default void initAfter(){} + default void initAfter() { + } /** * Returns the file where widgets are to be saved and loaded from. @@ -94,6 +96,7 @@ default void initAfter(){} default File getWidgetsFile() { return WIDGETS_FILE; } + /** * Returns the keybind to open the {@link AbstractMoveableScreen} instance. * @@ -116,7 +119,7 @@ default KeyBinding getKeyBind() { * * @return The widget renderer. */ - default WidgetRenderer getWidgetRenderer(){ + default WidgetRenderer getWidgetRenderer() { return new WidgetRenderer(WidgetManager.getWidgets()); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index ff97576..9c4a431 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -17,16 +17,17 @@ public class DynamicHudTest implements DynamicHudIntegration { TextWidget Example2Widget; DynamicValueRegistry registry; WidgetRenderer renderer; + @Override public void init() { //Global registry - DynamicValueRegistry.registerGlobal("FPS",() -> "FPS: "+ DynamicHUD.MC.getCurrentFps()); + DynamicValueRegistry.registerGlobal("FPS", () -> "FPS: " + DynamicHUD.MC.getCurrentFps()); //Local registry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); - registry.registerLocal("FPS",()-> "FPS C-DVR: "+ DynamicHUD.MC.getCurrentFps()); + registry.registerLocal("FPS", () -> "FPS C-DVR: " + DynamicHUD.MC.getCurrentFps()); - textWidget = new TextWidget.Builder() + textWidget = new TextWidget.Builder() .setX(300) .setY(100) .setDraggable(true) @@ -36,7 +37,7 @@ public void init() { .shouldScale(false) .build(); - Example2Widget = new TextWidget.Builder() + Example2Widget = new TextWidget.Builder() .setX(200) .setY(100) .setDraggable(true) @@ -53,7 +54,8 @@ public void addWidgets() { WidgetManager.addWidget(textWidget); WidgetManager.addWidget(Example2Widget); } - public void initAfter(){ + + public void initAfter() { List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); renderer = new WidgetRenderer(widgets); @@ -64,7 +66,8 @@ public void initAfter(){ @Override public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor"), renderer) {}; + return new AbstractMoveableScreen(Text.literal("Editor"), renderer) { + }; } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java index a449c5e..9615f2c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java @@ -2,19 +2,16 @@ import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.option.OptionsScreen; import net.minecraft.client.option.KeyBinding; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; -import org.lwjgl.opengl.GL; import java.io.File; import java.util.List; @@ -22,10 +19,11 @@ public class DynamicHudTestTWO implements DynamicHudIntegration { TextWidget exampleWidget; WidgetRenderer renderer; + @Override public void init() { //Global registry - DynamicValueRegistry.registerGlobal("CPS",() -> "NOT FPS"); + DynamicValueRegistry.registerGlobal("CPS", () -> "NOT FPS"); exampleWidget = new TextWidget.Builder() @@ -51,14 +49,15 @@ public KeyBinding getKeyBind() { @Override public File getWidgetsFile() { - return new File(FILE_DIRECTORY,"widgets_new.nbt"); + return new File(FILE_DIRECTORY, "widgets_new.nbt"); } @Override public void addWidgets() { WidgetManager.addWidget(exampleWidget); } - public void initAfter(){ + + public void initAfter() { List widgets = WidgetManager.getWidgetsForMod("CustomMod"); renderer = new WidgetRenderer(widgets); @@ -69,7 +68,8 @@ public void initAfter(){ @Override public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor 2"), renderer) {}; + return new AbstractMoveableScreen(Text.literal("Editor 2"), renderer) { + }; } @Override diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java index bd842b0..48a7014 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java @@ -7,8 +7,8 @@ public class HudRender implements HudRenderCallback { @Override public void onHudRender(DrawContext drawContext, float tickDelta) { - for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ - widgetRenderer.renderWidgets(drawContext,-120,-120); + for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { + widgetRenderer.renderWidgets(drawContext, -120, -120); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java index e59ad0c..64a97f7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java @@ -11,7 +11,6 @@ import net.minecraft.util.Identifier; public class GlobalConfig { - private static GlobalConfig INSTANCE = new GlobalConfig(); public static ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) .id(new Identifier("dynamichud", "dynamichud_config")) .serializer(config -> GsonConfigSerializerBuilder.create(config) @@ -19,15 +18,19 @@ public class GlobalConfig { .setJson5(true) .build()) .build(); - + private static final GlobalConfig INSTANCE = new GlobalConfig(); /** * Common scale for all widgets. Set by the user using YACL. */ @SerialEntry public float scale = 1.0f; + public static GlobalConfig get() { + return INSTANCE; + } + public Screen createYACLGUI() { - return YetAnotherConfigLib.createBuilder() + return YetAnotherConfigLib.createBuilder() .title(Text.literal("DynamicHUD config screen.")) .category(ConfigCategory.createBuilder() .name(Text.literal("General")) @@ -39,14 +42,11 @@ public Screen createYACLGUI() { .name(Text.literal("Scale")) .description(OptionDescription.of(Text.literal("Set scale for all widgets."))) .binding(1.0f, () -> this.scale, newVal -> this.scale = newVal) - .controller(floatOption -> FloatSliderControllerBuilder.create(floatOption).range(0.1f,2.5f).step(0.1f)) + .controller(floatOption -> FloatSliderControllerBuilder.create(floatOption).range(0.1f, 2.5f).step(0.1f)) .build()) .build()) .build()) .build() .generateScreen(null); } - public static GlobalConfig get(){ - return INSTANCE; - } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java index 8a35f38..7426687 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java @@ -9,28 +9,18 @@ */ public class ColorHelper { public static int r, g, b, a; + public ColorHelper(int r, int g, int b) { - this.r = r; - this.g = g; - this.b = b; - this.a = 255; + ColorHelper.r = r; + ColorHelper.g = g; + ColorHelper.b = b; + a = 255; validate(); } + public ColorHelper() { } - public void validate() { - if (r < 0) r = 0; - else if (r > 255) r = 255; - - if (g < 0) g = 0; - else if (g > 255) g = 255; - if (b < 0) b = 0; - else if (b > 255) b = 255; - - if (a < 0) a = 0; - else if (a > 255) a = 255; - } /** * Returns a color as an integer value given its red, green and blue components. * @@ -82,10 +72,10 @@ public static int getColorFromHue(float hue) { public static int ColorToInt(Color color) { return color.getRGB(); } - public static float[] getRainbowColor() - { + + public static float[] getRainbowColor() { float x = System.currentTimeMillis() % 2000 / 1000F; - float pi = (float)Math.PI; + float pi = (float) Math.PI; float[] rainbow = new float[3]; rainbow[0] = 0.5F + 0.5F * MathHelper.sin(x * pi); @@ -105,7 +95,6 @@ public static Color getRainbowColor(int speed) { return Color.getHSBColor(hue, 1.0f, 1.0f); } - /** * Changes alpha on color. * @@ -119,6 +108,7 @@ public static Color changeAlpha(Color color, int alpha) { else return new Color(0); } + public static int fromRGBA(int r, int g, int b, int a) { return (r << 16) + (g << 8) + (b) + (a << 24); } @@ -138,8 +128,22 @@ public static int toRGBAB(int color) { public static int toRGBAA(int color) { return (color >> 24) & 0x000000FF; } - public int toInt() - { - return new Color(r,b,g,a).getRGB(); + + public void validate() { + if (r < 0) r = 0; + else if (r > 255) r = 255; + + if (g < 0) g = 0; + else if (g > 255) g = 255; + + if (b < 0) b = 0; + else if (b > 255) b = 255; + + if (a < 0) a = 0; + else if (a > 255) a = 255; + } + + public int toInt() { + return new Color(r, b, g, a).getRGB(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java index d036afd..ea1d60f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java @@ -281,6 +281,7 @@ public static void drawRainbowGradient(Matrix4f matrix, float x, float y, float /* ==== Drawing filled and outline circles ==== */ + /** * Draws an outline of a circle * @@ -783,10 +784,6 @@ public static void drawHorizontalLine(Matrix4f matrix4f, float x1, float width, drawRectangle(matrix4f, x1, y, width, thickness, color); } - public enum Direction { - /* LEFT_RIGHT means from left to right. Same for others */ - LEFT_RIGHT, TOP_BOTTOM, RIGHT_LEFT, BOTTOM_TOP - } /** * Draws an outlined box on the screen. * @@ -805,8 +802,9 @@ public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int /** * This method assumes that the x, y coords are the origin of a widget. - * @param x X position of widget - * @param y Y position of widget + * + * @param x X position of widget + * @param y Y position of widget * @param scale Scale the matrices */ public static void scaleAndPosition(MatrixStack matrices, float x, float y, float scale) { @@ -818,17 +816,19 @@ public static void scaleAndPosition(MatrixStack matrices, float x, float y, floa // Scale the matrix matrices.scale(scale, scale, 1.0F); - matrices.translate(-x,-y,0); + matrices.translate(-x, -y, 0); } + /** * This method scales the matrices by the centre of the widget - * @param x X position of widget - * @param y Y position of widget + * + * @param x X position of widget + * @param y Y position of widget * @param height height of widget - * @param width width of widget - * @param scale Scale the matrices + * @param width width of widget + * @param scale Scale the matrices */ - public static void scaleAndPosition(MatrixStack matrices, float x, float y,float width, float height, float scale) { + public static void scaleAndPosition(MatrixStack matrices, float x, float y, float width, float height, float scale) { matrices.push(); // Save the current transformation state // Translate the origin back to the desired position @@ -840,8 +840,13 @@ public static void scaleAndPosition(MatrixStack matrices, float x, float y,float matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f), 0); } - public static void stopScaling(MatrixStack matrices){ + public static void stopScaling(MatrixStack matrices) { matrices.pop(); // Restore the previous transformation state } + public enum Direction { + /* LEFT_RIGHT means from left to right. Same for others */ + LEFT_RIGHT, TOP_BOTTOM, RIGHT_LEFT, BOTTOM_TOP + } + } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java index 37c36c6..f73aaae 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java @@ -202,7 +202,7 @@ public static void drawItemTextureWithTextAndScale(DrawContext drawContext, drawContext.getMatrices().scale(textScale, textScale, 11.0f); float scaledX = textX / textScale; float scaledY = textY / textScale; - drawContext.drawText(textRenderer, text, (int) scaledX + 1, (int) scaledY +1, color, false); + drawContext.drawText(textRenderer, text, (int) scaledX + 1, (int) scaledY + 1, color, false); drawContext.getMatrices().pop(); } customItemRenderer = new CustomItemRenderer(itemStack, itemScale); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index ef22c98..72194f5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -6,13 +6,12 @@ import net.minecraft.text.Text; public abstract class AbstractMoveableScreen extends Screen { - protected boolean shouldPause = false; // To pause if the screen is opened or not public final WidgetRenderer widgetRenderer; public int snapSize = 100; + protected boolean shouldPause = false; // To pause if the screen is opened or not /** * Constructs a AbstractMoveableScreen object. - * */ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { super(title); @@ -21,19 +20,19 @@ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { @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, snapSize); return false; } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - widgetRenderer.mouseClicked(mouseX,mouseY,button); + widgetRenderer.mouseClicked(mouseX, mouseY, button); return false; } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - widgetRenderer.mouseReleased(mouseX,mouseY,button); + widgetRenderer.mouseReleased(mouseX, mouseY, button); return false; } @@ -51,7 +50,7 @@ public boolean keyReleased(int keyCode, int scanCode, int modifiers) { @Override public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { - widgetRenderer.mouseScrolled(mouseX,mouseY,verticalAmount,horizontalAmount); + widgetRenderer.mouseScrolled(mouseX, mouseY, verticalAmount, horizontalAmount); return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); } @@ -65,12 +64,12 @@ public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmou */ @Override public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { - if(this.client.world == null) { + if (this.client.world == null) { this.renderBackgroundTexture(drawContext); } // Draw each widget widgetRenderer.isInEditor = true; - widgetRenderer.renderWidgets(drawContext,mouseX,mouseY); + widgetRenderer.renderWidgets(drawContext, mouseX, mouseY); } @Override @@ -88,7 +87,8 @@ public void setShouldPause(boolean shouldPause) { public boolean shouldPause() { return shouldPause; } - public void setSnapSize(int size){ + + public void setSnapSize(int size) { this.snapSize = size; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java index 393a969..811ef62 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java @@ -1,6 +1,8 @@ package com.tanishisherewith.dynamichud.newTrial.utils; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import java.util.function.Supplier; /** @@ -20,12 +22,14 @@ public class DynamicValueRegistry extends System { /** * A map that holds the global registry of suppliers. + * * @see #localRegistry */ private static final Map> globalRegistry = new HashMap<>(); /** * A map that holds the local registry of suppliers. + * * @see #globalRegistry */ private final Map> localRegistry = new HashMap<>(); @@ -43,23 +47,13 @@ public DynamicValueRegistry(String modId) { /** * Registers a supplier in the global registry. * - * @param key The key under which the supplier is to be registered. + * @param key The key under which the supplier is to be registered. * @param supplier The supplier to be registered. */ public static void registerGlobal(String key, Supplier supplier) { globalRegistry.put(key, supplier); } - /** - * 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. - */ - public void registerLocal(String key, Supplier supplier) { - localRegistry.put(key, supplier); - } - /** * Retrieves a supplier from the global registry. * @@ -70,6 +64,16 @@ public static Supplier getGlobal(String key) { return globalRegistry.get(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. + */ + 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. * @@ -93,7 +97,7 @@ public Supplier get(String key) { * * @param map The map to be set as the local registry. */ - public void setLocalRegistry(Map> map){ + public void setLocalRegistry(Map> map) { localRegistry.putAll(map); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java index 8022537..f741907 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java @@ -5,20 +5,19 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class System { - protected final String modId; - // A map to store all instances of DynamicValueRegistry by modId protected static final Map> instances = new ConcurrentHashMap<>(); + protected final String modId; public System(String modId) { this.modId = modId; } - public String getModId() { - return modId; - } - public static List getInstances(String modId) { return instances.get(modId); } + + public String getModId() { + return modId; + } } \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java index 0bfe69b..d1e04c4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java @@ -3,10 +3,6 @@ import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; public class Util { - public enum Quadrant { - UPPER_LEFT, UPPER_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT - } - public static Quadrant getQuadrant(int x, int y) { int screenWidth = DynamicHUD.MC.getWindow().getScaledWidth(); int screenHeight = DynamicHUD.MC.getWindow().getScaledHeight(); @@ -26,4 +22,8 @@ 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/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index 398037c..2f1d401 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -8,32 +8,32 @@ import java.util.List; public class ContextMenu { - public int x,y; - protected float scale = 0.0f; private final List> options = new ArrayList<>(); // The list of options in the context menu + public int x, y; public int width = 0; public int height = 0; public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light grey color public int padding = 5; // The amount of padding around the rectangle public int heightOffset = 4; // Height offset from the widget public boolean shouldDisplay = false; + protected float scale = 0.0f; - public ContextMenu(int x,int y){ + public ContextMenu(int x, int y) { this.x = x; this.y = y + heightOffset; } - public void addOption(Option option){ + public void addOption(Option option) { options.add(option); } - public void render(DrawContext drawContext, int x, int y, int height){ + public void render(DrawContext drawContext, int x, int y, int height) { this.x = x; this.y = y + heightOffset + height; - if(!shouldDisplay) return; + if (!shouldDisplay) return; update(); - DrawHelper.scaleAndPosition(drawContext.getMatrices(),x,y,scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, scale); int x1 = this.x - 1; int y1 = this.y; @@ -45,8 +45,8 @@ public void render(DrawContext drawContext, int x, int y, int height){ int yOffset = y1 + 3; this.width = 10; - for(Option option: options){ - option.render(drawContext,x + 2,yOffset); + for (Option option : options) { + option.render(drawContext, x + 2, yOffset); this.width = Math.max(this.width, option.width + padding); yOffset += option.height + 1; } @@ -55,6 +55,7 @@ public void render(DrawContext drawContext, int x, int y, int height){ DrawHelper.stopScaling(drawContext.getMatrices()); } + public void update() { // Update the scale float scaleSpeed = 0.1f; @@ -64,49 +65,55 @@ public void update() { } } - public void close(){ + public void close() { shouldDisplay = false; scale = 0.0f; } - public void open(){ + + public void open() { shouldDisplay = true; update(); } - public void toggleDisplay(){ - if(shouldDisplay){ + + public void toggleDisplay() { + if (shouldDisplay) { close(); - }else{ + } else { open(); } } - public void mouseClicked(double mouseX, double mouseY, int button){ - if(!shouldDisplay) return; - for(Option option: options){ + public void mouseClicked(double mouseX, double mouseY, int button) { + if (!shouldDisplay) return; + for (Option option : options) { option.mouseClicked(mouseX, mouseY, button); } } - public void mouseReleased(double mouseX, double mouseY, int button){ - if(!shouldDisplay) return; - for(Option option: options){ + + public void mouseReleased(double mouseX, double mouseY, int button) { + if (!shouldDisplay) return; + for (Option option : options) { option.mouseReleased(mouseX, mouseY, button); } } - public void mouseDragged(double mouseX, double mouseY, int button){ - if(!shouldDisplay) return; - for(Option option: options){ + + public void mouseDragged(double mouseX, double mouseY, int button) { + if (!shouldDisplay) return; + for (Option option : options) { option.mouseDragged(mouseX, mouseY, button); } } - public void keyPressed(int key){ - if(!shouldDisplay) return; - for(Option option: options){ + + public void keyPressed(int key) { + if (!shouldDisplay) return; + for (Option option : options) { option.keyPressed(key); } } - public void keyReleased(int key){ - if(!shouldDisplay) return; - for(Option option: options){ + + public void keyReleased(int key) { + if (!shouldDisplay) return; + for (Option option : options) { option.keyReleased(key); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java index 2c4907e..676af06 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -8,52 +8,58 @@ import java.util.function.Supplier; public abstract class Option { - public int x,y; - protected float scale = 0.0f; - private Widget selectedWidget; // The widget that this context menu is associated with + public int x, y; public int width = 0; public int height = 0; - protected Supplier getter; - protected Consumer setter; public T value = null; + protected float scale = 0.0f; + protected Supplier getter; + protected Consumer setter; protected T defaultValue = null; protected MinecraftClient mc = MinecraftClient.getInstance(); + private Widget selectedWidget; // The widget that this context menu is associated with - public Option(Supplier getter, Consumer setter){ + public Option(Supplier getter, Consumer setter) { this.getter = getter; this.setter = setter; value = get(); defaultValue = get(); } - protected T get(){ + protected T get() { return getter.get(); } - protected void set(T value){ + + protected void set(T value) { this.value = value; setter.accept(value); } - public void render(DrawContext drawContext, int x, int y){ + public void render(DrawContext drawContext, int x, int y) { this.x = x; this.y = y; } - public boolean mouseClicked(double mouseX, double mouseY, int button){ + public boolean mouseClicked(double mouseX, double mouseY, int button) { return isMouseOver(mouseX, mouseY); } - public boolean mouseReleased(double mouseX, double mouseY, int button){ + + public boolean mouseReleased(double mouseX, double mouseY, int button) { return isMouseOver(mouseX, mouseY); } - public boolean mouseDragged(double mouseX, double mouseY, int button){ + + public boolean mouseDragged(double mouseX, double mouseY, int button) { return isMouseOver(mouseX, mouseY); } - public void keyPressed(int key){ + + public void keyPressed(int key) { } - public void keyReleased(int key){ + + public void keyReleased(int key) { } + 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/newTrial/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java index d7f9fb6..bc23270 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java @@ -22,7 +22,7 @@ public void render(DrawContext drawContext, int x, int y) { value = get(); int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); - drawContext.drawText(mc.textRenderer,Text.of(name),x,y, color,false); + drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name) + 1; } @@ -30,7 +30,7 @@ public void render(DrawContext drawContext, int x, int y) { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { super.mouseClicked(mouseX, mouseY, button); - if(isMouseOver(mouseX, mouseY)) { + if (isMouseOver(mouseX, mouseY)) { value = !value; set(value); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java index 644f2ed..05a6319 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java @@ -12,10 +12,11 @@ public class DoubleOption extends Option { public String name = "Empty"; - private boolean isDragging = false; - private double minValue = 0.0,maxValue = 0.0; float step = 0.1f; - public DoubleOption(String name,double minValue,double maxValue,float step,Supplier getter, Consumer setter) { + private boolean isDragging = false; + private double minValue = 0.0, maxValue = 0.0; + + public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter) { super(getter, setter); this.name = name; this.value = get(); @@ -24,8 +25,9 @@ public DoubleOption(String name,double minValue,double maxValue,float step,Suppl this.width = 30; this.height = 16; this.step = step; - Validate.isTrue(this.step>0.0f,"Step cannot be less than or equal to 0 (zero)"); + Validate.isTrue(this.step > 0.0f, "Step cannot be less than or equal to 0 (zero)"); } + @Override public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); @@ -35,10 +37,10 @@ public void render(DrawContext drawContext, int x, int y) { this.height = 16; // Draw the label TextRenderer textRenderer = mc.textRenderer; - DrawHelper.scaleAndPosition(drawContext.getMatrices(),x,y,0.7f); + 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); + this.width = Math.max(this.width, labelWidth); drawContext.drawTextWithShadow(textRenderer, labelText, x, y + 1, 0xFFFFFFFF); DrawHelper.stopScaling(drawContext.getMatrices()); @@ -53,10 +55,10 @@ public void render(DrawContext drawContext, int x, int y) { // Draw the handle DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), - (float)handleX, - (float)handleY, - handleWidth, - handleHeight, + (float) handleX, + (float) handleY, + handleWidth, + handleHeight, 1, 0xFFFFFFFF, 90, @@ -65,8 +67,8 @@ public void render(DrawContext drawContext, int x, int y) { } private 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(), 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()); } } @@ -74,7 +76,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 (isMouseOver(mouseX, mouseY)) { step(mouseX); isDragging = true; } @@ -86,7 +88,8 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) { isDragging = false; return super.mouseReleased(mouseX, mouseY, button); } - private void step(double mouseX){ + + private 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; @@ -95,7 +98,7 @@ private void step(double mouseX){ @Override public boolean mouseDragged(double mouseX, double mouseY, int button) { - if(isMouseOver(mouseX, mouseY) && isDragging) { + if (isMouseOver(mouseX, mouseY) && isDragging) { step(mouseX); } return super.mouseDragged(mouseX, mouseY, button); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java index dde3f95..5cd0725 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java @@ -1,18 +1,17 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; -import java.awt.Color; +import java.awt.*; import java.util.function.Consumer; import java.util.function.Supplier; public class EnumOption> extends Option { private final E[] values; - private int currentIndex = 0; public String name = "Empty"; + private int currentIndex = 0; public EnumOption(String name, Supplier getter, Consumer setter, E[] values) { super(getter, setter); @@ -43,15 +42,15 @@ public void render(DrawContext drawContext, int x, int y) { public boolean mouseClicked(double mouseX, double mouseY, int button) { super.mouseClicked(mouseX, mouseY, button); if (isMouseOver(mouseX, mouseY)) { - if(button == 0) { + if (button == 0) { currentIndex = (currentIndex + 1) % values.length; - if(currentIndex > values.length - 1){ + if (currentIndex > values.length - 1) { currentIndex = 0; } value = values[currentIndex]; - }else if(button == 1){ + } else if (button == 1) { currentIndex = (currentIndex - 1) % values.length; - if(currentIndex < 0){ + if (currentIndex < 0) { currentIndex = values.length - 1; } value = values[currentIndex]; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java index 3e69407..3622dd3 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java @@ -1,20 +1,18 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import java.awt.*; -import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; public class ListOption extends Option { private final List values; - private int currentIndex = 0; public String name = "Empty"; + private int currentIndex = 0; public ListOption(String name, Supplier getter, Consumer setter, List values) { super(getter, setter); @@ -46,15 +44,15 @@ public void render(DrawContext drawContext, int x, int y) { public boolean mouseClicked(double mouseX, double mouseY, int button) { super.mouseClicked(mouseX, mouseY, button); if (isMouseOver(mouseX, mouseY)) { - if(button == 0) { + if (button == 0) { currentIndex = (currentIndex + 1) % values.size(); - if(currentIndex > values.size() - 1){ + if (currentIndex > values.size() - 1) { currentIndex = 0; } value = values.get(currentIndex); - }else if(button == 1){ + } else if (button == 1) { currentIndex = (currentIndex - 1) % values.size(); - if(currentIndex < 0){ + if (currentIndex < 0) { currentIndex = values.size() - 1; } value = values.get(currentIndex); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java index c62fc3b..43d230e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java @@ -10,16 +10,17 @@ public class RunnableOption extends Option { public String name = "Empty"; - private Runnable task; + private final Runnable task; /** * Runnable option which runs a task when clicked on it. - * @param name The name to be displayed + * + * @param name The name to be displayed * @param getter Get a default value to run the task by default * @param setter Return a boolean based on if the task is running or not. - * @param task The task to run + * @param task The task to run */ - public RunnableOption(String name, Supplier getter, Consumer setter,Runnable task) { + public RunnableOption(String name, Supplier getter, Consumer setter, Runnable task) { super(getter, setter); this.name = "Run: " + name; // prepend the "run" symbol to the name this.task = task; @@ -33,16 +34,16 @@ public void render(DrawContext drawContext, int x, int y) { this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth("Run: " + name) + 1; int color = value ? Color.BLUE.getRGB() : Color.GRAY.getRGB(); - drawContext.drawText(mc.textRenderer,Text.of(name),x,y, color,false); + 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 (isMouseOver(mouseX, mouseY)) { value = !value; set(value); - if(value){ + if (value) { task.run(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java index 4193f9e..b85fbea 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java @@ -3,7 +3,6 @@ import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; -import net.minecraft.util.math.MathHelper; import java.awt.*; @@ -16,7 +15,8 @@ public class AlphaSlider { private Color color; private int alphaHandleY = 0; private float alpha; - public AlphaSlider(int x,int y,int width, int height, Color color) { + + public AlphaSlider(int x, int y, int width, int height, Color color) { this.width = width; this.height = height; this.color = color; @@ -25,29 +25,30 @@ public AlphaSlider(int x,int y,int width, int height, Color color) { alpha = color.getAlpha() / 255f; } - public void setColor(Color color) { - this.color = color; - } public void render(DrawContext drawContext, int x, int y) { this.x = x; this.y = y; - DrawHelper.drawOutlinedBox(drawContext,x - 2,y - 2,x + width + 2,y + height + 2,Color.WHITE.getRGB()); - DrawHelper.drawGradient(drawContext.getMatrices().peek().getPositionMatrix(),x,y,width,height,color.getRGB(), ColorHelper.changeAlpha(color,0).getRGB(), DrawHelper.Direction.TOP_BOTTOM); - drawContext.fill(x-2, y + alphaHandleY-1,x+width+2, y +alphaHandleY+1,Color.WHITE.getRGB()); + DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + width + 2, y + height + 2, Color.WHITE.getRGB()); + DrawHelper.drawGradient(drawContext.getMatrices().peek().getPositionMatrix(), x, y, width, height, color.getRGB(), ColorHelper.changeAlpha(color, 0).getRGB(), DrawHelper.Direction.TOP_BOTTOM); + drawContext.fill(x - 2, y + alphaHandleY - 1, x + width + 2, y + alphaHandleY + 1, Color.WHITE.getRGB()); } public Color getColor() { - return ColorHelper.changeAlpha(color, (int) (alpha*255f)); + return ColorHelper.changeAlpha(color, (int) (alpha * 255f)); + } + + public void setColor(Color color) { + this.color = color; } public void onClick(double mouseX, double mouseY, int button) { if (button == 0 && isMouseOver(mouseX, mouseY)) { - alphaHandleY = (int) mouseY-y; + alphaHandleY = (int) mouseY - y; alpha = 1.0f - (alphaHandleY / (float) height); - if(alpha < 0.0f){ + if (alpha < 0.0f) { alpha = 0.0f; - }else if(alpha > 1.0f){ + } else if (alpha > 1.0f) { alpha = 1.0f; } this.isDragging = true; @@ -74,11 +75,11 @@ public void onRelease(double mouseX, double mouseY, int button) { public void onDrag(double mouseX, double mouseY, int button) { if (isDragging && isMouseOver(mouseX, mouseY)) { - alphaHandleY = (int) mouseY-y; + alphaHandleY = (int) mouseY - y; alpha = 1.0f - (alphaHandleY / (float) height); - if(alpha < 0.0f){ + if (alpha < 0.0f) { alpha = 0.0f; - }else if(alpha > 1.0f){ + } else if (alpha > 1.0f) { alpha = 1.0f; } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java index afc4880..b9e69f8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -1,6 +1,5 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.gui.DrawContext; @@ -9,18 +8,17 @@ import java.awt.*; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.function.Consumer; public class ColorGradientPicker { - 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 ColorPickerButton colorPickerButton; private final AlphaSlider alphaSlider; - private int x,y; private final int boxSize; + MinecraftClient client = MinecraftClient.getInstance(); + private int x, y; private boolean display = false; public ColorGradientPicker(int x, int y, Color initialColor, Consumer onColorSelected, int boxSize, int colors) { @@ -37,29 +35,32 @@ public ColorGradientPicker(int x, int y, Color initialColor, Consumer onC this.gradientBox.setSaturation(hsv[1]); this.gradientBox.setValue(hsv[2]); - this.alphaSlider = new AlphaSlider(x,y,10,boxSize,initialColor); + this.alphaSlider = new AlphaSlider(x, y, 10, boxSize, initialColor); this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 30, 18); } - public void setPos(int x, int y){ + + public void setPos(int x, int y) { this.x = x; this.y = y; } + public void display() { display = true; } + public void close() { display = false; } public void render(DrawContext drawContext, int x1, int y1) { - setPos(x1,y1); - if(!display){ + setPos(x1, y1); + if (!display) { return; } - gradientSlider.render(drawContext,x + 30, y +client.textRenderer.fontHeight + 4); - gradientBox.render(drawContext,x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); - colorPickerButton.render(drawContext,x+ 55 + boxSize,y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); - alphaSlider.render(drawContext,x + 40 + boxSize,y + client.textRenderer.fontHeight +gradientSlider.getHeight() + 10); + gradientSlider.render(drawContext, x + 30, y + client.textRenderer.fontHeight + 4); + gradientBox.render(drawContext, x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); + colorPickerButton.render(drawContext, x + 55 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); + alphaSlider.render(drawContext, x + 40 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking()) { // Draw the cursor @@ -82,7 +83,7 @@ public void render(DrawContext drawContext, int x1, int y1) { } public boolean mouseClicked(double mouseX, double mouseY, int button) { - if(!display){ + if (!display) { return false; } if (colorPickerButton.onClick(mouseX, mouseY, button)) { @@ -124,7 +125,7 @@ public void mouseReleased(double mouseX, double mouseY, int button) { } public void mouseDragged(double mouseX, double mouseY, int button) { - if(!display){ + if (!display) { return; } gradientSlider.onDrag(mouseX, mouseY, button); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java index bf870c6..9d90874 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java @@ -11,15 +11,16 @@ import java.util.function.Supplier; public class ColorOption extends Option { - public String name = "Empty"; - public boolean isVisible = false; - private ColorGradientPicker colorPicker = null; + public String name = "Empty"; + public boolean isVisible = false; public ContextMenu parentMenu = null; - public ColorOption(String name,ContextMenu parentMenu, Supplier getter, Consumer setter) { + private ColorGradientPicker colorPicker = 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.width + 10,y - 10,value, this::set,50,100 ); + colorPicker = new ColorGradientPicker(x + this.parentMenu.width + 10, y - 10, value, this::set, 50, 100); } @Override @@ -29,7 +30,7 @@ public void render(DrawContext drawContext, int x, int y) { int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name) + 12; - drawContext.drawText(mc.textRenderer, Text.of(name),x,y, color,false); + drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); DrawHelper.drawRoundedRectangleWithShadowBadWay(drawContext.getMatrices().peek().getPositionMatrix(), x + width - 8, y, @@ -39,24 +40,23 @@ public void render(DrawContext drawContext, int x, int y) { value.getRGB(), 90, 1, - 1 ); + 1); - colorPicker.render(drawContext,this.x + width/3 + parentMenu.width + 10,y - 10); + colorPicker.render(drawContext, this.x + width / 3 + parentMenu.width + 10, y - 10); } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if(isMouseOver(mouseX, mouseY)) { + if (isMouseOver(mouseX, mouseY)) { isVisible = !isVisible; - if(isVisible) - { - colorPicker.setPos(x + parentMenu.width + 10,y - 10); + if (isVisible) { + colorPicker.setPos(x + parentMenu.width + 10, y - 10); colorPicker.display(); - }else{ + } else { colorPicker.close(); } } - colorPicker.mouseClicked(mouseX,mouseY,button); + colorPicker.mouseClicked(mouseX, mouseY, button); return super.mouseClicked(mouseX, mouseY, button); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java index 149c595..39f541e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -4,10 +4,10 @@ import net.minecraft.client.gui.DrawContext; public class ColorPickerButton { - private int x; - private int y; private final int width; private final int height; + private int x; + private int y; private boolean isPicking = false; public ColorPickerButton(int x, int y, int width, int height) { @@ -21,7 +21,7 @@ public void render(DrawContext drawContext, int x, int y) { this.x = x; this.y = y; drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,404); + drawContext.getMatrices().translate(0, 0, 404); // Draw the button drawContext.fill(x + 2, y + 2, x + width - 2, y + height - 2, 0xFFAAAAAA); drawContext.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, "Pick", x + width / 2, y + (height - 8) / 2, 0xFFFFFFFF); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java index e1b5fc8..ce0f0f9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -22,14 +20,15 @@ public GradientBox(int x, int y, int size) { this.y = y; this.size = size; } + public void render(DrawContext drawContext, int x, int y) { - setPosition(x,y); + setPosition(x, y); drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,406); + drawContext.getMatrices().translate(0, 0, 406); DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + size + 2, y + size + 2, -1); // Draw the gradient - com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size,2); + com.tanishisherewith.dynamichud.newTrial.helpers.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; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java index 8aa7e32..60498df 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java @@ -1,8 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -35,9 +33,9 @@ public void setPosition(int x, int y) { } public void render(DrawContext drawContext, int x, int y) { - setPosition(x,y); + setPosition(x, y); drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,401); + drawContext.getMatrices().translate(0, 0, 401); DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + width + 2, y + height + 2, -1); // Draw the gradient @@ -51,12 +49,12 @@ public void render(DrawContext drawContext, int x, int y) { // Draw the handle - float handleWidth = 3; - float handleHeight = height + 4; - float handleX = x + hue * width - handleWidth / 2.0f; - float handleY = y - (handleHeight - height) / 2.0f; + float handleWidth = 3; + float handleHeight = height + 4; + float handleX = x + hue * width - handleWidth / 2.0f; + float handleY = y - (handleHeight - height) / 2.0f; - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); + DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index a5abc47..8512958 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -14,12 +14,12 @@ public abstract class Widget { - protected MinecraftClient mc = MinecraftClient.getInstance(); - + public static WidgetData DATA; /** * This is the UID of the widget used to identify during loading and saving. *

* It's different from modID because this is unique to each widget. + * * @see #modId */ public UID uid = UID.generate(); @@ -33,35 +33,32 @@ public abstract class Widget { //To enable/disable snapping public boolean shiftDown = false; - int startX, startY; - // Absolute position of the widget on screen in pixels. public int x, y; - + public boolean shouldScale = true; + /** + * An identifier for widgets to group them under one ID. + *

+ * Doesn't necessarily have to be the mod ID of mod, but it's preferred to use mod ID if you are only grouping widgets under one ID. + * Can be any string if wanted. + * + * @see #uid + */ + 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; - public boolean shouldScale = true; - /** * Scale of the current widget. + * * @see GlobalConfig#scale */ protected float scale = 1.0f; - - /** - * An identifier for widgets to group them under one ID. - *

- * Doesn't necessarily have to be the mod ID of mod, but it's preferred to use mod ID if you are only grouping widgets under one ID. - * Can be any string if wanted. - * @see #uid - */ - public String modId = "unknown"; - //Dimensions of the widget protected WidgetBox widgetBox; - public static WidgetData DATA; + int startX, startY; public Widget(WidgetData DATA, String modId) { Widget.DATA = DATA; @@ -104,8 +101,8 @@ public float getHeight() { } public void setPosition(int x, int y) { - this.x = x; - this.y = y; + this.x = x; + this.y = y; } public void setDraggable(boolean draggable) { @@ -134,9 +131,9 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { if (!shouldDisplay()) return; if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); } - renderWidget(drawContext,mouseX,mouseY); + renderWidget(drawContext, mouseX, mouseY); if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); @@ -151,9 +148,9 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { displayBg(drawContext); if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(),GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); } - renderWidgetInEditor(drawContext,mouseX,mouseY); + renderWidgetInEditor(drawContext, mouseX, mouseY); if (shouldScale) { DrawHelper.stopScaling(drawContext.getMatrices()); @@ -168,10 +165,10 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { *

* * @param context - * @param mouseX X position of mouse. - * @param mouseY Y position of mouse + * @param mouseX X position of mouse. + * @param mouseY Y position of mouse */ - public abstract void renderWidget(DrawContext context,int mouseX, int mouseY); + public abstract void renderWidget(DrawContext context, int mouseX, int mouseY); /** @@ -181,10 +178,10 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { * * @param context */ - private void renderWidgetInEditor(DrawContext context,int mouseX, int mouseY) { + private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { //displayBg(context); - renderWidget(context,mouseX,mouseY); + renderWidget(context, mouseX, mouseY); } public boolean mouseClicked(double mouseX, double mouseY, int button) { @@ -220,7 +217,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSi 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(); + this.yPercent = (float) this.y / mc.getWindow().getScaledHeight(); return true; } @@ -237,14 +234,15 @@ 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) { + public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { } public boolean toggle() { return this.display = !this.display; } - public void onClose(){ + + public void onClose() { this.shiftDown = false; } @@ -257,7 +255,7 @@ public void onClose(){ protected void displayBg(DrawContext context) { int backgroundColor = this.shouldDisplay() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); WidgetBox box = this.getWidgetBox(); - DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), + DrawHelper.drawRectangle(context.getMatrices().peek().getPositionMatrix(), box.x, box.y, box.getWidth(), diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java index 4ac9f25..0082496 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java @@ -1,9 +1,9 @@ package com.tanishisherewith.dynamichud.newTrial.widget; public class WidgetBox { + public float x = 0, y = 0; private float width; private float height; - public float x = 0, y = 0; public WidgetBox(int x, int y, int width, int height) { this.x = x; @@ -45,22 +45,24 @@ public boolean intersects(WidgetBox other) { return !(this.y + this.height < other.y); } - public void setSizeAndPosition(float x, float y, float width, float height){ + public void setSizeAndPosition(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 setSizeAndPosition(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); - this.width = width * (shouldScale? scale : 1.0f); + this.height = height * (shouldScale ? scale : 1.0f); + this.width = width * (shouldScale ? scale : 1.0f); } - public void setSize(double width, double height,boolean shouldScale, float scale) { + + public void setSize(double width, double height, boolean shouldScale, float scale) { if (width >= 0) - this.width = (int) Math.ceil(width * (shouldScale? scale : 1.0f)); + this.width = (int) Math.ceil(width * (shouldScale ? scale : 1.0f)); if (height >= 0) - this.height = (int) Math.ceil(height * (shouldScale? scale : 1.0f)); + this.height = (int) Math.ceil(height * (shouldScale ? scale : 1.0f)); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 08758df..75208a4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -1,16 +1,22 @@ package com.tanishisherewith.dynamichud.newTrial.widget; -import java.io.*; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.*; - import com.tanishisherewith.dynamichud.DynamicHUD; import net.fabricmc.fabric.api.util.NbtType; -import net.minecraft.nbt.*; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NbtList; import net.minecraft.util.math.MathHelper; -import static com.tanishisherewith.dynamichud.DynamicHUD.*; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.*; + +import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; +import static com.tanishisherewith.dynamichud.DynamicHUD.printWarn; /** * Manages a collection of widgets, providing methods to add, remove, save, and load widgets. @@ -31,8 +37,8 @@ public class WidgetManager { * * @param data The WidgetData object to add. */ - public static void addWidgetData(WidgetData data){ - widgetDataMap.put(data.name(),data); + public static void addWidgetData(WidgetData data) { + widgetDataMap.put(data.name(), data); } /** @@ -40,8 +46,8 @@ public static void addWidgetData(WidgetData data){ * * @param widgetDatas The WidgetData objects to add. */ - public static void addWidgetDatas(WidgetData... widgetDatas){ - for(WidgetData data: widgetDatas) { + public static void addWidgetDatas(WidgetData... widgetDatas) { + for (WidgetData data : widgetDatas) { widgetDataMap.put(data.name(), data); } } @@ -106,41 +112,41 @@ public static void removeWidget(Widget widget) { * Larger the GUI scale, more accurate is the position. *

*

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

*

* - * @param newWidth Screen width after resize - * @param newHeight Screen height after resize - * @param previousWidth Screen width before resize + * @param newWidth Screen width after resize + * @param newHeight Screen height after resize + * @param previousWidth Screen width before resize * @param previousHeight Screen height before resize */ - public static void onScreenResized(int newWidth, int newHeight, int previousWidth, int previousHeight) { - for (Widget widget : widgets) { - // To ensure that infinite coords is not returned - if(widget.xPercent <= 0.0f){ - widget.xPercent = (float) widget.getX()/previousWidth; - } - if(widget.yPercent <= 0.0f){ - 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; - - // 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; - } - } + public static void onScreenResized(int newWidth, int newHeight, int previousWidth, int previousHeight) { + for (Widget widget : widgets) { + // To ensure that infinite coords is not returned + if (widget.xPercent <= 0.0f) { + widget.xPercent = (float) widget.getX() / previousWidth; + } + if (widget.yPercent <= 0.0f) { + 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; + + // 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; + } + } /** @@ -148,7 +154,7 @@ public static void onScreenResized(int newWidth, int newHeight, int previousWidt * * @param file The file to save to */ - public static void saveWidgets(File file,List widgets) throws IOException { + public static void saveWidgets(File file, List widgets) throws IOException { NbtCompound rootTag = new NbtCompound(); NbtList widgetList = new NbtList(); @@ -202,18 +208,18 @@ public static void loadWidgets(File file) throws IOException { widgets.clear(); if (file.exists()) { - NbtCompound rootTag = NbtIo.read(file.toPath()); - NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); - - 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); - widgets.add(widget); - } - }else{ + NbtCompound rootTag = NbtIo.read(file.toPath()); + NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); + + 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); + widgets.add(widget); + } + } else { printWarn("Widget File does not exist. Try saving one first"); } } @@ -226,6 +232,7 @@ public static void loadWidgets(File file) throws IOException { public static List getWidgets() { return widgets; } + /** * Returns the list of managed widgets with the same modID. * diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index f299f26..34baac0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -12,10 +12,10 @@ public class WidgetRenderer { public final List> allowedScreens = new CopyOnWriteArrayList<>(); - private boolean renderInGameHud = true; public boolean isInEditor = false; - List widgets; public Widget selectedWidget = null; + List widgets; + private boolean renderInGameHud = true; /** * Add the list of widgets the widgetRenderer should render @@ -24,15 +24,16 @@ public class WidgetRenderer { * * @param widgets List of widgets to render */ - public WidgetRenderer(List widgets){ + public WidgetRenderer(List widgets) { this.widgets = widgets; addScreen(GameMenuScreen.class); } - public void addWidget(Widget widget){ + + public void addWidget(Widget widget) { widgets.add(widget); } - public void addScreen(Class screen){ + public void addScreen(Class screen) { allowedScreens.add(screen); } @@ -41,93 +42,98 @@ public void shouldRenderInGameHud(boolean renderInGameHud) { } public void renderWidgets(DrawContext context, int mouseX, int mouseY) { - if(WidgetManager.getWidgets().isEmpty()) return; + if (WidgetManager.getWidgets().isEmpty()) return; Screen currentScreen = DynamicHUD.MC.currentScreen; - if(currentScreen == null && renderInGameHud){ + if (currentScreen == null && renderInGameHud) { for (Widget widget : widgets) { widget.isInEditor = false; - widget.render(context,0,0); + widget.render(context, 0, 0); } return; } - if(currentScreen instanceof AbstractMoveableScreen){ + if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { widget.isInEditor = true; - widget.renderInEditor(context,mouseX,mouseY); + widget.renderInEditor(context, mouseX, mouseY); } return; } if (currentScreen != null && allowedScreens.contains(DynamicHUD.MC.currentScreen.getClass()) && !this.isInEditor) { for (Widget widget : widgets) { widget.isInEditor = false; - widget.render(context,0,0); + widget.render(context, 0, 0); } } } - public void mouseClicked(double mouseX, double mouseY, int button){ + + public void mouseClicked(double mouseX, double mouseY, int button) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if(currentScreen == null) { + if (currentScreen == null) { return; } - if(currentScreen instanceof AbstractMoveableScreen){ + 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.mouseClicked(mouseX,mouseY,button)){ + if (widget.mouseClicked(mouseX, mouseY, button)) { selectedWidget = widget; return; } } } } - public void mouseDragged(double mouseX, double mouseY, int button, int snapSize){ + + public void mouseDragged(double mouseX, double mouseY, int button, int snapSize) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if(currentScreen == null) { + if (currentScreen == null) { return; } - if(currentScreen instanceof AbstractMoveableScreen){ + 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)){ + if (widget.mouseDragged(mouseX, mouseY, button, snapSize)) { selectedWidget = widget; return; } } } } - public void mouseScrolled(double mouseX, double mouseY, double vAmount,double hAmount){ + + public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if(currentScreen == null) { + if (currentScreen == null) { return; } - if(currentScreen instanceof AbstractMoveableScreen){ + if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - widget.mouseScrolled(mouseX,mouseY,vAmount,hAmount); + widget.mouseScrolled(mouseX, mouseY, vAmount, hAmount); } } } - public void keyPressed(int keyCode){ + 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)) { + if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { widget.shiftDown = true; } } } - public void keyReleased(int keyCode){ + + 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)) { + if (currentScreen instanceof AbstractMoveableScreen && (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT)) { for (Widget widget : widgets) { widget.shiftDown = false; } } } - public void onCloseScreen(){ - if(DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen){ + + public void onCloseScreen() { + if (DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { widget.onClose(); } @@ -138,14 +144,14 @@ public List getWidgets() { return widgets; } - public void mouseReleased(double mouseX, double mouseY, int button){ + public void mouseReleased(double mouseX, double mouseY, int button) { Screen currentScreen = DynamicHUD.MC.currentScreen; - if(currentScreen == null) { + if (currentScreen == null) { return; } - if(currentScreen instanceof AbstractMoveableScreen){ + if (currentScreen instanceof AbstractMoveableScreen) { for (Widget widget : widgets) { - widget.mouseReleased(mouseX,mouseY,button); + widget.mouseReleased(mouseX, mouseY, button); } } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index a75269f..5715ce1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -4,33 +4,34 @@ import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.*; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.DoubleOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.EnumOption; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.ListOption; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption.ColorOption; import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.nbt.NbtCompound; import org.lwjgl.glfw.GLFW; -import java.awt.Color; -import java.util.*; +import java.awt.*; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; public class TextWidget extends Widget { - public static WidgetData DATA = new WidgetData<>("TextWidget","Display Text on screen",TextWidget::new); - Supplier textSupplier; - String dynamicRegistryKey = ""; - DynamicValueRegistry dynamicValueRegistry = null; + public Color textColor; public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); 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 + Supplier textSupplier; + String dynamicRegistryKey = ""; + DynamicValueRegistry dynamicValueRegistry = null; private ContextMenu menu; - public Color textColor; - public TextWidget() { - this(null,null,false,false,Color.WHITE,"unknown"); + this(null, null, false, false, Color.WHITE, "unknown"); } /** @@ -40,8 +41,8 @@ public TextWidget() { * @param shadow * @param rainbow */ - public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,Color color,String modID) { - super(DATA,modID); + public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow, Color color, String modID) { + super(DATA, modID); this.dynamicRegistryKey = dynamicRegistryKey; textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); this.shadow = shadow; @@ -57,11 +58,11 @@ public TextWidget(String dynamicRegistryKey, boolean shadow, boolean rainbow,Col * @param shadow * @param rainbow */ - public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegistryKey, boolean shadow, boolean rainbow,Color color,String modID) { - super(DATA,modID); + public TextWidget(DynamicValueRegistry dynamicValueRegistry, String dynamicRegistryKey, boolean shadow, boolean rainbow, Color color, String modID) { + super(DATA, modID); this.dynamicRegistryKey = dynamicRegistryKey; this.dynamicValueRegistry = dynamicValueRegistry; - if(dynamicValueRegistry != null) { + if (dynamicValueRegistry != null) { textSupplier = (Supplier) dynamicValueRegistry.get(dynamicRegistryKey); } this.textColor = color; @@ -69,49 +70,46 @@ public TextWidget(DynamicValueRegistry dynamicValueRegistry,String dynamicRegist this.rainbow = rainbow; createMenu(); } - 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)); - menu.addOption(new ColorOption("TextColor",menu,()-> textColor, value -> textColor = value)); - menu.addOption(new DoubleOption("RainbowSpeed",1,4,1.0f, ()->(double)this.rainbowSpeed, value-> this.rainbowSpeed = value.intValue())); + + 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)); + menu.addOption(new ColorOption("TextColor", menu, () -> textColor, value -> textColor = value)); + menu.addOption(new DoubleOption("RainbowSpeed", 1, 4, 1.0f, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue())); /* TEST */ AtomicReference enums = new AtomicReference<>(Enum.Enum1); AtomicReference option = new AtomicReference<>("Enum1"); menu.addOption(new EnumOption<>("Enum", enums::get, enums::set, Enum.values())); - List options = Arrays.asList("List1","List2","List3"); + List options = Arrays.asList("List1", "List2", "List3"); menu.addOption(new ListOption<>("List", option::get, option::set, options)); } - public enum Enum{ - Enum1, - Enum2, - Enum3 - } + @Override - public void renderWidget(DrawContext drawContext,int mouseX, int mouseY) { + public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { 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); - widgetBox.setSizeAndPosition(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2,this.shouldScale,GlobalConfig.get().scale); + 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().scale); } menu.render(drawContext, getX() - 2, 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)){ + if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) { menu.toggleDisplay(); } - menu.mouseClicked(mouseX,mouseY,button); + 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); + menu.mouseReleased(mouseX, mouseY, button); super.mouseReleased(mouseX, mouseY, button); } @@ -130,11 +128,11 @@ public void onClose() { @Override public void writeToTag(NbtCompound tag) { super.writeToTag(tag); - tag.putString("DynamicRegistryKey",dynamicRegistryKey); - tag.putBoolean("Shadow",shadow); - tag.putBoolean("Rainbow",rainbow); - tag.putInt("TextColor",textColor.getRGB()); - tag.putInt("RainbowSpeed",rainbowSpeed); + tag.putString("DynamicRegistryKey", dynamicRegistryKey); + tag.putBoolean("Shadow", shadow); + tag.putBoolean("Rainbow", rainbow); + tag.putInt("TextColor", textColor.getRGB()); + tag.putInt("RainbowSpeed", rainbowSpeed); // 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); @@ -152,20 +150,27 @@ public void readFromTag(NbtCompound tag) { // 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){ + if (!dvrObj) { this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); return; } - for(DynamicValueRegistry dvr: DynamicValueRegistry.getInstances(modId)){ + 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); return; } createMenu(); - } - public static class Builder extends WidgetBuilder { + } + + public enum Enum { + Enum1, + Enum2, + Enum3 + } + + public static class Builder extends WidgetBuilder { protected boolean shadow = false; protected boolean rainbow = false; protected String dynamicRegistryKey = ""; @@ -181,14 +186,17 @@ public Builder rainbow(boolean rainbow) { this.rainbow = rainbow; return self(); } + public Builder setDRKey(String dynamicRegistryKey) { this.dynamicRegistryKey = dynamicRegistryKey; return self(); } + public Builder setDVR(DynamicValueRegistry dynamicValueRegistry) { this.dynamicValueRegistry = dynamicValueRegistry; return self(); } + public Builder setTextColor(Color textColor) { this.textColor = textColor; return self(); @@ -202,15 +210,17 @@ 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); + if (dynamicValueRegistry == null) { + widget = new TextWidget(dynamicRegistryKey, shadow, rainbow, textColor, modID); + } else { + widget = new TextWidget(dynamicValueRegistry, dynamicRegistryKey, shadow, rainbow, textColor, modID); } - widget.setPosition(x,y); + widget.setPosition(x, y); widget.setDraggable(isDraggable); widget.setShouldScale(shouldScale); return widget; } } + + } From 9ac11007401c7b0a6e0249d2889b8e5ddd86eec9 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Fri, 12 Apr 2024 00:21:16 +0530 Subject: [PATCH 20/33] SubMenuOption, some changes and javadocs --- .../dynamichud/newTrial/DynamicHUD.java | 14 ++-- .../dynamichud/newTrial/DynamicHudTest.java | 5 ++ ...HudTestTWO.java => DynamicHudTestTwo.java} | 2 +- .../dynamichud/newTrial/HudRender.java | 4 + .../contextmenu/options/SubMenuOption.java | 77 +++++++++++++++++++ .../coloroption/ColorGradientPicker.java | 10 ++- .../newTrial/widget/WidgetManager.java | 4 +- .../newTrial/widgets/TextWidget.java | 8 +- 8 files changed, 111 insertions(+), 13 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/newTrial/{DynamicHudTestTWO.java => DynamicHudTestTwo.java} (97%) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 8ac82e1..6ff2a1d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -69,9 +69,10 @@ public void onInitializeClient() { printInfo("Initialising DynamicHud"); // Add WidgetData of included widgets - WidgetManager.addWidgetDatas( + WidgetManager.registerCustomWidgets( TextWidget.DATA ); + //YACL load GlobalConfig.HANDLER.load(); @@ -81,12 +82,16 @@ public void onInitializeClient() { .forEach(entrypoint -> { 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(); DHIntegration.init(); - File widgetsFile = DHIntegration.getWidgetsFile(); + widgetsFile = DHIntegration.getWidgetsFile(); if (widgetsFile.exists()) { WidgetManager.loadWidgets(widgetsFile); @@ -97,11 +102,11 @@ public void onInitializeClient() { screen = DHIntegration.getMovableScreen(); - KeyBinding binding = DHIntegration.getKeyBind(); + binding = DHIntegration.getKeyBind(); DHIntegration.registerCustomWidgets(); - WidgetRenderer widgetRenderer = DHIntegration.getWidgetRenderer(); + widgetRenderer = DHIntegration.getWidgetRenderer(); addWidgetRenderer(widgetRenderer); List widgets = fileMap.get(widgetsFile.getName()); @@ -139,7 +144,6 @@ public void onInitializeClient() { ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> GlobalConfig.HANDLER.save()); ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> GlobalConfig.HANDLER.save()); Runtime.getRuntime().addShutdownHook(new Thread(() -> GlobalConfig.HANDLER.save())); - GlobalConfig.HANDLER.save(); HudRenderCallback.EVENT.register(new HudRender()); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java index 9c4a431..fd888c5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java @@ -55,6 +55,11 @@ public void addWidgets() { WidgetManager.addWidget(Example2Widget); } + @Override + public void registerCustomWidgets() { + //WidgetManager.addWidgetData(MyWidget.DATA); + } + public void initAfter() { List widgets = WidgetManager.getWidgetsForMod(DynamicHUD.MOD_ID); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java similarity index 97% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java rename to src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java index 9615f2c..82479c8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTWO.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java @@ -16,7 +16,7 @@ import java.io.File; import java.util.List; -public class DynamicHudTestTWO implements DynamicHudIntegration { +public class DynamicHudTestTwo implements DynamicHudIntegration { TextWidget exampleWidget; WidgetRenderer renderer; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java index 48a7014..2a80dc3 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java @@ -4,6 +4,10 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.gui.DrawContext; +/** + * 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 { @Override public void onHudRender(DrawContext drawContext, float tickDelta) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java new file mode 100644 index 0000000..9bc04e9 --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java @@ -0,0 +1,77 @@ +package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; + +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * SubMenu option displays a sub menu beside a boolean-like button. + *

+ * The {@link #getter} gets a boolean value to display/close the subMenu by default. + *

+ * 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; + public String name = "Empty"; + + + public SubMenuOption(String name, @NotNull ContextMenu parentMenu, Supplier getter, Consumer setter) { + super(getter, setter); + Objects.requireNonNull(parentMenu,"Parent Menu cannot be null"); + this.name = name; + this.parentMenu = parentMenu; + this.subMenu = new ContextMenu(parentMenu.x + parentMenu.width,this.y); + this.subMenu.heightOffset = 0; + this.subMenu.shouldDisplay = get(); + } + + @Override + public void render(DrawContext drawContext, int x, int y) { + super.render(drawContext, x, y); + + int color = value ? Color.GREEN.getRGB() : Color.RED.getRGB(); + drawContext.drawText(mc.textRenderer, Text.of(name), x, y, color, false); + + subMenu.render(drawContext, this.x + parentMenu.width, this.y, 0); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (super.mouseClicked(mouseX, mouseY, button)) { + subMenu.toggleDisplay(); + set(subMenu.shouldDisplay); + return true; + } + subMenu.mouseClicked(mouseX, mouseY, button); + return false; + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + subMenu.mouseReleased(mouseX, mouseY, button); + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button) { + subMenu.mouseDragged(mouseX, mouseY, button); + return super.mouseDragged(mouseX, mouseY, button); + } + + public SubMenuOption getOption(){ + return this; + } + + public ContextMenu getSubMenu() { + return subMenu; + } +} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java index b9e69f8..701e145 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -59,11 +59,13 @@ public void render(DrawContext drawContext, int x1, int y1) { } gradientSlider.render(drawContext, x + 30, y + client.textRenderer.fontHeight + 4); gradientBox.render(drawContext, x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); - colorPickerButton.render(drawContext, x + 55 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); + colorPickerButton.render(drawContext, x + 54 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); alphaSlider.render(drawContext, x + 40 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking()) { - // Draw the cursor + // 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(); @@ -71,14 +73,18 @@ public void render(DrawContext drawContext, int x1, int y1) { 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 = GlAllocationUtils.allocateByteBuffer(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(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 75208a4..6520b51 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -37,7 +37,7 @@ public class WidgetManager { * * @param data The WidgetData object to add. */ - public static void addWidgetData(WidgetData data) { + public static void registerCustomWidget(WidgetData data) { widgetDataMap.put(data.name(), data); } @@ -46,7 +46,7 @@ public static void addWidgetData(WidgetData data) { * * @param widgetDatas The WidgetData objects to add. */ - public static void addWidgetDatas(WidgetData... widgetDatas) { + public static void registerCustomWidgets(WidgetData... widgetDatas) { for (WidgetData data : widgetDatas) { widgetDataMap.put(data.name(), data); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 5715ce1..657ab53 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -22,7 +22,8 @@ import java.util.function.Supplier; public class TextWidget extends Widget { - public Color textColor; public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); + public Color textColor; + public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); 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 @@ -95,7 +96,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().scale); } - menu.render(drawContext, getX() - 2, getY(), (int) Math.ceil(getHeight())); + menu.render(drawContext, getX(), getY(), (int) Math.ceil(getHeight())); } @Override @@ -149,9 +150,10 @@ public void readFromTag(NbtCompound tag) { // 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"); - + System.out.println(dvrObj); if (!dvrObj) { this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); + System.out.println(textSupplier); return; } From 18665bb0938d024490d49c7a6648293be7b484db Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 10:49:04 +0530 Subject: [PATCH 21/33] Fixed a few bugs. --- .../dynamichud/newTrial/DynamicHUD.java | 44 +++++++++++++------ .../newTrial/DynamicHudIntegration.java | 9 ++++ .../screens/AbstractMoveableScreen.java | 7 ++- .../utils/contextmenu/ContextMenu.java | 2 +- .../dynamichud/newTrial/widget/Widget.java | 1 + .../newTrial/widgets/TextWidget.java | 4 +- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 6ff2a1d..900c4ce 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -7,6 +7,7 @@ import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; +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; @@ -30,7 +31,7 @@ public class DynamicHUD implements ClientModInitializer { *

* Allows saving widgets across different mods with same save file name. */ - public static final HashMap> fileMap = new HashMap<>(); + public static final HashMap> FILE_MAP = new HashMap<>(); private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); private static final List widgetRenderers = new ArrayList<>(); public static MinecraftClient MC = MinecraftClient.getInstance(); @@ -89,33 +90,43 @@ public void onInitializeClient() { 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 (widgetsFile.exists()) { WidgetManager.loadWidgets(widgetsFile); } else { DHIntegration.addWidgets(); } + + //Calls the second init method DHIntegration.initAfter(); + // Get the instance of AbstractMoveableScreen screen = DHIntegration.getMovableScreen(); + // 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 = fileMap.get(widgetsFile.getName()); + List widgets = FILE_MAP.get(widgetsFile.getName()); - if (widgets == null) { - fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + if (widgets == null || widgets.isEmpty()) { + FILE_MAP.put(widgetsFile.getName(), widgetRenderer.getWidgets()); } else { - widgetRenderer.getWidgets().addAll(widgets); - fileMap.put(widgetsFile.getName(), widgetRenderer.getWidgets()); + widgets.addAll(widgetRenderer.getWidgets()); + FILE_MAP.put(widgetsFile.getName(), widgets); } //Register events for rendering, saving, loading, and opening the hudEditor @@ -123,12 +134,19 @@ public void onInitializeClient() { openDynamicScreen(binding, screen); }); - // Save during exiting a world, server or Minecraft itself - // Also saved when a resource pack is reloaded. - ServerLifecycleEvents.SERVER_STOPPING.register(server -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, s) -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName()))); - Runtime.getRuntime().addShutdownHook(new Thread(() -> saveWidgetsSafely(widgetsFile, fileMap.get(widgetsFile.getName())))); + /* === Saving === */ + + //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) { @@ -143,7 +161,7 @@ public void onInitializeClient() { 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()); - Runtime.getRuntime().addShutdownHook(new Thread(() -> GlobalConfig.HANDLER.save())); + ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient)->GlobalConfig.HANDLER.save()); HudRenderCallback.EVENT.register(new HudRender()); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java index 1a7ef92..6018497 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java @@ -1,6 +1,7 @@ package com.tanishisherewith.dynamichud.newTrial; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -75,6 +76,14 @@ public interface DynamicHudIntegration { /** * To register custom widgets. This method can be overridden by implementations. + *

+ * Use {@link WidgetManager#registerCustomWidget(WidgetData)} to register custom widgets. + *

+     * Example:
+     *     {@code
+     *     WidgetManager.registerCustomWidget(TextWidget.DATA);
+     *     }
+     * 
*/ default void registerCustomWidgets() { } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index 72194f5..ce53614 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -18,6 +18,12 @@ public AbstractMoveableScreen(Text title, WidgetRenderer renderer) { this.widgetRenderer = renderer; } + @Override + public void onDisplayed() { + super.onDisplayed(); + widgetRenderer.isInEditor = true; + } + @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { widgetRenderer.mouseDragged(mouseX, mouseY, button, snapSize); @@ -68,7 +74,6 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) this.renderBackgroundTexture(drawContext); } // Draw each widget - widgetRenderer.isInEditor = true; widgetRenderer.renderWidgets(drawContext, mouseX, mouseY); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index 2f1d401..18086f9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -12,7 +12,7 @@ public class ContextMenu { public int x, y; public int width = 0; public int height = 0; - public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light grey color + public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light greyish - blue color public int padding = 5; // The amount of padding around the rectangle public int heightOffset = 4; // Height offset from the widget public boolean shouldDisplay = false; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java index 8512958..fe826d9 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java @@ -183,6 +183,7 @@ 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) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 657ab53..2536f77 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -134,7 +134,6 @@ public void writeToTag(NbtCompound tag) { tag.putBoolean("Rainbow", rainbow); tag.putInt("TextColor", textColor.getRGB()); tag.putInt("RainbowSpeed", rainbowSpeed); - // 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); } @@ -150,10 +149,8 @@ public void readFromTag(NbtCompound tag) { // 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"); - System.out.println(dvrObj); if (!dvrObj) { this.textSupplier = (Supplier) DynamicValueRegistry.getGlobal(dynamicRegistryKey); - System.out.println(textSupplier); return; } @@ -161,6 +158,7 @@ public void readFromTag(NbtCompound tag) { //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; } createMenu(); From b93262157fb12695307f01076130a37a12e53127 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:14:22 +0530 Subject: [PATCH 22/33] Changes --- .../dynamichud/DynamicHUD.java | 1 - .../dynamichud/newTrial/DynamicHUD.java | 1 + .../newTrial/DynamicHudIntegration.java | 8 +- .../newTrial/DynamicHudTestTwo.java | 80 ------------------- .../newTrial/utils/DynamicValueRegistry.java | 2 +- .../utils/contextmenu/ContextMenu.java | 1 + .../newTrial/utils/contextmenu/Option.java | 17 ++++ 7 files changed, 24 insertions(+), 86 deletions(-) delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index 18b14c4..1c86728 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -13,7 +13,6 @@ import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; import net.minecraft.resource.LifecycledResourceManager; import net.minecraft.server.MinecraftServer; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 900c4ce..5643c84 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -163,6 +163,7 @@ public void onInitializeClient() { ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> GlobalConfig.HANDLER.save()); ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient)->GlobalConfig.HANDLER.save()); + HudRenderCallback.EVENT.register(new HudRender()); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java index 6018497..e28a507 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java @@ -40,10 +40,10 @@ public interface DynamicHudIntegration { * The key binding for opening the editor screen. */ KeyBinding EDITOR_SCREEN_KEY_BINDING = KeyBindingHelper.registerKeyBinding(new KeyBinding( - TRANSLATION_KEY, - INPUT_TYPE, - KEY, - KEYBIND_CATEGORY + "DynamicHud Editor Screen", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_RIGHT_SHIFT, + "DynamicHud" )); /** diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java deleted file mode 100644 index 82479c8..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTestTwo.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.tanishisherewith.dynamichud.newTrial; - -import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.newTrial.widget.Widget; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; -import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.gui.screen.option.OptionsScreen; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; - -import java.io.File; -import java.util.List; - -public class DynamicHudTestTwo implements DynamicHudIntegration { - TextWidget exampleWidget; - WidgetRenderer renderer; - - @Override - public void init() { - //Global registry - DynamicValueRegistry.registerGlobal("CPS", () -> "NOT FPS"); - - - exampleWidget = new TextWidget.Builder() - .setX(150) - .setY(100) - .setDraggable(true) - .rainbow(true) - .setDRKey("CPS") - .setModID("CustomMod") - .shouldScale(true) - .build(); - } - - @Override - public KeyBinding getKeyBind() { - return KeyBindingHelper.registerKeyBinding(new KeyBinding( - "DynamicHUD editor screenn", - INPUT_TYPE, - GLFW.GLFW_KEY_RIGHT_CONTROL, - "CATEGORY 2" - )); - } - - @Override - public File getWidgetsFile() { - return new File(FILE_DIRECTORY, "widgets_new.nbt"); - } - - @Override - public void addWidgets() { - WidgetManager.addWidget(exampleWidget); - } - - public void initAfter() { - List widgets = WidgetManager.getWidgetsForMod("CustomMod"); - - renderer = new WidgetRenderer(widgets); - renderer.shouldRenderInGameHud(true); - renderer.addScreen(OptionsScreen.class); - renderer.addScreen(TitleScreen.class); - } - - @Override - public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor 2"), renderer) { - }; - } - - @Override - public WidgetRenderer getWidgetRenderer() { - return renderer; - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java index 811ef62..6eee0ba 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java @@ -13,7 +13,7 @@ *
  *     {@code
  *     DynamicValueRegistry dvr = new DynamicValueRegistry("mod_id");
- *     dvr.registerGlobal("ABC",//YourSupplier);
+ *     dvr.registerLocal("ABC",//YourSupplier);
  *     Supplier result = dvr.get("ABC");
  *     }
  * 
diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index 18086f9..1911b5d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -46,6 +46,7 @@ public void render(DrawContext drawContext, int x, int y, int height) { int yOffset = y1 + 3; this.width = 10; for (Option option : options) { + if(!option.shouldRender())continue; option.render(drawContext, x + 2, yOffset); this.width = Math.max(this.width, option.width + padding); yOffset += option.height + 1; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java index 676af06..8244df8 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -18,6 +18,7 @@ public abstract class Option { protected T defaultValue = null; protected MinecraftClient mc = MinecraftClient.getInstance(); private Widget selectedWidget; // The widget that this context menu is associated with + public Supplier shouldRender = ()->true; public Option(Supplier getter, Consumer setter) { this.getter = getter; @@ -25,6 +26,13 @@ public Option(Supplier getter, Consumer setter) { value = get(); defaultValue = get(); } + public Option(Supplier getter, Consumer setter,Supplier shouldRender) { + this.getter = getter; + this.setter = setter; + this.shouldRender = shouldRender; + value = get(); + defaultValue = get(); + } protected T get() { return getter.get(); @@ -63,4 +71,13 @@ public void keyReleased(int key) { public boolean isMouseOver(double mouseX, double mouseY) { return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; } + + public Option setShouldRender(Supplier shouldRender) { + this.shouldRender = shouldRender; + return this; + } + + public boolean shouldRender(){ + return shouldRender.get(); + } } From 18d26278edc30cd5d2988e721fae10d115a69c48 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 21:54:32 +0530 Subject: [PATCH 23/33] Removed old code --- .../dynamichud/DynamicHUD.java | 164 ------- .../dynamichud/DynamicHUDtest.java | 177 ------- .../handlers/DefaultDragHandler.java | 32 -- .../handlers/DefaultMouseHandler.java | 78 ---- .../dynamichud/handlers/DragHandler.java | 12 - .../dynamichud/handlers/MouseHandler.java | 21 - .../dynamichud/helpers/ColorHelper.java | 146 ------ .../dynamichud/helpers/DrawHelper.java | 249 ---------- .../dynamichud/helpers/TextureHelper.java | 233 --------- .../huds/AbstractMoveableScreen.java | 214 --------- .../dynamichud/huds/MoveableScreen.java | 175 ------- .../dynamichud/interfaces/IWigdets.java | 12 - .../dynamichud/interfaces/TextGenerator.java | 6 - .../dynamichud/interfaces/WidgetLoading.java | 34 -- .../dynamichud/newTrial/DynamicHUD.java | 6 +- .../newTrial/config/GlobalConfig.java | 2 +- .../newTrial/helpers/DrawHelper.java | 3 +- .../newTrial/helpers/TextureHelper.java | 233 --------- .../screens/AbstractMoveableScreen.java | 1 + .../utils/contextmenu/ContextMenu.java | 2 +- .../newTrial/utils/contextmenu/Option.java | 2 +- .../coloroption/ColorGradientPicker.java | 2 +- .../options/coloroption/GradientBox.java | 4 +- .../options/coloroption/GradientSlider.java | 4 +- .../newTrial/widget/WidgetManager.java | 34 +- .../newTrial/widget/WidgetRenderer.java | 2 +- .../newTrial/widgets/TextWidget.java | 5 +- .../dynamichud/util/CustomItemRenderer.java | 39 -- .../dynamichud/util/CustomTextRenderer.java | 39 -- .../dynamichud/util/DynamicUtil.java | 104 ----- .../util/colorpicker/ColorGradientPicker.java | 116 ----- .../util/colorpicker/ColorPickerButton.java | 46 -- .../util/colorpicker/GradientBox.java | 129 ----- .../util/colorpicker/GradientSlider.java | 125 ----- .../util/contextmenu/ContextMenu.java | 441 ------------------ .../ContextMenuOptionsProvider.java | 6 - .../util/contextmenu/DataInputScreen.java | 57 --- .../util/contextmenu/DoubleInputScreen.java | 60 --- .../util/contextmenu/TextWidgetButtonExt.java | 13 - .../dynamichud/widget/Widget.java | 218 --------- .../dynamichud/widget/WidgetBox.java | 75 --- .../dynamichud/widget/WidgetManager.java | 200 -------- .../dynamichud/widget/armor/ArmorWidget.java | 141 ------ .../dynamichud/widget/item/ItemWidget.java | 141 ------ .../widget/slider/ScaleSliderWidget.java | 34 -- .../widget/slider/SliderWidget.java | 216 --------- .../widget/slider/SliderWidgetBuilder.java | 77 --- .../dynamichud/widget/text/TextWidget.java | 277 ----------- 48 files changed, 22 insertions(+), 4385 deletions(-) delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/DynamicHUDtest.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultDragHandler.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultMouseHandler.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/handlers/DragHandler.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/handlers/MouseHandler.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/huds/AbstractMoveableScreen.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/interfaces/IWigdets.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/interfaces/TextGenerator.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/interfaces/WidgetLoading.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/CustomItemRenderer.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/CustomTextRenderer.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorGradientPicker.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorPickerButton.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientBox.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientSlider.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenuOptionsProvider.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DataInputScreen.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DoubleInputScreen.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/armor/ArmorWidget.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/item/ItemWidget.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/slider/ScaleSliderWidget.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidget.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidgetBuilder.java delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/text/TextWidget.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java deleted file mode 100644 index 1c86728..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.tanishisherewith.dynamichud; - -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.interfaces.IWigdets; -import com.tanishisherewith.dynamichud.newTrial.utils.UID; -import com.tanishisherewith.dynamichud.util.DynamicUtil; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; -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.minecraft.client.MinecraftClient; -import net.minecraft.client.util.InputUtil; -import net.minecraft.resource.LifecycledResourceManager; -import net.minecraft.server.MinecraftServer; -import org.lwjgl.glfw.GLFW; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; - -public class DynamicHUD implements ClientModInitializer { - - public static MinecraftClient MC = MinecraftClient.getInstance(); - - public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); - static AbstractMoveableScreen Screen; - private static String keybingCategory = "DynamicHud"; - private static String TranslationKey = "DynamicHud Editor Screen"; - private static InputUtil.Type inputType = InputUtil.Type.KEYSYM; - private static int key = GLFW.GLFW_KEY_RIGHT_SHIFT; - // public static final KeyBinding EditorScreenKeyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( -// TranslationKey, -// inputType, -// key, -// keybingCategory -// )); - private static String filename = "widgets.nbt"; - private static File fileDirectory = FabricLoader.getInstance().getConfigDir().toFile(); - public static final File WIDGETS_FILE = new File(fileDirectory, filename); - private static DynamicUtil dynamicutil; - private static IWigdets iWigdets; - MinecraftClient mc = MinecraftClient.getInstance(); - - public static File getFileDirectory() { - return fileDirectory; - } - - public static String getFilename() { - return filename; - } - - public static String getTranslationKey() { - return TranslationKey; - } - - public static String getKeybingCategory() { - return keybingCategory; - } - - public static InputUtil.Type getInputType() { - return inputType; - } - - public static void setInputType(InputUtil.Type inputType) { - DynamicHUD.inputType = inputType; - } - - public static void setKeyBindKey(int key) { - DynamicHUD.key = key; - } - - public static void setKeybingCategory(String keybingCategory) { - DynamicHUD.keybingCategory = keybingCategory; - } - - public static void setTranslationKey(String translationKey) { - TranslationKey = translationKey; - } - - public static void setFilename(String filename) { - DynamicHUD.filename = filename; - } - - public static void setFileDirectory(File fileDirectory) { - DynamicHUD.fileDirectory = fileDirectory; - } - - public static void setAbstractScreen(AbstractMoveableScreen screen) { - Screen = screen; - } - - public static AbstractMoveableScreen getScreen() { - return Screen; - } - - public static DynamicUtil getDynamicUtil() { - return dynamicutil; - } - - public static IWigdets getIWigdets() { - return iWigdets; - } - - public static void setIWigdets(IWigdets iWigdets) { - DynamicHUD.iWigdets = iWigdets; - } - - public static void printInfo(String msg) { - logger.info(msg); - } - - public static void printWarn(String msg) { - logger.warn(msg); - } - - @Override - public void onInitializeClient() { - dynamicutil = new DynamicUtil(mc); - printInfo("DynamicHud Initialised"); - - //Save and Load - ClientTickEvents.START_CLIENT_TICK.register(server -> { - if (iWigdets != null) { - if (!WIDGETS_FILE.exists()) { - if (!dynamicutil.WidgetAdded) { - iWigdets.addWigdets(dynamicutil); - } - if (!dynamicutil.MainMenuWidgetAdded) { - iWigdets.addMainMenuWigdets(dynamicutil); - } - } - - if (WIDGETS_FILE.exists() && !dynamicutil.WidgetLoaded) { - iWigdets.loadWigdets(dynamicutil); - printInfo("Widgets loaded"); - File FileDirectory = new File(fileDirectory, filename); - printInfo("Load file Directory: " + FileDirectory); - } - } - // DynamicUtil.openDynamicScreen(EditorScreenKeyBinding, Screen); - }); - - //RenderCallBack - HudRenderCallback.EVENT.register((drawContext, tickDelta) -> dynamicutil.render(drawContext, tickDelta)); - - // Save during exiting a world, server or Minecraft itself - ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStopping); - ServerLifecycleEvents.END_DATA_PACK_RELOAD.register(this::onEndDataPackReload); - ServerPlayConnectionEvents.DISCONNECT.register((handler, packetSender) -> dynamicutil.getWidgetManager().saveWidgets(WIDGETS_FILE)); - Runtime.getRuntime().addShutdownHook(new Thread(() -> dynamicutil.getWidgetManager().saveWidgets(WIDGETS_FILE))); - } - - private void onEndDataPackReload(MinecraftServer server, LifecycledResourceManager lifecycledResourceManager, boolean b) { - dynamicutil.getWidgetManager().saveWidgets(WIDGETS_FILE); - } - - private void onServerStopping(MinecraftServer server) { - dynamicutil.getWidgetManager().saveWidgets(WIDGETS_FILE); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUDtest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUDtest.java deleted file mode 100644 index d606440..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUDtest.java +++ /dev/null @@ -1,177 +0,0 @@ -package com.tanishisherewith.dynamichud; - -import com.tanishisherewith.dynamichud.helpers.TextureHelper; -import com.tanishisherewith.dynamichud.huds.MoveableScreen; -import com.tanishisherewith.dynamichud.interfaces.IWigdets; -import com.tanishisherewith.dynamichud.interfaces.WidgetLoading; -import com.tanishisherewith.dynamichud.util.DynamicUtil; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.armor.ArmorWidget; -import com.tanishisherewith.dynamichud.widget.item.ItemWidget; -import com.tanishisherewith.dynamichud.widget.text.TextWidget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.item.Items; -import net.fabricmc.api.ClientModInitializer; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; - -import java.awt.*; -import java.util.HashSet; -import java.util.Set; - -import static com.tanishisherewith.dynamichud.DynamicHUD.WIDGETS_FILE; -import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; - -public class DynamicHUDtest implements ClientModInitializer, IWigdets, WidgetLoading { - protected Set widgets = new HashSet<>(); - protected Set MainMenuwidgets = new HashSet<>(); - MinecraftClient mc = MinecraftClient.getInstance(); - private DynamicUtil dynamicutil; - - - @Override - public void onInitializeClient() { - dynamicutil = DynamicHUD.getDynamicUtil(); - widgets.clear(); - MainMenuwidgets.clear(); - - DynamicHUD.setAbstractScreen(new MoveableScreen(Text.of("Editor Screen"), dynamicutil)); - DynamicHUD.setIWigdets(new DynamicHUDtest()); - dynamicutil.getWidgetManager().setWidgetLoading(new DynamicHUDtest()); - } - - @Override - public void addWigdets(DynamicUtil dynamicUtil) { - if (mc.player != null) { - printInfo("Widgets added"); - addTextWidgets(dynamicUtil); - addArmorWidgets(dynamicUtil); - addItemWidgets(dynamicUtil); - dynamicUtil.WidgetAdded = true; - } - } - - private void addTextWidgets(DynamicUtil dynamicUtil) { - widgets.add(new TextWidget(mc, "Non Draggable FPS: ", () -> mc.fpsDebugString.split(" ")[0], 0.5f, 0.5f, true, true, -1, -1, true)); - widgets.add(new TextWidget(mc, "Dynamic", () -> "HUD", 0.7f, 0.3f, false, false, -1, -1, true)); - widgets.add(new TextWidget(mc, "Test", () -> "", 0.08f, 0.5f, false, false, -1, -1, true)); - widgets.add(new TextWidget(mc, "", () -> "Data Test", 0.4f, 0.8f, false, false, -1, -1, true)); - widgets.add(new TextWidget(mc, "HUD Test ", () -> "", 0.83f, 0.8f, false, false, -1, -1, true)); - - for (Widget widget : widgets) { - if (widget instanceof TextWidget textWidget) { - if (textWidget.getText().equalsIgnoreCase("Non Draggable FPS: ")) { - textWidget.setDraggable(false); - } - } - dynamicUtil.getWidgetManager().addWidget(widget); - } - } - - private void addArmorWidgets(DynamicUtil dynamicUtil) { - String text = "Text"; - widgets.add(new ArmorWidget(mc, EquipmentSlot.CHEST, 0.01f, 0.01f, true, - TextureHelper.Position.ABOVE, - () -> text, - () -> Color.RED, - true, - "Text")); - widgets.add(new ArmorWidget(mc, - EquipmentSlot.LEGS, - 0.05f, - 0.01f, - true, - TextureHelper.Position.LEFT, - () -> String.valueOf(MinecraftClient.getInstance().getCurrentFps()), - () -> Color.WHITE, - true, - "FPS")); - - for (Widget widget : widgets) { - if (widget instanceof ArmorWidget armorWidget) { - dynamicUtil.getWidgetManager().addWidget(armorWidget); - } - } - } - - private void addItemWidgets(DynamicUtil dynamicUtil) { - widgets.add(new ItemWidget(mc, - Items.DIAMOND_AXE::getDefaultStack, - 0.15f, - 0.15f, - true, - TextureHelper.Position.ABOVE, - () -> "Label", - () -> Color.RED, - true, - "Label")); - - for (Widget widgetItem : widgets) { - if (widgetItem instanceof ItemWidget itemWidgetItem) { - dynamicUtil.getWidgetManager().addWidget(itemWidgetItem); - } - } - } - - - @Override - public void addMainMenuWigdets(DynamicUtil dynamicUtil) { - printInfo("MainMenu Widgets added"); - - MainMenuwidgets.add(new TextWidget(mc, "Test ", () -> "", 0.83f, 0.8f, false, false, -1, -1, true)); - MainMenuwidgets.add(new TextWidget(mc, "E Test ", () -> "", 0.85f, 0.3f, false, false, -1, -1, true)); - MainMenuwidgets.add(new TextWidget(mc, "Non Draggable FPS: ", () -> String.valueOf(mc.getCurrentFps()), 0.67f, 0.5f, false, false, -1, -1, true)); - for (Widget mmwigdet : MainMenuwidgets) { - if (mmwigdet instanceof TextWidget textWidget) { - if (textWidget.getText().equalsIgnoreCase("Non Draggable FPS: ")) { - textWidget.setDraggable(false); - } - } - dynamicUtil.getWidgetManager().addMainMenuWidget(mmwigdet); - } - dynamicUtil.MainMenuWidgetAdded = true; - } - - @Override - public void loadWigdets(DynamicUtil dynamicUtil) { - Set widgets = dynamicUtil.getWidgetManager().loadWigdets(WIDGETS_FILE); - Set MainMenuWidget = dynamicUtil.getWidgetManager().loadMainMenuWigdets(WIDGETS_FILE); - - Widget.addTextGenerator("Non Draggable FPS: ", () -> String.valueOf(mc.getCurrentFps())); - Widget.addTextGenerator("Dynamic", () -> "HUD"); - Widget.addTextGenerator("Test", () -> ""); - Widget.addTextGenerator("", () -> "Data Test"); - Widget.addTextGenerator("HUD Test ", () -> ""); - Widget.addTextGenerator("Text", () -> "Text"); - Widget.addTextGenerator("Test ", () -> String.valueOf(mc.getCurrentFps())); - Widget.addTextGenerator("Non Draggable FPS: ", () -> String.valueOf(mc.getCurrentFps())); - Widget.addTextGenerator("Label", () -> "Label"); - - for (Widget widget : widgets) { - dynamicUtil.getWidgetManager().addWidget(widget); - } - - for (Widget widgetItem : MainMenuWidget) { - dynamicUtil.getWidgetManager().addMainMenuWidget(widgetItem); - } - - dynamicUtil.WidgetLoaded = true; - } - - - @Override - public Widget loadWidgetsFromTag(String className, NbtCompound widgetTag) { - //SAMPLE CODE EXAMPLE : - /*if (className.equals(ItemWidget.class.getName())) { - ItemWidget widget = new ItemWidget(MinecraftClient.getInstance(), ItemStack.EMPTY, 0, 0, true, TextureHelper.Position.ABOVE, () -> "", Color.BLUE); - widget.readFromTag(widgetTag); - return widget; - }*/ - System.out.println("widget tag loaded"); - return WidgetLoading.super.loadWidgetsFromTag(className, widgetTag); - } -} - - - diff --git a/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultDragHandler.java b/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultDragHandler.java deleted file mode 100644 index 02e77db..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultDragHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.tanishisherewith.dynamichud.handlers; - -import com.tanishisherewith.dynamichud.widget.Widget; - -public class DefaultDragHandler implements DragHandler { - private int dragStartX = 0; - private int dragStartY = 0; - - @Override - public boolean startDragging(Widget widget, double mouseX, double mouseY) { - if (widget.getWidgetBox().contains(widget, mouseX, mouseY, Widget.getScale())) { - dragStartX = (int) (mouseX - widget.getX()); - dragStartY = (int) (mouseY - widget.getY()); - return true; - } - return false; - } - - @Override - public void updateDragging(Widget widget, double mouseX, double mouseY) { - int newX = (int) (dragStartX + mouseX); - int newY = (int) (dragStartY + mouseY); - widget.setX(newX + (newX / 2)); - widget.setY(newY + (newY / 2)); - } - - @Override - public void stopDragging(Widget widget) { - // Nothing to do here in the default implementation - } -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultMouseHandler.java b/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultMouseHandler.java deleted file mode 100644 index 5a9c03f..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/handlers/DefaultMouseHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.tanishisherewith.dynamichud.handlers; - -import com.tanishisherewith.dynamichud.util.colorpicker.ColorGradientPicker; -import com.tanishisherewith.dynamichud.util.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.widget.slider.SliderWidget; -import com.tanishisherewith.dynamichud.widget.text.TextWidget; - -import java.util.List; - -public class DefaultMouseHandler implements MouseHandler { - private final ColorGradientPicker colorPicker; - private final List contextMenu; - private final List sliderWidget; - - public DefaultMouseHandler(ColorGradientPicker colorPicker, List contextMenu, List sliderWidget) { - this.colorPicker = colorPicker; - this.contextMenu = contextMenu; - this.sliderWidget = sliderWidget; - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (contextMenu != null && sliderWidget != null) { - for (ContextMenu contextMenu : contextMenu) { - if (contextMenuClicked(mouseX, mouseY, button, contextMenu)) { - return true; - } - } - for (SliderWidget sliderWidget : sliderWidget) { - if (sliderClicked(mouseX, mouseY, button, sliderWidget)) { - return true; - } - } - } - return colorPickerClicked(mouseX, mouseY, button); - } - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (sliderWidget != null) { - for (SliderWidget sliderWidget : sliderWidget) { - if (sliderWidget != null && sliderWidget.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) { - return true; - } - } - } - if (this.colorPicker != null) { - colorPicker.mouseDragged(mouseX, mouseY, button); - return true; - } - return false; - } - - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (this.colorPicker != null) { - colorPicker.mouseReleased(mouseX, mouseY, button); - return true; - } - return false; - } - - - @Override - public boolean contextMenuClicked(double mouseX, double mouseY, int button, ContextMenu contextMenu) { - return contextMenu != null && contextMenu.mouseClicked(mouseX, mouseY, button); - } - - @Override - public boolean colorPickerClicked(double mouseX, double mouseY, int button) { - return colorPicker != null && colorPicker.mouseClicked(mouseX, mouseY, button); - } - - @Override - public boolean sliderClicked(double mouseX, double mouseY, int button, SliderWidget sliderWidget) { - return sliderWidget != null && sliderWidget.mouseClicked(mouseX, mouseY, button); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/handlers/DragHandler.java b/src/main/java/com/tanishisherewith/dynamichud/handlers/DragHandler.java deleted file mode 100644 index 8c2c090..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/handlers/DragHandler.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.tanishisherewith.dynamichud.handlers; - -import com.tanishisherewith.dynamichud.widget.Widget; - -public interface DragHandler { - boolean startDragging(Widget widget, double mouseX, double mouseY); - - void updateDragging(Widget widget, double mouseX, double mouseY); - - void stopDragging(Widget widget); -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/handlers/MouseHandler.java b/src/main/java/com/tanishisherewith/dynamichud/handlers/MouseHandler.java deleted file mode 100644 index bb587f3..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/handlers/MouseHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.tanishisherewith.dynamichud.handlers; - -import com.tanishisherewith.dynamichud.util.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.widget.slider.SliderWidget; - -public interface MouseHandler { - boolean mouseClicked(double mouseX, double mouseY, int button); - - boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY); - - boolean mouseReleased(double mouseX, double mouseY, int button); - - boolean contextMenuClicked(double mouseX, double mouseY, int button, ContextMenu contextMenu); - - boolean colorPickerClicked(double mouseX, double mouseY, int button); - - boolean sliderClicked(double mouseX, double mouseY, int button, SliderWidget sliderWidget); - - -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java deleted file mode 100644 index 9e3884f..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.tanishisherewith.dynamichud.helpers; - -import net.minecraft.network.packet.Packet; -import net.minecraft.util.math.MathHelper; - -import java.awt.*; - -/** - * This class provides helper methods for working with colors. - */ -public class ColorHelper { - public static int r, g, b, a; - public ColorHelper(int r, int g, int b) { - this.r = r; - this.g = g; - this.b = b; - this.a = 255; - validate(); - } - public ColorHelper() { - } - public void validate() { - if (r < 0) r = 0; - else if (r > 255) r = 255; - - if (g < 0) g = 0; - else if (g > 255) g = 255; - - if (b < 0) b = 0; - else if (b > 255) b = 255; - - if (a < 0) a = 0; - else if (a > 255) a = 255; - } - /** - * Returns a color as an integer value given its red, green and blue components. - * - * @param red The red component of the color - * @param green The green component of the color - * @param blue The blue component of the color - * @return The color as an integer value - */ - public static int getColor(int red, int green, int blue) { - return getColor(red, green, blue, 255); - } - - /** - * Returns a color as an integer value given its red, green, blue and alpha components. - * - * @param red The red component of the color - * @param green The green component of the color - * @param blue The blue component of the color - * @param alpha The alpha component of the color - * @return The color as an integer value - */ - public static int getColor(int red, int green, int blue, int alpha) { - return (alpha << 24) | (red << 16) | (green << 8) | blue; - } - - public static Color getColorFromInt(int color) { - int red = (color >> 16) & 0xFF; - int green = (color >> 8) & 0xFF; - int blue = color & 0xFF; - return new Color(red, green, blue); - } - - /** - * Returns a color as an integer value given its hue. - * - * @param hue The hue of the color - * @return The color as an integer value - */ - public static int getColorFromHue(float hue) { - return Color.HSBtoRGB(hue, 1.0f, 1.0f); - } - - /** - * Converts a color to an integer. - * - * @param color The color to convert - * @return The integer representation of the JWT color - */ - public static int ColorToInt(Color color) { - return color.getRGB(); - } - public static float[] getRainbowColor() - { - float x = System.currentTimeMillis() % 2000 / 1000F; - float pi = (float)Math.PI; - - float[] rainbow = new float[3]; - rainbow[0] = 0.5F + 0.5F * MathHelper.sin(x * pi); - rainbow[1] = 0.5F + 0.5F * MathHelper.sin((x + 4F / 3F) * pi); - rainbow[2] = 0.5F + 0.5F * MathHelper.sin((x + 8F / 3F) * pi); - return rainbow; - } - - /** - * Rainbow color with custom speed. - * - * @param speed - * @return Current rainbow color. - */ - public static Color getRainbowColor(int speed) { - float hue = (System.currentTimeMillis() % (speed * 100)) / (speed * 100.0f); - return Color.getHSBColor(hue, 1.0f, 1.0f); - } - - - /** - * Changes alpha on color. - * - * @param color Target color. - * @param alpha Target alpha. - * @return Color with changed alpha. - */ - public static Color changeAlpha(Color color, int alpha) { - if (color != null) - return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); - else - return new Color(0); - } - public static int fromRGBA(int r, int g, int b, int a) { - return (r << 16) + (g << 8) + (b) + (a << 24); - } - - public static int toRGBAR(int color) { - return (color >> 16) & 0x000000FF; - } - - public static int toRGBAG(int color) { - return (color >> 8) & 0x000000FF; - } - - public static int toRGBAB(int color) { - return (color) & 0x000000FF; - } - - public static int toRGBAA(int color) { - return (color >> 24) & 0x000000FF; - } - public int toInt() - { - return new Color(r,b,g,a).getRGB(); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java deleted file mode 100644 index f997e28..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java +++ /dev/null @@ -1,249 +0,0 @@ -package com.tanishisherewith.dynamichud.helpers; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; -import com.tanishisherewith.dynamichud.util.CustomTextRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.*; -import net.minecraft.client.util.math.MatrixStack; -import org.joml.Matrix4f; - -public class DrawHelper extends DrawContext { - public static CustomTextRenderer customTextRenderer; - - public DrawHelper(MinecraftClient client, VertexConsumerProvider.Immediate vertexConsumers) { - super(client, vertexConsumers); - } - - /** - * Fills a box on the screen with a specified color. - * - * @param drawContext The matrix stack used for rendering - * @param x The x position of the rectangle - * @param y The y position of the rectangle - * @param width The width of the rectangle - * @param height The height of the rectangle - * @param color The color to fill the rectangle with - */ - public static void drawBox(DrawContext drawContext, int x, int y, int width, int height, int color) { - drawContext.fill(x, y, x + width, y + height, color); - } - - /** - * Fills a rectangle on the screen with a specified color. - * - * @param x1 The x position of the top left corner of the rectangle - * @param y1 The y position of the top left corner of the rectangle - * @param x2 The x position of the bottom right corner of the rectangle - * @param y2 The y position of the bottom right corner of the rectangle - * @param color The color to fill the rectangle with - */ - public static void fill(DrawContext drawContext, int x1, int y1, int x2, int y2, int color) { - drawContext.fill(x1, y1, x2, y2, color); - } - - /** - * Draws text on screen. - * - * @param textRenderer - TextRenderer instance used for rendering. - * @param text - Text to be drawn. - * @param x - X position to draw at. - * @param y - Y position to draw at. - * @param color - Color to draw with. - */ - public static void drawText(DrawContext drawContext, - TextRenderer textRenderer, - String text, - int x, - int y, - int color, - boolean shadow) { - drawContext.drawText(textRenderer, text, x, y, color, shadow); - } - - - /** - * Draws text on screen. - * - * @param drawContext - drawContext used for rendering. - * @param text - Text to be drawn. - * @param x - X position to draw at. - * @param y - Y position to draw at. - * @param color - Color to draw with. - */ - public static void drawTextWithScale(DrawContext drawContext, - String text, - int x, - int y, - int color, - boolean shadow, - float scale) { - customTextRenderer = new CustomTextRenderer(MinecraftClient.getInstance(), scale); - customTextRenderer.draw(drawContext, text, x, y, color, shadow); - } - - - public static void drawCutRectangle(DrawContext drawContext, int x1, int y1, int x2, int y2, int z, int color, int cornerRadius) { - // Draw the rectangles - drawContext.fill(x1 + cornerRadius, y1, x2 - cornerRadius, y1 + cornerRadius, z, color); - drawContext.fill(x1 + cornerRadius, y2 - cornerRadius, x2 - cornerRadius, y2, z, color); - drawContext.fill(x1, y1 + cornerRadius, x2, y2 - cornerRadius, z, color); - } - - - /** - * Fills a rounded rectangle on screen with specified color. - * This causes a lot of problems and for some reason does not work for ArmorWidget when used for contextMenu - * - * @param matrix4f - Matrix4f used for rendering. - * @param x1 - X position of top left corner of rectangle. - * @param y1 - Y position of top left corner of rectangle. - * @param x2 - X position of bottom right corner of rectangle. - * @param y2 - Y position of bottom right corner of rectangle. - * @param cornerRadius - Radius of rounded corners. - * @param color - Color to fill rectangle with. - */ - public static void fillRoundedRect(Matrix4f matrix4f, int x1, int y1, int x2, int y2, int cornerRadius, int color) { - float alpha = (float) (color >> 24 & 255) / 255.0F; - float red = (float) (color >> 16 & 255) / 255.0F; - float green = (float) (color >> 8 & 255) / 255.0F; - float blue = (float) (color & 255) / 255.0F; - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); - - // Draw the center rectangle - bufferBuilder.vertex(matrix4f, x1 + cornerRadius, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x2 - cornerRadius, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x2 - cornerRadius, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x1 + cornerRadius, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - - // Draw the side rectangles - bufferBuilder.vertex(matrix4f, x1, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x1 + cornerRadius, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x1 + cornerRadius, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x1, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - - bufferBuilder.vertex(matrix4f, x2, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x2 - cornerRadius, y1 + cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x2 - cornerRadius, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, x2, y2 - cornerRadius, 0).color(red, green, blue, alpha).next(); - - - // Draw the rounded corners - for (int i = 0; i <= 90; i += 5) { - double angle = Math.toRadians(i); - double sin = Math.sin(angle); - double cos = Math.cos(angle); - bufferBuilder.vertex(matrix4f, (float) (x1 + cornerRadius * (1 - cos)), (float) (y1 + cornerRadius * (1 - sin)), 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, (float) (x1 + cornerRadius * (1 - cos)), (float) (y2 - cornerRadius * (1 - sin)), 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, (float) (x2 - cornerRadius * (1 - cos)), (float) (y2 - cornerRadius * (1 - sin)), 0).color(red, green, blue, alpha).next(); - bufferBuilder.vertex(matrix4f, (float) (x2 - cornerRadius * (1 - cos)), (float) (y1 + cornerRadius * (1 - sin)), 0).color(red, green, blue, alpha).next(); - } - tessellator.draw(); - RenderSystem.disableBlend(); - } - - public static void fillRoundedRect(DrawContext drawContext, int left, int top, int right, int bottom, int color) { - drawContext.fill(left + 1, top, right - 1, top + 1, color); - drawContext.fill(left + 1, bottom - 1, right - 1, bottom, color); - drawContext.fill(left, top + 1, left + 1, bottom - 1, color); - drawContext.fill(right - 1, top + 1, right, bottom - 1, color); - drawContext.fill(left + 1, top + 1, right - 1, bottom - 1, color); - } - - /** - * Fills a rectangle on screen with a gradient. - * - * @param matrix4f - Matrix4f used for rendering. - * @param x1 - X position of top left corner of rectangle. - * @param y1 - Y position of top left corner of rectangle. - * @param x2 - X position of bottom right corner of rectangle. - * @param y2 - Y position of bottom right corner of rectangle. - * @param topColor - Color at top of gradient. - * @param bottomColor - Color at bottom of gradient. - */ - public static void fillGradient(Matrix4f matrix4f, int x1, int y1, int x2, int y2, int topColor, int bottomColor) { - float topAlpha = (float) (topColor >> 24 & 255) / 255.0F; - float topRed = (float) (topColor >> 16 & 255) / 255.0F; - float topGreen = (float) (topColor >> 8 & 255) / 255.0F; - float topBlue = (float) (topColor & 255) / 255.0F; - float bottomAlpha = (float) (bottomColor >> 24 & 255) / 255.0F; - float bottomRed = (float) (bottomColor >> 16 & 255) / 255.0F; - float bottomGreen = (float) (bottomColor >> 8 & 255) / 255.0F; - float bottomBlue = (float) (bottomColor & 255) / 255.0F; - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); - bufferBuilder.vertex(matrix4f, x1, y2, 0).color(topRed, topGreen, topBlue, topAlpha).next(); - bufferBuilder.vertex(matrix4f, x2, y2, 0).color(topRed, topGreen, topBlue, topAlpha).next(); - bufferBuilder.vertex(matrix4f, x2, y1, 0).color(bottomRed, bottomGreen, bottomBlue, bottomAlpha).next(); - bufferBuilder.vertex(matrix4f, x1, y1, 0).color(bottomRed, bottomGreen, bottomBlue, bottomAlpha).next(); - tessellator.draw(); - RenderSystem.disableBlend(); - } - - /** - * Draws an outlined box on the screen. - * - * @param x1 The x position of the top left corner of the box - * @param y1 The y position of the top left corner of the box - * @param x2 The x position of the bottom right corner of the box - * @param y2 The y position of the bottom right corner of the box - * @param color The color to draw the box with - */ - public static void drawOutlinedBox(DrawContext drawContext, int x1, int y1, int x2, int y2, int color) { - drawContext.fill(x1, y1, x2, y1 + 1, color); - drawContext.fill(x1, y2 - 1, x2, y2, color); - drawContext.fill(x1, y1 + 1, x1 + 1, y2 - 1, color); - drawContext.fill(x2 - 1, y1 + 1, x2, y2 - 1, color); - } - - /** - * This method assumes that the x, y coords are the origin of a widget. - * @param x X position of widget - * @param y Y position of widget - * @param scale Scale the matrices - */ - public static void scaleAndPosition(MatrixStack matrices, float x, float y, float scale) { - matrices.push(); // Save the current transformation state - - // Translate the origin back to the desired position - matrices.translate(x, y, 0); - - // Scale the matrix - matrices.scale(scale, scale, 1.0F); - - matrices.translate(-x,-y,0); - } - /** - * This method scales the matrices by the centre of the widget - * @param x X position of widget - * @param y Y position of widget - * @param height height of widget - * @param width width of widget - * @param scale Scale the matrices - */ - public static void scaleAndPosition(MatrixStack matrices, float x, float y,float width, float height, float scale) { - matrices.push(); // Save the current transformation state - - // Translate the origin back to the desired position - matrices.translate(x + width / 2.0f, y + height / 2.0f, 0); - - // Scale the matrix - matrices.scale(scale, scale, 1.0F); - - matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f), 0); - } - - public static void stopScaling(MatrixStack matrices){ - matrices.pop(); // Restore the previous transformation state - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java deleted file mode 100644 index 0fade01..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.tanishisherewith.dynamichud.helpers; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.tanishisherewith.dynamichud.util.CustomItemRenderer; -import com.tanishisherewith.dynamichud.util.CustomTextRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; - -/** - * This class provides helper methods for drawing textures on the screen. - */ -public class TextureHelper extends DrawContext { - public static CustomTextRenderer customTextRenderer; - public static CustomItemRenderer customItemRenderer; - - - public TextureHelper(MinecraftClient client, VertexConsumerProvider.Immediate vertexConsumers) { - super(client, vertexConsumers); - } - - /** - * Draws an item texture on the screen. - * - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - */ - public static void drawItemTexture(DrawContext drawContext, - ItemStack itemStack, - int x, - int y) { - drawContext.drawItem(itemStack, x, y); - } - - /** - * Draws the texture of the item in the player's main hand on the screen. - * - * @param client The Minecraft client instance - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - */ - public static void drawMainHandTexture(DrawContext drawContext, - MinecraftClient client, - int x, - int y) { - assert client.player != null; - ItemStack mainHandItem = client.player.getMainHandStack(); - drawItemTexture(drawContext, mainHandItem, x, y); - } - - /** - * Draws a textured rectangle on the screen. - * - * @param x The x position of the top left corner of the rectangle - * @param y The y position of the top left corner of the rectangle - * @param u The x position of the texture within the texture image - * @param v The y position of the texture within the texture image - * @param width The width of the rectangle - * @param height The height of the rectangle - * @param textureWidth The width of the texture image - * @param textureHeight The height of the texture image - */ - public static void drawTexture(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - drawContext.drawTexture(texture, x, y, u, v, width, height, textureWidth, textureHeight); - } - - /** - * Draws a textured rectangle on the screen with a specified color. - * - * @param x The x position of the top left corner of the rectangle - * @param y The y position of the top left corner of the rectangle - * @param u The x position of the texture within the texture image - * @param v The y position of the texture within the texture image - * @param width The width of the rectangle - * @param height The height of the rectangle - * @param color The color to draw the rectangle with - */ - public static void drawTexturedRect(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int color) { - RenderSystem.setShaderColor((color >> 16 & 255) / 255.0F, - (color >> 8 & 255) / 255.0F, - (color & 255) / 255.0F, - (color >> 24 & 255) / 255.0F); - drawContext.drawTexture(texture, x, y, u, v, width, height); - } - - /** - * Draws an item texture on the screen with text at a specified position relative to it. - * - * @param textRenderer The text renderer instance used for rendering the text - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - * @param text The text to draw relative to the texture - * @param color The color to draw the text with - * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) - * @param scale The scale factor to apply to the text (1.0 is normal size) - */ - public static void drawItemTextureWithText(DrawContext drawContext, - TextRenderer textRenderer, - ItemStack itemStack, - int x, - int y, - String text, - int color, - Position position, - float scale, - boolean textBackground - ) { - // Calculate the position of the text based on its size and the specified position - int textWidth = (int) (textRenderer.getWidth(text) * scale); - int textHeight = (int) (textRenderer.fontHeight * scale); - int textX = 0; - int textY = 0; - switch (position) { - case ABOVE -> { - textX = x + (16 - textWidth) / 2; - textY = y - textHeight; - } - case BELOW -> { - textX = x + (17 - textWidth) / 2; - textY = y + 16; - } - case LEFT -> { - textX = x - textWidth - 2; - textY = y + (16 - textHeight) / 2; - } - case RIGHT -> { - textX = x + 18; - textY = y + (16 - textHeight) / 2; - } - } - - // Draw semi-opaque black rectangle - if (text != null) { - if (textBackground && !text.trim().isEmpty()) { - int backgroundColor = 0x40000000; // ARGB format: 50% opaque black - drawContext.fill(textX - 1, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); - } - // Draw the scaled text at the calculated position - drawContext.getMatrices().push(); - drawContext.getMatrices().scale(scale, scale, 1.0f); - float scaledX = textX / scale; - float scaledY = textY / scale; - drawContext.drawText(textRenderer, text, (int) scaledX, (int) scaledY, color, false); - drawContext.getMatrices().pop(); - } - // Draw the item texture - drawContext.drawItem(itemStack, x, y); - } - - /** - * Draws an item texture on the screen with text at a specified position relative to it. - * - * @param itemScale The scale for the item to be rendered at - * @param textRenderer The text renderer instance used for rendering the text - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - * @param text The text to draw relative to the texture - * @param color The color to draw the text with - * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) - * @param textScale The scale factor to apply to the text (1.0 is normal size) - */ - public static void drawItemTextureWithTextAndScale(DrawContext drawContext, - float itemScale, - TextRenderer textRenderer, - ItemStack itemStack, - int x, - int y, - String text, - int color, - Position position, - float textScale, - boolean textBackground) { - if (text != null && !text.trim().isEmpty()) { - // Calculate the position of the text based on its size and the specified position - int textWidth = (int) (textRenderer.getWidth(text) * textScale); - int textHeight = (int) (textRenderer.fontHeight * textScale); - int textX = switch (position) { - case ABOVE, BELOW -> x + (int) ((16 * itemScale - textWidth) / 2); - case LEFT -> x - textWidth - 2; - case RIGHT -> x + (int) (16 * itemScale + 2); - }; - int textY = switch (position) { - case ABOVE -> y - textHeight - 2; - case BELOW -> y + (int) (16 * itemScale + 2); - case LEFT, RIGHT -> y + (int) ((16 * itemScale - textHeight) / 2); - }; - - // Draw semi-opaque black rectangle - if (textBackground) { - int backgroundColor = 0x40000000; // ARGB format: 50% opaque black - drawContext.fill(textX, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); - } - - // Draw the scaled text at the calculated position - drawContext.getMatrices().push(); - drawContext.getMatrices().scale(textScale, textScale, 11.0f); - float scaledX = textX / textScale; - float scaledY = textY / textScale; - drawContext.drawText(textRenderer, text, (int) scaledX + 1, (int) scaledY +1, color, false); - drawContext.getMatrices().pop(); - } - customItemRenderer = new CustomItemRenderer(itemStack, itemScale); - customItemRenderer.draw(drawContext, x, y, color); - } - - public enum Position { - ABOVE("Above"), - RIGHT("Right"), - BELOW("Below"), - LEFT("Left"); - private final String name; - - Position(String name) { - this.name = name; - } - - public static Position getByUpperCaseName(String name) { - if (name == null || name.isEmpty()) { - return null; - } - - return Position.valueOf(name.toUpperCase()); - } - } - - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/huds/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/huds/AbstractMoveableScreen.java deleted file mode 100644 index 5d33fb5..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/huds/AbstractMoveableScreen.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.tanishisherewith.dynamichud.huds; - -import com.tanishisherewith.dynamichud.handlers.DefaultDragHandler; -import com.tanishisherewith.dynamichud.handlers.DefaultMouseHandler; -import com.tanishisherewith.dynamichud.handlers.DragHandler; -import com.tanishisherewith.dynamichud.handlers.MouseHandler; -import com.tanishisherewith.dynamichud.util.DynamicUtil; -import com.tanishisherewith.dynamichud.util.colorpicker.ColorGradientPicker; -import com.tanishisherewith.dynamichud.util.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.slider.SliderWidget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -public abstract class AbstractMoveableScreen extends Screen { - protected final DynamicUtil dynamicutil; // The DynamicUtil instance used by this screen - protected MinecraftClient mc = MinecraftClient.getInstance(); - protected Widget selectedWidget = null; // The currently selected widget - protected int dragStartX = 0, dragStartY = 0; // The starting position of a drag operation - protected List contextMenus = new ArrayList<>(); // The context menu that is currently displayed - protected ColorGradientPicker colorPicker = null; // The color picker that is currently displayed - protected Widget sliderWigdet = null; // The widget that is currently being edited by the slider - protected List Sliders = new ArrayList<>(); // The List of sliders - protected MouseHandler mouseHandler; - protected DragHandler dragHandler; - protected int gridSize = 3; // The size of each grid cell in pixels - protected boolean ShouldPause = false; // To pause if the screen is opened or not - protected boolean ShouldBeAffectedByResize = false; // If the stuff drawn on screen to be affected by screen resize or not - protected int widgetX; - protected int widgetY; - - - /** - * Constructs a AbstractMoveableScreen object. - * - * @param dynamicutil The DynamicUtil instance used by this screen - */ - public AbstractMoveableScreen(Text title, DynamicUtil dynamicutil) { - super(title); - this.dynamicutil = dynamicutil; - updateMouseHandler(this.colorPicker, contextMenus, Sliders); - dragHandler = new DefaultDragHandler(); - } - - /** - * Handles mouse dragging on this screen. - * - * @param mouseX - Current X position of mouse cursor. - * @param mouseY - Current Y position of mouse cursor. - * @param button - Mouse button being dragged. - * @param deltaX - Change in X position since last call to this method. - * @param deltaY - Change in Y position since last call to this method. - * @return true if mouse dragging was handled by this screen. - */ - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (mouseHandler.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) { - return true; - } - if (selectedWidget != null && selectedWidget.isDraggable) { - // Update the position of the widget while dragging - int newX = (int) (mouseX - dragStartX); - int newY = (int) (mouseY - dragStartY); - - // Snap the widget to the grid - newX = (newX / gridSize) * gridSize; - newY = (newY / gridSize) * gridSize; - - selectedWidget.setX(newX); - selectedWidget.setY(newY); - return true; - } - return false; - } - - /** - * Handles mouse clicks on this screen. - * - * @param mouseX - X position of mouse cursor. - * @param mouseY - Y position of mouse cursor. - * @param button - Mouse button that was clicked. - * @return true if mouse click was handled by this screen, false otherwise. - */ - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (mouseHandler.mouseClicked(mouseX, mouseY, button)) { - return true; - } - - for (Widget widget : dynamicutil.getWidgetManager().getWidgets()) { - if (widget.getWidgetBox().contains(widget, mouseX, mouseY, Widget.getScale())) { - // Start dragging the widget - colorPicker = null; - contextMenus.clear(); - Sliders.clear(); - if (button == 1) { // Right-click - handleRightClickOnWidget(widget); - } else if (button == 0) { - widget.enabled = !widget.enabled; - } - if (dragHandler.startDragging(widget, mouseX, mouseY) && button == 0 && widget.isDraggable) { - selectedWidget = widget; - for (ContextMenu contextmenu : contextMenus) { - contextmenu.updatePosition(); - } - for (SliderWidget sliderWidget : Sliders) { - sliderWidget.updatePosition(); - } - return true; - } - } - } - return false; - } - - /** - * Handles mouse release events on this screen. - * - * @param mouseX The current x position of the mouse cursor - * @param mouseY The current y position of the mouse cursor - * @param button The mouse button that was released - * @return True if the mouse release event was handled by this screen, false otherwise - */ - @Override - public boolean mouseReleased(double mouseX, double mouseY, int button) { - // Stop dragging or scaling the widget - if (mouseHandler.mouseReleased(mouseX, mouseY, button)) { - return true; - } - if (selectedWidget != null) { - selectedWidget = null; - return true; - } - return contextMenus != null; - } - - /** - * Renders this screen and its widgets on the screen. - * - * @param drawContext The matrix stack used for rendering - * @param mouseX The current x position of the mouse cursor - * @param mouseY The current y position of the mouse cursor - * @param delta The time elapsed since the last frame in seconds - */ - @Override - public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { - super.render(drawContext, mouseX, mouseY, delta); - - // Draw each widget - for (Widget widget : dynamicutil.getWidgetManager().getWidgets()) { - widget.render(drawContext); - } - - // Draw the slider and other stuff - for (SliderWidget sliderWidget : Sliders) { - sliderWidget.render(drawContext); - } - for (ContextMenu contextMenu : contextMenus) { - contextMenu.render(drawContext); - } - - if (colorPicker != null) { - colorPicker.render(drawContext); - } - - if (selectedWidget != null) { - widgetX = selectedWidget.getX(); - widgetY = selectedWidget.getY(); - } - - updateMouseHandler(colorPicker, contextMenus, Sliders); - } - - private void updateMouseHandler(ColorGradientPicker colorPicker, List contextMenus, List Sliders) { - this.colorPicker = colorPicker; - this.contextMenus = contextMenus; - this.Sliders = Sliders; - mouseHandler = new DefaultMouseHandler(colorPicker, contextMenus, Sliders); - } - - public void setGridSize(int gridSize) { - this.gridSize = gridSize; - } - - public void setShouldPause(boolean shouldpause) { - this.ShouldPause = shouldpause; - } - - public void setShouldBeAffectedByResize(boolean shouldBeAffectedByResize) { - this.ShouldBeAffectedByResize = shouldBeAffectedByResize; - } - - @Override - public void resize(MinecraftClient client, int width, int height) { - if (ShouldBeAffectedByResize) - super.resize(client, width, height); - } - - @Override - public boolean shouldPause() { - return ShouldPause; - } - - protected abstract boolean handleRightClickOnWidget(Widget widget); - - protected abstract void menu(Widget widget, int x, int y); -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java deleted file mode 100644 index fd5085d..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/huds/MoveableScreen.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.tanishisherewith.dynamichud.huds; - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.TextureHelper; -import com.tanishisherewith.dynamichud.util.DynamicUtil; -import com.tanishisherewith.dynamichud.util.colorpicker.ColorGradientPicker; -import com.tanishisherewith.dynamichud.util.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.armor.ArmorWidget; -import com.tanishisherewith.dynamichud.widget.item.ItemWidget; -import com.tanishisherewith.dynamichud.widget.slider.SliderWidget; -import com.tanishisherewith.dynamichud.widget.slider.SliderWidgetBuilder; -import com.tanishisherewith.dynamichud.widget.text.TextWidget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; - -import java.awt.*; - -public class MoveableScreen extends AbstractMoveableScreen { - SliderWidget SliderWidget; - /** - * Constructs a AbstractMoveableScreen object. - * - * @param title - * @param dynamicutil The DynamicUtil instance used by this screen - */ - public MoveableScreen(Text title, DynamicUtil dynamicutil) { - super(title, dynamicutil); - setGridSize(1); - setShouldPause(false); - setShouldBeAffectedByResize(false); - } - - @Override - public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) { - super.render(drawContext, mouseX, mouseY, delta); - assert client != null; - /*SliderWidget = new SliderWidgetBuilder(client) - .setX(client.getWindow().getScaledWidth() - 120) - .setY(client.getWindow().getScaledHeight() - 20) - .setWidth(105) - .setHeight(10) - .setLabel("Scale") - .setValue(Widget.getScale()) - .getValue(Widget::setScale) - .setMinValue(0.5f) - .setMaxValue(4f) - .setSelectedWidget(null) - .build();*/ - drawContext.drawTextWithShadow(textRenderer, "Editors Screen", (int) (MinecraftClient.getInstance().getWindow().getScaledWidth() / 2f - textRenderer.getWidth("Editor Screen") / 2f), 5, ColorHelper.ColorToInt(Color.WHITE)); - // SliderWidget.render(drawContext); - } - - @Override - protected boolean handleRightClickOnWidget(Widget widget) { - selectedWidget = widget; - sliderWigdet = widget; - // Show context menu - menu(widget, widgetX, widgetY); - return true; - } - - @Override - protected void menu(Widget widget, int x, int y) { - contextMenus.clear(); - contextMenus.add(new ContextMenu(mc, x, y + widget.getHeight() + 5, selectedWidget, this)); - if (widget instanceof ArmorWidget armorWidget) { - ArmorWidgetMenu(armorWidget, x, y); - } - if (widget instanceof ItemWidget itemWidget) { - ItemWidgetMenu(itemWidget, x, y); - } - if (widget instanceof TextWidget textWidget) { - TextWidgetMenu(textWidget, x, y); - } - } - - protected void ItemWidgetMenu(ItemWidget itemWidget, int x, int y) { - Sliders.clear(); - colorPicker = null; - contextMenus.clear(); - } - - protected void ArmorWidgetMenu(ArmorWidget armorWidget, int x, int y) { - Sliders.clear(); - contextMenus.get(0).setHeightFromWidget(14); - contextMenus.get(0).setPadding(5); - contextMenus.get(0).addEnumCycleOption("", TextureHelper.Position.values(), () -> armorWidget.currentTextPosition[0], newPosition -> { - armorWidget.currentTextPosition[0] = newPosition; - }); - } - - protected void TextWidgetMenu(TextWidget textWidget, int x, int y) { - contextMenus.get(0).setHeightFromWidget(2); - contextMenus.get(0).setPadding(5); - - contextMenus.get(0).addOption("Shadow", () -> { - textWidget.setShadow(!textWidget.hasShadow()); - }); - contextMenus.get(0).addOption("Rainbow", () -> { - textWidget.setRainbow(!textWidget.hasRainbow()); - }); - if (!textWidget.getText().isEmpty()) { - contextMenus.get(0).addOption("TextColor", () -> { - textWidget.toggleTextColorOption(); - - if (textWidget.isTextcolorOptionEnabled()) - colorPicker = new ColorGradientPicker(mc, widgetX +110, widgetY + textWidget.getHeight() + 5, textWidget.getTextcolor(), textWidget::setTextColor, 50, 100, selectedWidget); - else - colorPicker = null; - }); - } - if (!textWidget.getDataText().trim().isEmpty()) { - contextMenus.get(0).addOption("DataColor", () -> { - textWidget.toggleDataColorOption(); - - if (textWidget.isDatacolorOptionEnabled()) - colorPicker = new ColorGradientPicker(mc, widgetX + 110, widgetY + textWidget.getHeight() + 5, textWidget.getDatacolor(), textWidget::setDataColor, 50, 100, selectedWidget); - else - colorPicker = null; - }); - } - /* contextMenus.get(0).addOption("SubMenu: ",()-> - { - if (contextMenus.size()>1) contextMenus.remove(1); - contextMenus.add(new ContextMenu(mc, contextMenus.get(0).getX() + 40, contextMenus.get(0).getOptionY(6), selectedWidget,this)); - contextMenus.get(1).addOption("Option: 1",()->System.out.println("Pressed 1 ")); - contextMenus.get(1).addOption("Option: 2",()->System.out.println("Pressed 2 ")); - contextMenus.get(1).addOption("Option: 3",()->System.out.println("Pressed 3 ")); - }); - contextMenus.get(0).addDataTextOption(("Enter data"), data -> { - System.out.println("Entered data: " + data); - },widgetX,widgetY); - contextMenus.get(0).addDoubleTextOption(("Enter double"), data -> { - System.out.println("Entered data: " + data); - },widgetX,widgetY);*/ - - SliderWidget sliderWidget =new SliderWidgetBuilder(client) - .setX(x) - .setY(y) - .setWidth(105) - .setHeight(contextMenus.get(0).getHeight() + 7) - .setLabel("Rainbow Speed") - .setValue(textWidget.getRainbowSpeed()) - .setMinValue(5f) - .setMaxValue(25.0f) - .getValue(TextWidget::setRainbowSpeed) - .setSelectedWidget(selectedWidget) - .build(); - Sliders.add(sliderWidget); - } - - - @Override - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - // if(SliderWidget.mouseDragged(mouseX,mouseY,button,deltaX,deltaY)) - //{ - // return true; - //} - return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); - } - - @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - // if(SliderWidget.mouseClicked(mouseX,mouseY,button)) - // { - // SliderWidget.updatePosition(); - // return true; - // } - return super.mouseClicked(mouseX, mouseY, button); - } -} - - diff --git a/src/main/java/com/tanishisherewith/dynamichud/interfaces/IWigdets.java b/src/main/java/com/tanishisherewith/dynamichud/interfaces/IWigdets.java deleted file mode 100644 index d27675e..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/interfaces/IWigdets.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.tanishisherewith.dynamichud.interfaces; - -import com.tanishisherewith.dynamichud.util.DynamicUtil; - -public interface IWigdets { - - void addWigdets(DynamicUtil dynamicUtil); - - void addMainMenuWigdets(DynamicUtil dynamicUtil); - - void loadWigdets(DynamicUtil dynamicUtil); -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/interfaces/TextGenerator.java b/src/main/java/com/tanishisherewith/dynamichud/interfaces/TextGenerator.java deleted file mode 100644 index 009f0dc..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/interfaces/TextGenerator.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.tanishisherewith.dynamichud.interfaces; - -@FunctionalInterface -public interface TextGenerator { - String generateText(); -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/interfaces/WidgetLoading.java b/src/main/java/com/tanishisherewith/dynamichud/interfaces/WidgetLoading.java deleted file mode 100644 index fe7a7be..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/interfaces/WidgetLoading.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.tanishisherewith.dynamichud.interfaces; - -import com.tanishisherewith.dynamichud.helpers.TextureHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.armor.ArmorWidget; -import com.tanishisherewith.dynamichud.widget.item.ItemWidget; -import com.tanishisherewith.dynamichud.widget.text.TextWidget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; - -import java.awt.*; - -public interface WidgetLoading { - default Widget loadWidgetsFromTag(String className, NbtCompound widgetTag) { - if (className.equals(TextWidget.class.getName())) { - TextWidget widget = new TextWidget(MinecraftClient.getInstance(), "", () -> "", 0, 0, false, false, -1, -1, true); - widget.readFromTag(widgetTag); - return widget; - } - if (className.equals(ArmorWidget.class.getName())) { - ArmorWidget widget = new ArmorWidget(MinecraftClient.getInstance(), EquipmentSlot.CHEST, 0, 0, false, TextureHelper.Position.ABOVE, () -> "", () -> Color.RED, true, ""); - widget.readFromTag(widgetTag); - return widget; - } - if (className.equals(ItemWidget.class.getName())) { - ItemWidget widget = new ItemWidget(MinecraftClient.getInstance(), () -> ItemStack.EMPTY, 0, 0, true, TextureHelper.Position.ABOVE, () -> "", () -> Color.WHITE, true, ""); - widget.readFromTag(widgetTag); - return widget; - } - return null; - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java index 5643c84..b3bb2cd 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java @@ -32,7 +32,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<>(); - private static final Logger logger = LoggerFactory.getLogger("DynamicHud"); + public static final Logger logger = LoggerFactory.getLogger("DynamicHud"); private static final List widgetRenderers = new ArrayList<>(); public static MinecraftClient MC = MinecraftClient.getInstance(); public static String MOD_ID = "dynamichud"; @@ -130,9 +130,7 @@ public void onInitializeClient() { } //Register events for rendering, saving, loading, and opening the hudEditor - ClientTickEvents.START_CLIENT_TICK.register((client) -> { - openDynamicScreen(binding, screen); - }); + ClientTickEvents.START_CLIENT_TICK.register((client) -> openDynamicScreen(binding, screen)); /* === Saving === */ diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java index 64a97f7..4ce8478 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java @@ -11,7 +11,7 @@ import net.minecraft.util.Identifier; public class GlobalConfig { - public static ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) + public static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class) .id(new Identifier("dynamichud", "dynamichud_config")) .serializer(config -> GsonConfigSerializerBuilder.create(config) .setPath(FabricLoader.getInstance().getConfigDir().resolve("dynamichud.json5")) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java index ea1d60f..ab6b5b0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java @@ -2,7 +2,6 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.*; @@ -659,7 +658,7 @@ public static void drawRoundedRectangle(Matrix4f matrix4f, float x, float y, boo } /** - * Draws a outline rounded gradient rectangle + * Draws an outline rounded gradient rectangle * * @param matrix4f Matrix4f object to draw the rounded gradient rectangle * @param color1 is applied to the bottom-left vertex (x, y + height). diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java deleted file mode 100644 index f73aaae..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/TextureHelper.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.tanishisherewith.dynamichud.newTrial.helpers; - -import com.mojang.blaze3d.systems.RenderSystem; -import com.tanishisherewith.dynamichud.util.CustomItemRenderer; -import com.tanishisherewith.dynamichud.util.CustomTextRenderer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; - -/** - * This class provides helper methods for drawing textures on the screen. - */ -public class TextureHelper extends DrawContext { - public static CustomTextRenderer customTextRenderer; - public static CustomItemRenderer customItemRenderer; - - - public TextureHelper(MinecraftClient client, VertexConsumerProvider.Immediate vertexConsumers) { - super(client, vertexConsumers); - } - - /** - * Draws an item texture on the screen. - * - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - */ - public static void drawItemTexture(DrawContext drawContext, - ItemStack itemStack, - int x, - int y) { - drawContext.drawItem(itemStack, x, y); - } - - /** - * Draws the texture of the item in the player's main hand on the screen. - * - * @param client The Minecraft client instance - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - */ - public static void drawMainHandTexture(DrawContext drawContext, - MinecraftClient client, - int x, - int y) { - assert client.player != null; - ItemStack mainHandItem = client.player.getMainHandStack(); - drawItemTexture(drawContext, mainHandItem, x, y); - } - - /** - * Draws a textured rectangle on the screen. - * - * @param x The x position of the top left corner of the rectangle - * @param y The y position of the top left corner of the rectangle - * @param u The x position of the texture within the texture image - * @param v The y position of the texture within the texture image - * @param width The width of the rectangle - * @param height The height of the rectangle - * @param textureWidth The width of the texture image - * @param textureHeight The height of the texture image - */ - public static void drawTexture(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - drawContext.drawTexture(texture, x, y, u, v, width, height, textureWidth, textureHeight); - } - - /** - * Draws a textured rectangle on the screen with a specified color. - * - * @param x The x position of the top left corner of the rectangle - * @param y The y position of the top left corner of the rectangle - * @param u The x position of the texture within the texture image - * @param v The y position of the texture within the texture image - * @param width The width of the rectangle - * @param height The height of the rectangle - * @param color The color to draw the rectangle with - */ - public static void drawTexturedRect(DrawContext drawContext, Identifier texture, int x, int y, int u, int v, int width, int height, int color) { - RenderSystem.setShaderColor((color >> 16 & 255) / 255.0F, - (color >> 8 & 255) / 255.0F, - (color & 255) / 255.0F, - (color >> 24 & 255) / 255.0F); - drawContext.drawTexture(texture, x, y, u, v, width, height); - } - - /** - * Draws an item texture on the screen with text at a specified position relative to it. - * - * @param textRenderer The text renderer instance used for rendering the text - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - * @param text The text to draw relative to the texture - * @param color The color to draw the text with - * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) - * @param scale The scale factor to apply to the text (1.0 is normal size) - */ - public static void drawItemTextureWithText(DrawContext drawContext, - TextRenderer textRenderer, - ItemStack itemStack, - int x, - int y, - String text, - int color, - Position position, - float scale, - boolean textBackground - ) { - // Calculate the position of the text based on its size and the specified position - int textWidth = (int) (textRenderer.getWidth(text) * scale); - int textHeight = (int) (textRenderer.fontHeight * scale); - int textX = 0; - int textY = 0; - switch (position) { - case ABOVE -> { - textX = x + (16 - textWidth) / 2; - textY = y - textHeight; - } - case BELOW -> { - textX = x + (17 - textWidth) / 2; - textY = y + 16; - } - case LEFT -> { - textX = x - textWidth - 2; - textY = y + (16 - textHeight) / 2; - } - case RIGHT -> { - textX = x + 18; - textY = y + (16 - textHeight) / 2; - } - } - - // Draw semi-opaque black rectangle - if (text != null) { - if (textBackground && !text.trim().isEmpty()) { - int backgroundColor = 0x40000000; // ARGB format: 50% opaque black - drawContext.fill(textX - 1, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); - } - // Draw the scaled text at the calculated position - drawContext.getMatrices().push(); - drawContext.getMatrices().scale(scale, scale, 1.0f); - float scaledX = textX / scale; - float scaledY = textY / scale; - drawContext.drawText(textRenderer, text, (int) scaledX, (int) scaledY, color, false); - drawContext.getMatrices().pop(); - } - // Draw the item texture - drawContext.drawItem(itemStack, x, y); - } - - /** - * Draws an item texture on the screen with text at a specified position relative to it. - * - * @param itemScale The scale for the item to be rendered at - * @param textRenderer The text renderer instance used for rendering the text - * @param itemStack The item stack to render the texture for - * @param x The x position to draw the texture at - * @param y The y position to draw the texture at - * @param text The text to draw relative to the texture - * @param color The color to draw the text with - * @param position The position of the text relative to the texture (ABOVE, BELOW, LEFT, or RIGHT) - * @param textScale The scale factor to apply to the text (1.0 is normal size) - */ - public static void drawItemTextureWithTextAndScale(DrawContext drawContext, - float itemScale, - TextRenderer textRenderer, - ItemStack itemStack, - int x, - int y, - String text, - int color, - Position position, - float textScale, - boolean textBackground) { - if (text != null && !text.trim().isEmpty()) { - // Calculate the position of the text based on its size and the specified position - int textWidth = (int) (textRenderer.getWidth(text) * textScale); - int textHeight = (int) (textRenderer.fontHeight * textScale); - int textX = switch (position) { - case ABOVE, BELOW -> x + (int) ((16 * itemScale - textWidth) / 2); - case LEFT -> x - textWidth - 2; - case RIGHT -> x + (int) (16 * itemScale + 2); - }; - int textY = switch (position) { - case ABOVE -> y - textHeight - 2; - case BELOW -> y + (int) (16 * itemScale + 2); - case LEFT, RIGHT -> y + (int) ((16 * itemScale - textHeight) / 2); - }; - - // Draw semi-opaque black rectangle - if (textBackground) { - int backgroundColor = 0x40000000; // ARGB format: 50% opaque black - drawContext.fill(textX, textY - 1, textX + textWidth + 1, textY + textHeight + 1, backgroundColor); - } - - // Draw the scaled text at the calculated position - drawContext.getMatrices().push(); - drawContext.getMatrices().scale(textScale, textScale, 11.0f); - float scaledX = textX / textScale; - float scaledY = textY / textScale; - drawContext.drawText(textRenderer, text, (int) scaledX + 1, (int) scaledY + 1, color, false); - drawContext.getMatrices().pop(); - } - customItemRenderer = new CustomItemRenderer(itemStack, itemScale); - customItemRenderer.draw(drawContext, x, y, color); - } - - public enum Position { - ABOVE("Above"), - RIGHT("Right"), - BELOW("Below"), - LEFT("Left"); - private final String name; - - Position(String name) { - this.name = name; - } - - public static Position getByUpperCaseName(String name) { - if (name == null || name.isEmpty()) { - return null; - } - - return Position.valueOf(name.toUpperCase()); - } - } - - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java index ce53614..313823a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java @@ -70,6 +70,7 @@ 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) { this.renderBackgroundTexture(drawContext); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java index 1911b5d..2750069 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java index 8244df8..4f2e080 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; -import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.newTrial.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 701e145..4d00518 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -17,7 +17,7 @@ public class ColorGradientPicker { private final ColorPickerButton colorPickerButton; private final AlphaSlider alphaSlider; private final int boxSize; - MinecraftClient client = MinecraftClient.getInstance(); + final MinecraftClient client = MinecraftClient.getInstance(); private int x, y; private boolean display = false; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java index ce0f0f9..6f63968 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -35,7 +35,7 @@ public void render(DrawContext drawContext, int x, int y) { float handleX = x + saturation * size - handleSize / 2.0f; float handleY = y + (1.0f - value) * size - handleSize / 2.0f; - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleSize), (int) (handleY + handleSize), -1); + DrawHelper.drawFilledCircle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, 1,-1); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java index 60498df..c56cf16 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -54,7 +54,7 @@ public void render(DrawContext drawContext, int x, int y) { float handleX = x + hue * width - handleWidth / 2.0f; float handleY = y - (handleHeight - height) / 2.0f; - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); + DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, handleWidth, handleHeight, 2,-1); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java index 6520b51..c4a685e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.widget; -import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; import net.fabricmc.fabric.api.util.NbtType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; @@ -15,8 +15,8 @@ import java.nio.file.StandardCopyOption; import java.util.*; -import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; -import static com.tanishisherewith.dynamichud.DynamicHUD.printWarn; +import static com.tanishisherewith.dynamichud.newTrial.DynamicHUD.printInfo; +import static com.tanishisherewith.dynamichud.newTrial.DynamicHUD.printWarn; /** * Manages a collection of widgets, providing methods to add, remove, save, and load widgets. @@ -78,29 +78,6 @@ public static void addWidgets(Widget... widget) { public static void removeWidget(Widget widget) { widgets.remove(widget); } - /* public static void onScreenResized(int newWidth, int newHeight) { - float scaleX = (float) newWidth / MC.getWindow().getScaledWidth(); - float scaleY = (float) newHeight / MC.getWindow().getScaledHeight(); - System.out.println("newWidth: " + newWidth); - System.out.println("newHeight: " + newHeight); - - System.out.println("scaleX: " + scaleX); - - for (Widget widget : widgets) { - float newX = widget.getX() * scaleX; - float newY = widget.getY() * scaleY; - System.out.println("newX: " + newX); - - // Ensure the widget is within the screen bounds - newX = MathHelper.clamp(newX,0,newWidth - widget.getWidth()); - newY = MathHelper.clamp(newY,0,newHeight - widget.getHeight()); - System.out.println("newX2: " + newX); - - widget.setPosition(newX, newY); - } - } - - */ /** * Attempts to restore the widgets back to their place on screen resize. @@ -210,7 +187,10 @@ public static void loadWidgets(File file) throws IOException { if (file.exists()) { 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); + return; + } for (int i = 0; i < widgetList.size(); i++) { NbtCompound widgetTag = widgetList.getCompound(i); WidgetData widgetData = widgetDataMap.get(widgetTag.getString("name")); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java index 34baac0..b57043e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud.newTrial.widget; -import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.GameMenuScreen; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java index 2536f77..311bc11 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java @@ -1,7 +1,7 @@ package com.tanishisherewith.dynamichud.newTrial.widgets; -import com.tanishisherewith.dynamichud.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; +import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; @@ -28,7 +28,7 @@ public class TextWidget extends Widget { protected boolean rainbow; // Whether to apply a rainbow effect to the text protected int rainbowSpeed = 2; //Speed of the rainbow effect Supplier textSupplier; - String dynamicRegistryKey = ""; + String dynamicRegistryKey; DynamicValueRegistry dynamicValueRegistry = null; private ContextMenu menu; public TextWidget() { @@ -161,7 +161,6 @@ public void readFromTag(NbtCompound tag) { dynamicValueRegistry = dvr; return; } - createMenu(); } public enum Enum { diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/CustomItemRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/util/CustomItemRenderer.java deleted file mode 100644 index d5beee6..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/CustomItemRenderer.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.tanishisherewith.dynamichud.util; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.item.ItemStack; - -public class CustomItemRenderer { - private final ItemStack itemStack; // The text renderer instance - private final float scale; // The scaling factor of the text - - /** - * Constructs a CustomTextRenderer object. - * - * @param stack The stack to render - * @param scale The scaling factor of the text - */ - public CustomItemRenderer(ItemStack stack, float scale) { - // The Minecraft client instance - this.itemStack = stack; - this.scale = scale; - } - - /** - * Draws a text with shadow on the screen with the given parameters. - * - * @param context The drawContext to use for rendering - * @param x The x position of the text in pixels - * @param y The y position of the text in pixels - * @param color The color of the text in ARGB format - */ - public void draw(DrawContext context, int x, int y, int color) { - context.getMatrices().push(); // Pushes the current matrix onto the stack - context.getMatrices().scale(scale, scale, scale); // Scales the matrix by the scaling factor - context.drawItem(itemStack,(int) (x/scale), (int) (y/scale),color); - context.getMatrices().pop(); // Pops the current matrix from the stack and restores the previous one - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/CustomTextRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/util/CustomTextRenderer.java deleted file mode 100644 index 0bb0621..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/CustomTextRenderer.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.tanishisherewith.dynamichud.util; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; - -public class CustomTextRenderer { - private final TextRenderer textRenderer; // The text renderer instance - private final float scale; // The scaling factor of the text - - /** - * Constructs a CustomTextRenderer object. - * - * @param client The Minecraft client instance - * @param scale The scaling factor of the text - */ - public CustomTextRenderer(MinecraftClient client, float scale) { - // The Minecraft client instance - this.textRenderer = client.textRenderer; - this.scale = scale; - } - - /** - * Draws a text with shadow on the screen with the given parameters. - * - * @param context The drawContext to use for rendering - * @param text The text to draw - * @param x The x position of the text in pixels - * @param y The y position of the text in pixels - * @param color The color of the text in ARGB format - */ - public void draw(DrawContext context, String text, int x, int y, int color, boolean shadow) { - context.getMatrices().push(); // Pushes the current matrix onto the stack - context.getMatrices().scale(scale, scale, scale); // Scales the matrix by the scaling factor - context.drawText(textRenderer,text, (int) (x/scale), (int) (y/scale),color,shadow); - context.getMatrices().pop(); // Pops the current matrix from the stack and restores the previous one - } -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java b/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java deleted file mode 100644 index b169aa4..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/DynamicUtil.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.tanishisherewith.dynamichud.util; - - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.huds.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.WidgetBox; -import com.tanishisherewith.dynamichud.widget.WidgetManager; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.VertexConsumerProvider; - -import java.util.Set; - - -/** - * This class provides utility methods for working with the DynamicHUD mod. - */ -public class DynamicUtil extends DrawContext { - static MinecraftClient client = MinecraftClient.getInstance(); - private final WidgetManager widgetManager; // The WidgetManager instance used by this class - public boolean WidgetAdded = false; - public boolean MainMenuWidgetAdded = false; - public boolean WidgetLoaded = false; - - - /** - * Constructs a DynamicUtil object. - * - * @param client The Minecraft client instance - */ - public DynamicUtil(MinecraftClient client) { - super(client, VertexConsumerProvider.immediate(new BufferBuilder(3))); - this.widgetManager = new WidgetManager(); - } - - /** - * 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()) { - client.setScreen(screen); - } - } - - /** - * Renders widgets on screen. - * - * @param context - MatrixStack used for rendering. - * @param delta - Time elapsed since last frame in seconds. - */ - public void render(DrawContext context, float delta) { - Set mainMenuWidgets = widgetManager.getMainMenuWidgets(); - Set widgets = widgetManager.getWidgets(); - - if (client.currentScreen instanceof TitleScreen) { - // Draw each Menu widget - for (Widget widget : mainMenuWidgets) { - widget.render(context); - widget.updatePosition(); - int backgroundColor = widget.isEnabled() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); - WidgetBox box = widget.getWidgetBox(); - DrawHelper.fill(context, (int) (box.x1 - 2), (int) (box.y1 - 2), (int) (box.x2 + 2), (int) (box.y2 + 2), backgroundColor); - } - return; - } - - // Draw each widget - if (client.currentScreen instanceof AbstractMoveableScreen) { - for (Widget widget : widgets) { - if (client.currentScreen instanceof AbstractMoveableScreen) { - widget.render(context); - } else if (widget.isEnabled()) { - widget.render(context); - } - // Draw a red box around the widget if the HUD is disabled - if (client.currentScreen instanceof AbstractMoveableScreen) { - int backgroundColor = widget.isEnabled() ? ColorHelper.getColor(0, 0, 0, 128) : ColorHelper.getColor(255, 0, 0, 128); - WidgetBox box = widget.getWidgetBox(); - DrawHelper.fill(context, (int) (box.x1 - 2), (int) (box.y1 - 2), (int) (box.x2 + 2), (int) (box.y2 + 2), backgroundColor); - } - widget.updatePosition(); - } - } - } - - - /** - * Returns WidgetManager instance used by this class. - * - * @return WidgetManager instance used by this class. - */ - public WidgetManager getWidgetManager() { - return widgetManager; - } - -} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorGradientPicker.java deleted file mode 100644 index 6086188..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorGradientPicker.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.tanishisherewith.dynamichud.util.colorpicker; - -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.util.GlAllocationUtils; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.nio.ByteBuffer; -import java.util.function.Consumer; - -public class ColorGradientPicker { - private final MinecraftClient client; // The Minecraft client instance - private final Consumer onColorSelected; // The callback to call when a color is selected - private final GradientSlider gradientSlider; - private final GradientBox gradientBox; - private final ColorPickerButton colorPickerButton; - - - public ColorGradientPicker(MinecraftClient client, int x, int y, int initialColor, Consumer onColorSelected, int BoxSize, int Colors, Widget selectedWidget) { - this.client = client; - this.onColorSelected = onColorSelected; - float[] hsv = new float[3]; - Color.RGBtoHSB((initialColor >> 16) & 0xFF, (initialColor >> 8) & 0xFF, initialColor & 0xFF, hsv); - - // The initial color has an alpha component - hsv[0] = 0.0f; // Set hue to default value - hsv[1] = 1.0f; // Set saturation to default value - hsv[2] = 1.0f; // Set value to default value - this.gradientSlider = new GradientSlider(x, y, Colors, 10, selectedWidget); - this.gradientSlider.setHue(hsv[0]); - - this.gradientBox = new GradientBox(x, y + 20, BoxSize, selectedWidget); - this.gradientBox.setHue(hsv[0]); - this.gradientBox.setSaturation(hsv[1]); - this.gradientBox.setValue(hsv[2]); - this.colorPickerButton = new ColorPickerButton(x + BoxSize + 8, y + 20, 35, 20); - - } - - public void tick() { - gradientSlider.tick(); - gradientBox.tick(); - } - - public void render(DrawContext drawContext) { - tick(); - gradientSlider.render(drawContext); - gradientBox.render(drawContext); - colorPickerButton.render(drawContext); - if (colorPickerButton.isPicking()) { - // Draw the cursor - 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()); - - ByteBuffer buffer = GlAllocationUtils.allocateByteBuffer(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.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); - } - } - - public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (colorPickerButton.onClick(mouseX, mouseY, button)) { - return true; - } 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()) { - 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 = GlAllocationUtils.allocateByteBuffer(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); - } - onColorSelected.accept(gradientBox.getColor()); - return true; - } - - public void mouseReleased(double mouseX, double mouseY, int button) { - gradientSlider.onRelease(mouseX, mouseY, button); - gradientBox.onRelease(mouseX, mouseY, button); - } - - public void mouseDragged(double mouseX, double mouseY, int button) { - gradientSlider.onDrag(mouseX, mouseY, button); - gradientBox.setHue(gradientSlider.getHue()); - gradientBox.onDrag(mouseX, mouseY, button); - onColorSelected.accept(gradientBox.getColor()); - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorPickerButton.java deleted file mode 100644 index b47c625..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/ColorPickerButton.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.tanishisherewith.dynamichud.util.colorpicker; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; - -public class ColorPickerButton { - private final int x; - private final int y; - private final int width; - private final int height; - private boolean isPicking = false; - - public ColorPickerButton(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - public void render(DrawContext drawContext) { - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,404); - // Draw the button - drawContext.fill(x, y, x + width, y + height, 0xFFAAAAAA); - drawContext.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, "Pick", x + width / 2, y + (height - 8) / 2, 0xFFFFFFFF); - drawContext.getMatrices().pop(); - } - - public boolean onClick(double mouseX, double mouseY, int button) { - if (button == 0) { - if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { - isPicking = true; - return true; - } - } - return false; - } - - public boolean isPicking() { - return isPicking; - } - - public void setPicking(boolean picking) { - isPicking = picking; - } -} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientBox.java deleted file mode 100644 index 3df903f..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientBox.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.tanishisherewith.dynamichud.util.colorpicker; - -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; - -import java.awt.*; - -public class GradientBox { - private final int size; - private final float alphaSpeed = 0.05f; - private final Widget selectedWidget; - private int x; - private int y; - private float hue = 0.0f; - private float saturation = 1.0f; - private float value = 1.0f; - private boolean isDragging = false; - private float alpha = 0.0f; - - - public GradientBox(int x, int y, int size, Widget selectedWidget) { - this.x = x; - this.y = y; - this.size = size; - this.selectedWidget = selectedWidget; - } - - public void tick() { - // Update the alpha - alpha += alphaSpeed; - if (alpha > 1.0f) { - alpha = 1.0f; - } - } - - public void render(DrawContext drawContext) { - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,401); - DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + size + 2, y + size + 2, -1); - - // Draw the gradient - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - float saturation = (float) i / size; - float value = 1.0f - (float) j / size; - int color = Color.HSBtoRGB(hue, saturation, value); - color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); - drawContext.fill(x + i, y + j, x + i + 1, y + j + 1, color); - } - } - - // Draw the handle - float handleSize = 3; - float handleX = x + saturation * size - handleSize / 2.0f; - float handleY = y + (1.0f - value) * size - handleSize / 2.0f; - - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleSize), (int) (handleY + handleSize), -1); - if (this.selectedWidget != null) - setPosition(selectedWidget.getX() + 30, selectedWidget.getY() + MinecraftClient.getInstance().textRenderer.fontHeight + 4); - drawContext.getMatrices().pop(); - } - - /** - * Sets position. - * - * @param x - X position to set. - * @param y - Y position to set. - */ - public void setPosition(int x, int y) { - this.x = x; - this.y = y; - } - - public void onClick(double mouseX, double mouseY, int button) { - if (button == 0) { - float handleSize = 5; - float handleX = x + saturation * size - handleSize / 2.0f; - float handleY = y + (1.0f - value) * size - handleSize / 2.0f; - - 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.isDragging = true; - } - } - } - - public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= x && mouseX <= x + size && mouseY >= y && mouseY <= y + size; - } - - public void onRelease(double mouseX, double mouseY, int button) { - if (button == 0) { - isDragging = false; - } - } - - 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); - - value = 1.0f - (float) (mouseY - y) / size; - value = Math.max(0, value); - value = Math.min(1, value); - } - } - - public void setHue(float hue) { - this.hue = hue; - } - - public void setSaturation(float saturation) { - this.saturation = saturation; - } - - public void setValue(float value) { - this.value = value; - } - - public int getColor() { - return Color.HSBtoRGB(hue, saturation, value); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientSlider.java deleted file mode 100644 index 1e53c6a..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/colorpicker/GradientSlider.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.tanishisherewith.dynamichud.util.colorpicker; - -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; - -import java.awt.*; - -public class GradientSlider { - private final int width; - private final int height; - private final float progressSpeed = 0.1f; - private final float alphaSpeed = 0.05f; - private final Widget selectedWidget; - private int x; - private int y; - private float hue = 0.0f; - private float progress = 0.0f; - private boolean isDragging = false; - private float alpha = 0.0f; - - public GradientSlider(int x, int y, int width, int height, Widget selectedWidget) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.selectedWidget = selectedWidget; - } - - public void tick() { - // Update the progress - progress += progressSpeed; - if (progress > 1.0f) { - progress = 1.0f; - } - - // Update the alpha - alpha += alphaSpeed; - if (alpha > 1.0f) { - alpha = 1.0f; - } - } - - /** - * Sets position. - * - * @param x - X position to set. - * @param y - Y position to set. - */ - public void setPosition(int x, int y) { - this.x = x; - this.y = y; - } - - public void render(DrawContext drawContext) { - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,401); - DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + width + 2, y + height + 2, -1); - - // Draw the gradient - for (int i = 0; i < width; i++) { - float hue = (float) i / width; - int color = Color.HSBtoRGB(hue, 1.0f, 1.0f); - color = (color & 0x00FFFFFF) | ((int) (alpha * 255) << 24); - drawContext.fill(x + i, y, x + i + 1, y + height, color); - } - - // Draw the handle - if (progress >= 1.0f) { - float handleWidth = 3; - float handleHeight = height + 4; - float handleX = x + hue * width - handleWidth / 2.0f; - float handleY = y - (handleHeight - height) / 2.0f; - - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), -1); - } - if (this.selectedWidget != null) - setPosition(selectedWidget.getX() + 30, selectedWidget.getY() + MinecraftClient.getInstance().textRenderer.fontHeight + 4); - drawContext.getMatrices().pop(); - } - - public void onClick(double mouseX, double mouseY, int button) { - if (button == 0) { - float handleWidth = 3; - float handleHeight = height + 4; - float handleX = x + hue * width - handleWidth / 2.0f; - float handleY = y - (handleHeight - height) / 2.0f; - - 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.isDragging = true; - } - } - } - - public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; - } - - public void onRelease(double mouseX, double mouseY, int button) { - if (button == 0) { - isDragging = false; - } - } - - 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); - } - } - - public float getHue() { - return hue; - } - - public void setHue(float hue) { - this.hue = hue; - } -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java deleted file mode 100644 index 2d533aa..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenu.java +++ /dev/null @@ -1,441 +0,0 @@ -package com.tanishisherewith.dynamichud.util.contextmenu; - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; - -import java.awt.*; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Supplier; - - -public class ContextMenu { - private static int optionY; - private final MinecraftClient client; // The Minecraft client instance - private final List options = new ArrayList<>(); // The list of options in the context menu - private final Widget selectedWidget; // The widget that this context menu is associated with - private final Screen parentScreen; - private int width = 0; // The width of the context menu - private int x; // The x position of the context menu - private int y; // The y position of the context menu - private int backgroundColor = 0x90C0C0C0;// Semi-transparent light grey color - private int padding = 5; // The amount of padding around the rectangle - private int HeightFromWidget = 5; // The amount of padding around the rectangle - private float scale = 0.0f; - private int height = 0; - private String dataInputValue = ""; - private String doubleInputValue = ""; - - - /** - * Constructs a ContextMenu object. - * - * @param client The Minecraft client instance - * @param x The x position of the context menu - * @param y The y position of the context menu - * @param selectedWidget The widget that this context menu is associated with - */ - public ContextMenu(MinecraftClient client, int x, int y, Widget selectedWidget, Screen parentScreen) { - this.client = client; - this.selectedWidget = selectedWidget; - this.parentScreen = parentScreen; - this.x = x; - this.y = Math.round(y + selectedWidget.getWidgetBox().getHeight()); - } - - public static int getOptionY() { - return optionY; - } - - /** - * Sets the options to enable or disable based on values - * - * @param label The label of the option - * @param option Context Menu options - */ - public void setOptions(String label, ContextMenuOption option) { - if (selectedWidget instanceof ContextMenuOptionsProvider optionsProvider) { - option.enabled = optionsProvider.isOptionEnabled(label); - } - } - - /** - * Adds an option to the context menu. - * - * @param label The label of the option - * @param action The action to perform when the option is clicked - */ - public void addOption(String label, Runnable action) { - ContextMenuOption option = new ContextMenuOption(label, action); - if (selectedWidget != null) { - setOptions(label, option); - } - options.add(option); - } - - public void addDataTextOption(String label, Consumer action, int WidgetX, int WidgetY) { - int OptionY = WidgetY + HeightFromWidget + 2; - WidgetX += client.textRenderer.getWidth(label + dataInputValue); - OptionY += options.size() * (client.textRenderer.fontHeight + 2); - DataInputOption option = new DataInputOption(label + dataInputValue, text -> { - action.accept(text); - dataInputValue = text; - }, WidgetX, OptionY); - if (selectedWidget != null) { - setOptions(label, option); - } - options.add(option); - } - - public void addDoubleTextOption(String label, Consumer action, int WidgetX, int WidgetY) { - int OptionY = WidgetY + HeightFromWidget + 2; - WidgetX += client.textRenderer.getWidth(label + dataInputValue); - OptionY += options.size() * (client.textRenderer.fontHeight + 2); - DoubleInputOption option = new DoubleInputOption(label + doubleInputValue, text -> { - action.accept(text); - doubleInputValue = String.valueOf(text); - }, WidgetX, OptionY); - if (selectedWidget != null) { - setOptions(label, option); - } - options.add(option); - } - - public void setBackgroundColor(int backgroundColor) { - this.backgroundColor = backgroundColor; - } - - /** - * Returns whether the given point is within the bounds of this context menu. - * - * @param x - X position of the point. - * @param y - Y position of the point. - * @return true if the point is within the bounds of this context menu, false otherwise. - */ - public boolean contains(double x, double y) { - return x >= this.x - 3 && x <= this.x + width + 13 && y >= this.y + HeightFromWidget - 3 && y <= this.y + height + HeightFromWidget + 3; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public int getWidth() { - return width; - } - - public Screen getParentScreen() { - return parentScreen; - } - - public Widget getSelectedWidget() { - return selectedWidget; - } - - public float getScale() { - return scale; - } - - public int getHeight() { - return height; - } - - public int getOptionY(int optionIndex) { - int OptionY = y + HeightFromWidget + 2; - OptionY += optionIndex * (client.textRenderer.fontHeight + 2); - return OptionY; - } - - /** - * Adds an option to the context menu that cycles through the values of an enum. - *

- * Usage Example: - * Position currentPosition = Position.ABOVE; - *

- * ContextMenu contextMenu = new ContextMenu(client, x, y); - *

- * contextMenu.addEnumCycleOption("Position", Position.values(), () -> currentPosition, newPosition -> { - * currentPosition = newPosition; - * }); - * - * @param labelPrefix The label to display for this option in the context menu - * @param values An array of enum values that specifies the possible values that this option can cycle through - * @param getter A Supplier that returns the current value of the enum - * @param setter A Consumer that sets the new value of the enum - * @param The type of the enum - */ - public > void addEnumCycleOption(String labelPrefix, T[] values, Supplier getter, Consumer setter) { - ContextMenuOption option = new EnumCycleContextMenuOption<>(labelPrefix, values, getter, () -> { - // Get the current value of the enum - T currentValue = getter.get(); - - // Find the index of the current value in the values array - int index = -1; - for (int i = 0; i < values.length; i++) { - if (values[i] == currentValue) { - index = i; - break; - } - } - - // Increment the index and wrap around if necessary - index = (index + 1) % values.length; - - // Set the new value of the enum - setter.accept(values[index]); - }); - options.add(option); - } - - - public void tick() { - // Update the scale - float scaleSpeed = 0.1f; - scale += scaleSpeed; - if (scale > 1.0f) { - scale = 1.0f; - } - } - - /** - * Updates the position of this context menu to avoid getting out of the screen. - */ - public void updatePosition() { - // Check if the context menu is outside the bounds of the screen - int screenWidth = client.getWindow().getScaledWidth(); - int screenHeight = client.getWindow().getScaledHeight(); - if (x + width + 14 > screenWidth) { - x = screenWidth - width - 14; - } - if (y + HeightFromWidget - 2 < 0) { - y = HeightFromWidget + 2; - } - if (y + height + HeightFromWidget + 2 > screenHeight) { - y = screenHeight - height - HeightFromWidget - 2; - } - } - - /** - * Renders this context menu on screen. - * - * @param drawContext - MatrixStack used for rendering. - */ - public void render(DrawContext drawContext) { - tick(); - TextRenderer textRenderer = client.textRenderer; - calculateSize(textRenderer); - applyScale(drawContext); - int x1 = x - 1; - int y1 = y + HeightFromWidget - 2; - int x2 = x + width + 8; - int y2 = y + height + HeightFromWidget + 2; - // Draw the background - DrawHelper.drawCutRectangle(drawContext, x1, y1, x2, y2, 0, backgroundColor, 1); - optionY = y + HeightFromWidget + 2; - drawOptions(drawContext, textRenderer); - if (selectedWidget != null) - setPosition(selectedWidget.getX(), selectedWidget.getY() + textRenderer.fontHeight + 4); - drawContext.getMatrices().pop(); - updatePosition(); - } - - private void applyScale(DrawContext drawContext) { - // Apply the scale - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(x + width / 2.0f + 5, y + height / 2.0f + HeightFromWidget, 300); - drawContext.getMatrices().scale(scale, scale, 1.0f); - drawContext.getMatrices().translate(-(x + width / 2.0f + 5), -(y + height / 2.0f + HeightFromWidget), 300); - } - - private void calculateSize(TextRenderer textRenderer) { - // Calculate the size of the context menu - width = 0; - height = 0; - for (ContextMenuOption option : options) { - width = Math.max(width, textRenderer.getWidth(option.label) + padding); - height += textRenderer.fontHeight + 2; - } - } - - private void drawOptions(DrawContext drawContext, TextRenderer textRenderer) { - int labelTextcolor; - for (ContextMenuOption option : options) { - if (option instanceof EnumCycleContextMenuOption enumOption) { - enumOption.updateLabel(); - labelTextcolor = Color.WHITE.getRGB(); - } else if (option instanceof DataInputOption) { - labelTextcolor = Color.YELLOW.getRGB(); - - // Draw a black box around the value text - String[] splitLabel = option.label.split(":"); - if (splitLabel.length > 1) { - String valueText = splitLabel[1].trim(); - int valueTextWidth = textRenderer.getWidth(valueText); - int labelWidth = textRenderer.getWidth(splitLabel[0].trim()); - int boxX = x + labelWidth + 9; - int boxY = optionY - 2; - int boxWidth = valueTextWidth + 2; - int boxHeight = textRenderer.fontHeight + 1; - DrawHelper.fill(drawContext, boxX, boxY, boxX + boxWidth, boxY + boxHeight, 0x7F000000); - } - - } else if (option instanceof DoubleInputOption) { - labelTextcolor = ColorHelper.ColorToInt(Color.BLUE.brighter()); - // Draw a black box around the value text - String[] splitLabel = option.label.split(":"); - if (splitLabel.length > 1) { - String valueText = splitLabel[1].trim(); - int valueTextWidth = textRenderer.getWidth(valueText); - int labelWidth = textRenderer.getWidth(splitLabel[0].trim()); - int boxX = x + labelWidth + 9; - int boxY = optionY - 2; - int boxWidth = valueTextWidth + 2; - int boxHeight = textRenderer.fontHeight + 1; - DrawHelper.fill(drawContext, boxX, boxY, boxX + boxWidth, boxY + boxHeight, 0x7F000000); - } - } else { - labelTextcolor = option.enabled ? 0xFF00FF00 : 0xFFFF0000; - } - drawContext.drawText(textRenderer, option.label, x + 5, optionY, labelTextcolor, false); - optionY += textRenderer.fontHeight + 2; - } - } - - /** - * Sets position of this context menu. - * - * @param x - X position to set. - * @param y - Y position to set. - */ - public void setPosition(int x, int y) { - this.x = x; - this.y = y; - } - - public void setPadding(int padding) { - this.padding = padding; - } - - public void setHeightFromWidget(int HeightFromWidget) { - this.HeightFromWidget = HeightFromWidget; - } - - public List getOptions() { - return options; - } - - /** - * Handles mouse clicks on this context menu. - * - * @param mouseX - X position of mouse cursor. - * @param mouseY - Y position of mouse cursor. - * @param button - Mouse button that was clicked. - * @return true if mouse click was handled by this context menu. - */ - public boolean mouseClicked(double mouseX, double mouseY, int button) { - TextRenderer textRenderer = client.textRenderer; - int optionY = y + HeightFromWidget + 2; - for (ContextMenuOption option : options) { - if (mouseX >= x && mouseX <= x + textRenderer.getWidth(option.label) + 10 && mouseY >= optionY && mouseY <= optionY + textRenderer.fontHeight + 2) { - // Run the action of the selected option - option.action.run(); - option.enabled = !option.enabled; - return true; - } - optionY += textRenderer.fontHeight + 2; - } - return false; - } - - - private static class ContextMenuOption { - Runnable action; // The action to perform when the option is clicked - String label; // The label of the option - private boolean enabled = false; // Whether the option is enabled - - /** - * Constructs a ContextMenuOption object. - * - * @param label - Label of this option. - * @param action - Action to perform when this option is clicked. - */ - public ContextMenuOption(String label, Runnable action) { - this.label = label; - this.action = action; - } - - public String getLabel() { - return label; - } - - public void setLabel(String newLabel) { - this.label = newLabel; - } - - public void setAction(Runnable action) { - this.action = action; - } - } - - private static class EnumCycleContextMenuOption> extends ContextMenuOption { - private final String labelPrefix; - private final T[] values; - private final Supplier getter; - - public EnumCycleContextMenuOption(String labelPrefix, T[] values, Supplier getter, Runnable action) { - super(labelPrefix + getter.get(), action); - this.labelPrefix = labelPrefix; - this.values = values; - this.getter = getter; - } - - public void updateLabel() { - label = labelPrefix + getter.get(); - } - } - - public class DataInputOption extends ContextMenuOption { - private final Consumer labelSetter; - - public DataInputOption(String label, Consumer consumer, int x, int y) { - super(label, null); - setAction(() -> { - // Open a new screen to allow the player to input data - MinecraftClient.getInstance().setScreen(new DataInputScreen(consumer, x, y, parentScreen, this)); - }); - this.labelSetter = text -> setLabel(label + ": " + text); - } - - public Consumer getLabelSetter() { - return labelSetter; - } - } - - public class DoubleInputOption extends ContextMenuOption { - private final Consumer labelSetter; - - public DoubleInputOption(String label, Consumer consumer, int x, int y) { - super(label, null); - setAction(() -> { - // Open a new screen to allow the player to input data - MinecraftClient.getInstance().setScreen(new DoubleInputScreen(consumer, x, y, parentScreen, this)); - }); - this.labelSetter = text -> setLabel(label + ": " + text); - } - - public Consumer getLabelSetter() { - return labelSetter; - } - } - -} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenuOptionsProvider.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenuOptionsProvider.java deleted file mode 100644 index 33ab859..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/ContextMenuOptionsProvider.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.tanishisherewith.dynamichud.util.contextmenu; - -public interface ContextMenuOptionsProvider { - boolean isOptionEnabled(String label); -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DataInputScreen.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DataInputScreen.java deleted file mode 100644 index 31c68c5..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DataInputScreen.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.tanishisherewith.dynamichud.util.contextmenu; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; - -import java.util.function.Consumer; - -public class DataInputScreen extends Screen { - private final Consumer consumer; - private final Screen parentScreen; - private final ContextMenu.DataInputOption DataInputOption; - private TextWidgetButtonExt textField; - private int x, y; - - - public DataInputScreen(Consumer consumer, int x, int y, Screen parentScreen, ContextMenu.DataInputOption dataInputOption) { - super(Text.of("Data Input")); - this.consumer = consumer; - this.x = x; - this.y = y; - this.parentScreen = parentScreen; - this.DataInputOption = dataInputOption; - if (this.x > MinecraftClient.getInstance().getWindow().getScaledWidth()) - this.x = MinecraftClient.getInstance().getWindow().getScaledWidth() - 110; - if (this.y > MinecraftClient.getInstance().getWindow().getScaledWidth()) - this.y = MinecraftClient.getInstance().getWindow().getScaledHeight() - 14; - if (this.x < 0) this.x = MinecraftClient.getInstance().getWindow().getScaledWidth() + 110; - if (this.y < 0) this.y = MinecraftClient.getInstance().getWindow().getScaledHeight() + 14; - } - - @Override - protected void init() { - // Create a text field for the player to input data - this.textField = new TextWidgetButtonExt(this.textRenderer, x, y, 100, 14, Text.of("")); - this.addDrawableChild(this.textField); - } - - @Override - public boolean shouldPause() { - return false; - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { - // Close the screen and pass the entered data to the consumer when the Enter key is pressed - String text = this.textField.getText(); - this.consumer.accept(text); - MinecraftClient.getInstance().setScreen(parentScreen); - DataInputOption.getLabelSetter().accept(text); - } - return super.keyPressed(keyCode, scanCode, modifiers); - } -} - diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DoubleInputScreen.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DoubleInputScreen.java deleted file mode 100644 index cfd074b..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/DoubleInputScreen.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.tanishisherewith.dynamichud.util.contextmenu; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; - -import java.util.function.Consumer; - -public class DoubleInputScreen extends Screen { - private final Consumer consumer; - private final Screen parentScreen; - private final ContextMenu.DoubleInputOption doubleInputOption; - private TextWidgetButtonExt textField; - private int x, y; - - public DoubleInputScreen(Consumer consumer, int x, int y, Screen parentScreen, ContextMenu.DoubleInputOption doubleInputOption) { - super(Text.of("Double Input")); - this.consumer = consumer; - this.x = x; - this.y = y; - this.parentScreen = parentScreen; - this.doubleInputOption = doubleInputOption; - if (this.x > MinecraftClient.getInstance().getWindow().getScaledWidth()) - this.x = MinecraftClient.getInstance().getWindow().getScaledWidth() - 110; - if (this.y > MinecraftClient.getInstance().getWindow().getScaledWidth()) - this.y = MinecraftClient.getInstance().getWindow().getScaledHeight() - 14; - if (this.x < 0) this.x = MinecraftClient.getInstance().getWindow().getScaledWidth() + 110; - if (this.y < 0) this.y = MinecraftClient.getInstance().getWindow().getScaledHeight() + 14; - } - - @Override - protected void init() { - // Create a text field for the player to input data - this.textField = new TextWidgetButtonExt(this.textRenderer, x, y, 100, 14, Text.of("")); - this.addDrawableChild(this.textField); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { - // Close the screen and pass the entered data to the consumer when the Enter key is pressed - try { - double value = Double.parseDouble(this.textField.getText()); - this.consumer.accept(value); - MinecraftClient.getInstance().setScreen(parentScreen); - doubleInputOption.getLabelSetter().accept(value); - } catch (NumberFormatException e) { - // Handle invalid input - this.textField.setText(""); - } - } - return super.keyPressed(keyCode, scanCode, modifiers); - } - - @Override - public boolean shouldPause() { - return false; - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java b/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java deleted file mode 100644 index 60be115..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/util/contextmenu/TextWidgetButtonExt.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.tanishisherewith.dynamichud.util.contextmenu; - -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.text.Text; - -public class TextWidgetButtonExt extends TextFieldWidget { - public TextWidgetButtonExt(TextRenderer textRenderer, int x, int y, int width, int height, Text text) { - super(textRenderer, x, y, width, height, text); - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java deleted file mode 100644 index 30927be..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.tanishisherewith.dynamichud.widget; - -import com.tanishisherewith.dynamichud.interfaces.TextGenerator; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.nbt.NbtCompound; - -import java.awt.*; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; - -/** - * This class represents a widget that can be displayed on the screen. - */ -public abstract class Widget { - protected static Map textGenerators = new HashMap<>(); - - protected final MinecraftClient client; // The Minecraft client instance - public boolean enabled = true; // Whether the widget is enabled - public boolean isDraggable = true; - protected float xPercent; // The x position of the widget as a percentage of the screen width - protected float yPercent; // The y position of the widget as a percentage of the screen height - protected String label; - protected static float scale = 1f; // The scaling factor of the widget - - /** - * Constructs a Widget object. - * - * @param client The Minecraft client instance - */ - public Widget(MinecraftClient client, String label) { - this.client = client; - this.label = label; - } - - public static void addTextGenerator(String label, TextGenerator textGenerator) { - textGenerators.put(label, textGenerator); - } - - public abstract void setTextGeneratorFromLabel(); - - /** - * Gets the box around the widget for some purpose - */ - public abstract WidgetBox getWidgetBox(); - - public void setDraggable(boolean draggable) { - isDraggable = draggable; - } - - - public boolean isOverlapping(Set other) { - for (Widget widget : other) { - if ((this.getX() < widget.getX() + widget.getWidgetBox().getWidth() && this.getX() + this.getWidgetBox().getWidth() > widget.getX() && - this.getY() < widget.getY() + widget.getWidgetBox().getHeight() && this.getY() + this.getWidgetBox().getHeight() > widget.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(); - } - - /** - * Renders the widget on the screen. - */ - public abstract void render(DrawContext drawContext); - - public void updatePosition() { - int screenWidth = client.getWindow().getScaledWidth(); - int screenHeight = client.getWindow().getScaledHeight(); - } - - /** - * Returns whether the widget is enabled. - * - * @return True if the widget is enabled, false otherwise - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Returns the x position of the widget. - * - * @return The x position of the widget in pixels - */ - public int getX() { - return (int) (client.getWindow().getScaledWidth() * xPercent); - } - /** - * Returns the scaling factor of the widget. - * - * @return The scaling factor of the widget - */ - public static float getScale() { - return scale; - } - - /** - * Sets the scaling factor of the widget. - * - * @param scale The new scaling factor of the widget - */ - public static void setScale(float scale) { - Widget.scale = scale; - } - /** - * Sets the x position of the widget. - * - * @param x The new x position of the widget in pixels - */ - public void setX(float x) { - int screenWidth = client.getWindow().getScaledWidth(); - if (x < 0) { - x = 0; - } else if (x + getWidgetBox().getWidth() > screenWidth) { - x = screenWidth - getWidgetBox().getWidth(); - } - this.xPercent = (float) x / screenWidth; - } - - /** - * Returns the y position of the widget. - * - * @return The y position of the widget in pixels - */ - public int getY() { - return (int) (client.getWindow().getScaledHeight() * yPercent); - } - - /** - * Sets the y position of the widget. - * - * @param y The new y position of the widget in pixels - */ - public void setY(float y) { - int screenHeight = client.getWindow().getScaledHeight(); - if (y < 0) { - y = 0; - } else if (y + getWidgetBox().getHeight() > screenHeight) { - y = (screenHeight) - getWidgetBox().getHeight(); - } - this.yPercent = (float) y / screenHeight; - } - - /** - * Returns the fontheight - * - * @return fontHeight from TextRenderer - */ - public int getHeight() { - return client.textRenderer.fontHeight; - } - - public void readFromTag(NbtCompound tag) { - xPercent = tag.getFloat("xPercent"); - yPercent = tag.getFloat("yPercent"); - enabled = tag.getBoolean("Enabled"); - isDraggable = tag.getBoolean("isDraggable"); - label = tag.getString("label"); - scale = tag.getFloat("scale"); - - setTextGeneratorFromLabel(); - } - - /** - * Writes the state of this widget to the given tag. - * - * @param tag The tag to write to - */ - public void writeToTag(NbtCompound tag) { - tag.putString("class", getClass().getName()); - tag.putBoolean("isDraggable", isDraggable); - tag.putFloat("xPercent", xPercent); - tag.putFloat("yPercent", yPercent); - tag.putBoolean("Enabled", enabled); - tag.putString("label", label); - tag.putFloat("scale", scale); - - - for (Field field : getClass().getDeclaredFields()) { - if (Modifier.isStatic(field.getModifiers())) continue; - - field.setAccessible(true); - - try { - Object value = field.get(this); - - if (value instanceof Boolean) { - tag.putBoolean(field.getName(), (Boolean) value); - } else if (value instanceof Byte) { - tag.putByte(field.getName(), (Byte) value); - } else if (value instanceof Short) { - tag.putShort(field.getName(), (Short) value); - } else if (value instanceof Integer) { - tag.putInt(field.getName(), (Integer) value); - } else if (value instanceof Long) { - tag.putLong(field.getName(), (Long) value); - } else if (value instanceof Float) { - tag.putFloat(field.getName(), (Float) value); - } else if (value instanceof Double) { - tag.putDouble(field.getName(), (Double) value); - } else if (value instanceof String) { - tag.putString(field.getName(), (String) value); - } else if (value instanceof Color colorvalue) { - tag.putInt(field.getName(), colorvalue.getRGB()); - }// Add more cases here for other data types - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java deleted file mode 100644 index a61db70..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.tanishisherewith.dynamichud.widget; - -public class WidgetBox { - private float width; - private float height; - public float x1 = 0, x2 = 0, y1 = 0, y2 = 0; - - public WidgetBox(float x1, float y1, float x2, float y2, float scale) { - this.width = (x2 - x1) * scale; - this.height = (y2 - y1) * scale; - this.x1 = x1; - this.x2 = x1 + width; - this.y1 = y1; - this.y2 = y1 + height; - } - - public WidgetBox(float x1, float y1, double width, double height, float scale) { - this.width = (float) (width * scale); - this.height = (float) (height * scale); - this.x1 = x1; - this.x2 = x1 + this.width; - this.y1 = y1; - this.y2 = y1 + this.height; - } - - public boolean contains(Widget widget, double x, double y, float scale) { - if (x1 == 0 || x2 == 0 || y1 == 0 || y2 == 0) { - x1 = widget.getX() - width / 2; - y1 = widget.getY() - height / 2; - x2 = widget.getX() + width / 2; - y2 = widget.getY() + height / 2; - } - return x >= x1 && x <= x2 && y >= y1 && y <= y2; - } - - public boolean intersects(float otherX1, float otherY1, float otherX2, float otherY2) { - return !(otherX1 > x2 || otherX2 < x1 || otherY1 > y2 || otherY2 < y1); - } - public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= x1 && mouseX <= x1 + width && mouseY >= y1 && mouseY <= y2 + height; - } - - public float getWidth() { - return width; - } - - public float getHeight() { - return height; - } - - public void setSizeAndPosition(float x, float y, float width, float height){ - this.x1 = x; - this.y1 = y; - this.height = height; - this.width = width; - } - public void setSizeAndPosition(float x, float y, float width, float height,boolean shouldScale, float scale){ - this.x1 = x; - this.y1 = y; - this.height = height * (shouldScale? scale : 1.0f); - this.width = width * (shouldScale? scale : 1.0f); - } - public void setSize(double width, double height) { - if (width >= 0) - this.width = (int) Math.ceil(width); - if (height >= 0) - this.height = (int) Math.ceil(height); - } - public void setPosition(float x,float y, float x2, float y2){ - this.x1 = x; - this.x2 = x2; - this.y1 = y; - this.y2 = y2; - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java deleted file mode 100644 index a16c90a..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.tanishisherewith.dynamichud.widget; - -import com.tanishisherewith.dynamichud.DynamicHUD; -import com.tanishisherewith.dynamichud.interfaces.WidgetLoading; -import net.fabricmc.fabric.api.util.NbtType; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.NbtList; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.HashSet; -import java.util.Set; - -import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; - -/** - * This class manages a list of widgets that can be added, removed and retrieved. - */ -public class WidgetManager { - private final Set widgets = new HashSet<>(); // The list of widgets - private final Set MainMenuWidgets = new HashSet<>(); // The list of MainMenu widgets - private WidgetLoading widgetLoading = new WidgetLoading() { - }; - - /** - * Adds a widget to the list. - * - * @param widget The widget to add - */ - public void addWidget(Widget widget) { - widget.setTextGeneratorFromLabel(); - widgets.add(widget); - } - - /** - * Adds a MainMenu widget to the list. - * - * @param widget The widget to add - */ - public void addMainMenuWidget(Widget widget) { - widget.setTextGeneratorFromLabel(); - MainMenuWidgets.add(widget); - } - - public void setWidgetLoading(WidgetLoading widgetLoading) { - this.widgetLoading = widgetLoading; - } - - /** - * Removes a widget from the list. - * - * @param widget The widget to remove - */ - public void removeWidget(Widget widget) { - widgets.remove(widget); - } - - /** - * Removes a MainMenu widget from the list. - * - * @param widget The Main Menu widget to remove - */ - public void removeMainMenuWidget(Widget widget) { - MainMenuWidgets.remove(widget); - } - - - /** - * Returns list of all widgets. - * - * @return list of all widgets. - */ - public Set getWidgets() { - return widgets; - } - - /** - * Returns Set of all MainMenu widgets. - * - * @return Set of all MainMenu widgets. - */ - public Set getMainMenuWidgets() { - return MainMenuWidgets; - } - - public Set getOtherWidgets(Widget SelectedWidget) { - Set otherWidgets = new HashSet<>(); - for (Widget widget : getWidgets()) { - if (widget != SelectedWidget) { - otherWidgets.add(widget); - } - } - return otherWidgets; - } - - /** - * Saves the state of all widgets to the given file. - * - * @param file The file to save to - */ - public void saveWidgets(File file) { - NbtCompound rootTag = new NbtCompound(); - NbtList widgetList = new NbtList(); - NbtList MainMenuwidgetList = new NbtList(); - - printInfo("Saving widgets"); - - if (widgets.isEmpty() && MainMenuWidgets.isEmpty()) { - printInfo("Widgets are empty.. Saving interrupted to prevent empty file"); - return; - } - - Set widgetSet = new HashSet<>(); - for (Widget widget : widgets) { - NbtCompound widgetTag = new NbtCompound(); - widget.writeToTag(widgetTag); - // Check for duplicates - if (widgetSet.add(widgetTag.toString())) { - widgetList.add(widgetTag); - } - } - - rootTag.put("Widgets", widgetList); - - Set MainMenuWidgetSet = new HashSet<>(); - for (Widget mmwidget : MainMenuWidgets) { - NbtCompound widgetTag = new NbtCompound(); - mmwidget.writeToTag(widgetTag); - // Check for duplicates - if (MainMenuWidgetSet.add(widgetTag.toString())) { - MainMenuwidgetList.add(widgetTag); - } - } - rootTag.put("MainMenuWidgets", MainMenuwidgetList); - - // Use a temporary file to write the data - File tempFile = new File(file.getAbsolutePath() + ".tmp"); - try (DataOutputStream out = new DataOutputStream(new FileOutputStream(tempFile))) { - NbtIo.writeCompressed(rootTag, out); - // Check if the data has been written successfully - if (tempFile.length() > 0) { - // Check if the temporary file exists and can be renamed - Files.move(tempFile.toPath(), file.toPath(), StandardCopyOption.REPLACE_EXISTING); - } else { - throw new IOException("Failed to write data to temporary file OR Empty data passed"); - } - } catch (IOException e) { - // Delete the temporary file if an error occurs - boolean temp = tempFile.delete(); - e.printStackTrace(); - } - } - - - - public Set loadWigdets(File file) { - Set widgets = new HashSet<>(); - if (file.exists()) { - printInfo("Widgets File exists"); - try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { - DataInput input = new DataInputStream(in); - NbtCompound rootTag = NbtIo.readCompound(input); - NbtList widgetList = rootTag.getList("Widgets", NbtType.COMPOUND); - for (int i = 0; i < widgetList.size(); i++) { - NbtCompound widgetTag = widgetList.getCompound(i); - String className = widgetTag.getString("class"); - widgets.add(widgetLoading.loadWidgetsFromTag(className, widgetTag)); - printInfo("Wigdet " + i + ": " + widgets.stream().toList().get(i).toString()); - } - } catch (IOException e) { - e.printStackTrace(); - } - } else - DynamicHUD.printWarn("Widgets File does not exist"); - return widgets; - } - - public Set loadMainMenuWigdets(File file) { - Set MainMenuwidgets = new HashSet<>(); - if (file.exists()) { - try (DataInputStream in = new DataInputStream(new FileInputStream(file))) { - DataInput input = new DataInputStream(in); - NbtCompound rootTag = NbtIo.readCompound(input); - NbtList MainMenuwidgetList = rootTag.getList("MainMenuWidgets", NbtType.COMPOUND); - for (int i = 0; i < MainMenuwidgetList.size(); i++) { - NbtCompound widgetTag = MainMenuwidgetList.getCompound(i); - String className = widgetTag.getString("class"); - MainMenuwidgets.add(widgetLoading.loadWidgetsFromTag(className, widgetTag)); - printInfo("MainMenu Wigdet " + i + ": " + MainMenuwidgets.stream().toList().get(i).toString()); - } - } catch (IOException e) { - e.printStackTrace(); - } - } else - DynamicHUD.printWarn("Widgets File does not exist"); - return MainMenuwidgets; - } -} \ No newline at end of file diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/armor/ArmorWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/armor/ArmorWidget.java deleted file mode 100644 index f433a5b..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/armor/ArmorWidget.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.armor; - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.TextureHelper; -import com.tanishisherewith.dynamichud.interfaces.TextGenerator; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.WidgetBox; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; - -import java.awt.*; -import java.util.function.Supplier; - -/** - * This class represents a widget that displays the armor item in a specified equipment slot. - */ -public class ArmorWidget extends Widget { - public final TextureHelper.Position[] currentTextPosition = TextureHelper.Position.values(); - protected EquipmentSlot slot; // The equipment slot to display the armor item from - protected TextGenerator textGenerator; - protected Supplier color; - protected boolean TextBackground; - - /** - * Constructs an ArmorWidget object. - * - * @param client The Minecraft client instance - * @param slot The equipment slot to display the armor item from - * @param xPercent The x position of the widget as a percentage of the screen width - * @param yPercent The y position of the widget as a percentage of the screen height - */ - public ArmorWidget(MinecraftClient client, EquipmentSlot slot, float xPercent, float yPercent, boolean enabled, TextureHelper.Position currentTextPosition, TextGenerator textGenerator, Supplier color, boolean Textbackground, String label) { - super(client, label); - this.slot = slot; - this.xPercent = xPercent; - this.yPercent = yPercent; - this.enabled = enabled; - this.currentTextPosition[0] = currentTextPosition; - this.textGenerator = textGenerator; - this.color = color; - this.TextBackground = Textbackground; - } - - /** - * Renders the widget on the screen. - */ - @Override - public void render(DrawContext drawContext) { - ItemRenderer itemRenderer = client.getItemRenderer(); - ItemStack armorItem; - TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - if (client.player == null) { - armorItem = Items.DIAMOND_CHESTPLATE.getDefaultStack(); - } else { - armorItem = client.player.getEquippedStack(slot); - } - TextureHelper.drawItemTextureWithTextAndScale(drawContext, scale, textRenderer, armorItem, getX(), getY(), getText(), ColorHelper.ColorToInt(getColor()), currentTextPosition[0], scale*0.5f, TextBackground); - } - - @Override - public void setTextGeneratorFromLabel() { - TextGenerator textGenerator = textGenerators.get(label); - if (textGenerator != null) { - setTextGenerator(textGenerator); - } - } - - @Override - public WidgetBox getWidgetBox() { - return new WidgetBox(this.getX(), this.getY(), this.getX() + this.getWidth(), this.getY() + this.getHeight(),scale); - } - - /** - * Returns the width of the widget. - * - * @return The width of the widget in pixels - */ - public int getWidth() { - return 16; // The width of an item texture is 16 pixels - } - - /** - * Returns the height of the widget. - * - * @return The height of the widget in pixels - */ - public int getHeight() { - return 16; // The height of an item texture is 16 pixels - } - - /** - * Returns the text displayed by this widget. - * - * @return The text displayed by this widget - */ - public String getText() { - return textGenerator.generateText(); - } - - public void setTextGenerator(TextGenerator textGenerator) { - this.textGenerator = textGenerator; - } - - public Color getColor() { - return color.get(); - } - - public void setColor(Supplier color) { - this.color = color; - } - - @Override - public void writeToTag(NbtCompound tag) { - super.writeToTag(tag); - tag.putString("slot", slot.getName()); - tag.putString("Position", String.valueOf(this.currentTextPosition[0])); - if (this.getText() != null) tag.putString("text", this.getText()); - tag.putInt("Color", this.getColor().getRGB()); - tag.putBoolean("TextBackground", this.TextBackground); - } - - @Override - public void readFromTag(NbtCompound tag) { - super.readFromTag(tag); - slot = EquipmentSlot.byName(tag.getString("slot")); - String Position = tag.getString("Position"); - color = () -> ColorHelper.getColorFromInt(tag.getInt("Color")); - if (TextureHelper.Position.getByUpperCaseName(Position) != null && !(tag.getString("Position") == null) && !tag.getString("Position").isEmpty()) - currentTextPosition[0] = TextureHelper.Position.getByUpperCaseName(Position); - else - currentTextPosition[0] = TextureHelper.Position.ABOVE; - TextBackground = tag.getBoolean("TextBackground"); - label = tag.getString("label"); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/item/ItemWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/item/ItemWidget.java deleted file mode 100644 index 6c5ac60..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/item/ItemWidget.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.item; - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.TextureHelper; -import com.tanishisherewith.dynamichud.interfaces.TextGenerator; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.WidgetBox; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; - -import java.awt.*; -import java.util.function.Supplier; - -public class ItemWidget extends Widget { - public final TextureHelper.Position[] currentTextPosition = TextureHelper.Position.values(); - protected Supplier color; - protected TextGenerator textGenerator; - protected Supplier itemStack; - protected boolean TextBackground; - - /** - * Constructs a Widget object. - * - * @param client The Minecraft client instance - */ - public ItemWidget(MinecraftClient client, Supplier itemStack, float xPercent, float yPercent, boolean enabled, TextureHelper.Position currentTextPosition, TextGenerator textGenerator, Supplier color, boolean Textbackground, String label) { - super(client, label); - this.xPercent = xPercent; - this.yPercent = yPercent; - this.enabled = enabled; - this.itemStack = itemStack; - this.currentTextPosition[0] = currentTextPosition; - this.textGenerator = textGenerator; - this.color = color; - this.TextBackground = Textbackground; - } - - @Override - public WidgetBox getWidgetBox() { - return new WidgetBox(this.getX(), this.getY(), this.getX() + this.getWidth(), this.getY() + this.getHeight(),scale); - } - - /** - * Returns the width of the widget. - * - * @return The width of the widget in pixels - */ - public int getWidth() { - return 16; // The width of an item texture is 16 pixels - } - - /** - * Returns the height of the widget. - * - * @return The height of the widget in pixels - */ - public int getHeight() { - return 16; // The height of an item texture is 16 pixels - } - - public ItemStack getItemStack() { - return itemStack.get(); - } - - public void setItemStack(Supplier itemStack) { - this.itemStack = itemStack; - } - - /** - * Returns the text displayed by this widget. - * - * @return The text displayed by this widget - */ - public String getText() { - return textGenerator.generateText(); - } - - public void setTextGenerator(TextGenerator textGenerator) { - this.textGenerator = textGenerator; - } - - public Supplier getColor() { - return color; - } - - public void setColor(Supplier color) { - this.color = color; - } - - @Override - public void setTextGeneratorFromLabel() { - TextGenerator textGenerator = textGenerators.get(label); - if (textGenerator != null) { - setTextGenerator(textGenerator); - } - } - - @Override - public void writeToTag(NbtCompound tag) { - super.writeToTag(tag); - tag.putString("Position", String.valueOf(this.currentTextPosition[0])); - tag.putInt("ItemID", Item.getRawId(getItemStack().getItem())); - tag.putInt("ItemCount", getItemStack().getMaxCount()); - tag.putString("text", getText()); - tag.putBoolean("TextBackground", this.TextBackground); - } - - @Override - public void readFromTag(NbtCompound tag) { - super.readFromTag(tag); - String Position = tag.getString("Position"); - - int itemID = tag.getInt("ItemID"); - int itemCount = tag.getInt("ItemCount"); - itemStack = () -> getItemStack(itemID, itemCount); - - if (TextureHelper.Position.getByUpperCaseName(Position) != null && !tag.getString("Position").isEmpty()) - currentTextPosition[0] = TextureHelper.Position.getByUpperCaseName(Position); - else - currentTextPosition[0] = TextureHelper.Position.ABOVE; - TextBackground = tag.getBoolean("TextBackground"); - label = tag.getString("label"); - } - - public ItemStack getItemStack(int itemID, int itemCount) { - Item item = Item.byRawId(itemID); - return new ItemStack(item, itemCount); - } - - @Override - public void render(DrawContext drawContext) { - ItemRenderer itemRenderer = client.getItemRenderer(); - TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - TextureHelper.drawItemTextureWithTextAndScale(drawContext, scale, textRenderer, getItemStack(), getX(), getY(), getText(), ColorHelper.ColorToInt(color.get()), currentTextPosition[0], scale*0.5f, TextBackground); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/ScaleSliderWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/slider/ScaleSliderWidget.java deleted file mode 100644 index 0e60528..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/ScaleSliderWidget.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.slider; - -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.gui.widget.SliderWidget; -import net.minecraft.text.Text; -import java.text.DecimalFormat; - -public class ScaleSliderWidget extends SliderWidget { - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.##"); - private final float minValue; - private final float maxValue; - - public ScaleSliderWidget(int x, int y, int width, int height, Text message, double value, float minValue, float maxValue) { - super(x, y, width, height, message, value); - this.minValue = minValue; - this.maxValue = maxValue; - } - - public float getValue(){ - return (float) (minValue + (maxValue - minValue) * value); - } - - @Override - protected void updateMessage() { - String formattedValue = DECIMAL_FORMAT.format(getValue()); - setMessage(Text.of("Widgets Scale: " + formattedValue)); - } - - @Override - protected void applyValue() { - Widget.setScale(getValue()); - } - -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidget.java deleted file mode 100644 index 84b70ad..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidget.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.slider; - -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; - -import java.util.function.Consumer; - -/** - * This class represents a slider widget that allows the user to select a value within a specified range. - */ -public class SliderWidget { - private final MinecraftClient client; - private final int width; // The width of the widget - private final String label; // The label displayed above the slider - private final float minValue; // The minimum value of the slider - private final float maxValue; // The maximum value of the slider - private final int height; // The height of the widget - private int x; // The x position of the widget - private int y; // The y position of the widget - private float value; // The current value of the slider - private Widget selectedWidget = null; - private Consumer getValue; - private float progress = 0.0f; - private float progressSpeed = 0.1f; - private float textProgress = 0.0f; - private float textProgressSpeed = 0.05f; - private boolean MouseClicked = false; - - /** - * Constructs a SliderWidget object. - * - * @param client The Minecraft client instance - * @param x The x position of the widget - * @param y The y position of the widget - * @param width The width of the widget - * @param height The height of the widget - * @param label The label displayed above the slider - * @param value The initial value of the slider - * @param minValue The minimum value of the slider - * @param maxValue The maximum value of the slider - * @param selectedWidget The widget which was selected to display this slider - */ - public SliderWidget(MinecraftClient client, int x, int y, int width, int height, String label, float value, float minValue, float maxValue, Consumer getValue, Widget selectedWidget) { - this.client = client; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.label = label; - this.value = value; - this.minValue = minValue; - this.maxValue = maxValue; - this.getValue=getValue; - this.selectedWidget = selectedWidget; - } - - public void tick() { - // Update the progress - progress += progressSpeed; - if (progress > 1.0f) { - progress = 1.0f; - } - // Update the text progress - textProgress += textProgressSpeed; - if (textProgress > 1.0f) { - textProgress = 1.0f; - } - } - - /** - * Updates the position of this Slider to avoid getting out of the screen. - */ - public void updatePosition() { - // Check if the Slider is outside the bounds of the screen - int screenWidth = client.getWindow().getScaledWidth(); - int screenHeight = client.getWindow().getScaledHeight(); - if (x + width > screenWidth) { - x = screenWidth - width + 1; - } - if (y + 2 < 0) { - y += 2; - } - if (y + height + 2 > screenHeight) { - y = screenHeight - height - 2; - } - } - - /** - * Renders the widget on the screen. - * - * @param drawContext The matrix stack used for rendering - */ - public void render(DrawContext drawContext) { - tick(); - // Draw the label - TextRenderer textRenderer = client.textRenderer; - String labelText = label + ": " + String.format("%.1f", value); - int labelWidth = textRenderer.getWidth(labelText); - int labelX = (int) (x + (width - labelWidth) / 2.0f * textProgress) - 1; - int labelY = y + height - textRenderer.fontHeight - 6; - drawContext.drawTextWithShadow(textRenderer, labelText, labelX, labelY, 0xFFFFFFFF); - - // Draw the slider - int sliderWidth = width - 8; - int sliderHeight = 2; - int sliderX = x; - int sliderY = y + height - sliderHeight; - - drawSlider(drawContext, sliderX, sliderY, sliderWidth, sliderHeight); - - // Draw the handle - float handleWidth = 4; - float handleHeight = 10; - float handleX = sliderX + (value - minValue) / (maxValue - minValue) * (sliderWidth - handleWidth); - float handleY = sliderY + ((sliderHeight - handleHeight) / 2); - - if (progress >= 1.0f) { - DrawHelper.fillRoundedRect(drawContext, (int) handleX, (int) handleY, (int) (handleX + handleWidth), (int) (handleY + handleHeight), 0xFFFFFFFF); - } - - if (selectedWidget != null) - setPosition(selectedWidget.getX(), selectedWidget.getY() + textRenderer.fontHeight + 67); - updatePosition(); - } - - private void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, int sliderHeight) { - int visibleSliderWidth = (int) (sliderWidth * progress); - DrawHelper.fill(drawContext, sliderX, sliderY, sliderX + visibleSliderWidth, sliderY + sliderHeight, 0xFFFFFFFF); - } - - /** - * Returns whether the given point is within the bounds of this widget. - * - * @param x - X position of the point. - * @param y - Y position of the point. - * @return true if the point is within the bounds of this context menu, false otherwise. - */ - public boolean contains(double x, double y) { - return x >= this.x + 2 && x <= this.x - 2 + width && y >= this.y + 2 && y <= this.y - 2 + height; - } - - - /** - * Sets the position of the widget. - * - * @param x The new x position of the widget - * @param y The new y position of the widget - */ - public void setPosition(int x, int y) { - this.x = x; - this.y = y; - } - - /** - * Handles mouse clicks on the widget. - * - * @param mouseX The x position of the mouse cursor - * @param mouseY The y position of the mouse cursor - * @param button The mouse button that was clicked - * @return True if the mouse click was handled by the widget, false otherwise - */ - public boolean mouseClicked(double mouseX, double mouseY, int button) { - // Check if the mouse is over the slider - if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { - // Update the value based on the mouse position - MouseClicked = !MouseClicked; - setValue(minValue + (float) (mouseX - x) / width * (maxValue - minValue) - 0.001f); - getValue.accept(value); - return true; - } - MouseClicked = false; - return false; - } - - /** - * Handles mouse dragging on the widget. - * - * @param mouseX The current x position of the mouse cursor - * @param mouseY The current y position of the mouse cursor - * @param button The mouse button that is being dragged - * @param deltaX The change in x position of the mouse cursor since the last call to this method - * @param deltaY The change in y position of the mouse cursor since the last call to this method - * @return True if the mouse dragging was handled by the widget, false otherwise - */ - public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - // Check if the mouse is over the slider - if (mouseX >= x && mouseX <= x + width && MouseClicked) { - // Update the value based on the mouse position - setValue(minValue + (float) (mouseX - x) / width * (maxValue - minValue)); - getValue.accept(value); - return true; - } - return false; - } - - /** - * Returns the current value of the slider. - * - * @return The current value of the slider - */ - public float getValue() { - return value; - } - - /** - * Sets the value of the slider. - * - * @param value The new value of the slider - */ - public void setValue(float value) { - this.value = Math.min(Math.max(value, minValue), maxValue); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidgetBuilder.java b/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidgetBuilder.java deleted file mode 100644 index e79cd96..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/slider/SliderWidgetBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.slider; - -import com.tanishisherewith.dynamichud.widget.Widget; -import net.minecraft.client.MinecraftClient; - -import java.util.function.Consumer; - -public class SliderWidgetBuilder { - private final MinecraftClient client; - private int x; - private int y; - private int width; - private int height; - private String label; - private float value; - private float minValue; - private float maxValue; - private Widget selectedWidget; - private Consumer getValue; - - public SliderWidgetBuilder(MinecraftClient client) { - this.client = client; - } - - public SliderWidgetBuilder setX(int x) { - this.x = x; - return this; - } - - public SliderWidgetBuilder setY(int y) { - this.y = y; - return this; - } - - public SliderWidgetBuilder setWidth(int width) { - this.width = width; - return this; - } - - public SliderWidgetBuilder setHeight(int height) { - this.height = height; - return this; - } - - public SliderWidgetBuilder setLabel(String label) { - this.label = label; - return this; - } - - public SliderWidgetBuilder setValue(float value) { - this.value = value; - return this; - } - - public SliderWidgetBuilder setMinValue(float minValue) { - this.minValue = minValue; - return this; - } - - public SliderWidgetBuilder setMaxValue(float maxValue) { - this.maxValue = maxValue; - return this; - } - public SliderWidgetBuilder getValue(Consumer getValue) { - this.getValue = getValue; - return this; - } - - public SliderWidgetBuilder setSelectedWidget(Widget selectedWidget) { - this.selectedWidget = selectedWidget; - return this; - } - - public SliderWidget build() { - return new SliderWidget(client, x, y, width, height, label, value, minValue, maxValue,getValue, selectedWidget); - } -} diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/text/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/text/TextWidget.java deleted file mode 100644 index d8a6fcd..0000000 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/text/TextWidget.java +++ /dev/null @@ -1,277 +0,0 @@ -package com.tanishisherewith.dynamichud.widget.text; - -import com.tanishisherewith.dynamichud.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.interfaces.TextGenerator; -import com.tanishisherewith.dynamichud.util.contextmenu.ContextMenuOptionsProvider; -import com.tanishisherewith.dynamichud.widget.Widget; -import com.tanishisherewith.dynamichud.widget.WidgetBox; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.Text; - - -/** - * This class represents a text widget that displays a specified text on the screen. - */ -public class TextWidget extends Widget implements ContextMenuOptionsProvider { - protected static float rainbowSpeed = 15f; // The speed of the rainbow effect - protected String text; - protected TextGenerator dataText; - 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 Textcolor; // The color of the text - protected int Datacolor; // The color of the Data - protected boolean TextcolorOptionEnabled = false; - protected boolean DatacolorOptionEnabled = false; - - - - /** - * Constructs a TextWidget object. - * - * @param client The Minecraft client instance - * @param text The text to display - * @param xPercent The x position of the widget as a percentage of the screen width - * @param yPercent The y position of the widget as a percentage of the screen height - */ - public TextWidget(MinecraftClient client, String text, TextGenerator dataText, float xPercent, float yPercent, boolean Shadow, boolean Rainbow, int Textcolor, int Datacolor, boolean enabled) { - super(client, text); - this.text = text; - this.dataText = dataText; - this.xPercent = xPercent; - this.yPercent = yPercent; - this.shadow = Shadow; - this.rainbow = Rainbow; - this.Textcolor = Textcolor; - this.Datacolor = Datacolor; - this.enabled = enabled; - } - - /** - * Toggles whether the Data color option is enabled. - */ - public void toggleTextColorOption() { - TextcolorOptionEnabled = !TextcolorOptionEnabled; - } - - /** - * Toggles whether the Text color option is enabled. - */ - public void toggleDataColorOption() { - DatacolorOptionEnabled = !DatacolorOptionEnabled; - } - - /** - * Sets whether the rainbow effect is enabled. - * - * @param rainbow True if the rainbow effect should be enabled, false otherwise - */ - public void setRainbow(boolean rainbow) { - this.rainbow = rainbow; - } - - /** - * Sets whether the shadow is enabled. - * - * @param shadow True if the shadow should be enabled, false otherwise - */ - public void setShadow(boolean shadow) { - this.shadow = shadow; - } - - /** - * Returns the speed of the rainbow effect. - * - * @return The speed of the rainbow effect - */ - public float getRainbowSpeed() { - return rainbowSpeed; - } - - /** - * Sets the speed of the rainbow effect. - * - * @param rainbowSpeed The new speed of the rainbow effect - */ - public static void setRainbowSpeed(float rainbowSpeed) { - TextWidget.rainbowSpeed = rainbowSpeed; - } - - /** - * Returns whether the rainbow effect is enabled. - * - * @return True if the rainbow effect is enabled, false otherwise - */ - public boolean hasRainbow() { - return rainbow; - } - - /** - * Returns whether the shadow is enabled. - * - * @return True if the shadow is enabled, false otherwise - */ - public boolean hasShadow() { - return shadow; - } - - - /** - * Returns the text displayed by this widget. - * - * @return The text displayed by this widget - */ - public String getText() { - return text; - } - - /** - * Returns the text displayed by this widget. - * - * @return The text displayed by this widget - */ - public String getDataText() { - return dataText.generateText(); - } - - - public void setDataTextGenerator(TextGenerator textGenerator) { - this.dataText = textGenerator; - } - - /** - * Returns the color of the text. - * - * @return The color of the text - */ - public int getTextcolor() { - return Textcolor; - } - - /** - * Returns the color of the Data. - * - * @return The color of the Data - */ - public int getDatacolor() { - return Datacolor; - } - - @Override - public void setTextGeneratorFromLabel() { - TextGenerator textGenerator = textGenerators.get(getText()); - if (textGenerator != null) { - setDataTextGenerator(textGenerator); - } - } - - /** - * Sets the color of the text. - * - * @param color The new color of the text - */ - public void setTextColor(int color) { - this.Textcolor = color; - } - - /** - * Sets the color of the text. - * - * @param color The new color of the text - */ - public void setDataColor(int color) { - this.Datacolor = color; - } - - - /** - * Returns whether color options are enabled for this widget. - * - * @return true if color options are enabled for this widget, false otherwise. - */ - public boolean isTextcolorOptionEnabled() { - return TextcolorOptionEnabled; - } - - /** - * Returns whether color options are enabled for this widget. - * - * @return true if color options are enabled for this widget, false otherwise. - */ - public boolean isDatacolorOptionEnabled() { - return DatacolorOptionEnabled; - } - - @Override - public WidgetBox getWidgetBox() { - TextRenderer textRenderer = client.textRenderer; - String cmtxt=getDataText()+getText() + "."; - float x1 = getX(); //- client.textRenderer.getWidth(textWidget.getText()); - float x2 = getX() + textRenderer.getWidth(cmtxt); - float y1 = getY() - 1 ; - float y2 = getY() + textRenderer.fontHeight - 1; - return new WidgetBox(x1, y1, x2, y2, scale); - } - - - /** - * Renders this widget on screen. - */ - @Override - public void render(DrawContext drawContext) { - drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0, 0, 300); - int Textcolour = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / (rainbowSpeed * 400f)) : this.Textcolor; - int Datacolour = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % 10000) / (rainbowSpeed * 400f)) : this.Datacolor; - drawTwoTexts(drawContext, getText(), getDataText(), ((getX() + 1)), (getY()), Textcolour, Datacolour, scale); - drawContext.getMatrices().pop(); - } - - - - - @Override - public void writeToTag(NbtCompound tag) { - super.writeToTag(tag); - tag.putBoolean("Rainbow", hasRainbow()); - tag.putBoolean("Shadow", hasShadow()); - tag.putInt("TextColor", Textcolor); - tag.putInt("DataColor", Datacolor); - tag.putString("Text", text); - } - - @Override - public void readFromTag(NbtCompound tag) { - super.readFromTag(tag); - shadow = tag.getBoolean("Shadow"); - rainbow = tag.getBoolean("Rainbow"); - Textcolor = tag.getInt("TextColor"); - Datacolor = tag.getInt("DataColor"); - text = tag.getString("Text"); - } - public void drawTwoTexts(DrawContext drawContext, String text1, String text2, int x, int y, int color1, int color2, float scale) { - drawText(drawContext, text1, x, y, color1); - int x2 = Math.round(x + client.textRenderer.getWidth(text1) * scale); - drawText(drawContext, text2, x2, y, color2); - } - - private void drawText(DrawContext drawContext, String text, int x, int y, int color) { - DrawHelper.drawTextWithScale(drawContext, text, x, y, color, shadow, scale); - //client.textRenderer.draw(text, getX(), getY(), color, scale); - - } - - @Override - public boolean isOptionEnabled(String label) { - return switch (label) { - case "Shadow" -> hasShadow(); - case "Rainbow" -> hasRainbow(); - case "TextColor" -> isTextcolorOptionEnabled(); - case "DataColor" -> isDatacolorOptionEnabled(); - default -> false; - }; - } -} From 320164f747dfb308de4b3b0e98838ccbb93dbdf4 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 22:09:41 +0530 Subject: [PATCH 24/33] Final refactor and cleanup --- .../dynamichud/{newTrial => }/DynamicHUD.java | 20 ++++++------ .../{newTrial => }/DynamicHudIntegration.java | 12 +++---- .../{newTrial => }/DynamicHudTest.java | 14 ++++----- .../dynamichud/{newTrial => }/HudRender.java | 4 +-- .../dynamichud/ModMenuIntegration.java | 3 +- .../{newTrial => }/config/GlobalConfig.java | 2 +- .../{newTrial => }/helpers/ColorHelper.java | 2 +- .../{newTrial => }/helpers/DrawHelper.java | 4 +-- .../dynamichud/mixins/ScreenMixin.java | 24 ++++++++------ .../screens/AbstractMoveableScreen.java | 4 +-- .../utils/DynamicValueRegistry.java | 2 +- .../{newTrial => }/utils/System.java | 2 +- .../dynamichud/{newTrial => }/utils/UID.java | 2 +- .../dynamichud/{newTrial => }/utils/Util.java | 4 +-- .../utils/contextmenu/ContextMenu.java | 6 ++-- .../utils/contextmenu/Option.java | 11 ++++--- .../contextmenu/options/BooleanOption.java | 4 +-- .../contextmenu/options/DoubleOption.java | 6 ++-- .../utils/contextmenu/options/EnumOption.java | 4 +-- .../utils/contextmenu/options/ListOption.java | 4 +-- .../contextmenu/options/RunnableOption.java | 6 ++-- .../contextmenu/options/SubMenuOption.java | 16 +++++----- .../options/coloroption/AlphaSlider.java | 6 ++-- .../coloroption/ColorGradientPicker.java | 6 ++-- .../options/coloroption/ColorOption.java | 8 ++--- .../coloroption/ColorPickerButton.java | 2 +- .../options/coloroption/GradientBox.java | 8 ++--- .../options/coloroption/GradientSlider.java | 6 ++-- .../{newTrial => }/widget/Widget.java | 12 +++---- .../{newTrial => }/widget/WidgetBox.java | 2 +- .../{newTrial => }/widget/WidgetData.java | 2 +- .../{newTrial => }/widget/WidgetManager.java | 10 +++--- .../{newTrial => }/widget/WidgetRenderer.java | 6 ++-- .../{newTrial => }/widgets/TextWidget.java | 31 ++++++++++--------- src/main/resources/fabric.mod.json | 4 +-- 35 files changed, 133 insertions(+), 126 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/DynamicHUD.java (92%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/DynamicHudIntegration.java (88%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/DynamicHudTest.java (82%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/HudRender.java (83%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/config/GlobalConfig.java (97%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/helpers/ColorHelper.java (98%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/helpers/DrawHelper.java (99%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/screens/AbstractMoveableScreen.java (96%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/DynamicValueRegistry.java (98%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/System.java (91%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/UID.java (93%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/Util.java (86%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/ContextMenu.java (95%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/Option.java (86%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/BooleanOption.java (88%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/DoubleOption.java (94%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/EnumOption.java (93%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/ListOption.java (93%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/RunnableOption.java (91%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/SubMenuOption.java (79%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/AlphaSlider.java (91%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/ColorGradientPicker.java (97%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/ColorOption.java (88%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/ColorPickerButton.java (94%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/GradientBox.java (86%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/utils/contextmenu/options/coloroption/GradientSlider.java (94%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widget/Widget.java (96%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widget/WidgetBox.java (97%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widget/WidgetData.java (86%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widget/WidgetManager.java (96%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widget/WidgetRenderer.java (96%) rename src/main/java/com/tanishisherewith/dynamichud/{newTrial => }/widgets/TextWidget.java (88%) diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java similarity index 92% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java rename to src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java index b3bb2cd..84166ea 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHUD.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java @@ -1,11 +1,11 @@ -package com.tanishisherewith.dynamichud.newTrial; - -import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; -import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.newTrial.widget.Widget; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; -import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; +package com.tanishisherewith.dynamichud; + +import com.tanishisherewith.dynamichud.config.GlobalConfig; +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 com.tanishisherewith.dynamichud.widgets.TextWidget; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; @@ -144,7 +144,7 @@ public void onInitializeClient() { 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((minecraftClient) -> saveWidgetsSafely(widgetsFile, FILE_MAP.get(widgetsFile.getName()))); printInfo(String.format("Integration of mod %s was successful", modId)); } catch (Throwable e) { @@ -159,7 +159,7 @@ public void onInitializeClient() { 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()); + ClientLifecycleEvents.CLIENT_STOPPING.register((minecraftClient) -> GlobalConfig.HANDLER.save()); HudRenderCallback.EVENT.register(new HudRender()); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java similarity index 88% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java rename to src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java index e28a507..d8959f7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudIntegration.java @@ -1,9 +1,9 @@ -package com.tanishisherewith.dynamichud.newTrial; +package com.tanishisherewith.dynamichud; -import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +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; @@ -64,7 +64,7 @@ public interface DynamicHudIntegration { /** * Initializes the DynamicHud integration. *

- * Suggested to be used to initialize {@link com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry} and widgets with their respective values + * Suggested to be used to initialize {@link com.tanishisherewith.dynamichud.utils.DynamicValueRegistry} and widgets with their respective values *

*/ void init(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java similarity index 82% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java rename to src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java index fd888c5..cc256c6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java @@ -1,11 +1,11 @@ -package com.tanishisherewith.dynamichud.newTrial; +package com.tanishisherewith.dynamichud; -import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; -import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.newTrial.widget.Widget; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; -import com.tanishisherewith.dynamichud.newTrial.widgets.TextWidget; +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.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java similarity index 83% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java rename to src/main/java/com/tanishisherewith/dynamichud/HudRender.java index 2a80dc3..b4e301e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/HudRender.java +++ b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial; +package com.tanishisherewith.dynamichud; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.minecraft.client.gui.DrawContext; diff --git a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java index c9aec49..30fffb4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java +++ b/src/main/java/com/tanishisherewith/dynamichud/ModMenuIntegration.java @@ -1,6 +1,6 @@ package com.tanishisherewith.dynamichud; -import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; +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; @@ -8,6 +8,7 @@ public class ModMenuIntegration implements ModMenuApi { public static Screen YACL_CONFIG_SCREEN = GlobalConfig.get().createYACLGUI(); + @Override public ConfigScreenFactory getModConfigScreenFactory() { return parent -> YACL_CONFIG_SCREEN; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java similarity index 97% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java rename to src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index 4ce8478..0fd6e0a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.config; +package com.tanishisherewith.dynamichud.config; import dev.isxander.yacl3.api.*; import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java similarity index 98% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java rename to src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java index 7426687..b119142 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/ColorHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.helpers; +package com.tanishisherewith.dynamichud.helpers; import net.minecraft.util.math.MathHelper; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java similarity index 99% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java rename to src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java index ab6b5b0..3794f06 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/helpers/DrawHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java @@ -1,8 +1,8 @@ -package com.tanishisherewith.dynamichud.newTrial.helpers; +package com.tanishisherewith.dynamichud.helpers; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; +import com.tanishisherewith.dynamichud.DynamicHUD; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.render.*; import net.minecraft.client.util.math.MatrixStack; diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java index 226f3ad..1ce36e5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java +++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java @@ -1,8 +1,8 @@ package com.tanishisherewith.dynamichud.mixins; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetManager; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.widget.WidgetManager; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; @@ -14,23 +14,27 @@ @Mixin(Screen.class) public abstract class ScreenMixin { - @Shadow public int width; + @Shadow + public int width; - @Shadow public int height; + @Shadow + public int height; @Inject(at = @At("TAIL"), method = "render") private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { - for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ - widgetRenderer.renderWidgets(context,mouseX,mouseY); + for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { + widgetRenderer.renderWidgets(context, mouseX, mouseY); } } + @Inject(at = @At("HEAD"), method = "resize") - private void onScreenResize(MinecraftClient client,int width, int height, CallbackInfo ci) { - WidgetManager.onScreenResized(width,height,this.width,this.height); + private void onScreenResize(MinecraftClient client, int width, int height, CallbackInfo ci) { + WidgetManager.onScreenResized(width, height, this.width, this.height); } + @Inject(at = @At("HEAD"), method = "close") private void onClose(CallbackInfo ci) { - for(WidgetRenderer widgetRenderer: DynamicHUD.getWidgetRenderers()){ + for (WidgetRenderer widgetRenderer : DynamicHUD.getWidgetRenderers()) { widgetRenderer.onCloseScreen(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java rename to src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index 313823a..f1bcfe7 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.screens; +package com.tanishisherewith.dynamichud.screens; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetRenderer; +import com.tanishisherewith.dynamichud.widget.WidgetRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java similarity index 98% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java index 6eee0ba..f3c8390 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/DynamicValueRegistry.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/DynamicValueRegistry.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.utils; +package com.tanishisherewith.dynamichud.utils; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java b/src/main/java/com/tanishisherewith/dynamichud/utils/System.java similarity index 91% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/System.java index f741907..3cbc6a0 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/System.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/System.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.utils; +package com.tanishisherewith.dynamichud.utils; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java b/src/main/java/com/tanishisherewith/dynamichud/utils/UID.java similarity index 93% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/UID.java index cbe721b..6a1735f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/UID.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/UID.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.utils; +package com.tanishisherewith.dynamichud.utils; import java.util.Random; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java similarity index 86% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/Util.java index d1e04c4..b7f2ccc 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/Util.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils; +package com.tanishisherewith.dynamichud.utils; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; +import com.tanishisherewith.dynamichud.DynamicHUD; public class Util { public static Quadrant getQuadrant(int x, int y) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java similarity index 95% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java index 2750069..6de1633 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; +package com.tanishisherewith.dynamichud.utils.contextmenu; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -46,7 +46,7 @@ public void render(DrawContext drawContext, int x, int y, int height) { int yOffset = y1 + 3; this.width = 10; for (Option option : options) { - if(!option.shouldRender())continue; + if (!option.shouldRender()) continue; option.render(drawContext, x + 2, yOffset); this.width = Math.max(this.width, option.width + padding); yOffset += option.height + 1; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java similarity index 86% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java index 4f2e080..7d1831d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu; +package com.tanishisherewith.dynamichud.utils.contextmenu; -import com.tanishisherewith.dynamichud.newTrial.widget.Widget; +import com.tanishisherewith.dynamichud.widget.Widget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -12,13 +12,13 @@ public abstract class Option { public int width = 0; public int height = 0; public T value = null; + public Supplier shouldRender = () -> true; protected float scale = 0.0f; protected Supplier getter; protected Consumer setter; protected T defaultValue = null; protected MinecraftClient mc = MinecraftClient.getInstance(); private Widget selectedWidget; // The widget that this context menu is associated with - public Supplier shouldRender = ()->true; public Option(Supplier getter, Consumer setter) { this.getter = getter; @@ -26,7 +26,8 @@ public Option(Supplier getter, Consumer setter) { value = get(); defaultValue = get(); } - public Option(Supplier getter, Consumer setter,Supplier shouldRender) { + + public Option(Supplier getter, Consumer setter, Supplier shouldRender) { this.getter = getter; this.setter = setter; this.shouldRender = shouldRender; @@ -77,7 +78,7 @@ public Option setShouldRender(Supplier shouldRender) { return this; } - public boolean shouldRender(){ + public boolean shouldRender() { return shouldRender.get(); } } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java similarity index 88% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java index bc23270..5b32b6b 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/BooleanOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java similarity index 94% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java index 05a6319..399a10c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/DoubleOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java @@ -1,7 +1,7 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +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; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java similarity index 93% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java index 5cd0725..1351d17 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/EnumOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java similarity index 93% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java index 3622dd3..e7d63bb 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/ListOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java similarity index 91% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java index 43d230e..6b8c4f5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/RunnableOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/RunnableOption.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -9,8 +9,8 @@ import java.util.function.Supplier; public class RunnableOption extends Option { - public String name = "Empty"; private final Runnable task; + public String name = "Empty"; /** * Runnable option which runs a task when clicked on it. diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java similarity index 79% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java index 9bc04e9..7546c4a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/SubMenuOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/SubMenuOption.java @@ -1,7 +1,7 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options; +package com.tanishisherewith.dynamichud.utils.contextmenu.options; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu; +import com.tanishisherewith.dynamichud.utils.contextmenu.Option; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import org.jetbrains.annotations.NotNull; @@ -14,9 +14,9 @@ /** * SubMenu option displays a sub menu beside a boolean-like button. *

- * The {@link #getter} gets a boolean value to display/close the subMenu by default. + * The {@link #getter} gets a boolean value to display/close the subMenu by default. *

- * The {@link #setter} returns a boolean value depending on if the subMenu is visible or not + * 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; @@ -26,10 +26,10 @@ public class SubMenuOption extends Option { public SubMenuOption(String name, @NotNull ContextMenu parentMenu, Supplier getter, Consumer setter) { super(getter, setter); - Objects.requireNonNull(parentMenu,"Parent Menu cannot be null"); + Objects.requireNonNull(parentMenu, "Parent Menu cannot be null"); this.name = name; this.parentMenu = parentMenu; - this.subMenu = new ContextMenu(parentMenu.x + parentMenu.width,this.y); + this.subMenu = new ContextMenu(parentMenu.x + parentMenu.width, this.y); this.subMenu.heightOffset = 0; this.subMenu.shouldDisplay = get(); } @@ -67,7 +67,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button) { return super.mouseDragged(mouseX, mouseY, button); } - public SubMenuOption getOption(){ + public SubMenuOption getOption() { return this; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java similarity index 91% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java index b85fbea..bd78b6f 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/AlphaSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/AlphaSlider.java @@ -1,7 +1,7 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java similarity index 97% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java index 4d00518..a11d61d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorGradientPicker.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradientPicker.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; @@ -11,13 +11,13 @@ import java.util.function.Consumer; public class ColorGradientPicker { + 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 ColorPickerButton colorPickerButton; private final AlphaSlider alphaSlider; private final int boxSize; - final MinecraftClient client = MinecraftClient.getInstance(); private int x, y; private boolean display = false; @@ -81,7 +81,7 @@ public void render(DrawContext drawContext, int x1, int y1) { int blue = buffer.get(2) & 0xFF; drawContext.getMatrices().push(); - drawContext.getMatrices().translate(0,0,500); + 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(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java similarity index 88% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java index 9d90874..17f5eec 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java @@ -1,8 +1,8 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.Option; +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 net.minecraft.text.Text; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java similarity index 94% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java index 39f541e..fa2b8f1 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/ColorPickerButton.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorPickerButton.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java similarity index 86% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java index 6f63968..e67d856 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientBox.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -28,14 +28,14 @@ public void render(DrawContext drawContext, int x, int y) { DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + size + 2, y + size + 2, -1); // Draw the gradient - com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size, 2); + com.tanishisherewith.dynamichud.helpers.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 handleX = x + saturation * size - handleSize / 2.0f; float handleY = y + (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, 1, -1); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java similarity index 94% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java index c56cf16..9115e19 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/utils/contextmenu/options/coloroption/GradientSlider.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/GradientSlider.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption; +package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; import net.minecraft.client.gui.DrawContext; import java.awt.*; @@ -54,7 +54,7 @@ public void render(DrawContext drawContext, int x, int y) { float handleX = x + hue * width - handleWidth / 2.0f; float handleY = y - (handleHeight - height) / 2.0f; - DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, handleWidth, handleHeight, 2,-1); + DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), handleX, handleY, handleWidth, handleHeight, 2, -1); drawContext.getMatrices().pop(); } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java rename to src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index fe826d9..bda7cbf 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -1,9 +1,9 @@ -package com.tanishisherewith.dynamichud.newTrial.widget; +package com.tanishisherewith.dynamichud.widget; -import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; -import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.newTrial.helpers.DrawHelper; -import com.tanishisherewith.dynamichud.newTrial.utils.UID; +import com.tanishisherewith.dynamichud.config.GlobalConfig; +import com.tanishisherewith.dynamichud.helpers.ColorHelper; +import com.tanishisherewith.dynamichud.helpers.DrawHelper; +import com.tanishisherewith.dynamichud.utils.UID; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; @@ -161,7 +161,7 @@ public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { /** * Renders the widget on the screen *

- * The mouse position values are only passed when in a {@link com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen} screen. + * The mouse position values are only passed when in a {@link com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen} screen. *

* * @param context diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java similarity index 97% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java rename to src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java index 0082496..cf2670d 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetBox.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.widget; +package com.tanishisherewith.dynamichud.widget; public class WidgetBox { public float x = 0, y = 0; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java similarity index 86% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java rename to src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java index 7939e21..0305a78 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetData.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetData.java @@ -1,4 +1,4 @@ -package com.tanishisherewith.dynamichud.newTrial.widget; +package com.tanishisherewith.dynamichud.widget; import java.util.function.Supplier; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java rename to src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java index c4a685e..65a414e 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetManager.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java @@ -1,6 +1,6 @@ -package com.tanishisherewith.dynamichud.newTrial.widget; +package com.tanishisherewith.dynamichud.widget; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; +import com.tanishisherewith.dynamichud.DynamicHUD; import net.fabricmc.fabric.api.util.NbtType; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; @@ -15,8 +15,8 @@ import java.nio.file.StandardCopyOption; import java.util.*; -import static com.tanishisherewith.dynamichud.newTrial.DynamicHUD.printInfo; -import static com.tanishisherewith.dynamichud.newTrial.DynamicHUD.printWarn; +import static com.tanishisherewith.dynamichud.DynamicHUD.printInfo; +import static com.tanishisherewith.dynamichud.DynamicHUD.printWarn; /** * Manages a collection of widgets, providing methods to add, remove, save, and load widgets. @@ -187,7 +187,7 @@ public static void loadWidgets(File file) throws IOException { if (file.exists()) { NbtCompound rootTag = NbtIo.read(file.toPath()); NbtList widgetList = rootTag.getList("widgets", NbtType.COMPOUND); - if(widgetList == null){ + if (widgetList == null) { printWarn("RootTag is null. File is either empty or corrupted," + file); return; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java rename to src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index b57043e..b850815 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -1,7 +1,7 @@ -package com.tanishisherewith.dynamichud.newTrial.widget; +package com.tanishisherewith.dynamichud.widget; -import com.tanishisherewith.dynamichud.newTrial.DynamicHUD; -import com.tanishisherewith.dynamichud.newTrial.screens.AbstractMoveableScreen; +import com.tanishisherewith.dynamichud.DynamicHUD; +import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.Screen; diff --git a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java similarity index 88% rename from src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java rename to src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 311bc11..5805b36 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/newTrial/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -1,16 +1,16 @@ -package com.tanishisherewith.dynamichud.newTrial.widgets; - -import com.tanishisherewith.dynamichud.newTrial.config.GlobalConfig; -import com.tanishisherewith.dynamichud.newTrial.helpers.ColorHelper; -import com.tanishisherewith.dynamichud.newTrial.utils.DynamicValueRegistry; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.ContextMenu; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.BooleanOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.DoubleOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.EnumOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.ListOption; -import com.tanishisherewith.dynamichud.newTrial.utils.contextmenu.options.coloroption.ColorOption; -import com.tanishisherewith.dynamichud.newTrial.widget.Widget; -import com.tanishisherewith.dynamichud.newTrial.widget.WidgetData; +package com.tanishisherewith.dynamichud.widgets; + +import com.tanishisherewith.dynamichud.config.GlobalConfig; +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.options.BooleanOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.EnumOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.ListOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorOption; +import com.tanishisherewith.dynamichud.widget.Widget; +import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; import net.minecraft.nbt.NbtCompound; import org.lwjgl.glfw.GLFW; @@ -23,8 +23,7 @@ public class TextWidget extends Widget { public Color textColor; - public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new); - protected boolean shadow; // Whether to draw a shadow behind the text + 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 protected int rainbowSpeed = 2; //Speed of the rainbow effect Supplier textSupplier; @@ -222,4 +221,6 @@ public TextWidget build() { } + + } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cb56d52..13c0184 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -19,10 +19,10 @@ "environment": "client", "entrypoints": { "client": [ - "com.tanishisherewith.dynamichud.newTrial.DynamicHUD" + "com.tanishisherewith.dynamichud.DynamicHUD" ], "dynamicHud": [ - "com.tanishisherewith.dynamichud.newTrial.DynamicHudTest" + "com.tanishisherewith.dynamichud.DynamicHudTest" ], "modmenu": [ "com.tanishisherewith.dynamichud.ModMenuIntegration" From cf61d7d8ff7d994fb08596257e0bcb324b34b5bb Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 22:15:18 +0530 Subject: [PATCH 25/33] Cleanup messed this one up --- .../com/tanishisherewith/dynamichud/widgets/TextWidget.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 5805b36..4f77aaf 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -23,7 +23,8 @@ public class TextWidget extends Widget { 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 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 protected int rainbowSpeed = 2; //Speed of the rainbow effect Supplier textSupplier; From 0c5355787d7e53a159fb097972677ae183473ba4 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 22:23:05 +0530 Subject: [PATCH 26/33] Small change --- .../contextmenu/options/{coloroption => }/ColorOption.java | 3 ++- .../utils/contextmenu/options/coloroption/GradientBox.java | 4 ++-- .../com/tanishisherewith/dynamichud/widgets/TextWidget.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/{coloroption => }/ColorOption.java (96%) diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java similarity index 96% rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java index 17f5eec..57d9b16 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorOption.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java @@ -1,8 +1,9 @@ -package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption; +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; 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/GradientBox.java index e67d856..f30b184 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/GradientBox.java @@ -32,8 +32,8 @@ public void render(DrawContext drawContext, int x, int y) { // Draw the handle float handleSize = 3; - float handleX = x + saturation * size - handleSize / 2.0f; - float handleY = y + (1.0f - value) * size - handleSize / 2.0f; + 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); drawContext.getMatrices().pop(); diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 4f77aaf..c5b0b7a 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -8,7 +8,7 @@ import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; import com.tanishisherewith.dynamichud.utils.contextmenu.options.EnumOption; import com.tanishisherewith.dynamichud.utils.contextmenu.options.ListOption; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; From 9e4091c30c553e72ebe2aa25c9af68980ce8f115 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Sat, 13 Apr 2024 23:37:22 +0530 Subject: [PATCH 27/33] Visual changes --- .../utils/contextmenu/ContextMenu.java | 30 +++++++++++-------- .../dynamichud/utils/contextmenu/Option.java | 3 ++ .../contextmenu/options/ColorOption.java | 4 ++- .../contextmenu/options/SubMenuOption.java | 7 +++-- .../options/coloroption/AlphaSlider.java | 2 +- .../options/coloroption/GradientSlider.java | 2 +- .../dynamichud/widgets/TextWidget.java | 2 +- 7 files changed, 31 insertions(+), 19 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 6de1633..7ce748c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -10,12 +10,13 @@ public class ContextMenu { private final List> options = new ArrayList<>(); // The list of options in the context menu public int x, y; - public int width = 0; + public int width = 0, finalWidth = 0; public int height = 0; - public int backgroundColor = new Color(107, 112, 126, 124).getRGB();// Semi-transparent light greyish - blue color + public Color backgroundColor = new Color(107, 112, 126, 124);// Semi-transparent light greyish - blue color 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 ContextMenu(int x, int y) { @@ -27,7 +28,7 @@ public void addOption(Option option) { options.add(option); } - public void render(DrawContext drawContext, int x, int y, int height) { + 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; @@ -35,27 +36,32 @@ public void render(DrawContext drawContext, int x, int y, int height) { update(); DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, scale); - int x1 = this.x - 1; - int y1 = this.y; - int x2 = this.x + width; - int y2 = this.y + this.height; - // Draw the background - DrawHelper.drawCutRectangle(drawContext, x1, y1, x2, y2, 0, backgroundColor, 1); + 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,width + 1,this.height,2,0.7f,backgroundColor.darker().darker().darker().darker().darker().getRGB()); + } - int yOffset = y1 + 3; + int yOffset = this.y + 3; this.width = 10; for (Option option : options) { if (!option.shouldRender()) continue; - option.render(drawContext, x + 2, yOffset); + 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()); + } + option.render(drawContext, x + 2, yOffset,mouseX,mouseY); this.width = Math.max(this.width, option.width + padding); yOffset += option.height + 1; } this.width = this.width + 3; - this.height = (yOffset - y1); + 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){ + return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height; + } public void update() { // Update the scale 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 7d1831d..7f24f05 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -48,6 +48,9 @@ public void render(DrawContext drawContext, int x, int y) { this.x = x; this.y = y; } + public void render(DrawContext drawContext, int x, int y,int mouseX, int mouseY) { + this.render(drawContext, x, y); + } public boolean mouseClicked(double mouseX, double mouseY, int button) { return isMouseOver(mouseX, mouseY); 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 57d9b16..ab92642 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 @@ -32,6 +32,8 @@ public void render(DrawContext drawContext, int x, int y) { this.height = mc.textRenderer.fontHeight; this.width = mc.textRenderer.getWidth(name) + 12; 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 - 8, y, @@ -39,7 +41,7 @@ public void render(DrawContext drawContext, int x, int y) { 8, 2, value.getRGB(), - 90, + shadowOpacity, 1, 1); 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 7546c4a..6823ad0 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 @@ -35,13 +35,14 @@ public SubMenuOption(String name, @NotNull ContextMenu parentMenu, Supplier Date: Sun, 14 Apr 2024 15:38:06 +0530 Subject: [PATCH 28/33] Polishing changes --- .../dynamichud/config/GlobalConfig.java | 7 +++-- .../utils/contextmenu/ContextMenu.java | 12 ++++--- .../dynamichud/utils/contextmenu/Option.java | 1 - .../contextmenu/options/ColorOption.java | 11 ++++--- .../contextmenu/options/DoubleOption.java | 8 +++-- .../utils/contextmenu/options/ListOption.java | 2 +- .../contextmenu/options/RunnableOption.java | 7 +++-- .../contextmenu/options/SubMenuOption.java | 8 +++-- .../options/coloroption/AlphaSlider.java | 2 +- .../coloroption/ColorGradientPicker.java | 31 +++++++++++++------ .../options/coloroption/GradientBox.java | 2 +- .../dynamichud/widget/Widget.java | 13 ++++---- .../dynamichud/widget/WidgetRenderer.java | 2 +- .../dynamichud/widgets/TextWidget.java | 28 +++++++++++------ 14 files changed, 85 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java index 0fd6e0a..7c34869 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java +++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java @@ -23,13 +23,13 @@ public class GlobalConfig { * Common scale for all widgets. Set by the user using YACL. */ @SerialEntry - public float scale = 1.0f; + private float scale = 1.0f; public static GlobalConfig get() { return INSTANCE; } - public Screen createYACLGUI() { + public final Screen createYACLGUI() { return YetAnotherConfigLib.createBuilder() .title(Text.literal("DynamicHUD config screen.")) .category(ConfigCategory.createBuilder() @@ -49,4 +49,7 @@ public Screen createYACLGUI() { .build() .generateScreen(null); } + public float getScale(){ + return scale; + } } 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 7ce748c..dfef1f5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -12,7 +12,9 @@ public class ContextMenu { public int x, y; public int width = 0, finalWidth = 0; public int height = 0; - public Color backgroundColor = new Color(107, 112, 126, 124);// Semi-transparent light greyish - blue color + public Color backgroundColor = new Color(107, 112, 126, 124); + private Color darkerBorderColor = backgroundColor.darker().darker().darker().darker().darker().darker(); + //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; @@ -39,7 +41,7 @@ public void render(DrawContext drawContext, int x, int y, int height, int mouseX // 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,width + 1,this.height,2,0.7f,backgroundColor.darker().darker().darker().darker().darker().getRGB()); + DrawHelper.drawOutlineRoundedBox(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1,this.y,width + 1,this.height,2,0.7f,darkerBorderColor.getRGB()); } int yOffset = this.y + 3; @@ -47,13 +49,13 @@ public void render(DrawContext drawContext, int x, int y, int height, int mouseX 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()); + DrawHelper.drawRoundedRectangle(drawContext.getMatrices().peek().getPositionMatrix(), this.x,yOffset - 1.24f,this.finalWidth - 2,option.height + 0.48f,2,backgroundColor.darker().darker().getRGB()); } option.render(drawContext, x + 2, yOffset,mouseX,mouseY); - this.width = Math.max(this.width, option.width + padding); + this.width = Math.max(this.width, option.width); yOffset += option.height + 1; } - this.width = this.width + 3; + this.width = this.width + padding; this.finalWidth = this.width; this.height = (yOffset - this.y); 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 7f24f05..dfea08c 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/Option.java @@ -18,7 +18,6 @@ public abstract class Option { protected Consumer setter; protected T defaultValue = null; protected MinecraftClient mc = MinecraftClient.getInstance(); - private Widget selectedWidget; // The widget that this context menu is associated with public Option(Supplier getter, Consumer setter) { this.getter = getter; 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 ab92642..b30f8a6 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,8 @@ public ColorOption(String name, ContextMenu parentMenu, Supplier getter, super(getter, setter); this.name = name; this.parentMenu = parentMenu; - colorPicker = new ColorGradientPicker(x + this.parentMenu.width + 10, y - 10, value, this::set, 50, 100); + System.out.println(get()); + colorPicker = new ColorGradientPicker(x + this.parentMenu.finalWidth, y - 10, get(), this::set, 50, 100); } @Override @@ -30,13 +31,13 @@ public void render(DrawContext drawContext, int x, int y) { int color = isVisible ? Color.GREEN.getRGB() : Color.RED.getRGB(); this.height = mc.textRenderer.fontHeight; - this.width = mc.textRenderer.getWidth(name) + 12; + 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 - 8, - y, + x + width - 4, + y - 1, 8, 8, 2, @@ -45,7 +46,7 @@ public void render(DrawContext drawContext, int x, int y) { 1, 1); - colorPicker.render(drawContext, this.x + width / 3 + parentMenu.width + 10, y - 10); + colorPicker.render(drawContext, this.x + parentMenu.finalWidth + 7, y - 10); } @Override 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 399a10c..90123ee 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 @@ -1,6 +1,7 @@ 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 net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -15,8 +16,9 @@ public class DoubleOption extends Option { float step = 0.1f; private boolean isDragging = false; private double minValue = 0.0, maxValue = 0.0; + ContextMenu parentMenu; - public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter) { + public DoubleOption(String name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu parentMenu) { super(getter, setter); this.name = name; this.value = get(); @@ -25,6 +27,7 @@ public DoubleOption(String name, double minValue, double maxValue, float step, S this.width = 30; this.height = 16; this.step = step; + this.parentMenu = parentMenu; Validate.isTrue(this.step > 0.0f, "Step cannot be less than or equal to 0 (zero)"); } @@ -33,8 +36,9 @@ public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); value = get(); - this.width = 30; + this.width = 35; this.height = 16; + // Draw the label TextRenderer textRenderer = mc.textRenderer; DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, 0.7f); 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 e7d63bb..a7aef94 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 @@ -32,7 +32,7 @@ public void render(DrawContext drawContext, int x, int y) { super.render(drawContext, x, y); value = get(); - this.height = mc.textRenderer.fontHeight; + 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); 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 6b8c4f5..a1b3497 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,9 @@ public RunnableOption(String name, Supplier getter, Consumer s this.name = "Run: " + name; // prepend the "run" symbol to the name this.task = task; } + 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) { @@ -32,8 +35,8 @@ public void render(DrawContext drawContext, int x, int y) { value = get(); this.height = mc.textRenderer.fontHeight; - this.width = mc.textRenderer.getWidth("Run: " + name) + 1; - int color = value ? Color.BLUE.getRGB() : Color.GRAY.getRGB(); + 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); } 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 6823ad0..c917ee8 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 @@ -29,7 +29,7 @@ public SubMenuOption(String name, @NotNull ContextMenu parentMenu, Supplier= y && mouseY <= y + height) { alphaHandleY = (int) mouseY - y; alpha = 1.0f - (alphaHandleY / (float) height); if (alpha < 0.0f) { 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 a11d61d..8d70df3 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 @@ -20,22 +20,26 @@ public class ColorGradientPicker { private final int boxSize; 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; this.y = y; + this.initialColor = initialColor; this.onColorSelected = onColorSelected; - float[] hsv = Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), null); - this.boxSize = boxSize; this.gradientSlider = new GradientSlider(x, y, colors, 10); - this.gradientSlider.setHue(hsv[0]); - this.gradientBox = new GradientBox(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); + + this.boxSize = boxSize; + this.gradientSlider.setHue(hsv[0]); this.gradientBox.setHue(hsv[0]); this.gradientBox.setSaturation(hsv[1]); this.gradientBox.setValue(hsv[2]); - this.alphaSlider = new AlphaSlider(x, y, 10, boxSize, initialColor); this.colorPickerButton = new ColorPickerButton(x + boxSize + 8, y + 20, 30, 18); } @@ -57,10 +61,10 @@ public void render(DrawContext drawContext, int x1, int y1) { if (!display) { return; } - gradientSlider.render(drawContext, x + 30, y + client.textRenderer.fontHeight + 4); - gradientBox.render(drawContext, x + 30, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); - colorPickerButton.render(drawContext, x + 54 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 8); - alphaSlider.render(drawContext, x + 40 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); + 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); + alphaSlider.render(drawContext, x + 10 + boxSize, y + client.textRenderer.fontHeight + gradientSlider.getHeight() + 10); if (colorPickerButton.isPicking()) { // Draw the preview box near cursor @@ -92,6 +96,15 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!display) { return false; } + + float[] hsv1 = new float[3]; + Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), hsv1); + + this.gradientSlider.setHue(hsv1[0]); + this.gradientBox.setHue(hsv1[0]); + this.gradientBox.setSaturation(hsv1[1]); + this.gradientBox.setValue(hsv1[2]); + if (colorPickerButton.onClick(mouseX, mouseY, button)) { return true; } else if (gradientSlider.isMouseOver(mouseX, mouseY)) { 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/GradientBox.java index f30b184..49d7699 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/GradientBox.java @@ -28,7 +28,7 @@ public void render(DrawContext drawContext, int x, int y) { DrawHelper.drawOutlinedBox(drawContext, x - 2, y - 2, x + size + 2, y + size + 2, -1); // Draw the gradient - com.tanishisherewith.dynamichud.helpers.DrawHelper.drawRoundedGradientRectangle(drawContext.getMatrices().peek().getPositionMatrix(), Color.BLACK, Color.BLACK, Color.getHSBColor(hue, 1.0f, 1.0f), Color.WHITE, x, y, size, size, 2); + 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; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index bda7cbf..31bb9e6 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -53,7 +53,7 @@ public abstract class Widget { /** * Scale of the current widget. * - * @see GlobalConfig#scale + * @see GlobalConfig#getScale() */ protected float scale = 1.0f; //Dimensions of the widget @@ -68,7 +68,7 @@ public Widget(WidgetData DATA, String modId) { } /** - * This method is called at the end of the {@link Widget#Widget(WidgetData)} constructor. + * This method is called at the end of the {@link Widget#Widget(WidgetData, String)} constructor. */ public void init() { @@ -127,11 +127,11 @@ public boolean isOverlapping(Widget other) { /** * Renders the widget on the screen. */ - public void render(DrawContext drawContext, int mouseX, int mouseY) { + public final void render(DrawContext drawContext, int mouseX, int mouseY) { if (!shouldDisplay()) return; if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().getScale()); } renderWidget(drawContext, mouseX, mouseY); @@ -144,11 +144,11 @@ public void render(DrawContext drawContext, int mouseX, int mouseY) { /** * Renders the widget on the editor screen. */ - public void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { + public final void renderInEditor(DrawContext drawContext, int mouseX, int mouseY) { displayBg(drawContext); if (shouldScale) { - DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().scale); + DrawHelper.scaleAndPosition(drawContext.getMatrices(), getX(), getY(), GlobalConfig.get().getScale()); } renderWidgetInEditor(drawContext, mouseX, mouseY); @@ -183,6 +183,7 @@ 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) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java index b850815..db0c9c5 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java @@ -42,7 +42,7 @@ public void shouldRenderInGameHud(boolean renderInGameHud) { } public void renderWidgets(DrawContext context, int mouseX, int mouseY) { - if (WidgetManager.getWidgets().isEmpty()) return; + if (WidgetManager.getWidgets().isEmpty() || DynamicHUD.MC.getDebugHud().shouldShowDebugHud()) return; Screen currentScreen = DynamicHUD.MC.currentScreen; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 64556b3..67924b4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -4,11 +4,7 @@ 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.options.BooleanOption; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.EnumOption; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.ListOption; -import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption; +import com.tanishisherewith.dynamichud.utils.contextmenu.options.*; import com.tanishisherewith.dynamichud.widget.Widget; import com.tanishisherewith.dynamichud.widget.WidgetData; import net.minecraft.client.gui.DrawContext; @@ -18,6 +14,7 @@ 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; @@ -76,16 +73,26 @@ 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)); - menu.addOption(new ColorOption("TextColor", menu, () -> textColor, value -> textColor = value)); - menu.addOption(new DoubleOption("RainbowSpeed", 1, 4, 1.0f, () -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue())); + 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)); /* TEST */ AtomicReference enums = new AtomicReference<>(Enum.Enum1); AtomicReference option = new AtomicReference<>("Enum1"); - menu.addOption(new EnumOption<>("Enum", enums::get, enums::set, Enum.values())); - List options = Arrays.asList("List1", "List2", "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)); + 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); + } + public void printStuff(){ + System.out.println("Runnable works"); } @Override @@ -94,7 +101,7 @@ public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) { if (textSupplier != null) { String text = textSupplier.get(); 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().scale); + 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); } @@ -161,6 +168,7 @@ public void readFromTag(NbtCompound tag) { dynamicValueRegistry = dvr; return; } + createMenu(); } public enum Enum { From e4ee11ae85ffba1d08bb3198397ba6594e7b27f5 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:39:42 +0530 Subject: [PATCH 29/33] Brushing up --- .../options/coloroption/ColorGradientPicker.java | 9 --------- .../tanishisherewith/dynamichud/widgets/TextWidget.java | 6 ++---- 2 files changed, 2 insertions(+), 13 deletions(-) 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 8d70df3..66c676d 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 @@ -96,15 +96,6 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!display) { return false; } - - float[] hsv1 = new float[3]; - Color.RGBtoHSB(initialColor.getRed(), initialColor.getGreen(), initialColor.getBlue(), hsv1); - - this.gradientSlider.setHue(hsv1[0]); - this.gradientBox.setHue(hsv1[0]); - this.gradientBox.setSaturation(hsv1[1]); - this.gradientBox.setValue(hsv1[2]); - if (colorPickerButton.onClick(mouseX, mouseY, button)) { return true; } else if (gradientSlider.isMouseOver(mouseX, mouseY)) { diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java index 67924b4..efdf1a4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java @@ -76,7 +76,7 @@ public void createMenu() { 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)); - /* TEST */ + /* TEST AtomicReference enums = new AtomicReference<>(Enum.Enum1); AtomicReference option = new AtomicReference<>("Enum1"); List options = Arrays.asList("List1", "List2", "List3"); @@ -90,9 +90,7 @@ 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); - } - public void printStuff(){ - System.out.println("Runnable works"); + */ } @Override From b4360c461e12a82bafce2b8f33d482c8f2e11a31 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Mon, 15 Apr 2024 12:23:56 +0530 Subject: [PATCH 30/33] Last minute changes --- .../dynamichud/DynamicHudTest.java | 37 +++++++++++++------ .../screens/AbstractMoveableScreen.java | 2 + .../utils/contextmenu/ContextMenu.java | 2 +- .../dynamichud/widget/Widget.java | 9 +++-- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java index cc256c6..6f1b2f4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java +++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHudTest.java @@ -13,8 +13,9 @@ import java.util.List; public class DynamicHudTest implements DynamicHudIntegration { - TextWidget textWidget; - TextWidget Example2Widget; + TextWidget FPSWidget; + TextWidget HelloWidget; + TextWidget DynamicHUDWidget; DynamicValueRegistry registry; WidgetRenderer renderer; @@ -25,10 +26,12 @@ public void init() { //Local registry registry = new DynamicValueRegistry(DynamicHUD.MOD_ID); - registry.registerLocal("FPS", () -> "FPS C-DVR: " + DynamicHUD.MC.getCurrentFps()); + registry.registerLocal("Hello", () -> "Hello!"); + registry.registerLocal("DynamicHUD", () -> "DynamicHUD"); - textWidget = new TextWidget.Builder() - .setX(300) + + FPSWidget = new TextWidget.Builder() + .setX(250) .setY(100) .setDraggable(true) .rainbow(false) @@ -37,22 +40,35 @@ public void init() { .shouldScale(false) .build(); - Example2Widget = new TextWidget.Builder() + HelloWidget = new TextWidget.Builder() .setX(200) .setY(100) .setDraggable(true) .rainbow(false) - .setDRKey("FPS") + .setDRKey("Hello") + .setDVR(registry) + .setModID(DynamicHUD.MOD_ID) + .shouldScale(true) + .build(); + + DynamicHUDWidget = new TextWidget.Builder() + .setX(5) + .setY(5) + .setDraggable(false) + .rainbow(true) + .setDRKey("DynamicHUD") .setDVR(registry) .setModID(DynamicHUD.MOD_ID) .shouldScale(true) .build(); + } @Override public void addWidgets() { - WidgetManager.addWidget(textWidget); - WidgetManager.addWidget(Example2Widget); + WidgetManager.addWidget(FPSWidget); + WidgetManager.addWidget(HelloWidget); + WidgetManager.addWidget(DynamicHUDWidget); } @Override @@ -66,12 +82,11 @@ public void initAfter() { renderer = new WidgetRenderer(widgets); renderer.shouldRenderInGameHud(true); renderer.addScreen(TitleScreen.class); - renderer.addScreen(MultiplayerScreen.class); } @Override public AbstractMoveableScreen getMovableScreen() { - return new AbstractMoveableScreen(Text.literal("Editor"), renderer) { + return new AbstractMoveableScreen(Text.literal("Editor Screen"), renderer) { }; } diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java index f1bcfe7..9c3bc60 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java +++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java @@ -74,6 +74,8 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) if (this.client.world == null) { this.renderBackgroundTexture(drawContext); } + 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); } 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 dfef1f5..17d58e4 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java +++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java @@ -41,7 +41,7 @@ public void render(DrawContext drawContext, int x, int y, int height, int mouseX // 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,width + 1,this.height,2,0.7f,darkerBorderColor.getRGB()); + DrawHelper.drawOutlineRoundedBox(drawContext.getMatrices().peek().getPositionMatrix(), this.x - 1,this.y,this.width,this.height,2,0.7f,darkerBorderColor.getRGB()); } int yOffset = this.y + 3; diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java index 31bb9e6..6b36576 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java +++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java @@ -189,15 +189,18 @@ private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) { public boolean mouseClicked(double mouseX, double mouseY, int button) { if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { toggle(); - startX = (int) (mouseX - x); - startY = (int) (mouseY - y); - dragging = true; + if(isDraggable) { + startX = (int) (mouseX - x); + startY = (int) (mouseY - y); + dragging = true; + } return true; } return false; } public boolean mouseDragged(double mouseX, double mouseY, int button, int snapSize) { + if(!isDraggable) return false; if (dragging && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) { int newX = (int) (mouseX - startX); int newY = (int) (mouseY - startY); From d987604e16bf906b344efa9344bba5d3d93217a6 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:22:46 +0530 Subject: [PATCH 31/33] TextureHelper is back --- .../dynamichud/helpers/TextureHelper.java | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java new file mode 100644 index 0000000..db749ae --- /dev/null +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -0,0 +1,271 @@ +package com.tanishisherewith.dynamichud.helpers; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.texture.NativeImage; +import net.minecraft.util.Identifier; + +import java.io.IOException; +import java.io.InputStream; + +public class TextureHelper { + static MinecraftClient mc = MinecraftClient.getInstance(); + + public static NativeImage loadTexture(Identifier textureId) { + if(mc.getResourceManager().getResource(textureId).isPresent()) { + try (InputStream inputStream = mc.getResourceManager().getResource(textureId).get().getInputStream()) { + return NativeImage.read(inputStream); + } catch (IOException e) { + throw new RuntimeException("Failed to load texture " + textureId, e); + } + } + return null; + } + // Method 4: Resize a texture + public static NativeImage resizeTexture(NativeImage image, int newWidth, int newHeight) { + NativeImage result = new NativeImage(newWidth, newHeight, false); + + int oldWidth = image.getWidth(); + int oldHeight = image.getHeight(); + + for (int y = 0; y < newHeight; y++) { + for (int x = 0; x < newWidth; x++) { + int srcX = x * oldWidth / newWidth; + int srcY = y * oldHeight / newHeight; + + result.setColor(x, y, image.getColor(srcX, srcY)); + } + } + + 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_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); + + // 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); + + result.setColor(j, i, + ((((int)red)<<16)&0xff0000) | + ((((int)green)<<8)&0xff00) | + ((int)blue)&0xff); + } + } + + return result; + } + public static NativeImage invertTexture(NativeImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int argb = image.getColor(x, y); + + int alpha = (argb >> 24) & 0xFF; + int red = 255 - ((argb >> 16) & 0xFF); + int green = 255 - ((argb >> 8) & 0xFF); + int blue = 255 - (argb & 0xFF); + + int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; + + result.setColor(x, y, newArgb); + } + } + + return result; + } + + public static NativeImage rotateTexture(NativeImage image, int degrees) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(height, width, false); + + double centerX = width / 2.0; + double centerY = height / 2.0; + double angle = Math.toRadians(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); + + if (newX >= 0 && newX < width && newY >= 0 && newY < height) { + result.setColor(newY, newX, image.getColor(x, y)); + } + } + } + + return result; + } + + private static NativeImage flipTextureHorizontally(NativeImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + result.setColor(width - x - 1, y, image.getColor(x, y)); + } + } + + return result; + } + + private static NativeImage flipTextureVertically(NativeImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + result.setColor(x, height - y - 1, image.getColor(x, y)); + } + } + + return result; + } + + public static NativeImage flipTexture(NativeImage image, boolean flipVertically) { + if (flipVertically) { + return flipTextureVertically(image); + } else { + return flipTextureHorizontally(image); + } + } + + public static NativeImage applyGrayScaleFilter(NativeImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int argb = image.getColor(x, y); + + int alpha = (argb >> 24) & 0xFF; + int red = (argb >> 16) & 0xFF; + int green = (argb >> 8) & 0xFF; + int blue = argb & 0xFF; + + int gray = (red + green + blue) / 3; + int newArgb = (alpha << 24) | (gray << 16) | (gray << 8) | gray; + + result.setColor(x, y, newArgb); + } + } + + return result; + } + public static NativeImage cropTexture(NativeImage image, int x, int y, int width, int height) { + NativeImage result = new NativeImage(width, height, false); + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + result.setColor(j, i, image.getColor(x + j, y + i)); + } + } + + return result; + } + + public static NativeImage tintTexture(NativeImage image, int color) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int argb = image.getColor(x, y); + + int alpha = (argb >> 24) & 0xFF; + int red = ((argb >> 16) & 0xFF) * ((color >> 16) & 0xFF) / 255; + int green = ((argb >> 8) & 0xFF) * ((color >> 8) & 0xFF) / 255; + int blue = (argb & 0xFF) * (color & 0xFF) / 255; + + int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; + + result.setColor(x, y, newArgb); + } + } + + return result; + } + + public static NativeImage overlayTexture(NativeImage image, NativeImage overlay) { + int width = image.getWidth(); + int height = image.getHeight(); + NativeImage result = new NativeImage(width, height, false); + + 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 alpha = Math.max((argb1 >> 24) & 0xFF, (argb2 >> 24) & 0xFF); + int red = Math.min(255, ((argb1 >> 16) & 0xFF) + ((argb2 >> 16) & 0xFF)); + int green = Math.min(255, ((argb1 >> 8) & 0xFF) + ((argb2 >> 8) & 0xFF)); + int blue = Math.min(255, (argb1 & 0xFF) + (argb2 & 0xFF)); + + int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue; + + result.setColor(x, y, newArgb); + } + } + + return result; + } + + public static int getAverageColor(NativeImage image) { + long redTotal = 0; + long greenTotal = 0; + long blueTotal = 0; + int pixelCount = image.getWidth() * image.getHeight(); + + for (int y = 0; y < image.getHeight(); y++) { + for (int x = 0; x < image.getWidth(); x++) { + int argb = image.getColor(x, y); + + redTotal += (argb >> 16) & 0xFF; + greenTotal += (argb >> 8) & 0xFF; + blueTotal += argb & 0xFF; + } + } + + int redAverage = (int)(redTotal / pixelCount); + int greenAverage = (int)(greenTotal / pixelCount); + int blueAverage = (int)(blueTotal / pixelCount); + + return (redAverage << 16) | (greenAverage << 8) | blueAverage; + } + + +} From 7ccbe151b2fba6226e8eb6aa715b7f1fb6ab8eb7 Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:25:36 +0530 Subject: [PATCH 32/33] Documentation needed --- .../com/tanishisherewith/dynamichud/helpers/TextureHelper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java index db749ae..5301aaa 100644 --- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java +++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java @@ -20,7 +20,6 @@ public static NativeImage loadTexture(Identifier textureId) { } return null; } - // Method 4: Resize a texture public static NativeImage resizeTexture(NativeImage image, int newWidth, int newHeight) { NativeImage result = new NativeImage(newWidth, newHeight, false); From 00c928d27d7de461eb7a1ef92f34452c10b7891e Mon Sep 17 00:00:00 2001 From: tanishisherewithhh <120117618+tanishisherewithhh@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:28:01 +0530 Subject: [PATCH 33/33] Final change --- src/main/resources/fabric.mod.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 13c0184..6b684b8 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -21,9 +21,6 @@ "client": [ "com.tanishisherewith.dynamichud.DynamicHUD" ], - "dynamicHud": [ - "com.tanishisherewith.dynamichud.DynamicHudTest" - ], "modmenu": [ "com.tanishisherewith.dynamichud.ModMenuIntegration" ]