From d19168614cd34fed3d621ac02ff153eebd7ada61 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Thu, 26 Feb 2026 13:46:04 +0530
Subject: [PATCH 01/22] An attempt to 1.21.11
Runs, but rendering is broken.
---
build.gradle | 7 +-
gradle.properties | 13 +-
gradle/wrapper/gradle-wrapper.properties | 5 +-
.../dynamichud/DynamicHUD.java | 43 +-
.../dynamichud/HudRender.java | 30 -
.../dynamichud/IntegrationTest.java | 22 +-
.../dynamichud/config/GlobalConfig.java | 56 +-
.../dynamichud/helpers/ColorHelper.java | 16 +-
.../dynamichud/helpers/DrawHelper.java | 549 ++++++++----------
.../dynamichud/helpers/MouseColorQuery.java | 16 +-
.../dynamichud/helpers/TextureHelper.java | 50 +-
.../animations/MathAnimations.java | 20 +-
.../integration/DefaultIntegrationImpl.java | 6 +
.../integration/DynamicHudIntegration.java | 19 +-
.../integration/IntegrationManager.java | 20 +-
.../dynamichud/internal/IBufferBuilder.java | 8 +
.../dynamichud/internal/IRenderLayer.java | 22 -
.../dynamichud/internal/WarningScreen.java | 62 +-
.../dynamichud/mixins/BufferBuilderMixin.java | 33 ++
.../dynamichud/mixins/MinecraftMixin.java | 15 +
.../dynamichud/mixins/OptionsScreenMixin.java | 48 +-
.../dynamichud/mixins/RenderLayerMixin.java | 41 --
.../dynamichud/mixins/ScreenMixin.java | 13 +-
.../renderstates/GeometryRenderState.java | 38 ++
.../GradientShadowRenderState.java | 44 ++
.../InterpolatedCurveRenderState.java | 59 ++
.../QuadColorRectRenderState.java | 42 ++
.../renderstates/RoundedRectRenderState.java | 57 ++
.../screens/AbstractMoveableScreen.java | 109 ++--
.../dynamichud/utils/CustomRenderLayers.java | 152 +++--
.../dynamichud/utils/Util.java | 8 +-
.../utils/contextmenu/ContextMenu.java | 17 +-
.../utils/contextmenu/ContextMenuManager.java | 6 +-
.../contextmenuscreen/ContextMenuScreen.java | 62 +-
.../ContextMenuScreenFactory.java | 2 +-
.../ContextMenuScreenRegistry.java | 2 +-
.../DefaultContextMenuScreenFactory.java | 2 +-
.../contextmenu/layout/LayoutContext.java | 52 +-
.../contextmenu/options/BooleanOption.java | 24 +-
.../contextmenu/options/ColorOption.java | 4 +-
.../contextmenu/options/DoubleOption.java | 12 +-
.../utils/contextmenu/options/EnumOption.java | 4 +-
.../utils/contextmenu/options/ListOption.java | 4 +-
.../utils/contextmenu/options/Option.java | 26 +-
.../contextmenu/options/OptionGroup.java | 12 +-
.../contextmenu/options/RunnableOption.java | 6 +-
.../contextmenu/options/SubMenuOption.java | 10 +-
.../options/coloroption/AlphaSlider.java | 10 +-
.../options/coloroption/ColorGradient.java | 23 +-
.../coloroption/ColorPickerButton.java | 13 +-
.../options/coloroption/HueSlider.java | 14 +-
.../options/coloroption/SaturationHueBox.java | 13 +-
.../contextmenu/skinsystem/ClassicSkin.java | 121 ++--
.../contextmenu/skinsystem/MinecraftSkin.java | 219 ++++---
.../contextmenu/skinsystem/ModernSkin.java | 406 +++++++------
.../utils/contextmenu/skinsystem/Skin.java | 10 +-
.../skinsystem/interfaces/GroupableSkin.java | 4 +-
.../skinsystem/interfaces/SkinRenderer.java | 4 +-
.../utils/handlers/ScrollHandler.java | 9 +-
.../dynamichud/widget/DynamicValueWidget.java | 6 +-
.../dynamichud/widget/UserManageable.java | 6 -
.../dynamichud/widget/Widget.java | 79 ++-
.../dynamichud/widget/WidgetManager.java | 17 +-
.../dynamichud/widget/WidgetRenderer.java | 51 +-
.../dynamichud/widgets/GraphWidget.java | 141 ++---
.../dynamichud/widgets/ItemWidget.java | 20 +-
.../dynamichud/widgets/TextWidget.java | 93 ++-
src/main/resources/dynamichud.mixins.json | 11 +-
src/main/resources/fabric.mod.json | 5 +-
69 files changed, 1663 insertions(+), 1480 deletions(-)
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/HudRender.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/IBufferBuilder.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/internal/IRenderLayer.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/MinecraftMixin.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/mixins/RenderLayerMixin.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/widget/UserManageable.java
diff --git a/build.gradle b/build.gradle
index b6f4027..8d9cd23 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
plugins {
- id 'fabric-loom' version '1.10-SNAPSHOT'
+ id 'net.fabricmc.fabric-loom-remap' version "${loom_version}"
id 'maven-publish'
}
@@ -13,8 +13,6 @@ base {
allprojects {
apply plugin: "java"
apply plugin: "maven-publish"
-
- archivesBaseName = rootProject.archives_base_name
}
repositories {
@@ -33,7 +31,7 @@ repositories {
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
- mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
+ mappings loom.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
@@ -64,7 +62,6 @@ java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
- archivesBaseName = project.archives_base_name
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
diff --git a/gradle.properties b/gradle.properties
index d78b830..1c7c0d3 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,11 +2,14 @@
org.gradle.jvmargs=-Xmx1G
org.gradle.parallel=true
+# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
+org.gradle.configuration-cache=false
+
# Fabric Properties
# check these on https://fabricmc.net/develop
-minecraft_version=1.21.5
-yarn_mappings=1.21.5+build.1
-loader_version=0.16.10
+minecraft_version=1.21.11
+loader_version=0.18.2
+loom_version=1.14-SNAPSHOT
# Mod Properties
# need versioning system
@@ -15,5 +18,5 @@ maven_group = com.tanishisherewith
archives_base_name = dynamichud
# Dependencies
-fabric_version=0.119.5+1.21.5
-yacl_version=3.6.6+1.21.5-fabric
\ No newline at end of file
+fabric_version=0.139.4+1.21.11
+yacl_version=3.8.2+1.21.11-fabric
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 9bf7bd3..d205b54 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
+zipStorePath=wrapper/dists
\ 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 7021a07..53dc955 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
@@ -1,25 +1,41 @@
package com.tanishisherewith.dynamichud;
+import com.mojang.blaze3d.platform.InputConstants;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.MouseColorQuery;
import com.tanishisherewith.dynamichud.integration.IntegrationManager;
+import com.tanishisherewith.dynamichud.widget.WidgetRenderer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
-import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback;
-import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
-import net.minecraft.client.MinecraftClient;
+import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
+import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
+import net.fabricmc.fabric.api.client.rendering.v1.hud.VanillaHudElements;
+import net.fabricmc.fabric.impl.client.rendering.hud.HudElementRegistryImpl;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.rendertype.RenderType;
+import net.minecraft.client.renderer.rendertype.RenderTypes;
+import net.minecraft.resources.Identifier;
+import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Environment(EnvType.CLIENT)
public class DynamicHUD implements ClientModInitializer {
- public static MinecraftClient MC = MinecraftClient.getInstance();
+ public static Minecraft MC = Minecraft.getInstance();
public static final Logger logger = LoggerFactory.getLogger("DynamicHud");
public static String MOD_ID = "dynamichud";
+ static KeyMapping EDITOR_SCREEN_KEYBIND = KeyBindingHelper.registerKeyBinding(new KeyMapping(
+ "DynamicHud Editor Screen",
+ InputConstants.Type.KEYSYM,
+ GLFW.GLFW_KEY_RIGHT_SHIFT,
+ KeyMapping.Category.register(Identifier.fromNamespaceAndPath("dynamichud", "editor_screen"))
+ ));
+
public static void printInfo(String msg) {
logger.info(msg);
}
@@ -28,6 +44,7 @@ public static void printWarn(String msg) {
logger.warn(msg);
}
+
@Override
public void onInitializeClient() {
printInfo("Initialising DynamicHUD");
@@ -35,10 +52,22 @@ public void onInitializeClient() {
//YACL load
GlobalConfig.HANDLER.load();
- IntegrationManager.integrate();
+ ClientLifecycleEvents.CLIENT_STARTED.register((minecraft)-> IntegrationManager.integrate());
+
//In game screen render.
- HudLayerRegistrationCallback.EVENT.register(new HudRender());
+ /*
+ * Using the fabric event {@link HudElementRegistry} 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.
+ */
+ HudElementRegistryImpl.attachElementAfter(VanillaHudElements.MISC_OVERLAYS,
+ Identifier.fromNamespaceAndPath("dynamichud","hudrender_callback"),
+ (graphics, tickCounter) -> {
+ for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) {
+ widgetRenderer.renderWidgets(graphics, -120, -120);
+ }
+ });
+
ClientTickEvents.END_CLIENT_TICK.register(mc-> MouseColorQuery.processIfPending());
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java b/src/main/java/com/tanishisherewith/dynamichud/HudRender.java
deleted file mode 100644
index f7abd75..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/HudRender.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.tanishisherewith.dynamichud;
-
-import com.tanishisherewith.dynamichud.integration.IntegrationManager;
-import com.tanishisherewith.dynamichud.widget.WidgetRenderer;
-import net.fabricmc.fabric.api.client.rendering.v1.HudLayerRegistrationCallback;
-import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
-import net.fabricmc.fabric.api.client.rendering.v1.IdentifiedLayer;
-import net.fabricmc.fabric.api.client.rendering.v1.LayeredDrawerWrapper;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.render.RenderTickCounter;
-import net.minecraft.util.Identifier;
-
-/**
- * Using the fabric event {@link HudLayerRegistrationCallback} 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 HudLayerRegistrationCallback {
- @Override
- public void register(LayeredDrawerWrapper layeredDrawer) {
- layeredDrawer.attachLayerAfter(
- IdentifiedLayer.MISC_OVERLAYS,
- IdentifiedLayer.of(Identifier.of("dynamichud","hudrender_callback"),
- (context, tickCounter) -> {
- for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) {
- widgetRenderer.renderWidgets(context, -120, -120);
- }
- })
- );
- }
-}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
index e6c010c..1dd92c6 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud;
+import com.mojang.blaze3d.platform.InputConstants;
import com.tanishisherewith.dynamichud.integration.DynamicHudConfigurator;
import com.tanishisherewith.dynamichud.integration.DynamicHudIntegration;
import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen;
@@ -7,8 +8,12 @@
import com.tanishisherewith.dynamichud.widget.Widget;
import com.tanishisherewith.dynamichud.widgets.GraphWidget;
import com.tanishisherewith.dynamichud.widgets.TextWidget;
-import net.minecraft.client.gui.screen.TitleScreen;
-import net.minecraft.text.Text;
+import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.gui.screens.TitleScreen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.Identifier;
+import org.lwjgl.glfw.GLFW;
import java.awt.*;
@@ -23,13 +28,13 @@ public class IntegrationTest implements DynamicHudIntegration {
public void init() {
//Global registry
// We recommend using the syntax "modid:key_name" for easier debugging and to prevent data conflicts in global registries.
- DynamicValueRegistry.registerGlobal("dynamichud:FPS", () -> "FPS: " + DynamicHUD.MC.getCurrentFps());
+ DynamicValueRegistry.registerGlobal("dynamichud:FPS", () -> "FPS: " + DynamicHUD.MC.getFps());
//Local registry
registry = new DynamicValueRegistry(DynamicHUD.MOD_ID);
- registry.registerLocal("Hello", () -> "Hello " + DynamicHUD.MC.getSession().getUsername() + "!");
+ registry.registerLocal("Hello", () -> "Hello " + DynamicHUD.MC.getGameProfile().name() + "!");
registry.registerLocal("DynamicHUD", () -> "DynamicHUD");
- registry.registerLocal("FPS", () -> DynamicHUD.MC.getCurrentFps());
+ registry.registerLocal("FPS", () -> DynamicHUD.MC.getFps());
FPSWidget = new TextWidget.Builder()
.setX(250)
@@ -99,7 +104,7 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) {
//renderer.shouldRenderInGameHud(true);
renderer.addScreen(TitleScreen.class);
})
- .withMoveableScreen(config -> new AbstractMoveableScreen(Text.literal("Editor Screen"), config.getRenderer()) {});
+ .withMoveableScreen(config -> new AbstractMoveableScreen(Component.literal("Editor Screen"), config.getRenderer()) {});
return configurator;
}
@@ -108,4 +113,9 @@ public DynamicHudConfigurator configure(DynamicHudConfigurator configurator) {
public void registerCustomWidgets() {
//WidgetManager.addWidgetData(MyWidget.DATA);
}
+
+ @Override
+ public KeyMapping getKeyBind() {
+ return DynamicHUD.EDITOR_SCREEN_KEYBIND;
+ }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java
index e832380..b1dcd44 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/config/GlobalConfig.java
@@ -6,16 +6,16 @@
import dev.isxander.yacl3.config.v2.api.SerialEntry;
import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder;
import net.fabricmc.loader.api.FabricLoader;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.text.Text;
-import net.minecraft.util.Identifier;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.Identifier;
import java.awt.*;
public final class GlobalConfig {
public static final ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(GlobalConfig.class)
- .id(Identifier.of("dynamichud", "dynamichud_config"))
+ .id(Identifier.fromNamespaceAndPath("dynamichud", "dynamichud_config"))
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(FabricLoader.getInstance().getConfigDir().resolve("dynamichud.json5"))
.setJson5(true)
@@ -60,69 +60,69 @@ public static GlobalConfig get() {
public Screen createYACLGUI() {
return YetAnotherConfigLib.createBuilder()
- .title(Text.literal("DynamicHUD config screen."))
+ .title(Component.literal("DynamicHUD config screen."))
.category(ConfigCategory.createBuilder()
- .name(Text.literal("General"))
- .tooltip(Text.literal("Set the general settings for all widgets."))
+ .name(Component.literal("General"))
+ .tooltip(Component.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.")))
+ .name(Component.literal("Global"))
+ .description(OptionDescription.of(Component.literal("Global settings for all widgets.")))
.option(Option.createBuilder()
- .name(Text.literal("Scale"))
- .description(OptionDescription.of(Text.literal("Set scale for all widgets.")))
+ .name(Component.literal("Scale"))
+ .description(OptionDescription.of(Component.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())
.option(Option.createBuilder()
- .name(Text.literal("Render in debug screen"))
- .description(OptionDescription.of(Text.literal("Renders widgets even when the debug screen is on")))
+ .name(Component.literal("Render in debug screen"))
+ .description(OptionDescription.of(Component.literal("Renders widgets even when the debug screen is on")))
.binding(true, () -> this.renderInDebugScreen, newVal -> this.renderInDebugScreen = newVal)
.controller(booleanOption -> BooleanControllerBuilder.create(booleanOption).yesNoFormatter())
.build())
.option(Option.createBuilder()
- .name(Text.literal("Show Color picker preview"))
- .description(OptionDescription.of(Text.literal("Shows the preview below your mouse pointer on selecting color from the screen. Note: You may drop some frames with the preview on.")))
+ .name(Component.literal("Show Color picker preview"))
+ .description(OptionDescription.of(Component.literal("Shows the preview below your mouse pointer on selecting color from the screen. Note: You may drop some frames with the preview on.")))
.binding(true, () -> this.showColorPickerPreview, newVal -> this.showColorPickerPreview = newVal)
.controller(booleanOption -> BooleanControllerBuilder.create(booleanOption).yesNoFormatter())
.build())
.option(Option.createBuilder()
- .name(Text.literal("Show widget descriptions/tooltips"))
- .description(OptionDescription.of(Text.literal("Shows the description of widgets as tooltips.")))
+ .name(Component.literal("Show widget descriptions/tooltips"))
+ .description(OptionDescription.of(Component.literal("Shows the description of widgets as tooltips.")))
.binding(true, () -> this.displayDescriptions, newVal -> this.displayDescriptions = newVal)
.controller(booleanOption -> BooleanControllerBuilder.create(booleanOption).yesNoFormatter())
.build())
.option(Option.createBuilder()
- .name(Text.literal("Snap Size"))
- .description(OptionDescription.of(Text.literal("Grid size for snapping widgets")))
+ .name(Component.literal("Snap Size"))
+ .description(OptionDescription.of(Component.literal("Grid size for snapping widgets")))
.binding(100, () -> this.snapSize, newVal -> this.snapSize = newVal)
.controller(integerOption -> IntegerFieldControllerBuilder.create(integerOption).range(10, 500))
.build())
.build())
.option(Option.createBuilder()
- .name(Text.literal("Widget HUD Active Background Color"))
- .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will be rendered")))
+ .name(Component.literal("Widget HUD Active Background Color"))
+ .description(OptionDescription.of(Component.literal("Color of the background of the widget when it will be rendered")))
.binding(new Color(0, 0, 0, 128), () -> this.hudActiveColor, newVal -> this.hudActiveColor = newVal)
.controller(ColorControllerBuilder::create)
.build())
.option(Option.createBuilder()
- .name(Text.literal("Widget HUD Inactive Background Color"))
- .description(OptionDescription.of(Text.literal("Color of the background of the widget when it will NOT be rendered")))
+ .name(Component.literal("Widget HUD Inactive Background Color"))
+ .description(OptionDescription.of(Component.literal("Color of the background of the widget when it will NOT be rendered")))
.binding(new Color(255, 0, 0, 128), () -> this.hudInactiveColor, newVal -> this.hudInactiveColor = newVal)
.controller(ColorControllerBuilder::create)
.build())
.option(Option.createBuilder()
- .name(Text.literal("Settings Complexity"))
- .description(OptionDescription.of(Text.literal("The level of options to display. Options equal to or below this level will be displayed")))
+ .name(Component.literal("Settings Complexity"))
+ .description(OptionDescription.of(Component.literal("The level of options to display. Options equal to or below this level will be displayed")))
.binding(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.Simple, () -> this.complexity, newVal -> this.complexity = newVal)
.controller((option) -> EnumControllerBuilder.create(option)
.enumClass(com.tanishisherewith.dynamichud.utils.contextmenu.options.Option.Complexity.class)
- .formatValue(value -> Text.of(value.name()))
+ .formatValue(value -> Component.literal(value.name()))
)
.build())
.build())
.save(HANDLER::save)
.build()
- .generateScreen(MinecraftClient.getInstance().currentScreen);
+ .generateScreen(Minecraft.getInstance().screen);
}
public float getScale() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
index 3e39197..1e59066 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
@@ -1,16 +1,8 @@
package com.tanishisherewith.dynamichud.helpers;
-import com.mojang.blaze3d.systems.RenderSystem;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gl.Framebuffer;
-import net.minecraft.client.util.Window;
-import net.minecraft.util.math.MathHelper;
-import org.lwjgl.BufferUtils;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL30;
+import net.minecraft.util.Mth;
import java.awt.*;
-import java.nio.ByteBuffer;
/**
* This class provides helper methods for working with colors.
@@ -113,9 +105,9 @@ public static float[] getRainbowColor() {
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);
+ rainbow[0] = 0.5F + 0.5F * Mth.sin(x * pi);
+ rainbow[1] = 0.5F + 0.5F * Mth.sin((x + 4F / 3F) * pi);
+ rainbow[2] = 0.5F + 0.5F * Mth.sin((x + 8F / 3F) * pi);
return rainbow;
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index 0d26f32..e089219 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -1,25 +1,26 @@
package com.tanishisherewith.dynamichud.helpers;
-import com.mojang.blaze3d.systems.ProjectionType;
import com.mojang.blaze3d.systems.RenderSystem;
import com.tanishisherewith.dynamichud.DynamicHUD;
-import com.tanishisherewith.dynamichud.internal.IRenderLayer;
+import com.tanishisherewith.dynamichud.renderstates.GeometryRenderState;
+import com.tanishisherewith.dynamichud.renderstates.QuadColorRectRenderState;
+import com.tanishisherewith.dynamichud.renderstates.RoundedRectRenderState;
import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
import com.tanishisherewith.dynamichud.widget.WidgetBox;
-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 net.minecraft.client.util.math.Vector2f;
-import net.minecraft.text.Text;
+import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.navigation.ScreenPosition;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.renderer.RenderPipelines;
+import net.minecraft.network.chat.Component;
+import net.minecraft.util.ARGB;
import net.minecraft.util.Util;
-import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;
-import org.joml.Matrix4f;
+import org.joml.Matrix3x2fStack;
import org.joml.Vector4f;
-import org.lwjgl.opengl.GL40C;
import java.awt.*;
+import java.util.Arrays;
import java.util.Objects;
import static com.tanishisherewith.dynamichud.helpers.TextureHelper.mc;
@@ -40,59 +41,42 @@ public class DrawHelper {
* @param endColor end color of the gradient
* @param direction Draws the gradient in the given direction
*/
- public static void drawGradient(DrawContext drawContext, float x, float y, float width, float height, int startColor, int endColor, Direction direction) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugQuads());
-
- switch (direction) {
- case LEFT_RIGHT:
- consumer.vertex(matrix4f, x, y + height, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x + width, y + height, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x + width, y, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x, y, 0.0F).color(startColor);
- break;
- case TOP_BOTTOM:
- consumer.vertex(matrix4f, x, y + height, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x + width, y + height, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x + width, y, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x, y, 0.0F).color(startColor);
- break;
- case RIGHT_LEFT:
- consumer.vertex(matrix4f, x, y + height, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x + width, y + height, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x + width, y, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x, y, 0.0F).color(endColor);
- break;
- case BOTTOM_TOP:
- consumer.vertex(matrix4f, x, y + height, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x + width, y + height, 0.0F).color(startColor);
- consumer.vertex(matrix4f, x + width, y, 0.0F).color(endColor);
- consumer.vertex(matrix4f, x, y, 0.0F).color(endColor);
- break;
- }
- });
- }
-
- public static void enableScissor(int x, int y, int width, int height) {
- enableScissor(x, y, width, height, mc.getWindow().getScaleFactor());
- }
-
- public static void enableScissor(WidgetBox box) {
- enableScissor((int) box.x, (int) box.y, (int) box.getWidth(), (int) box.getHeight(), mc.getWindow().getScaleFactor());
- }
-
- public static void enableScissor(int x, int y, int width, int height, double scaleFactor) {
+ public static void drawGradient(GuiGraphics g, float x, float y, float width, float height, int startColor, int endColor, Direction direction) {
+ int[] c = switch(direction) {
+ case TOP_BOTTOM -> new int[]{startColor, startColor, endColor, endColor};
+ case LEFT_RIGHT -> new int[]{startColor, endColor, endColor, startColor};
+ case RIGHT_LEFT -> new int[]{endColor, startColor, startColor, endColor};
+ case BOTTOM_TOP -> new int[]{endColor, endColor, startColor, startColor};
+ };
+
+ g.guiRenderState.submitGuiElement(
+ new QuadColorRectRenderState(RenderPipelines.GUI,g.pose(),x,y,width,height,c,
+ new ScreenRectangle((int) x, (int) y,(int)width,(int) height),
+ g.scissorStack.peek())
+ );
+ }
+
+ public static void enableScissor(int x, int y, int width, int height, GuiGraphics graphics) {
+ enableScissor(x, y, width, height, mc.getWindow().getGuiScale(),graphics);
+ }
+
+ public static void enableScissor(WidgetBox box,GuiGraphics graphics) {
+ enableScissor((int) box.x, (int) box.y, (int) box.getWidth(), (int) box.getHeight(), mc.getWindow().getGuiScale(),graphics);
+ }
+
+ public static void enableScissor(int x, int y, int width, int height, double scaleFactor, GuiGraphics graphics) {
int scissorX = (int) (x * scaleFactor);
- int scissorY = (int) (DynamicHUD.MC.getWindow().getHeight() - ((y + height) * scaleFactor));
+ int scissorY = (int) (y * scaleFactor);
int scissorWidth = (int) (width * scaleFactor);
int scissorHeight = (int) (height * scaleFactor);
- RenderSystem.enableScissor(scissorX, scissorY, scissorWidth, scissorHeight);
+ ScreenRectangle rect = new ScreenRectangle(x, y, width, height);
+ graphics.scissorStack.push(rect);
}
- public static void disableScissor() {
- RenderSystem.disableScissor();
+
+ public static void disableScissor(GuiGraphics graphics) {
+ graphics.disableScissor();
}
/**
@@ -104,16 +88,8 @@ public static void disableScissor() {
* @param height Height of the rectangle
* @param color Color of the rectangle
*/
- public static void drawRectangle(DrawContext drawContext, float x, float y, float width, float height, int color) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugQuads());
-
- consumer.vertex(matrix4f, x, y + height, 0.0F).color(color);
- consumer.vertex(matrix4f, x + width, y + height, 0.0F).color(color);
- consumer.vertex(matrix4f, x + width, y, 0.0F).color(color);
- consumer.vertex(matrix4f, x, y, 0.0F).color(color);
- });
+ public static void drawRectangle(GuiGraphics graphics, float x, float y, float width, float height, int color) {
+ drawGradient(graphics,x,y,width,height,color,color,Direction.LEFT_RIGHT);
}
/* ==== Drawing Rectangles ==== */
@@ -127,11 +103,11 @@ public static void drawRectangle(DrawContext drawContext, float x, float y, floa
* @param height Height of the rectangle
* @param color Color of the rectangle
*/
- public static void drawOutlineBox(DrawContext drawContext, float x, float y, float width, float height, float thickness, int color) {
- drawRectangle(drawContext, x, y, width, thickness, color);
- drawRectangle(drawContext, x, y + height - thickness, width, thickness, color);
- drawRectangle(drawContext, x, y + thickness, thickness, height - thickness * 2, color);
- drawRectangle(drawContext, x + width - thickness, y + thickness, thickness, height - thickness * 2, color);
+ public static void drawOutlineBox(GuiGraphics graphics, float x, float y, float width, float height, float thickness, int color) {
+ drawRectangle(graphics, x, y, width, thickness, color);
+ drawRectangle(graphics, x, y + height - thickness, width, thickness, color);
+ drawRectangle(graphics, x, y + thickness, thickness, height - thickness * 2, color);
+ drawRectangle(graphics, x + width - thickness, y + thickness, thickness, height - thickness * 2, color);
}
/**
@@ -147,12 +123,12 @@ public static void drawOutlineBox(DrawContext drawContext, float x, float y, flo
* @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(DrawContext drawContext, float x, float y, float width, float height, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
+ public static void drawRectangleWithShadowBadWay(GuiGraphics graphics, float x, float y, float width, float height, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
// First, render the shadow
- drawRectangle(drawContext, x + shadowOffsetX, y + shadowOffsetY, width, height, ColorHelper.getColor(0, 0, 0, shadowOpacity));
+ drawRectangle(graphics, x + shadowOffsetX, y + shadowOffsetY, width, height, ColorHelper.getColor(0, 0, 0, shadowOpacity));
// Then, render the rectangle
- drawRectangle(drawContext, x, y, width, height, color);
+ drawRectangle(graphics, x, y, width, height, color);
}
/**
@@ -166,12 +142,12 @@ public static void drawRectangleWithShadowBadWay(DrawContext drawContext, float
* @param color Color of the rounded.fsh rectangle
* @param thickness thickness of the outline
*/
- public static void drawOutlineRoundedBox(DrawContext drawContext, float x, float y, float width, float height, float radius, float thickness, int color) {
+ public static void drawOutlineRoundedBox(GuiGraphics graphics, float x, float y, float width, float height, float radius, float thickness, int color) {
Color c = new Color(color, true);
- drawOutlineRoundedBox(drawContext,x,y,width,height,new Vector4f(radius),thickness,c,c,c,c);
+ drawOutlineRoundedBox(graphics,x,y,width,height,new Vector4f(radius),thickness,c,c,c,c);
}
- public static void drawOutlineRoundedBox(DrawContext drawContext, float x, float y, float width, float height, Vector4f radii, float thickness, Color tl, Color tr, Color br, Color bl) {
+ public static void drawOutlineRoundedBox(GuiGraphics graphics, float x, float y, float width, float height, Vector4f radii, float thickness, Color tl, Color tr, Color br, Color bl) {
if (width <= 0 || height <= 0) return;
float maxRadius = Math.min(width, height) / 2;
radii.set(Math.min(radii.x, maxRadius), // top-left
@@ -179,43 +155,42 @@ public static void drawOutlineRoundedBox(DrawContext drawContext, float x, float
Math.min(radii.z, maxRadius), // bottom-right
Math.min(radii.w, maxRadius) // bottom-left
);
- drawContext.draw(vcp -> {
- VertexConsumer dvc = vcp.getBuffer(CustomRenderLayers.ROUNDED_RECT_OUTLINE.apply(new CustomRenderLayers.OutlineParameters(radii, thickness ,new float[]{width, height})));
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
+ int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
- dvc.vertex(matrix4f, x, y + height, 0).texture(0, 0).color(bl.getRGB());
- dvc.vertex(matrix4f, x + width, y + height, 0).texture(width, 0).color(br.getRGB());
- dvc.vertex(matrix4f, x + width, y, 0).texture(width, height).color(tr.getRGB());
- dvc.vertex(matrix4f, x, y, 0).texture(0, height).color(tl.getRGB());
- });
+ graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
+ CustomRenderLayers.ROUNDED_RECT_OUTLINE,
+ graphics.pose(),
+ x, y, width, height, thickness, intColors, radii, graphics.scissorStack.peek(),
+ new ScreenRectangle(new ScreenPosition((int) x, (int) y), (int) width, (int) height)
+ ));
}
/**
- * Draw chroma text (text with a nice rainbow effect)
+ * Draw chroma Component (Component with a nice rainbow effect)
*
- * @param drawContext A drawContext object
- * @param text The text to display
- * @param x X pos of text
- * @param y Y pos of text
+ * @param graphics A graphics object
+ * @param Component The Component to display
+ * @param x X pos of Component
+ * @param y Y pos of Component
* @param speed Speed of rainbow
* @param saturation Saturation of the rainbow colors
* @param brightness Brightness of the rainbow colors
* @param spread How much the color difference should be between each character (ideally between 0.001 to 0.2)
- * @param shadow Whether to render the text as shadow.
+ * @param shadow Whether to render the Component as shadow.
*/
- public static void drawChromaText(@NotNull DrawContext drawContext, String text, int x, int y, float speed, float saturation, float brightness, float spread, boolean shadow) {
+ public static void drawChromaText(@NotNull GuiGraphics graphics, String Component, int x, int y, float speed, float saturation, float brightness, float spread, boolean shadow) {
long time = System.currentTimeMillis();
- int length = text.length();
+ int length = Component.length();
for (int i = 0; i < length; i++) {
float hue = (time % (int) (5000 / speed)) / (5000f / speed) + (i * spread); // Adjust the hue based on time and character position
- hue = MathHelper.floorMod(hue, 1.0f); // hue should stay within the range [0, 1]
+ hue = floorMod(hue, 1.0f); // hue should stay within the range [0, 1]
// Convert the hue to an RGB color
int color = Color.HSBtoRGB(hue, saturation, brightness);
// Draw the character with the calculated color
- drawContext.drawText(mc.textRenderer, String.valueOf(text.charAt(i)), x + mc.textRenderer.getWidth(text.substring(0, i)), y, color, shadow);
+ graphics.drawString(mc.font, String.valueOf(Component.charAt(i)), x + mc.font.width(Component.substring(0, i)), y, color, shadow);
}
}
@@ -231,20 +206,30 @@ public static void drawChromaText(@NotNull DrawContext drawContext, String text,
* @param radius radius of the circle outline
* @param color color of the circle outline
*/
- public static void drawOutlineCircle(DrawContext drawContext, float xCenter, float yCenter, float radius, float lineWidth, int color) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugLineStrip(lineWidth));
-
- 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);
- consumer.vertex(matrix4f, (float) x, (float) y, 0).color(color);
- consumer.vertex(matrix4f, (float) x2, (float) y2, 0).color(color);
- }
- });
+ public static void drawOutlineCircle(GuiGraphics graphics, float xCenter, float yCenter, float radius, float lineWidth, int color) {
+ int segments = 72; // 5-degree steps
+ float[] verts = new float[(segments + 1) * 4];
+ int[] colors = new int[(segments + 1) * 2];
+ Arrays.fill(colors, color);
+
+ for (int i = 0; i <= segments; i++) {
+ float rad = (float) Math.toRadians(i * 5);
+ float sin = (float) Math.sin(rad);
+ float cos = (float) Math.cos(rad);
+
+
+ int base = i * 4;
+ verts[base] = xCenter + sin * radius;
+ verts[base + 1] = yCenter + cos * radius;
+ verts[base + 2] = xCenter + sin * (radius + lineWidth);
+ verts[base + 3] = yCenter + cos * (radius + lineWidth);
+ }
+
+ graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
+ CustomRenderLayers.TRIANGLE_STRIP,
+ graphics.pose(),
+ verts, colors, graphics.scissorStack.peek()
+ ));
}
/**
@@ -255,19 +240,28 @@ public static void drawOutlineCircle(DrawContext drawContext, float xCenter, flo
* @param radius radius of the circle outline
* @param color color of the circle outline
*/
- public static void drawFilledCircle(DrawContext drawContext, float xCenter, float yCenter, float radius, int color) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugTriangleFan());
-
- consumer.vertex(matrix4f, xCenter, yCenter, 0).color(color);
+ public static void drawFilledCircle(GuiGraphics graphics, float xCenter, float yCenter, float radius, int color) {
+ int segments = 72; // 5-degree steps for smoothness
+ float[] verts = new float[(segments + 2) * 2];
+ int[] colors = new int[segments + 2];
+
+ // Center point
+ verts[0] = xCenter; verts[1] = yCenter;
+ colors[0] = color;
+
+ for (int i = 0; i <= segments; i++) {
+ float rad = (float) Math.toRadians(i * 5);
+ int idx = (i + 1) * 2;
+ verts[idx] = xCenter + (float) Math.sin(rad) * radius;
+ verts[idx + 1] = yCenter + (float) Math.cos(rad) * radius;
+ colors[i + 1] = 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;
- consumer.vertex(matrix4f, (float) x, (float) y, 0).color(color);
- }
- });
+ graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
+ CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
+ graphics.pose(),
+ verts, colors, graphics.scissorStack.peek()
+ ));
}
/**
@@ -281,42 +275,14 @@ public static void drawFilledCircle(DrawContext drawContext, float xCenter, floa
* @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(DrawContext drawContext, float xCenter, float yCenter, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
+ public static void drawCircleWithShadow(GuiGraphics graphics, float xCenter, float yCenter, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
// First, render the shadow
- drawFilledCircle(drawContext, xCenter + shadowOffsetX, yCenter + shadowOffsetY, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity));
+ drawFilledCircle(graphics, xCenter + shadowOffsetX, yCenter + shadowOffsetY, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity));
// Then, render the circle
- drawFilledCircle(drawContext, xCenter, yCenter, radius, color);
+ drawFilledCircle(graphics, xCenter, yCenter, radius, color);
}
- /**
- * Not Tested
- *
- * @param x
- * @param y
- * @param radius
- * @param startAngle
- * @param endAngle
- * @param color
- */
- @Deprecated
- public static void drawFilledArc(DrawContext drawContext, float x, float y, float radius, float startAngle, float endAngle, int color) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugLineStrip(1.0f));
-
- 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;
-
- consumer.vertex(matrix4f, x, y, 0).color(color);
- consumer.vertex(matrix4f, x1, y1, 0).color(color);
- consumer.vertex(matrix4f, x2, y2, 0).color(color);
- }
- });
- }
/* ==== Drawing Quadrants, Arcs, and Triangles ==== */
/**
@@ -329,37 +295,29 @@ public static void drawFilledArc(DrawContext drawContext, float x, float y, floa
* @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(DrawContext drawContext, 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;
-
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugTriangleFan());
-
- consumer.vertex(matrix4f, xCenter, yCenter, 0).color(startColor);
-
- 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;
+ public static void drawFilledGradientQuadrant(GuiGraphics graphics, float xCenter, float yCenter, float radius, int startColor, int endColor, int quadrant) {
+ int segments = 18; // 90 degrees / 5
+ float[] verts = new float[(segments + 2) * 2];
+ int[] colors = new int[segments + 2];
+
+ verts[0] = xCenter; verts[1] = yCenter;
+ colors[0] = startColor;
+
+ for (int i = 0; i <= segments; i++) {
+ float angle = (quadrant * 90) + (i * 5);
+ float rad = (float) Math.toRadians(angle);
+
+ int idx = (i + 1) * 2;
+ verts[idx] = xCenter + (float) Math.sin(rad) * radius;
+ verts[idx + 1] = yCenter + (float) Math.cos(rad) * radius;
+ colors[i + 1] = ARGB.linearLerp((float) i / segments, startColor, endColor);
+ }
- consumer.vertex(matrix4f, (float) x, (float) y, 0).color(red,green,blue,alpha);
- }
- });
+ graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
+ CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
+ graphics.pose(),
+ verts, colors, graphics.scissorStack.peek()
+ ));
}
/**
@@ -372,23 +330,37 @@ public static void drawFilledGradientQuadrant(DrawContext drawContext, float xCe
* @param endAngle end Angle of the arc
* @param thickness Thickness of the arc (width of the arc)
*/
- public static void drawArc(DrawContext drawContext, float xCenter, float yCenter, float radius, float thickness, int color, int startAngle, int endAngle) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugTriangleFan());
-
- 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;
+ public static void drawArc(GuiGraphics graphics, float xCenter, float yCenter, float radius, float thickness, int color, int startAngle, int endAngle) {
+ int segments = Math.max(1, (endAngle - startAngle) / 5);
+ float[] verts = new float[(segments + 1) * 4];
+ int[] colors = new int[(segments + 1) * 2];
+ Arrays.fill(colors, color);
+
+ for (int i = 0; i <= segments; i++) {
+ int currentAngle = startAngle + (i * 5);
+ if (currentAngle > endAngle) currentAngle = endAngle;
+
+ float rad = (float) Math.toRadians(currentAngle);
+ float sin = (float) Math.sin(rad);
+ float cos = (float) Math.cos(rad);
+
+ int base = i * 4;
+ // Inner Vertex
+ verts[base] = xCenter + sin * (radius - thickness);
+ verts[base + 1] = yCenter + cos * (radius - thickness);
+ // Outer Vertex
+ verts[base + 2] = xCenter + sin * radius;
+ verts[base + 3] = yCenter + cos * radius;
+ }
- consumer.vertex(matrix4f, (float) innerX, (float) innerY, 0).color(color);
- consumer.vertex(matrix4f, (float) outerX, (float) outerY, 0).color(color);
- }
- });
+ graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
+ CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
+ graphics.pose(),
+ verts, colors, graphics.scissorStack.peek()
+ ));
}
+
/**
* Draws a filled quadrant
*
@@ -398,44 +370,32 @@ public static void drawArc(DrawContext drawContext, float xCenter, float yCenter
* @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(DrawContext drawContext, float xCenter, float yCenter, float radius, int color, int quadrant) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getDebugTriangleFan());
-
- consumer.vertex(matrix4f, xCenter, yCenter, 0).color(color);
-
- 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;
- consumer.vertex(matrix4f, (float) x, (float) y, 0).color(color);
- }
- });
+ public static void drawFilledQuadrant(GuiGraphics graphics, float xCenter, float yCenter, float radius, int color, int quadrant) {
+ drawFilledGradientQuadrant(graphics, xCenter, yCenter, radius, color, color, quadrant);
}
/**
* Draws a Triangle with the given coordinates
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @param x3
- * @param y3
- * @param color
*/
- public static void drawOutlineTriangle(DrawContext drawContext, int x1, int y1, int x2, int y2, int x3, int y3, int color) {
- drawContext.draw(vcp -> {
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(RenderLayer.getLines());
-
- consumer.vertex(matrix4f, x1, y1, 0).color(color);
- consumer.vertex(matrix4f, x2, y2, 0).color(color);
- consumer.vertex(matrix4f, x3, y3, 0).color(color);
- consumer.vertex(matrix4f, x1, y1, 0).color(color);
- });
+ public static void drawOutlineTriangle(GuiGraphics graphics, int x1, int y1, int x2, int y2, int x3, int y3, int color) {
+ // 3 lines require 6 vertices (1-2, 2-3, 3-1) to form a closed loop
+ float[] vertices = {
+ (float)x1, (float)y1, (float)x2, (float)y2, // Line 1
+ (float)x2, (float)y2, (float)x3, (float)y3, // Line 2
+ (float)x3, (float)y3, (float)x1, (float)y1 // Line 3
+ };
+
+ int[] colors = new int[6];
+ java.util.Arrays.fill(colors, color);
+
+ graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
+ CustomRenderLayers.COLOR_LINE,
+ graphics.pose(),
+ vertices,
+ colors,
+ graphics.scissorStack.peek()
+ ));
}
-
/**
* Draws a outline quadrant
*
@@ -445,7 +405,7 @@ public static void drawOutlineTriangle(DrawContext drawContext, int x1, int y1,
* @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(DrawContext drawContext, float xCenter, float yCenter, float radius, int quadrant, int color) {
+ public static void drawOutlineQuadrant(GuiGraphics graphics, float xCenter, float yCenter, float radius, int quadrant, int color) {
int startAngle = 0;
int endAngle = 0;
@@ -462,7 +422,7 @@ public static void drawOutlineQuadrant(DrawContext drawContext, float xCenter, f
endAngle = 90;
}
- drawArc(drawContext, xCenter, yCenter, radius, 1f, color, startAngle, endAngle);
+ drawArc(graphics, xCenter, yCenter, radius, 1f, color, startAngle, endAngle);
}
/**
@@ -475,8 +435,8 @@ public static void drawOutlineQuadrant(DrawContext drawContext, float xCenter, f
* @param radius Radius of the quadrants / the rounded.fsh rectangle
* @param color Color of the rounded.fsh rectangle
*/
- public static void drawRoundedRectangle(DrawContext drawContext, float x, float y, float width, float height, float radius, int color) {
- drawRoundedRectangle(drawContext, x, y, true, true, true, true, width, height, radius, color);
+ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y, float width, float height, float radius, int color) {
+ drawRoundedRectangle(graphics, x, y, true, true, true, true, width, height, radius, color);
}
/* ==== Drawing Rounded Rectangles ==== */
@@ -495,17 +455,17 @@ public static void drawRoundedRectangle(DrawContext drawContext, float x, float
* @param radius Radius of the quadrants / the rounded.fsh rectangle
* @param color Color of the rounded.fsh rectangle
*/
- public static void drawRoundedRectangle(DrawContext drawContext, float x, float y, boolean TL, boolean TR, boolean BL, boolean BR, float width, float height, float radius, int color) {
+ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y, boolean TL, boolean TR, boolean BL, boolean BR, float width, float height, float radius, int color) {
Vector4f radii = new Vector4f(TR ? radius : 0.0f, BR ? radius : 0.0f, TL ? radius : 0.0f, BL ? radius : 0.0f);
// Turns out Color class takes rgb by default not rgba
Color c = new Color(color, true);
- drawRoundedRectangle(drawContext,x,y,width, height, radii, c,c,c,c);
+ drawRoundedRectangle(graphics,x,y,width, height, radii, c,c,c,c);
}
/**
* Draws a rounded rectangle with customizable corner radii, corner colors, and selective corner rounding.
- * @param drawContext DrawContext for rendering
+ * @param graphics GuiGraphics for rendering
* @param x X position
* @param y Y position
*
@@ -514,7 +474,7 @@ public static void drawRoundedRectangle(DrawContext drawContext, float x, float
* @param height Height of the rectangle
* @param radii Vector4f specifying radii for top-left, top-right, bottom-right, bottom-left corners
*/
- public static void drawRoundedRectangle(DrawContext drawContext, float x, float y, float width, float height,
+ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y, float width, float height,
Vector4f radii, Color tl, Color tr, Color br, Color bl) {
if (width <= 0 || height <= 0) return;
float maxRadius = Math.min(width, height) / 2;
@@ -523,17 +483,17 @@ public static void drawRoundedRectangle(DrawContext drawContext, float x, float
Math.min(radii.z, maxRadius), // bottom-right
Math.min(radii.w, maxRadius) // bottom-left
);
- drawContext.draw(vcp -> {
- VertexConsumer dvc = vcp.getBuffer(CustomRenderLayers.ROUNDED_RECT.apply(new CustomRenderLayers.RoundedParameters(radii, new float[]{width, height})));
- Matrix4f matrix4f = drawContext.getMatrices().peek().getPositionMatrix();
+ int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
- dvc.vertex(matrix4f, x, y + height, 0).texture(0, 0).color(bl.getRGB());
- dvc.vertex(matrix4f, x + width, y + height, 0).texture(width, 0).color(br.getRGB());
- dvc.vertex(matrix4f, x + width, y, 0).texture(width, height).color(tr.getRGB());
- dvc.vertex(matrix4f, x, y, 0).texture(0, height).color(tl.getRGB());
- });
+ graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
+ CustomRenderLayers.ROUNDED_RECT,
+ graphics.pose(),
+ x, y, width, height, 0f, intColors, radii, graphics.scissorStack.peek(),
+ new ScreenRectangle(new ScreenPosition((int) x, (int) y), (int) width, (int) height)
+ ));
}
+
/**
* Draws an outline rounded.fsh gradient rectangle
*
@@ -547,15 +507,8 @@ public static void drawRoundedRectangle(DrawContext drawContext, float x, float
* @param height Height of rounded.fsh gradient rectangle
* @param radius Radius of the quadrants / the rounded.fsh gradient rectangle
*/
- public static void drawOutlineGradientRoundedBox(DrawContext drawContext, float x, float y, float width, float height, float radius, float thickness, Color tl, Color tr, Color br, Color bl) {
- drawOutlineRoundedBox(drawContext,x,y,width,height,new Vector4f(radius),thickness,tl, tr, br,bl);
- }
-
- 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);
+ public static void drawOutlineGradientRoundedBox(GuiGraphics graphics, float x, float y, float width, float height, float radius, float thickness, Color tl, Color tr, Color br, Color bl) {
+ drawOutlineRoundedBox(graphics,x,y,width,height,new Vector4f(radius),thickness,tl, tr, br,bl);
}
/**
@@ -571,12 +524,12 @@ public static void drawCutRectangle(DrawContext drawContext, int x1, int y1, int
* @param shadowOffsetX X offset of the shadow
* @param shadowOffsetY Y offset of the shadow
*/
- public static void drawRoundedRectangleWithShadowBadWay(DrawContext drawContext, float x, float y, float width, float height, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
+ public static void drawRoundedRectangleWithShadowBadWay(GuiGraphics graphics, float x, float y, float width, float height, float radius, int color, int shadowOpacity, float shadowOffsetX, float shadowOffsetY) {
// First, render the shadow
- drawRoundedRectangle(drawContext, x + shadowOffsetX, y + shadowOffsetY, width, height, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity));
+ drawRoundedRectangle(graphics, x + shadowOffsetX, y + shadowOffsetY, width, height, radius, ColorHelper.getColor(0, 0, 0, shadowOpacity));
// Then, render the rounded.fsh rectangle
- drawRoundedRectangle(drawContext, x, y, width, height, radius, color);
+ drawRoundedRectangle(graphics, x, y, width, height, radius, color);
}
/**
@@ -592,8 +545,8 @@ public static void drawRoundedRectangleWithShadowBadWay(DrawContext drawContext,
* @param height Height of rounded.fsh gradient rectangle
* @param radius Radius of the quadrants / the rounded.fsh gradient rectangle
*/
- public static void drawRoundedGradientRectangle(DrawContext drawContext, Color tl, Color tr, Color br, Color bl, float x, float y, float width, float height, float radius) {
- drawRoundedGradientRectangle(drawContext, tl,tr,br,bl, x, y, width, height, radius, true, true, true, true);
+ public static void drawRoundedGradientRectangle(GuiGraphics graphics, Color tl, Color tr, Color br, Color bl, float x, float y, float width, float height, float radius) {
+ drawRoundedGradientRectangle(graphics, tl,tr,br,bl, x, y, width, height, radius, true, true, true, true);
}
/**
@@ -609,19 +562,19 @@ public static void drawRoundedGradientRectangle(DrawContext drawContext, Color t
* @param height Height of rounded.fsh gradient rectangle
* @param radius Radius of the quadrants / the rounded.fsh gradient rectangle
*/
- public static void drawRoundedGradientRectangle(DrawContext drawContext, Color tl, Color tr, Color br, Color bl, float x, float y, float width, float height, float radius, boolean TL, boolean TR, boolean BL, boolean BR) {
- drawRoundedRectangle(drawContext, x, y, width, height,
+ public static void drawRoundedGradientRectangle(GuiGraphics graphics, Color tl, Color tr, Color br, Color bl, float x, float y, float width, float height, float radius, boolean TL, boolean TR, boolean BL, boolean BR) {
+ drawRoundedRectangle(graphics, x, y, width, height,
new Vector4f(TR ? radius : 0.0f, BR ? radius : 0.0f, TL ? radius : 0.0f, BL ? radius : 0.0f),
tl,tr,br,bl);
}
/* ==== Drawing Lines ==== */
- public static void drawVerticalLine(DrawContext drawContext, float x, float y1, float height, float thickness, int color) {
- drawRectangle(drawContext, x, y1, thickness, height, color);
+ public static void drawVerticalLine(GuiGraphics graphics, float x, float y1, float height, float thickness, int color) {
+ drawRectangle(graphics, x, y1, thickness, height, color);
}
- public static void drawHorizontalLine(DrawContext drawContext, float x1, float width, float y, float thickness, int color) {
- drawRectangle(drawContext, x1, y, width, thickness, color);
+ public static void drawHorizontalLine(GuiGraphics graphics, float x1, float width, float y, float thickness, int color) {
+ drawRectangle(graphics, x1, y, width, thickness, color);
}
/**
@@ -633,23 +586,23 @@ public static void drawHorizontalLine(DrawContext drawContext, float x1, float w
* @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);
+ public static void drawOutlinedBox(GuiGraphics graphics, int x1, int y1, int x2, int y2, int color) {
+ graphics.fill(x1, y1, x2, y1 + 1, color);
+ graphics.fill(x1, y2 - 1, x2, y2, color);
+ graphics.fill(x1, y1 + 1, x1 + 1, y2 - 1, color);
+ graphics.fill(x2 - 1, y1 + 1, x2, y2 - 1, color);
}
public static void unscaledProjection() {
- RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth(), mc.getWindow().getFramebufferHeight(), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
+ //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getWidth(), mc.getWindow().getHeight(), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
}
public static void scaledProjection() {
- RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getFramebufferWidth() / mc.getWindow().getScaleFactor()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
+ //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getWidth() / mc.getWindow().getGuiScale()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
}
public static void customScaledProjection(float scale) {
- RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getFramebufferWidth() / scale, mc.getWindow().getFramebufferHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
+ //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getWidth() / scale, mc.getWindow().getHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
}
/**
@@ -659,16 +612,16 @@ public static void customScaledProjection(float scale) {
* @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
+ public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y, float scale) {
+ matrices.pushMatrix(); // Save the current transformation state
// Translate the origin back to the desired position
- matrices.translate(x, y, 0);
+ matrices.translate(x, y);
// Scale the matrix
- matrices.scale(scale, scale, 1.0F);
+ matrices.scale(scale, scale);
- matrices.translate(-x, -y, 0);
+ matrices.translate(-x, -y);
}
/**
@@ -680,48 +633,52 @@ public static void scaleAndPosition(MatrixStack matrices, float x, float y, floa
* @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
+ public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y, float width, float height, float scale) {
+ matrices.pushMatrix(); // Save the current transformation state
// Translate the origin back to the desired position
- matrices.translate(x + width / 2.0f, y + height / 2.0f, 0);
+ matrices.translate(x + width / 2.0f, y + height / 2.0f);
// Scale the matrix
- matrices.scale(scale, scale, 1.0F);
+ matrices.scale(scale, scale);
- matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f), 0);
+ matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f));
}
- public static void stopScaling(MatrixStack matrices) {
- matrices.pop(); // Restore the previous transformation state
+ public static void stopScaling(Matrix3x2fStack matrices) {
+ matrices.popMatrix(); // Restore the previous transformation state
}
/**
* From minecraft
*/
- public static void drawScrollableText(DrawContext context, TextRenderer textRenderer, Text text, int centerX, int startX, int startY, int endX, int endY, int color) {
- int i = textRenderer.getWidth(text);
+ public static void drawScrollableText(GuiGraphics graphics, Font font, Component Component, int centerX, int startX, int startY, int endX, int endY, int color) {
+ int i = font.width(Component);
int var10000 = startY + endY;
- Objects.requireNonNull(textRenderer);
+ Objects.requireNonNull(font);
int j = (var10000 - 9) / 2 + 1;
int k = endX - startX;
int l;
if (i > k) {
l = i - k;
- double d = (double) Util.getMeasuringTimeMs() / 1000.0;
+ double d = (double) Util.getMillis() / 1000.0;
double e = Math.max((double) l * 0.5, 3.0);
double f = Math.sin(1.5707963267948966 * Math.cos(6.283185307179586 * d / e)) / 2.0 + 0.5;
- double g = MathHelper.lerp(f, 0.0, l);
- context.enableScissor(startX, startY, endX, endY);
- context.drawTextWithShadow(textRenderer, text, startX - (int) g, j, color);
- context.disableScissor();
+ double g = org.joml.Math.lerp(f, 0.0, l);
+ graphics.enableScissor(startX, startY, endX, endY);
+ graphics.drawString(font, Component, startX - (int) g, j, color,true);
+ graphics.disableScissor();
} else {
- l = MathHelper.clamp(centerX, startX + i / 2, endX - i / 2);
- context.drawCenteredTextWithShadow(textRenderer, text, l, j, color);
+ l = Math.clamp(centerX, startX + i / 2, endX - i / 2);
+ graphics.drawCenteredString(font, Component, l, j, color);
}
}
+ public static float floorMod(float x, float y) {
+ return x - y * (float) Math.floor(x / y);
+ }
+
public enum Direction {
/* LEFT_RIGHT means from left to right. Same for others */
LEFT_RIGHT, TOP_BOTTOM, RIGHT_LEFT, BOTTOM_TOP
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/MouseColorQuery.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/MouseColorQuery.java
index 095bbf9..644b8ad 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/MouseColorQuery.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/MouseColorQuery.java
@@ -1,9 +1,9 @@
package com.tanishisherewith.dynamichud.helpers;
+import com.mojang.blaze3d.pipeline.RenderTarget;
+import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.systems.RenderSystem;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gl.Framebuffer;
-import net.minecraft.client.util.Window;
+import net.minecraft.client.Minecraft;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
@@ -26,14 +26,14 @@ public static void request(double mouseX, double mouseY, Consumer callbac
public static void processIfPending() {
if (pendingRequest == null) return;
- MinecraftClient client = MinecraftClient.getInstance();
- Framebuffer framebuffer = client.getFramebuffer();
+ Minecraft client = Minecraft.getInstance();
+ RenderTarget framebuffer = client.getMainRenderTarget();
Window window = client.getWindow();
int windowWidth = window.getWidth();
int windowHeight = window.getHeight();
- int framebufferWidth = framebuffer.textureWidth;
- int framebufferHeight = framebuffer.textureHeight;
+ int framebufferWidth = framebuffer.width;
+ int framebufferHeight = framebuffer.height;
double scaleX = (double) framebufferWidth / windowWidth;
double scaleY = (double) framebufferHeight / windowHeight;
@@ -50,11 +50,9 @@ public static void processIfPending() {
// Make sure rendering is complete
RenderSystem.assertOnRenderThread();
-
// buffer to store the pixel data
ByteBuffer buffer = BufferUtils.createByteBuffer(4);
-
GL11.glReadPixels(x, y, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
int red = buffer.get(0) & 0xFF;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java
index 48b5779..3dfaa37 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/TextureHelper.java
@@ -1,8 +1,8 @@
package com.tanishisherewith.dynamichud.helpers;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.texture.NativeImage;
-import net.minecraft.util.Identifier;
+import com.mojang.blaze3d.platform.NativeImage;
+import net.minecraft.client.Minecraft;
+import net.minecraft.resources.Identifier;
import java.io.IOException;
import java.io.InputStream;
@@ -11,11 +11,11 @@
* This class is entirely untested so some issues may occur which in case should be reported immediately.
*/
public class TextureHelper {
- static MinecraftClient mc = MinecraftClient.getInstance();
+ static Minecraft mc = Minecraft.getInstance();
public static NativeImage loadTexture(Identifier textureId) {
if (mc.getResourceManager().getResource(textureId).isPresent()) {
- try (InputStream inputStream = mc.getResourceManager().getResource(textureId).get().getInputStream()) {
+ try (InputStream inputStream = mc.getResourceManager().getResource(textureId).get().open()) {
return NativeImage.read(inputStream);
} catch (IOException e) {
throw new RuntimeException("Failed to load texture " + textureId, e);
@@ -35,7 +35,7 @@ public static NativeImage resizeTexture(NativeImage image, int newWidth, int new
int srcX = x * oldWidth / newWidth;
int srcY = y * oldHeight / newHeight;
- result.setColorArgb(x, y, image.getColorArgb(srcX, srcY));
+ result.setPixelABGR(x, y, image.getPixel(srcX, srcY));
}
}
@@ -58,10 +58,10 @@ public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage im
y_diff = (y_ratio * i) - y;
// Indexes of the 4 surrounding pixels
- a = image.getColorArgb(x, y);
- b = image.getColorArgb(x + 1, y);
- c = image.getColorArgb(x, y + 1);
- d = image.getColorArgb(x + 1, y + 1);
+ a = image.getPixel(x, y);
+ b = image.getPixel(x + 1, y);
+ c = image.getPixel(x, y + 1);
+ d = image.getPixel(x + 1, y + 1);
// Blue element
blue = (a & 0xff) * (1 - x_diff) * (1 - y_diff) + (b & 0xff) * (x_diff) * (1 - y_diff) +
@@ -75,7 +75,7 @@ public static NativeImage resizeTextureUsingBilinearInterpolation(NativeImage im
red = ((a >> 16) & 0xff) * (1 - x_diff) * (1 - y_diff) + ((b >> 16) & 0xff) * (x_diff) * (1 - y_diff) +
((c >> 16) & 0xff) * (y_diff) * (1 - x_diff) + ((d >> 16) & 0xff) * (x_diff * y_diff);
- result.setColorArgb(j, i,
+ result.setPixelABGR(j, i,
((((int) red) << 16) & 0xff0000) |
((((int) green) << 8) & 0xff00) |
((int) blue) & 0xff);
@@ -92,7 +92,7 @@ public static NativeImage invertTexture(NativeImage image) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- int argb = image.getColorArgb(x, y);
+ int argb = image.getPixel(x, y);
int alpha = (argb >> 24) & 0xFF;
int red = 255 - ((argb >> 16) & 0xFF);
@@ -101,7 +101,7 @@ public static NativeImage invertTexture(NativeImage image) {
int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
- result.setColorArgb(x, y, newArgb);
+ result.setPixelABGR(x, y, newArgb);
}
}
@@ -123,7 +123,7 @@ public static NativeImage rotateTexture(NativeImage image, int degrees) {
int newY = (int) ((x - centerX) * Math.sin(angle) + (y - centerY) * Math.cos(angle) + centerY);
if (newX >= 0 && newX < width && newY >= 0 && newY < height) {
- result.setColorArgb(newY, newX, image.getColorArgb(x, y));
+ result.setPixelABGR(newY, newX, image.getPixel(x, y));
}
}
}
@@ -138,7 +138,7 @@ private static NativeImage flipTextureHorizontally(NativeImage image) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- result.setColorArgb(width - x - 1, y, image.getColorArgb(x, y));
+ result.setPixelABGR(width - x - 1, y, image.getPixel(x, y));
}
}
@@ -152,7 +152,7 @@ private static NativeImage flipTextureVertically(NativeImage image) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- result.setColorArgb(x, height - y - 1, image.getColorArgb(x, y));
+ result.setPixelABGR(x, height - y - 1, image.getPixel(x, y));
}
}
@@ -174,7 +174,7 @@ public static NativeImage applyGrayScaleFilter(NativeImage image) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- int argb = image.getColorArgb(x, y);
+ int argb = image.getPixel(x, y);
int alpha = (argb >> 24) & 0xFF;
int red = (argb >> 16) & 0xFF;
@@ -184,7 +184,7 @@ public static NativeImage applyGrayScaleFilter(NativeImage image) {
int gray = (red + green + blue) / 3;
int newArgb = (alpha << 24) | (gray << 16) | (gray << 8) | gray;
- result.setColorArgb(x, y, newArgb);
+ result.setPixelABGR(x, y, newArgb);
}
}
@@ -196,7 +196,7 @@ public static NativeImage cropTexture(NativeImage image, int x, int y, int width
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
- result.setColorArgb(j, i, image.getColorArgb(x + j, y + i));
+ result.setPixelABGR(j, i, image.getPixel(x + j, y + i));
}
}
@@ -210,7 +210,7 @@ public static NativeImage tintTexture(NativeImage image, int color) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- int argb = image.getColorArgb(x, y);
+ int argb = image.getPixel(x, y);
int alpha = (argb >> 24) & 0xFF;
int red = ((argb >> 16) & 0xFF) * ((color >> 16) & 0xFF) / 255;
@@ -219,7 +219,7 @@ public static NativeImage tintTexture(NativeImage image, int color) {
int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
- result.setColorArgb(x, y, newArgb);
+ result.setPixelABGR(x, y, newArgb);
}
}
@@ -233,8 +233,8 @@ public static NativeImage overlayTexture(NativeImage image, NativeImage overlay)
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
- int argb1 = image.getColorArgb(x, y);
- int argb2 = overlay.getColorArgb(x, y);
+ int argb1 = image.getPixel(x, y);
+ int argb2 = overlay.getPixel(x, y);
int alpha = Math.max((argb1 >> 24) & 0xFF, (argb2 >> 24) & 0xFF);
int red = Math.min(255, ((argb1 >> 16) & 0xFF) + ((argb2 >> 16) & 0xFF));
@@ -243,7 +243,7 @@ public static NativeImage overlayTexture(NativeImage image, NativeImage overlay)
int newArgb = (alpha << 24) | (red << 16) | (green << 8) | blue;
- result.setColorArgb(x, y, newArgb);
+ result.setPixelABGR(x, y, newArgb);
}
}
@@ -258,7 +258,7 @@ public static int getAverageColor(NativeImage image) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
- int argb = image.getColorArgb(x, y);
+ int argb = image.getPixel(x, y);
redTotal += (argb >> 16) & 0xFF;
greenTotal += (argb >> 8) & 0xFF;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
index 6850fff..028e442 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
@@ -2,8 +2,10 @@
import com.tanishisherewith.dynamichud.helpers.animationhelper.Easing;
import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
-import net.minecraft.util.math.Vec2f;
-import net.minecraft.util.math.random.Random;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.phys.Vec2;
+
+import java.util.Random;
public class MathAnimations {
/// SHAKE: Random offset animation with smooth decay
@@ -14,8 +16,8 @@ public static float shake(float intensity, float frequency, float decay) {
}
/// 2D Shake with different X/Y frequencies
- public static Vec2f shake2D(float intensity, float freqX, float freqY) {
- return new Vec2f(
+ public static Vec2 shake2D(float intensity, float freqX, float freqY) {
+ return new Vec2(
(float) Math.sin(System.currentTimeMillis() * freqX) * intensity,
(float) Math.cos(System.currentTimeMillis() * freqY) * intensity
);
@@ -23,16 +25,16 @@ public static Vec2f shake2D(float intensity, float freqX, float freqY) {
/// FLICKER: Random flashing effect
public static float flicker(float min, float max, float chance) {
- Random rand = Random.create();
+ RandomSource rand = RandomSource.create();
return rand.nextFloat() < chance ?
min + (max - min) * rand.nextFloat() :
max;
}
/// CIRCULAR MOTION: Perfect for rotation/orbital animations
- public static Vec2f circularMotion(float radius, float speed, float phase) {
+ public static Vec2 circularMotion(float radius, float speed, float phase) {
double angle = Math.toRadians((System.currentTimeMillis() * speed) % 360 + phase);
- return new Vec2f(
+ return new Vec2(
(float) (Math.cos(angle) * radius),
(float) (Math.sin(angle) * radius)
);
@@ -68,9 +70,9 @@ public static float pulse1(float base, float amplitude, float frequency) {
}
/// SPIRAL: Circular motion with expanding radius
- public static Vec2f spiral(float baseRadius, float expansionRate, float speed) {
+ public static Vec2 spiral(float baseRadius, float expansionRate, float speed) {
float t = System.currentTimeMillis() / 1000f;
- return new Vec2f(
+ return new Vec2(
(float) ((baseRadius + expansionRate * t) * Math.cos(t * speed)),
(float) ((baseRadius + expansionRate * t) * Math.sin(t * speed))
);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java
index 33ae2b7..50bc203 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DefaultIntegrationImpl.java
@@ -4,6 +4,7 @@
import com.tanishisherewith.dynamichud.widgets.GraphWidget;
import com.tanishisherewith.dynamichud.widgets.ItemWidget;
import com.tanishisherewith.dynamichud.widgets.TextWidget;
+import net.minecraft.client.KeyMapping;
/**
* The default implementation for included widgets.
@@ -27,4 +28,9 @@ public void registerCustomWidgets() {
GraphWidget.DATA
);
}
+
+ @Override
+ public KeyMapping getKeyBind() {
+ return null;
+ }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java
index bcc32de..156ccb8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/DynamicHudIntegration.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud.integration;
+import com.mojang.blaze3d.platform.InputConstants;
import com.tanishisherewith.dynamichud.IntegrationTest;
import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen;
import com.tanishisherewith.dynamichud.widget.WidgetData;
@@ -7,8 +8,8 @@
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;
-import net.minecraft.client.util.InputUtil;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.resources.Identifier;
import org.lwjgl.glfw.GLFW;
import java.io.File;
@@ -19,16 +20,6 @@
* @see DefaultIntegrationImpl
*/
public interface DynamicHudIntegration {
- /**
- * The key binding for opening the editor screen.
- */
- KeyBinding EDITOR_SCREEN_KEY_BINDING = KeyBindingHelper.registerKeyBinding(new KeyBinding(
- "DynamicHud Editor Screen",
- InputUtil.Type.KEYSYM,
- GLFW.GLFW_KEY_RIGHT_SHIFT,
- "DynamicHud"
- ));
-
/**
* The filename for the widgets file.
*/
@@ -97,7 +88,5 @@ default File getWidgetsFile() {
*
* @return The keybind.
*/
- default KeyBinding getKeyBind() {
- return EDITOR_SCREEN_KEY_BINDING;
- }
+ KeyMapping getKeyBind();
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
index 485a616..fbaa215 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
@@ -13,8 +13,8 @@
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
import net.fabricmc.loader.api.metadata.ModMetadata;
-import net.minecraft.client.gui.screen.TitleScreen;
-import net.minecraft.client.option.KeyBinding;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.gui.screens.TitleScreen;
import java.io.File;
import java.io.IOException;
@@ -49,8 +49,8 @@ public static List getWidgetRenderers() {
* @param key The key to listen for
* @param screen The AbstractMoveableScreen instance to use to set the screen
*/
- public static void openScreen(KeyBinding key, AbstractMoveableScreen screen) {
- if (key.wasPressed()) {
+ public static void openScreen(KeyMapping key, AbstractMoveableScreen screen) {
+ if (key.isDown()) {
DynamicHUD.MC.setScreen(screen);
}
}
@@ -92,7 +92,7 @@ public static void integrate() {
String modId = metadata.getId();
AbstractMoveableScreen screen;
- KeyBinding binding;
+ KeyMapping binding;
WidgetRenderer widgetRenderer;
File widgetsFile;
try {
@@ -161,7 +161,7 @@ public static void integrate() {
ClientTickEvents.START_CLIENT_TICK.register((client) -> {
if (BooleanPool.get("WarningScreenFlag")) return;
- if (DynamicHUD.MC.currentScreen instanceof TitleScreen) {
+ if (DynamicHUD.MC.screen instanceof TitleScreen) {
DynamicHUD.MC.setScreen(new WarningScreen(bad_implementations));
BooleanPool.put("WarningScreenFlag", true);
}
@@ -185,13 +185,13 @@ private static List> getRegisteredInt
}
/**
- * This makes it so that if minecraft is launched with the program arguments
+ * If minecraft is launched with the program arguments
*
* {@code --dynamicHudTest true}
*
- * then it will
- * load the {@link com.tanishisherewith.dynamichud.IntegrationTest} class as an entrypoint, eliminating any errors due to human incapacity of
- * adding/removing a single line from the `fabric.mod.json`
+ * then it wil load the {@link com.tanishisherewith.dynamichud.IntegrationTest} class as an entrypoint,
+ * eliminating any errors due to human incapacity of adding/removing a single line from the `fabric.mod.json`
+ * This is for myself.
*/
private static EntrypointContainer getTestIntegration() {
DynamicHudIntegration testIntegration;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/IBufferBuilder.java b/src/main/java/com/tanishisherewith/dynamichud/internal/IBufferBuilder.java
new file mode 100644
index 0000000..0aaabea
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/internal/IBufferBuilder.java
@@ -0,0 +1,8 @@
+package com.tanishisherewith.dynamichud.internal;
+
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.mojang.blaze3d.vertex.VertexFormatElement;
+
+public interface IBufferBuilder {
+ VertexConsumer dynamicHUD$writeGenericFloats(VertexFormatElement element, float... values);
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/IRenderLayer.java b/src/main/java/com/tanishisherewith/dynamichud/internal/IRenderLayer.java
deleted file mode 100644
index 3dbc1a2..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/internal/IRenderLayer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.tanishisherewith.dynamichud.internal;
-
-import org.joml.Vector4f;
-
-public interface IRenderLayer {
- /**
- * Set uniform u to the value described by v4f, formatted as a vec4 (4 floats)
- * @param u Name
- * @param v4f Value
- */
- default void dynamichud$setUniform(String u, Vector4f v4f) {
- float[] v = new float[]{v4f.x, v4f.y, v4f.z, v4f.w};
- dynamichud$setUniform(u, v);
- }
-
- /**
- * Set uniform u to the value of v, should be an int[], float[] or Matrix4f
- * @param u Name
- * @param v Value
- */
- void dynamichud$setUniform(String u, Object v);
-}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java
index 2b7ef4b..204760e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/internal/WarningScreen.java
@@ -1,12 +1,13 @@
package com.tanishisherewith.dynamichud.internal;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.client.gui.widget.ButtonWidget;
-import net.minecraft.text.OrderedText;
-import net.minecraft.text.Text;
-import net.minecraft.util.Formatting;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.util.FormattedCharSequence;
import net.minecraft.util.Util;
import java.awt.*;
@@ -17,52 +18,53 @@ public class WarningScreen extends Screen {
private final List modErrors;
public WarningScreen(List modErrors) {
- super(Text.of("DynamicHUD Warning"));
+ super(Component.literal("DynamicHUD Warning"));
this.modErrors = modErrors;
}
@Override
protected void init() {
- ButtonWidget confirmButton = ButtonWidget.builder(Text.of("I Understand"), button -> MinecraftClient.getInstance().setScreen(null))
- .dimensions(this.width / 2 - 100, this.height - 40, 200, 20)
- .narrationSupplier((e) -> Text.literal("I understand"))
+ Button confirmButton = Button.builder(Component.literal("I Understand"), button -> Minecraft.getInstance().setScreen(null))
+ .bounds(this.width / 2 - 100, this.height - 40, 200, 20)
+ .createNarration((e) -> Component.literal("I understand"))
.build();
- ButtonWidget logs_folder = ButtonWidget.builder(Text.of("Open logs"), button -> {
- File logsFolder = new File(MinecraftClient.getInstance().runDirectory, "logs");
- Util.getOperatingSystem().open(logsFolder);
+ Button logs_folder = Button.builder(Component.literal("Open logs"), button -> {
+ File logsFolder = new File(Minecraft.getInstance().gameDirectory, "logs");
+ Util.getPlatform().openFile(logsFolder);
})
- .dimensions(this.width / 2 - 100, this.height - 70, 200, 20)
- .narrationSupplier((e) -> Text.literal("Open logs"))
+ .bounds(this.width / 2 - 100, this.height - 70, 200, 20)
+ .createNarration((e) -> Component.literal("Open logs"))
.build();
// Add "I Understand" button
- this.addDrawableChild(confirmButton);
- this.addDrawableChild(logs_folder);
+ this.addRenderableWidget(confirmButton);
+ this.addRenderableWidget(logs_folder);
}
@Override
- public void render(DrawContext context, int mouseX, int mouseY, float delta) {
- super.render(context, mouseX, mouseY, delta);
+ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
+ super.render(graphics, mouseX, mouseY, delta);
- context.drawCenteredTextWithShadow(this.textRenderer, this.title, this.width / 2, 20, 0xFFFFFF);
- context.drawCenteredTextWithShadow(this.textRenderer, "Mods with bad implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB());
+ graphics.drawCenteredString(this.font, this.title, this.width / 2, 20, 0xFFFFFF);
+ graphics.drawCenteredString(this.font, "Mods with bad implementation of DynamicHUD found!", this.width / 2, 35, Color.ORANGE.getRGB());
int y = 60;
for (ModError error : modErrors) {
- Text modName = Text.literal("> \"" + error.modName() + "\"").formatted(Formatting.RED);
- context.drawText(this.textRenderer, modName, this.width / 2 - 100, y, -1, false);
- List errorMessage = this.textRenderer.wrapLines(Text.literal("Error: " + error.errorMessage()), this.width / 2);
+ Component modName = Component.literal("> \"" + error.modName() + "\"").withStyle(ChatFormatting.RED);
+ graphics.drawString(this.font, modName, this.width / 2 - 100, y, -1, false);
+ List errorMessage =
+ this.font.split(Component.literal("Error: " + error.errorMessage()), this.width / 2);
- if (mouseX >= this.width / 2 - 100 && mouseX <= this.width / 2 - 100 + this.textRenderer.getWidth(modName) && mouseY >= y && mouseY <= y + this.textRenderer.fontHeight) {
- context.drawOrderedTooltip(textRenderer, errorMessage, mouseX, mouseY);
+ if (Skin.isMouseOver(mouseX,mouseY,(double) this.width / 2 - 102, y - 1, this.font.width(modName) + 4,this.font.lineHeight + 2)) {
+ graphics.setTooltipForNextFrame(errorMessage, mouseX, mouseY);
}
y += 11; // Space between mod errors
}
y += 5;
- context.drawCenteredTextWithShadow(this.textRenderer, Text.of("Please report this problem to the respective mod owners."), this.width / 2, y, -1);
- context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Widgets of these mods won't work.").formatted(Formatting.YELLOW), this.width / 2, y + 10, -1);
- context.drawCenteredTextWithShadow(this.textRenderer, Text.literal("Check latest.log for more details").formatted(Formatting.ITALIC), this.width / 2, y + 30, -1);
+ graphics.drawCenteredString(this.font, Component.literal("Please report this problem to the respective mod owners."), this.width / 2, y, -1);
+ graphics.drawCenteredString(this.font, Component.literal("Widgets of these mods won't work.").withStyle(ChatFormatting.YELLOW), this.width / 2, y + 10, -1);
+ graphics.drawCenteredString(this.font, Component.literal("Check latest.log for more details").withStyle(ChatFormatting.ITALIC), this.width / 2, y + 30, -1);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
new file mode 100644
index 0000000..8f2e442
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
@@ -0,0 +1,33 @@
+package com.tanishisherewith.dynamichud.mixins;
+
+import com.mojang.blaze3d.vertex.BufferBuilder;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.mojang.blaze3d.vertex.VertexFormatElement;
+import com.tanishisherewith.dynamichud.internal.IBufferBuilder;
+import org.lwjgl.system.MemoryUtil;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+
+@Mixin(BufferBuilder.class)
+public abstract class BufferBuilderMixin implements VertexConsumer, IBufferBuilder {
+
+ @Shadow
+ protected abstract long beginElement(VertexFormatElement element);
+
+ /**
+ * The "Library" secret sauce.
+ * This allows you to write N floats to a custom GENERIC element.
+ */
+ @Unique
+ public VertexConsumer dynamicHUD$writeGenericFloats(VertexFormatElement element, float... values) {
+ long addr = this.beginElement(element);
+ if (addr != -1L) {
+ for (int i = 0; i < values.length; i++) {
+ // We use the same MemoryUtil Mojang uses in addVertex and setUv
+ MemoryUtil.memPutFloat(addr + (i * 4L), values[i]);
+ }
+ }
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/MinecraftMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/MinecraftMixin.java
new file mode 100644
index 0000000..5a20cd4
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/MinecraftMixin.java
@@ -0,0 +1,15 @@
+package com.tanishisherewith.dynamichud.mixins;
+
+import com.tanishisherewith.dynamichud.DynamicHUD;
+import com.tanishisherewith.dynamichud.integration.IntegrationManager;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.main.GameConfig;
+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(Minecraft.class)
+public abstract class MinecraftMixin {
+
+}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
index 5b0367a..ba6887b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
@@ -2,11 +2,14 @@
import com.llamalad7.mixinextras.sugar.Local;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.client.gui.screen.option.OptionsScreen;
-import net.minecraft.client.gui.widget.ButtonWidget;
-import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
-import net.minecraft.text.Text;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
+import net.minecraft.client.gui.layouts.LayoutSettings;
+import net.minecraft.client.gui.layouts.LinearLayout;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.options.OptionsScreen;
+import net.minecraft.network.chat.Component;
+import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -18,21 +21,30 @@
@Mixin(OptionsScreen.class)
public abstract class OptionsScreenMixin extends Screen {
@Shadow
- protected abstract ButtonWidget createButton(Text message, Supplier screenSupplier);
+ protected abstract Button openScreenButton(Component component, Supplier supplier);
- protected OptionsScreenMixin(Text title) {
+ @Shadow
+ @Final
+ private HeaderAndFooterLayout layout;
+
+ protected OptionsScreenMixin(Component title) {
super(title);
}
- @Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/GridWidget$Adder;add(Lnet/minecraft/client/gui/widget/Widget;)Lnet/minecraft/client/gui/widget/Widget;", ordinal = 0))
- private void init(CallbackInfo ci, @Local(ordinal = 0) DirectionalLayoutWidget directionalLayoutWidget) {
- DirectionalLayoutWidget directionalLayoutWidget2 = directionalLayoutWidget.add(DirectionalLayoutWidget.horizontal());
-
- directionalLayoutWidget2.getMainPositioner().marginLeft(-26).marginY(-28);
-
- ButtonWidget widget = createButton(Text.of("DH"), () -> GlobalConfig.get().createYACLGUI());
- widget.setDimensions(20, 20);
-
- directionalLayoutWidget2.add(widget);
+ @Inject(
+ method = "init",
+ at = @At(
+ value = "INVOKE",
+ target = "Lnet/minecraft/client/gui/layouts/LinearLayout;addChild(Lnet/minecraft/client/gui/layouts/LayoutElement;)Lnet/minecraft/client/gui/layouts/LayoutElement;",
+ ordinal = 1 // this is where the FOV row is added
+ )
+ )
+ private void injectDHLayout(CallbackInfo ci, @Local(ordinal = 0) LinearLayout header) {
+ LinearLayout dhLayout = header.addChild(LinearLayout.vertical(), layoutSettings -> layoutSettings.paddingLeft(-20));
+
+ Button dhButton = openScreenButton(Component.literal("DH"), () -> GlobalConfig.get().createYACLGUI());
+ dhButton.setWidth(20);
+
+ dhLayout.addChild(dhButton);
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/RenderLayerMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/RenderLayerMixin.java
deleted file mode 100644
index cc4795f..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/mixins/RenderLayerMixin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.tanishisherewith.dynamichud.mixins;
-
-
-import com.llamalad7.mixinextras.sugar.Local;
-import com.mojang.blaze3d.systems.RenderPass;
-import com.tanishisherewith.dynamichud.internal.IRenderLayer;
-import net.minecraft.client.render.BuiltBuffer;
-import net.minecraft.client.render.RenderLayer;
-import org.joml.Matrix4f;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Unique;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Mixin(RenderLayer.MultiPhase.class)
-public class RenderLayerMixin implements IRenderLayer {
- @Unique
- private final Map uniforms = new HashMap<>();
-
- @Override
- public void dynamichud$setUniform(String u, Object v) {
- if (v == null) uniforms.remove(u);
- else uniforms.put(u, v);
- }
-
- @Inject(method = "draw", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderPass;drawIndexed(II)V"))
- void beforeDraw(BuiltBuffer par1, CallbackInfo ci, @Local(ordinal = 0) RenderPass pass) {
- uniforms.forEach((k, v) -> {
- switch (v) {
- case float[] fa -> pass.setUniform(k, fa);
- case int[] ia -> pass.setUniform(k, ia);
- case Matrix4f mat -> pass.setUniform(k, mat);
- default -> throw new IllegalStateException("Unknown uniform type " + v.getClass() + " (" + v + ")");
- }
- });
- }
-}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java
index 21446b4..bf685ba 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/ScreenMixin.java
@@ -3,9 +3,8 @@
import com.tanishisherewith.dynamichud.integration.IntegrationManager;
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;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -21,19 +20,19 @@ public abstract class ScreenMixin {
public int height;
@Inject(at = @At("RETURN"), method = "render")
- private void render(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ private void render(GuiGraphics graphics, int mouseX, int mouseY, float delta, CallbackInfo ci) {
for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) {
- widgetRenderer.renderWidgets(context, mouseX, mouseY);
+ widgetRenderer.renderWidgets(graphics, mouseX, mouseY);
}
}
//Injected before the screen is actually resized to get the new and also the old dimensions.
@Inject(at = @At("HEAD"), method = "resize")
- private void onScreenResize(MinecraftClient client, int width, int height, CallbackInfo ci) {
+ private void onScreenResize(int i, int j, CallbackInfo ci) {
WidgetManager.onScreenResized(width, height, this.width, this.height);
}
- @Inject(at = @At("HEAD"), method = "close")
+ @Inject(at = @At("HEAD"), method = "onClose")
private void onClose(CallbackInfo ci) {
for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) {
widgetRenderer.onCloseScreen();
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
new file mode 100644
index 0000000..8926ee4
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
@@ -0,0 +1,38 @@
+package com.tanishisherewith.dynamichud.renderstates;
+
+import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.gui.render.state.GuiElementRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix3x2fStack;
+
+// State for Geometric Shapes (Circles, Arcs, Fans)
+public record GeometryRenderState(
+ RenderPipeline pipeline,
+ Matrix3x2fStack pose,
+ float[] vertices, // Flat array: [x1, y1, x2, y2, ...]
+ int[] colors, // Parallel array of ARGB colors
+ @Nullable ScreenRectangle scissorArea
+) implements GuiElementRenderState {
+
+ public record VertexData(float x, float y, int color) {}
+
+ @Override
+ public void buildVertices(VertexConsumer consumer) {
+ for (int i = 0; i < vertices.length / 2; i++) {
+ consumer.addVertexWith2DPose(pose, vertices[i * 2], vertices[i * 2 + 1])
+ .setColor(colors[i]);
+ }
+ }
+
+ @Override
+ public TextureSetup textureSetup() {
+ return TextureSetup.noTexture();
+ }
+ @Override
+ public @Nullable ScreenRectangle bounds() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
new file mode 100644
index 0000000..1e4af63
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
@@ -0,0 +1,44 @@
+package com.tanishisherewith.dynamichud.renderstates;
+
+import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.gui.render.state.GuiElementRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix3x2fc;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+//TODO: just use fillGradient in GuiGraphics
+public record GradientShadowRenderState(
+ List points,
+ float bottomY,
+ int startColor,
+ int endColor,
+ Matrix3x2fc pose,
+ RenderPipeline pipeline,
+ @Nullable ScreenRectangle scissorArea
+) implements GuiElementRenderState {
+
+ @Override
+ public void buildVertices(@NonNull VertexConsumer consumer) {
+ for (float[] point : points) {
+ float x = point[0];
+ float y = point[1];
+
+ consumer.addVertexWith2DPose(pose, x, y).setColor(startColor);
+ consumer.addVertexWith2DPose(pose, x, bottomY).setColor(endColor);
+ }
+ }
+ @Override
+ public TextureSetup textureSetup() {
+ return TextureSetup.noTexture();
+ }
+
+ @Override
+ public @org.jspecify.annotations.Nullable ScreenRectangle bounds() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
new file mode 100644
index 0000000..96031ee
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
@@ -0,0 +1,59 @@
+package com.tanishisherewith.dynamichud.renderstates;
+
+import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.gui.render.state.GuiElementRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix3x2fc;
+import org.jspecify.annotations.NonNull;
+
+import java.util.List;
+
+public record InterpolatedCurveRenderState(
+ List points,
+ float thickness,
+ int color,
+ Matrix3x2fc pose,
+ RenderPipeline pipeline,
+ @Nullable ScreenRectangle scissorArea
+) implements GuiElementRenderState {
+
+ @Override
+ public void buildVertices(@NonNull VertexConsumer consumer) {
+ consumer.addVertexWith2DPose(pose, 10, 10).setColor(color);
+ consumer.addVertexWith2DPose(pose, 100, 10).setColor(color);
+ consumer.addVertexWith2DPose(pose, 10, 20).setColor(color);
+ consumer.addVertexWith2DPose(pose, 100, 20).setColor(color);
+ /*
+ for (int i = 0; i < points.size(); i++) {
+ float[] point = points.get(i);
+ float x = point[0];
+ float y = point[1];
+
+ float dx = (i < points.size() - 1) ? points.get(i + 1)[0] - x : x - points.get(i - 1)[0];
+ float dy = (i < points.size() - 1) ? points.get(i + 1)[1] - y : y - points.get(i - 1)[1];
+ float length = (float) Math.sqrt(dx * dx + dy * dy);
+ if (length == 0) continue;
+
+ float offsetX = (thickness * 0.5f * dy) / length;
+ float offsetY = (thickness * 0.5f * -dx) / length;
+
+ consumer.addVertexWith2DPose(pose, x + offsetX, y + offsetY).setColor(color);
+ consumer.addVertexWith2DPose(pose, x - offsetX, y - offsetY).setColor(color);
+ }
+
+ */
+ }
+
+ @Override
+ public TextureSetup textureSetup() {
+ return TextureSetup.noTexture();
+ }
+
+ @Override
+ public @Nullable ScreenRectangle bounds() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
new file mode 100644
index 0000000..4921a73
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
@@ -0,0 +1,42 @@
+package com.tanishisherewith.dynamichud.renderstates;
+
+import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.gui.render.state.GuiElementRenderState;
+import org.joml.Matrix3x2f;
+import org.jspecify.annotations.Nullable;
+
+import java.awt.*;
+
+public record QuadColorRectRenderState(
+ RenderPipeline pipeline,
+ Matrix3x2f pose,
+ float x,
+ float y,
+ float width,
+ float height,
+ int[] color,
+ ScreenRectangle bounds,
+ ScreenRectangle scissorArea
+) implements GuiElementRenderState {
+
+ @Override
+ public void buildVertices(VertexConsumer vertices) {
+ vertices.addVertexWith2DPose(this.pose(),x, y).setColor(this.color[1]);
+ vertices.addVertexWith2DPose(this.pose(), x, y + height).setColor(this.color[2]);
+ vertices.addVertexWith2DPose(this.pose(), x + width, y + height).setColor(this.color[3]);
+ vertices.addVertexWith2DPose(this.pose(), x + width, y).setColor(this.color[0]);
+ }
+
+ @Override
+ public TextureSetup textureSetup() {
+ return TextureSetup.noTexture();
+ }
+
+ @Override
+ public @Nullable ScreenRectangle bounds() {
+ return this.scissorArea != null ? this.scissorArea.intersection(bounds) : this.bounds;
+ }
+}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
new file mode 100644
index 0000000..01a6788
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
@@ -0,0 +1,57 @@
+package com.tanishisherewith.dynamichud.renderstates;
+
+import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.tanishisherewith.dynamichud.internal.IBufferBuilder;
+import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
+import net.minecraft.client.gui.navigation.ScreenRectangle;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.gui.render.state.GuiElementRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix3x2fc;
+import org.joml.Vector4f;
+import org.jspecify.annotations.NonNull;
+
+public record RoundedRectRenderState(
+ RenderPipeline pipeline,
+ Matrix3x2fc pose,
+ float x,
+ float y,
+ float width,
+ float height,
+ float thickness,
+ int[] colors,
+ Vector4f roundness,
+ @Nullable ScreenRectangle scissorArea,
+ @Nullable ScreenRectangle bounds
+) implements GuiElementRenderState {
+
+ @Override
+ public void buildVertices(@NonNull VertexConsumer consumer) {
+ if (consumer instanceof IBufferBuilder builder) {
+ float[][] uvs = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
+ float[][] coords = {{x, y}, {x, y + height}, {x + width, y + height}, {x + width, y}};
+
+ for (int i = 0; i < 4; i++) {
+ consumer.addVertexWith2DPose(pose, coords[i][0], coords[i][1])
+ .setColor(colors[i % colors.length])
+ .setUv(uvs[i][0], uvs[i][1]);
+
+ builder.dynamicHUD$writeGenericFloats(CustomRenderLayers.ELM_WIDTH_HEIGHT, width, height);
+
+ builder.dynamicHUD$writeGenericFloats(CustomRenderLayers.ELM_ROUNDNESS,
+ roundness.x, roundness.y, roundness.z, roundness.w);
+ }
+ }
+ }
+
+ @Override
+ public TextureSetup textureSetup() {
+ return TextureSetup.noTexture();
+ }
+
+ @Override
+ public @org.jspecify.annotations.Nullable ScreenRectangle bounds() {
+ return this.scissorArea != null ? this.scissorArea.intersection(this.bounds) : this.bounds;
+ }
+}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
index 55ad285..5dcf628 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
@@ -1,12 +1,19 @@
package com.tanishisherewith.dynamichud.screens;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
+import com.tanishisherewith.dynamichud.utils.Util;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager;
import com.tanishisherewith.dynamichud.widget.Widget;
import com.tanishisherewith.dynamichud.widget.WidgetRenderer;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.text.Text;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.input.CharacterEvent;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.client.input.MouseButtonEvent;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.entity.vehicle.minecart.Minecart;
+import org.jspecify.annotations.NonNull;
import org.lwjgl.glfw.GLFW;
public abstract class AbstractMoveableScreen extends Screen {
@@ -15,7 +22,7 @@ public abstract class AbstractMoveableScreen extends Screen {
/**
* Constructs a AbstractMoveableScreen object.
*/
- public AbstractMoveableScreen(Text title, WidgetRenderer renderer) {
+ public AbstractMoveableScreen(Component title, WidgetRenderer renderer) {
super(title);
this.widgetRenderer = renderer;
}
@@ -26,92 +33,95 @@ protected void init() {
}
@Override
- public void onDisplayed() {
- super.onDisplayed();
+ public void added() {
+ super.added();
widgetRenderer.isInEditor = true;
}
@Override
- public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
- widgetRenderer.mouseDragged(mouseX, mouseY, button, deltaX, deltaY, GlobalConfig.get().getSnapSize());
- ContextMenuManager.getInstance().mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
- return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
+ public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) {
+ widgetRenderer.mouseDragged(event.x(), event.y(), event.button(),
+ dx, dy,
+ GlobalConfig.get().getSnapSize());
+ ContextMenuManager.getInstance().mouseDragged(event.x(), event.y(), event.button(),
+ dx, dy);
+ return super.mouseDragged(event, dx, dy);
}
@Override
- public boolean mouseClicked(double mouseX, double mouseY, int button) {
- if (widgetRenderer.mouseClicked(mouseX, mouseY, button)) {
- handleClickOnWidget(widgetRenderer.selectedWidget, mouseX, mouseY, button);
+ public boolean mouseClicked(MouseButtonEvent event, boolean bl) {
+ if (widgetRenderer.mouseClicked(event.x(), event.y(), event.button())) {
+ handleClickOnWidget(widgetRenderer.selectedWidget, event.x(), event.y(), event.button());
}
- ContextMenuManager.getInstance().mouseClicked(mouseX, mouseY, button);
- return super.mouseClicked(mouseX, mouseY, button);
+ ContextMenuManager.getInstance().mouseClicked(event.x(), event.y(), event.button());
+ return super.mouseClicked(event, bl);
}
@Override
- public boolean charTyped(char chr, int modifiers) {
- widgetRenderer.charTyped(chr, modifiers);
- ContextMenuManager.getInstance().charTyped(chr, modifiers);
- return super.charTyped(chr, modifiers);
+ public boolean charTyped(CharacterEvent event) {
+ widgetRenderer.charTyped((char) event.codepoint(), event.modifiers());
+ ContextMenuManager.getInstance().charTyped((char) event.codepoint(), event.modifiers());
+ return super.charTyped(event);
}
@Override
- public boolean mouseReleased(double mouseX, double mouseY, int button) {
- widgetRenderer.mouseReleased(mouseX, mouseY, button);
- ContextMenuManager.getInstance().mouseReleased(mouseX, mouseY, button);
- return super.mouseReleased(mouseX, mouseY, button);
+ public boolean mouseReleased(MouseButtonEvent event) {
+ widgetRenderer.mouseReleased(event.x(), event.y(), event.button());
+ ContextMenuManager.getInstance().mouseReleased(event.x(), event.y(), event.button());
+ return super.mouseReleased(event);
}
@Override
- public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
- widgetRenderer.keyPressed(keyCode, scanCode, modifiers);
- ContextMenuManager.getInstance().keyPressed(keyCode, scanCode, modifiers);
- if (widgetRenderer.selectedWidget != null && (keyCode == GLFW.GLFW_KEY_DELETE || keyCode == GLFW.GLFW_KEY_BACKSPACE)) {
- // trayWidget.minimizeWidget(widgetRenderer.selectedWidget);
+ public boolean keyPressed(KeyEvent event) {
+ widgetRenderer.keyPressed(event.key(), event.scancode(), event.modifiers());
+ ContextMenuManager.getInstance().keyPressed(event.key(), event.scancode(), event.modifiers());
+ if (widgetRenderer.selectedWidget != null &&
+ (event.key() == GLFW.GLFW_KEY_DELETE || event.key() == GLFW.GLFW_KEY_BACKSPACE)) {
+ // trayWidget.minimizeWidget(widgetRenderer.selectedWidget);
}
-
- return super.keyPressed(keyCode, scanCode, modifiers);
+ return super.keyPressed(event);
}
@Override
- public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
- widgetRenderer.keyReleased(keyCode, scanCode, modifiers);
- ContextMenuManager.getInstance().keyReleased(keyCode, scanCode, modifiers);
- return super.keyReleased(keyCode, scanCode, modifiers);
+ public boolean keyReleased(KeyEvent event) {
+ widgetRenderer.keyReleased(event.key(), event.scancode(), event.modifiers());
+ ContextMenuManager.getInstance().keyReleased(event.key(), event.scancode(), event.modifiers());
+ return super.keyReleased(event);
}
@Override
- public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
- widgetRenderer.mouseScrolled(mouseX, mouseY, verticalAmount, horizontalAmount);
- ContextMenuManager.getInstance().mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
- return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
+ public boolean mouseScrolled(double x, double y, double horizontalAmount, double verticalAmount) {
+ widgetRenderer.mouseScrolled(x, y, verticalAmount, horizontalAmount);
+ ContextMenuManager.getInstance().mouseScrolled(x, y, horizontalAmount, verticalAmount);
+ return super.mouseScrolled(x, y, horizontalAmount, verticalAmount);
}
/**
* Renders this screen and its widgets on the screen.
*
- * @param drawContext The matrix stack used for rendering
+ * @param graphics 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) {
- if (this.client.world == null) {
- renderInGameBackground(drawContext);
+ public void render(@NonNull GuiGraphics graphics, int mouseX, int mouseY, float delta) {
+ if (this.minecraft.level == null) {
+ renderBackground(graphics,mouseX,mouseY,delta);
}
- drawContext.drawText(client.textRenderer, title, client.getWindow().getScaledWidth() / 2 - client.textRenderer.getWidth(title.getString()) / 2, textRenderer.fontHeight / 2, -1, true);
+ graphics.drawCenteredString(this.font, this.title, this.width / 2, this.font.lineHeight / 2,-1);
// Draw each widget
- widgetRenderer.renderWidgets(drawContext, mouseX, mouseY);
+ widgetRenderer.renderWidgets(graphics, mouseX, mouseY);
- ContextMenuManager.getInstance().renderAll(drawContext, mouseX, mouseY);
+ ContextMenuManager.getInstance().renderAll(graphics, mouseX, mouseY);
if (GlobalConfig.get().shouldDisplayDescriptions()) {
for (Widget widget : widgetRenderer.getWidgets()) {
if (widget == null || widget.isShiftDown) continue;
if (widget.getWidgetBox().isMouseOver(mouseX, mouseY)) {
- drawContext.drawTooltip(client.textRenderer, widget.tooltipText, mouseX, mouseY);
+ graphics.setTooltipForNextFrame(this.font, widget.tooltipText, mouseX, mouseY);
break;
}
}
@@ -122,16 +132,15 @@ public void handleClickOnWidget(Widget widget, double mouseX, double mouseY, int
}
@Override
- public void close() {
+ public void onClose() {
widgetRenderer.isInEditor = false;
widgetRenderer.onCloseScreen();
ContextMenuManager.getInstance().onClose();
- super.close();
+ super.onClose();
}
@Override
- public boolean shouldPause() {
+ public boolean isPauseScreen() {
return false;
}
}
-
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
index df17c3d..5e395c3 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
@@ -3,94 +3,116 @@
import com.mojang.blaze3d.pipeline.BlendFunction;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.platform.DestFactor;
-import com.mojang.blaze3d.platform.LogicOp;
import com.mojang.blaze3d.platform.SourceFactor;
+import com.mojang.blaze3d.shaders.UniformType;
+import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement;
-import com.tanishisherewith.dynamichud.internal.IRenderLayer;
-import net.minecraft.client.gl.RenderPipelines;
-import net.minecraft.client.gl.UniformType;
-import net.minecraft.client.render.RenderLayer;
-import net.minecraft.client.render.VertexFormats;
-import net.minecraft.client.util.math.Vector2f;
-import net.minecraft.util.Identifier;
-import net.minecraft.util.Util;
+import net.minecraft.client.renderer.RenderPipelines;
+import net.minecraft.resources.Identifier;
import org.joml.Vector4f;
-import java.awt.*;
-import java.util.function.Function;
public class CustomRenderLayers {
- public static RenderLayer QUADS_CUSTOM_BLEND = RenderLayer.of(
- "dynamichud/quads_custom_blend",
- 1536,
- false,
- true,
- RenderPipelines.register(RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
- .withLocation(Identifier.of("dynamichud", "pipeline/quad_custom_blend_func"))
- .withVertexFormat(VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.QUADS)
- .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
- .build()
- ),
- RenderLayer.MultiPhaseParameters.builder().build(false)
- );
+ public static final RenderPipeline COLOR_LINE = RenderPipeline.builder()
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "color_line"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.DEBUG_LINES)
+ .withFragmentShader(Identifier.withDefaultNamespace("position_color"))
+ .withVertexShader(Identifier.withDefaultNamespace("position_color"))
+ .build();
+
+ // Width/Height in UV1
+ public static final VertexFormatElement ELM_WIDTH_HEIGHT =
+ new VertexFormatElement(1, 2, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.UV, 8);
+
+ // Roundness in UV2
+ public static final VertexFormatElement ELM_ROUNDNESS =
+ new VertexFormatElement(2, 4, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.UV, 16);
+
+ public static final VertexFormat ROUNDED_FORMAT = VertexFormat.builder()
+ .add("Position", VertexFormatElement.POSITION)
+ .add("Color", VertexFormatElement.COLOR)
+ .add("UV0", VertexFormatElement.UV0)
+ .add("WidthHeight", ELM_WIDTH_HEIGHT)
+ .add("Roundness", ELM_ROUNDNESS)
+ .build();
+
- public static RenderLayer TRIANGLE_FAN_CUSTOM_BLEND = RenderLayer.of(
- "dynamichud/triangle_fan_custom_blend",
- 1536,
- false,
- true,
- RenderPipelines.register(RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
- .withLocation(Identifier.of("dynamichud", "pipeline/triangle_fan_custom_blend_func"))
- .withVertexFormat(VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.TRIANGLE_FAN)
- .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
+ public static final RenderPipeline ROUNDED_RECT = RenderPipelines.register(
+ RenderPipeline.builder()
+ .withVertexFormat(ROUNDED_FORMAT, VertexFormat.Mode.QUADS)
+ .withBlend(new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA))
+ .withFragmentShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withVertexShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/rounded"))
+ .withUniform("Roundness", UniformType.UNIFORM_BUFFER)
+ .withUniform("widthHeight", UniformType.UNIFORM_BUFFER)
.build()
- ),
- RenderLayer.MultiPhaseParameters.builder().build(false)
);
- public static RenderLayer TRIANGLE_STRIP = RenderLayer.of(
- "dynamichud/triangle_strip",
- 1536,
- false,
- true,
- RenderPipelines.register(RenderPipeline.builder(RenderPipelines.POSITION_COLOR_SNIPPET)
- .withLocation(Identifier.of("dynamichud", "pipeline/triangle_strip"))
- .withVertexFormat(VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.TRIANGLE_STRIP)
- .withBlend(BlendFunction.TRANSLUCENT)
+
+ public static final RenderPipeline ROUNDED_RECT_OUTLINE = RenderPipelines.register(
+ RenderPipeline.builder()
+ .withVertexFormat(ROUNDED_FORMAT, VertexFormat.Mode.QUADS)
+ .withBlend(new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA))
+ .withFragmentShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded_outline"))
+ .withVertexShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/rounded_outline"))
+ .withUniform("Roundness", UniformType.UNIFORM_BUFFER)
+ .withUniform("widthHeight", UniformType.UNIFORM_BUFFER)
+ .withUniform("Thickness", UniformType.UNIFORM_BUFFER)
.build()
- ),
- RenderLayer.MultiPhaseParameters.builder().build(false)
);
- private static final RenderPipeline ROUNDED = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.MATRICES_COLOR_SNIPPET)
+ public static RenderPipeline QUADS_CUSTOM_BLEND = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/quad_custom_blend_func"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS)
+ .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
+ .build()
+ );
+
+ public static RenderPipeline TRIANGLE_FAN_CUSTOM_BLEND = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_fan_custom_blend_func"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_FAN)
+ .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
+ .build()
+ );
+ public static RenderPipeline TRIANGLE_STRIP = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_strip"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP)
+ .withBlend(BlendFunction.TRANSLUCENT)
+ .build()
+ );
+
+ /*
+ private static final RenderPipeline ROUNDED = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET)
.withBlend(BlendFunction.TRANSLUCENT)
.withVertexFormat(VertexFormat.builder()
.add("Position", VertexFormatElement.POSITION)
.add("UV0", VertexFormatElement.UV0)
.add("Color", VertexFormatElement.COLOR)
- .build(), VertexFormat.DrawMode.QUADS)
+ .build(), VertexFormat.Mode.QUADS)
.withCull(true)
.withColorLogic(LogicOp.NONE)
- .withFragmentShader(Identifier.of("dynamichud", "core/rounded"))
- .withVertexShader(Identifier.of("dynamichud", "core/rounded"))
- .withLocation(Identifier.of("dynamichud", "pipeline/rounded"))
- .withUniform("Roundness", UniformType.VEC4)
- .withUniform("widthHeight", UniformType.VEC2)
+ .withFragmentShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withVertexShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/rounded"))
+ .withUniform("Roundness", UniformType.UNIFORM_BUFFER)
+ .withUniform("widthHeight", UniformType.UNIFORM_BUFFER)
.build());
- private static final RenderPipeline ROUNDED_OUTLINE = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.MATRICES_COLOR_SNIPPET)
+ private static final RenderPipeline ROUNDED_OUTLINE = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET)
.withBlend(BlendFunction.TRANSLUCENT)
.withVertexFormat(VertexFormat.builder()
.add("Position", VertexFormatElement.POSITION)
.add("UV0", VertexFormatElement.UV0)
.add("Color", VertexFormatElement.COLOR)
- .build(), VertexFormat.DrawMode.QUADS)
+ .build(), VertexFormat.Mode.QUADS)
.withCull(true)
.withColorLogic(LogicOp.NONE)
- .withFragmentShader(Identifier.of("dynamichud", "core/rounded_outline"))
- .withVertexShader(Identifier.of("dynamichud", "core/rounded"))
- .withLocation(Identifier.of("dynamichud", "pipeline/rounded_outline"))
- .withUniform("Thickness", UniformType.VEC4)
+ .withFragmentShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded_outline"))
+ .withVertexShader(Identifier.fromNamespaceAndPath("dynamichud", "core/rounded"))
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/rounded_outline"))
+ .withUniform("Thickness", UniformType)
.withUniform("Roundness", UniformType.VEC4)
.withUniform("widthHeight", UniformType.VEC2)
.build());
@@ -121,14 +143,15 @@ public class CustomRenderLayers {
.build(false)
);
((IRenderLayer) rl).dynamichud$setUniform("Roundness", params.roundness);
- ((IRenderLayer) rl).dynamichud$setUniform("Thickness", new Vector4f(params.thickness,0f,0f,0f));
+ ((IRenderLayer) rl).dynamichud$setUniform("Thickness", new Vector4f(params.thickness, 0f, 0f, 0f));
((IRenderLayer) rl).dynamichud$setUniform("widthHeight", params.widthHeight);
return rl;
});
+ */
private static int getNewVertexFormatElementsId() {
- for(int id = 0; id < 32; id++) {
+ for (int id = 0; id < 32; id++) {
if (VertexFormatElement.byId(id) == null) {
return id;
}
@@ -137,6 +160,9 @@ private static int getNewVertexFormatElementsId() {
}
- public record RoundedParameters(Vector4f roundness, float[] widthHeight){}
- public record OutlineParameters(Vector4f roundness, float thickness, float[] widthHeight){}
+ public record RoundedParameters(Vector4f roundness, float[] widthHeight) {
+ }
+
+ public record OutlineParameters(Vector4f roundness, float thickness, float[] widthHeight) {
+ }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
index 4210d61..c6ae850 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
@@ -4,8 +4,8 @@
public class Util {
public static Quadrant getQuadrant(int x, int y) {
- int screenWidth = DynamicHUD.MC.getWindow().getScaledWidth();
- int screenHeight = DynamicHUD.MC.getWindow().getScaledHeight();
+ int screenWidth = DynamicHUD.MC.getWindow().getGuiScaledWidth();
+ int screenHeight = DynamicHUD.MC.getWindow().getGuiScaledHeight();
if (x < screenWidth / 2) {
if (y < screenHeight / 2) {
@@ -35,4 +35,8 @@ public static boolean warnIfTrue(boolean expression, String message, Object... o
if (expression) DynamicHUD.logger.warn(message, objects);
return expression;
}
+
+ public static boolean isSafeToContinue() {
+ return DynamicHUD.MC.getWindow() != null && DynamicHUD.MC.font != null;
+ }
}
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 48a2cf6..65da6a9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -9,9 +9,8 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
import com.tanishisherewith.dynamichud.widget.WidgetBox;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.util.math.MathHelper;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
@@ -72,7 +71,7 @@ public void addOption(Option> option) {
options.add(option);
}
- public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY) {
+ public void render(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {
if (newScreenFlag && screenFactory != null) {
DynamicHUD.MC.setScreen(screenFactory.create(this, properties));
return;
@@ -83,12 +82,12 @@ public void render(DrawContext drawContext, int x, int y, int mouseX, int mouseY
update();
if (scale <= 0.0f || newScreenFlag) return;
- DrawHelper.scaleAndPosition(drawContext.getMatrices(), x, y, scale);
+ DrawHelper.scaleAndPosition(graphics.pose(), x, y, scale);
properties.getSkin().setContextMenu(this);
- properties.getSkin().renderContextMenu(drawContext, this, mouseX, mouseY);
+ properties.getSkin().renderContextMenu(graphics, this, mouseX, mouseY);
- DrawHelper.stopScaling(drawContext.getMatrices());
+ DrawHelper.stopScaling(graphics.pose());
}
public void update() {
@@ -104,7 +103,7 @@ public void update() {
scale -= 0.1f;
}
- scale = MathHelper.clamp(scale, 0, 1.0f);
+ scale = Math.clamp(scale, 0, 1.0f);
}
public void close() {
@@ -121,7 +120,7 @@ public void close() {
public void open() {
shouldDisplay = true;
update();
- parentScreen = DynamicHUD.MC.currentScreen;
+ parentScreen = DynamicHUD.MC.screen;
if (properties.getSkin().shouldCreateNewScreen()) {
newScreenFlag = true;
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
index 70edde9..c2b05f7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuManager.java
@@ -1,7 +1,7 @@
package com.tanishisherewith.dynamichud.utils.contextmenu;
import com.tanishisherewith.dynamichud.utils.Input;
-import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.GuiGraphics;
import java.util.ArrayList;
import java.util.List;
@@ -21,11 +21,11 @@ public void registerProvider(ContextMenuProvider provider) {
providers.add(provider);
}
- public void renderAll(DrawContext drawContext, int mouseX, int mouseY) {
+ public void renderAll(GuiGraphics graphics, int mouseX, int mouseY) {
for (ContextMenuProvider provider : providers) {
ContextMenu> contextMenu = provider.getContextMenu();
if (contextMenu != null) {
- contextMenu.render(drawContext, contextMenu.getX(), contextMenu.getY(), mouseX, mouseY);
+ contextMenu.render(graphics, contextMenu.getX(), contextMenu.getY(), mouseX, mouseY);
}
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java
index 1ccfce4..eeba531 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java
@@ -3,35 +3,37 @@
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.text.Text;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.client.input.MouseButtonEvent;
+import net.minecraft.network.chat.Component;
public class ContextMenuScreen extends Screen {
ContextMenu> contextMenu;
ContextMenuProperties properties;
protected ContextMenuScreen(ContextMenu> menu, ContextMenuProperties properties) {
- super(Text.of("ContextMenu screen"));
+ super(Component.literal("ContextMenu screen"));
this.contextMenu = menu;
this.properties = properties;
}
@Override
- public void onDisplayed() {
- super.onDisplayed();
+ public void added() {
+ super.added();
contextMenu.setVisible(true);
}
@Override
- public void render(DrawContext drawContext, int mouseX, int mouseY, float delta) {
+ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
contextMenu.update();
- DrawHelper.scaleAndPosition(drawContext.getMatrices(), (float) width / 2, (float) height / 2, contextMenu.getScale());
+ DrawHelper.scaleAndPosition(graphics.pose(), (float) width / 2, (float) height / 2, contextMenu.getScale());
properties.getSkin().setContextMenu(contextMenu);
- properties.getSkin().renderContextMenu(drawContext, contextMenu, mouseX, mouseY);
+ properties.getSkin().renderContextMenu(graphics, contextMenu, mouseX, mouseY);
- DrawHelper.stopScaling(drawContext.getMatrices());
+ DrawHelper.stopScaling(graphics.pose());
if (contextMenu.getScale() <= 0 && !contextMenu.isVisible()) {
contextMenu.close();
@@ -39,48 +41,48 @@ public void render(DrawContext drawContext, int mouseX, int mouseY, float delta)
}
@Override
- protected void renderDarkening(DrawContext context) {
+ public void renderBackground(GuiGraphics guiGraphics, int i, int j, float f) {
}
@Override
- public boolean mouseClicked(double mouseX, double mouseY, int button) {
- contextMenu.mouseClicked(mouseX, mouseY, button);
- return super.mouseClicked(mouseX, mouseY, button);
+ public boolean mouseClicked(MouseButtonEvent event, boolean bl) {
+ contextMenu.mouseClicked(event.x(), event.y(), event.button());
+ return super.mouseClicked(event, bl);
}
@Override
- public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
- contextMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
- return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
+ public boolean mouseDragged(MouseButtonEvent event, double dx, double dy) {
+ contextMenu.mouseDragged(event.x(), event.y(), event.button(), dx, dy);
+ return super.mouseDragged(event, dx, dy);
}
@Override
- public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
- contextMenu.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
- return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
+ public boolean mouseScrolled(double x, double y, double horizontalAmount, double verticalAmount) {
+ contextMenu.mouseScrolled(x, y, horizontalAmount, verticalAmount);
+ return super.mouseScrolled(x, y, horizontalAmount, verticalAmount);
}
@Override
- public boolean mouseReleased(double mouseX, double mouseY, int button) {
- contextMenu.mouseReleased(mouseX, mouseY, button);
- return super.mouseReleased(mouseX, mouseY, button);
+ public boolean mouseReleased(MouseButtonEvent event) {
+ contextMenu.mouseReleased(event.x(), event.y(), event.button());
+ return super.mouseReleased(event);
}
@Override
- public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
- contextMenu.keyReleased(keyCode, scanCode, modifiers);
- return super.keyReleased(keyCode, scanCode, modifiers);
+ public boolean keyReleased(KeyEvent event) {
+ contextMenu.keyReleased(event.key(), event.scancode(), event.modifiers());
+ return super.keyReleased(event);
}
@Override
- public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
- contextMenu.keyPressed(keyCode, scanCode, modifiers);
- return super.keyPressed(keyCode, scanCode, modifiers);
+ public boolean keyPressed(KeyEvent event) {
+ contextMenu.keyPressed(event.key(), event.scancode(), event.modifiers());
+ return super.keyPressed(event);
}
@Override
- public void close() {
+ public void onClose() {
contextMenu.close();
contextMenu.setVisible(false);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java
index 6dea3ec..b66b0c7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java
@@ -2,7 +2,7 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
-import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screens.Screen;
/**
* We will use this interface to provide the context menu with the screen required by its skins.
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
index 3bd3646..3e8ee1d 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
@@ -1,6 +1,6 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen;
-import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screens.Screen;
public class ContextMenuScreenRegistry {
public Class extends Screen> screenKlass;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java
index b156347..1b0bbc9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java
@@ -2,7 +2,7 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
-import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screens.Screen;
/**
* Default implementation of the {@link ContextMenuScreenFactory} providing a {@link ContextMenuScreen}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
index fb3d782..a20ce5f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
@@ -3,27 +3,11 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
//This was supposed to be used for something bigger but that got scraped.
-public class LayoutContext {
- private final Offset indent;
- private final Option> parentOption;
-
+public record LayoutContext(Offset indent, Option> parentOption) {
public LayoutContext() {
this(Offset.zero(), null);
}
- public LayoutContext(Offset margin, Option> parentOption) {
- this.indent = margin;
- this.parentOption = parentOption;
- }
-
- public Offset getIndent() {
- return indent;
- }
-
- public Option> getParentOption() {
- return parentOption;
- }
-
// Builder-style methods for creating new contexts
public LayoutContext withIndent(Offset indent) {
return new LayoutContext(indent, this.parentOption);
@@ -57,28 +41,20 @@ public int getEffectiveHeight(int baseHeight) {
return baseHeight + indent.top;
}
- public static class Offset {
- public final int left;
- public final int top;
-
- public Offset(int all) {
- this(all, all);
- }
-
- public Offset(int horizontal, int vertical) {
- this.left = horizontal;
- this.top = vertical;
- }
+ public record Offset(int left, int top) {
+ public Offset(int all) {
+ this(all, all);
+ }
public static Offset zero() {
- return new Offset(0);
+ return new Offset(0);
+ }
+
+ public Offset add(Offset other) {
+ return new Offset(
+ this.left + other.left,
+ this.top + other.top
+ );
+ }
}
-
- public Offset add(Offset other) {
- return new Offset(
- this.left + other.left,
- this.top + other.top
- );
- }
- }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
index d5f3b55..a4764d8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
@@ -1,8 +1,8 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.options;
import com.tanishisherewith.dynamichud.utils.BooleanPool;
-import net.minecraft.screen.ScreenTexts;
-import net.minecraft.text.Text;
+import net.minecraft.network.chat.CommonComponents;
+import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW;
import java.util.function.Consumer;
@@ -12,21 +12,21 @@
public class BooleanOption extends Option {
private final BooleanType booleanType;
- public BooleanOption(Text name, Supplier getter, Consumer setter, BooleanType booleanType) {
+ public BooleanOption(Component name, Supplier getter, Consumer setter, BooleanType booleanType) {
super(name, getter, setter);
this.booleanType = booleanType;
this.renderer.init(this);
}
- public BooleanOption(Text name, Supplier getter, Consumer setter) {
+ public BooleanOption(Component name, Supplier getter, Consumer setter) {
this(name, getter, setter, BooleanType.TRUE_FALSE);
}
- public BooleanOption(Text name, boolean defaultValue) {
+ public BooleanOption(Component name, boolean defaultValue) {
this(name, defaultValue, BooleanType.TRUE_FALSE);
}
- public BooleanOption(Text name, boolean defaultValue, BooleanType type) {
+ public BooleanOption(Component name, boolean defaultValue, BooleanType type) {
this(name, () -> BooleanPool.get(name.getString()), value -> BooleanPool.put(name.getString(), value), type);
BooleanPool.put(name.getString(), defaultValue);
}
@@ -46,17 +46,17 @@ public BooleanType getBooleanType() {
}
public enum BooleanType {
- ON_OFF(ScreenTexts::onOrOff),
- TRUE_FALSE(aBoolean -> aBoolean ? Text.of("True") : Text.of("False")),
- YES_NO(aBoolean -> aBoolean ? ScreenTexts.YES : ScreenTexts.NO);
+ ON_OFF(aBoolean -> aBoolean ? CommonComponents.OPTION_ON : CommonComponents.OPTION_OFF),
+ TRUE_FALSE(aBoolean -> aBoolean ? Component.literal("True") : Component.literal("False")),
+ YES_NO(aBoolean -> aBoolean ? CommonComponents.GUI_YES : CommonComponents.GUI_NO);
- private final Function function;
+ private final Function function;
- BooleanType(Function function) {
+ BooleanType(Function function) {
this.function = function;
}
- public Text getText(boolean val) {
+ public Component getText(boolean val) {
return function.apply(val);
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
index 9471f7c..c0f341d 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ColorOption.java
@@ -2,7 +2,7 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption.ColorGradient;
-import net.minecraft.text.Text;
+import net.minecraft.network.chat.Component;
import java.awt.*;
import java.util.function.Consumer;
@@ -13,7 +13,7 @@ public class ColorOption extends Option {
private ContextMenu> parentMenu = null;
private ColorGradient colorGradient = null;
- public ColorOption(Text name, Supplier getter, Consumer setter, ContextMenu> parentMenu) {
+ public ColorOption(Component name, Supplier getter, Consumer setter, ContextMenu> parentMenu) {
super(name, getter, setter);
this.parentMenu = parentMenu;
this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
index 27d8ec6..14208f4 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/DoubleOption.java
@@ -2,8 +2,8 @@
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.text.Text;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
import org.apache.commons.lang3.Validate;
import org.lwjgl.glfw.GLFW;
@@ -18,7 +18,7 @@ public class DoubleOption extends Option {
ContextMenu> parentMenu;
private boolean isDragging = false;
- public DoubleOption(Text name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu> parentMenu) {
+ public DoubleOption(Component name, double minValue, double maxValue, float step, Supplier getter, Consumer setter, ContextMenu> parentMenu) {
super(name, getter, setter);
this.value = get();
this.minValue = minValue;
@@ -31,10 +31,10 @@ public DoubleOption(Text name, double minValue, double maxValue, float step, Sup
this.renderer.init(this);
}
- public void drawSlider(DrawContext drawContext, int sliderX, int sliderY, int sliderWidth, double handleX) {
- DrawHelper.drawRectangle(drawContext, sliderX, sliderY, sliderWidth, 2, 0xFFFFFFFF);
+ public void drawSlider(GuiGraphics graphics, int sliderX, int sliderY, int sliderWidth, double handleX) {
+ DrawHelper.drawRectangle(graphics, sliderX, sliderY, sliderWidth, 2, 0xFFFFFFFF);
if (handleX - sliderX > 0) {
- DrawHelper.drawRectangle(drawContext, (float) sliderX, (float) sliderY, (float) ((value - minValue) / (maxValue - minValue) * (width - 3)), 2, Color.ORANGE.getRGB());
+ DrawHelper.drawRectangle(graphics, (float) sliderX, (float) sliderY, (float) ((value - minValue) / (maxValue - minValue) * (width - 3)), 2, Color.ORANGE.getRGB());
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
index 1eab358..f71cee2 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
@@ -1,6 +1,6 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.options;
-import net.minecraft.text.Text;
+import net.minecraft.network.chat.Component;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -9,7 +9,7 @@ public class EnumOption> extends Option {
private final E[] values;
private int currentIndex = 0;
- public EnumOption(Text name, Supplier getter, Consumer setter, E[] values) {
+ public EnumOption(Component name, Supplier getter, Consumer setter, E[] values) {
super(name, getter, setter);
this.values = values;
this.value = get();
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
index d407242..d948664 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
@@ -1,6 +1,6 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.options;
-import net.minecraft.text.Text;
+import net.minecraft.network.chat.Component;
import java.util.List;
import java.util.function.Consumer;
@@ -10,7 +10,7 @@ public class ListOption extends Option {
private final List values;
private int currentIndex = 0;
- public ListOption(Text name, Supplier getter, Consumer setter, List values) {
+ public ListOption(Component name, Supplier getter, Consumer setter, List values) {
super(name, getter, setter);
this.values = values;
this.value = getter.get();
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
index be4bf94..137b4c6 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
@@ -5,15 +5,15 @@
import com.tanishisherewith.dynamichud.utils.Input;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.text.Text;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.network.chat.Component;
import java.util.function.Consumer;
import java.util.function.Supplier;
public abstract class Option implements Input {
- public Text name, description = Text.empty();
+ public Component name, description = Component.empty();
public T value = null;
protected int x, y;
protected int width = 0;
@@ -22,16 +22,16 @@ public abstract class Option implements Input {
protected Supplier getter;
protected Consumer setter;
protected T defaultValue = null;
- protected MinecraftClient mc = MinecraftClient.getInstance();
+ protected Minecraft mc = Minecraft.getInstance();
protected ContextMenuProperties properties;
protected SkinRenderer
*
- * @param context DrawContext Object
+ * @param graphics GuiGraphics Object
* @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(GuiGraphics graphics, int mouseX, int mouseY);
/**
* Renders the widget in the editor screen with a background.
* Override this method without super call to remove the background.
* Could also be used to display placeholder values.
*/
- private void renderWidgetInEditor(DrawContext context, int mouseX, int mouseY) {
- //drawWidgetBackground(context);
+ private void renderWidgetInEditor(GuiGraphics graphics, int mouseX, int mouseY) {
+ //drawWidgetBackground(graphics);
- renderWidget(context, mouseX, mouseY);
+ renderWidget(graphics, mouseX, mouseY);
}
@Override
@@ -233,8 +232,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
/* Input related methods. Override with **super call** to add your own input-based code like contextMenu */
public void clampPosition() {
- this.x = (int) MathHelper.clamp(this.x, 0, mc.getWindow().getScaledWidth() - getWidth());
- this.y = (int) MathHelper.clamp(this.y, 0, mc.getWindow().getScaledHeight() - getHeight());
+ this.x = (int) org.joml.Math.clamp(this.x, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
+ this.y = (int) org.joml.Math.clamp(this.y, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
}
@Override
@@ -252,8 +251,8 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
// Higher the snapSize, more the grid boxes
if (this.isShiftDown) {
// Calculate the size of each snap box
- int snapBoxWidth = mc.getWindow().getScaledWidth() / snapSize;
- int snapBoxHeight = mc.getWindow().getScaledHeight() / snapSize;
+ int snapBoxWidth = mc.getWindow().getGuiScaledWidth() / snapSize;
+ int snapBoxHeight = mc.getWindow().getGuiScaledHeight() / 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
@@ -261,10 +260,10 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
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.x = (int) org.joml.Math.clamp(newX, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
+ this.y = (int) org.joml.Math.clamp(newY, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
- calculateOffset(x, y, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); // Set initial offset
+ calculateOffset(x, y, mc.getWindow().getGuiScaledWidth(), mc.getWindow().getGuiScaledHeight()); // Set initial offset
return true;
}
@@ -311,11 +310,11 @@ public void onClose() {
* Displays a faint grayish background if enabled or faint reddish background if disabled.
* Drawn with 2 pixel offset to all sides
*/
- protected void drawWidgetBackground(DrawContext context) {
+ protected void drawWidgetBackground(GuiGraphics graphics) {
int backgroundColor = this.isVisible() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB();
WidgetBox box = this.getWidgetBox();
- DrawHelper.drawRectangle(context,
+ DrawHelper.drawRectangle(graphics,
box.x,
box.y,
box.getWidth(),
@@ -324,13 +323,13 @@ protected void drawWidgetBackground(DrawContext context) {
}
/**
- * Set the tooltip text of the widget
+ * Set the tooltip Component of the widget
*/
- protected void setTooltipText(Text text) {
- this.tooltipText = text;
+ protected void setTooltipText(Component Component) {
+ this.tooltipText = Component;
}
- public void readFromTag(NbtCompound tag) {
+ public void readFromTag(CompoundTag tag) {
modId = tag.getString("modId").orElse("unknown");
uid = tag.contains("UID") ? new UID(tag.getString("UID").get()) : UID.generate();
// x = tag.getInt("x");
@@ -348,7 +347,7 @@ public void readFromTag(NbtCompound tag) {
*
* @param tag The tag to write to
*/
- public void writeToTag(NbtCompound tag) {
+ public void writeToTag(CompoundTag tag) {
tag.putString("name", DATA.name());
tag.putString("modId", modId);
tag.putString("UID", uid.getUniqueID());
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
index 1f0f05e..1e1aab6 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetManager.java
@@ -2,10 +2,9 @@
import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.mixins.ScreenMixin;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.NbtElement;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
-import net.minecraft.nbt.NbtList;
import java.io.DataOutputStream;
import java.io.File;
@@ -128,8 +127,8 @@ 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 {
- NbtCompound rootTag = new NbtCompound();
- NbtList widgetList = new NbtList();
+ CompoundTag rootTag = new CompoundTag();
+ ListTag widgetList = new ListTag();
printInfo("Saving widgets");
@@ -140,7 +139,7 @@ public static void saveWidgets(File file, List widgets) throws IOExcepti
Set widgetSet = new HashSet<>();
for (Widget widget : widgets) {
- NbtCompound widgetTag = new NbtCompound();
+ CompoundTag widgetTag = new CompoundTag();
//I faced this exception once and had to spend 10 minutes trying to find it. P.S. It leaves 0 stacktrace message
try {
widget.writeToTag(widgetTag);
@@ -190,20 +189,20 @@ public static List loadWidgets(File file) throws IOException {
file = new File(file.getAbsolutePath() + ".backup");
}
- NbtCompound rootTag = NbtIo.read(file.toPath());
+ CompoundTag rootTag = NbtIo.read(file.toPath());
if (rootTag == null) {
printWarn("RootTag is null. File is either empty or corrupted: " + file);
return Collections.emptyList();
}
- NbtList widgetList = rootTag.getList("widgets").orElse(null);
+ ListTag widgetList = rootTag.getList("widgets").orElse(null);
if (widgetList == null) {
printWarn("WidgetList is null. File is empty: " + file);
return Collections.emptyList();
}
List widgetsToAdd = new ArrayList<>();
for (int i = 0; i < widgetList.size(); i++) {
- NbtCompound widgetTag = widgetList.getCompound(i).orElse(null);
+ CompoundTag widgetTag = widgetList.getCompound(i).orElse(null);
if(widgetTag == null) continue;
WidgetData> widgetData = widgetDataMap.get(widgetTag.getString("name").orElse("unknown"));
if (widgetData == null) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
index d0bc2f1..cd6df72 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
@@ -6,10 +6,9 @@
import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen;
import com.tanishisherewith.dynamichud.utils.Input;
import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry;
-import dev.isxander.yacl3.gui.YACLScreen;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.GameMenuScreen;
-import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.PauseScreen;
+import net.minecraft.client.gui.screens.Screen;
import org.lwjgl.glfw.GLFW;
import java.util.List;
@@ -21,19 +20,19 @@ public class WidgetRenderer implements Input {
public Widget selectedWidget = null;
List widgets;
private boolean renderInGameHud = true;
- private int Z_Index = -1;
+ //private int Z_Index = -1;
/**
* 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.
+ * By default, it adds the {@link PauseScreen} 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;
// Render in GameMenuScreen
- this.allowedScreens = screen -> screen.getClass() == GameMenuScreen.class ||
+ this.allowedScreens = screen -> screen.getClass() == PauseScreen.class ||
System.getInstances(ContextMenuScreenRegistry.class, DynamicHUD.MOD_ID).stream().anyMatch(registry -> registry.screenKlass == screen.getClass());
}
@@ -88,22 +87,22 @@ private boolean renderInDebugScreen() {
if (GlobalConfig.get().renderInDebugScreen()) {
return true;
}
- return !DynamicHUD.MC.getDebugHud().shouldShowDebugHud();
+ return !DynamicHUD.MC.getDebugOverlay().showDebugScreen();
}
- public void renderWidgets(DrawContext context, int mouseX, int mouseY) {
+ public void renderWidgets(GuiGraphics graphics, int mouseX, int mouseY) {
if (WidgetManager.getWidgets().isEmpty() || !renderInDebugScreen()) return;
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
- context.getMatrices().push();
- context.getMatrices().translate(0, 0, Z_Index);
+ // graphics.pose().pushMatrix();
+ // graphics.pose().translate(0, 0,Z_Index);
//Render in editing screen
if (currentScreen instanceof AbstractMoveableScreen) {
for (Widget widget : widgets) {
widget.isInEditor = true;
- widget.renderInEditor(context, mouseX, mouseY);
+ widget.renderInEditor(graphics, mouseX, mouseY);
}
return;
}
@@ -111,15 +110,15 @@ public void renderWidgets(DrawContext context, int mouseX, int mouseY) {
if ((currentScreen == null && renderInGameHud) || allowedScreens.test(currentScreen)) {
for (Widget widget : widgets) {
widget.isInEditor = false;
- widget.render(context, 0, 0);
+ widget.render(graphics, 0, 0);
}
}
- context.getMatrices().pop();
+ //graphics.pose().popMatrix();
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen == null) {
return false;
}
@@ -139,7 +138,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
@Override
public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen == null) {
return;
}
@@ -155,7 +154,7 @@ public void charTyped(char c, int modifiers) {
}
public void onCloseScreen() {
- if (DynamicHUD.MC.currentScreen instanceof AbstractMoveableScreen) {
+ if (DynamicHUD.MC.screen instanceof AbstractMoveableScreen) {
for (Widget widget : widgets) {
widget.onClose();
}
@@ -168,7 +167,7 @@ public List getWidgets() {
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen == null) {
return false;
}
@@ -186,7 +185,7 @@ public final boolean mouseDragged(double mouseX, double mouseY, int button, doub
}
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY, int snapSize) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen == null) {
return false;
}
@@ -206,7 +205,7 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
@Override
public void keyPressed(int key, int scanCode, int modifiers) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen instanceof AbstractMoveableScreen && (key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT)) {
for (Widget widget : widgets) {
widget.isShiftDown = true;
@@ -216,7 +215,7 @@ public void keyPressed(int key, int scanCode, int modifiers) {
@Override
public void keyReleased(int key, int scanCode, int modifiers) {
- Screen currentScreen = DynamicHUD.MC.currentScreen;
+ Screen currentScreen = DynamicHUD.MC.screen;
if (currentScreen instanceof AbstractMoveableScreen && (key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT)) {
for (Widget widget : widgets) {
widget.isShiftDown = false;
@@ -224,8 +223,8 @@ public void keyReleased(int key, int scanCode, int modifiers) {
}
}
- public WidgetRenderer withZIndex(int z_Index) {
- this.Z_Index = z_Index;
- return this;
- }
+ // public WidgetRenderer withZIndex(int z_Index) {
+ // this.Z_Index = z_Index;
+ // return this;
+ // }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index e2e0d44..574ae6c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -3,9 +3,11 @@
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
-import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations;
+import com.tanishisherewith.dynamichud.renderstates.GradientShadowRenderState;
+import com.tanishisherewith.dynamichud.renderstates.InterpolatedCurveRenderState;
import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
+import com.tanishisherewith.dynamichud.utils.Util;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
@@ -18,12 +20,11 @@
import com.tanishisherewith.dynamichud.widget.WidgetBox;
import com.tanishisherewith.dynamichud.widget.WidgetData;
import com.twelvemonkeys.lang.Validate;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.render.VertexConsumer;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.text.Text;
-import net.minecraft.util.math.MathHelper;
-import org.joml.Matrix4f;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.render.TextureSetup;
+import net.minecraft.client.renderer.RenderPipelines;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.chat.Component;
import java.awt.*;
import java.util.ArrayList;
@@ -86,10 +87,11 @@ private void internal_init() {
this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
this.stepY = height / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
- this.scale = (float) MathHelper.clamp((stepY / 9.5), 0.0f, 1.0f);
+ this.scale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
+
computeOffset();
- setTooltipText(Text.of("Graph displaying: " + label));
+ setTooltipText(Component.literal("Graph displaying: " + label));
}
public GraphWidget() {
@@ -126,7 +128,7 @@ public void addDataPoint(Float value) {
}
int index = (head) % maxDataPoints;
- dataPoints[index] = MathHelper.clamp(value, minValue, maxValue);
+ dataPoints[index] = Math.clamp(value, minValue, maxValue);
head = (head + 1) % maxDataPoints; // Buffer full, overwrite oldest and move head
}
@@ -161,53 +163,26 @@ private List getInterpolatedPoints() {
}
// draw a continuous interpolated curve
- private void drawInterpolatedCurve(DrawContext drawContext, List points, int color, float thickness) {
+ private void drawInterpolatedCurve(GuiGraphics graphics, List points, int color, float thickness) {
if (points.size() < 2) return;
- drawContext.draw(vcp -> {
- Matrix4f matrix = drawContext.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(CustomRenderLayers.TRIANGLE_STRIP);
-
- for (int i = 0; i < points.size(); i++) {
- float[] point = points.get(i);
- float x = point[0];
- float y = point[1];
-
- // Create a thick line by offsetting vertices perpendicular to the curve
- float dx = (i < points.size() - 1) ? points.get(i + 1)[0] - x : x - points.get(i - 1)[0];
- float dy = (i < points.size() - 1) ? points.get(i + 1)[1] - y : y - points.get(i - 1)[1];
- float length = (float) Math.sqrt(dx * dx + dy * dy);
- if (length == 0) continue;
-
- float offsetX = (thickness * 0.5f * dy) / length;
- float offsetY = (thickness * 0.5f * -dx) / length;
-
- consumer.vertex(matrix, x + offsetX, y + offsetY, 0).color(color);
- consumer.vertex(matrix, x - offsetX, y - offsetY, 0).color(color);
- }
- });
+ graphics.guiRenderState.submitGuiElement(
+ new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.QUADS_CUSTOM_BLEND, graphics.scissorStack.peek())
+ );
}
+
// draw a gradient shadow under the curve
- private void drawGradientShadow(DrawContext context, List points, float bottomY, int startColor, int endColor) {
+ private void drawGradientShadow(GuiGraphics graphics, List points, float bottomY, int startColor, int endColor) {
if (points.size() < 2) return;
- context.draw(vcp -> {
- Matrix4f matrix = context.getMatrices().peek().getPositionMatrix();
- VertexConsumer consumer = vcp.getBuffer(CustomRenderLayers.TRIANGLE_STRIP);
-
- for (float[] point : points) {
- float x = point[0];
- float y = point[1];
-
- consumer.vertex(matrix, x, y, 0).color(startColor);
- consumer.vertex(matrix, x, bottomY, 0).color(endColor);
- }
- });
+ graphics.guiRenderState.submitGuiElement(
+ new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, graphics.scissorStack.peek())
+ );
}
@Override
- public void renderWidget(DrawContext context, int mouseX, int mouseY) {
+ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
if (valueSupplier != null) {
addDataPoint(getValue());
}
@@ -217,12 +192,12 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
if(graphColorRainbow) graphColor = ColorHelper.getRainbowColor(100);
- DrawHelper.enableScissor(widgetBox);
+ // DrawHelper.enableScissor(widgetBox);
// Draw gradient background with rounded.fsh corners
if (!isInEditor) {
DrawHelper.drawRoundedRectangle(
- context,
+ graphics,
x + offset,
y,
false,
@@ -242,18 +217,18 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
for (int i = 1; i <= gridLines; i++) {
float yPos = y + stepY * i;
- DrawHelper.drawHorizontalLine(context, x + offset, width, yPos, 0.5f, 0x4DFFFFFF); // Semi-transparent white
+ DrawHelper.drawHorizontalLine(graphics, x + offset, width, yPos, 0.5f, 0x4DFFFFFF); // Semi-transparent white
// Draw value labels on the left axis
float value = maxValue - (i * valueStep);
String valueText = formatValue(value);
- float texWidth = mc.textRenderer.getWidth(valueText) * scale;
+ float texWidth = mc.font.width(valueText) * scale;
- //Scale the text to its proper position and size with grid lines
- DrawHelper.scaleAndPosition(context.getMatrices(), x - 2, yPos, scale);
- context.drawText(mc.textRenderer, valueText, Math.round(x + offset - texWidth), (int) (yPos - (mc.textRenderer.fontHeight * scale) / 2.0f), 0xFFFFFFFF, true);
- DrawHelper.stopScaling(context.getMatrices());
+ //Scale the Component to its proper position and size with grid lines
+ DrawHelper.scaleAndPosition(graphics.pose(), x - 2, yPos, scale);
+ graphics.drawString(mc.font, valueText, Math.round(x + offset - texWidth), (int) (yPos - (mc.font.lineHeight * scale) / 2.0f), 0xFFFFFFFF, true);
+ DrawHelper.stopScaling(graphics.pose());
}
// Update the offsets for the rest of the elements drawn.
@@ -263,50 +238,49 @@ public void renderWidget(DrawContext context, int mouseX, int mouseY) {
float stepX = width / 5; // 5 vertical lines
for (int i = 1; i < 5; i++) {
float xPos = x + stepX * i;
- DrawHelper.drawVerticalLine(context, xPos, y, height, 0.5f, 0x4DFFFFFF);
+ DrawHelper.drawVerticalLine(graphics, xPos, y, height, 0.5f, 0x4DFFFFFF);
}
}
// Draw interpolated graph curve
List points = getInterpolatedPoints();
- drawInterpolatedCurve(context, points, graphColor.getRGB(), lineThickness);
+ drawInterpolatedCurve(graphics, points, graphColor.getRGB(), lineThickness);
// Draw shadow effect under the graph
drawGradientShadow(
- context, points, y + height,
+ graphics, points, y + height,
ColorHelper.changeAlpha(graphColor, 50).getRGB(),
0x00000000
);
-
DrawHelper.drawChromaText(
- context, label,
+ graphics, label,
x + 5, y + 5,
1.0f, 0.8f, 1.0f, 0.05f, true
);
// Draw axes
- DrawHelper.drawHorizontalLine(context, x, width, y + height - 1, 1.0f, 0xFFFFFFFF); // X-axis
- DrawHelper.drawVerticalLine(context, x, y, height, 1.0f, 0xFFFFFFFF); // Y-axis
+ DrawHelper.drawHorizontalLine(graphics, x, width, y + height - 1, 1.0f, 0xFFFFFFFF); // X-axis
+ DrawHelper.drawVerticalLine(graphics, x, y, height, 1.0f, 0xFFFFFFFF); // Y-axis
// Draw min and max value labels with formatted values
/*
DrawHelper.scaleAndPosition(context.getMatrices(),x - 5,y,0.5f);
String formattedMaxVal = formatValue(maxValue);
- context.drawText(mc.textRenderer, formattedMaxVal, x - 5 - mc.textRenderer.getWidth(formattedMaxVal), y - 4, 0xFFFFFFFF, true);
+ context.drawText(mc.font, formattedMaxVal, x - 5 - mc.font.width(formattedMaxVal), y - 4, 0xFFFFFFFF, true);
DrawHelper.stopScaling(context.getMatrices());
*/
- DrawHelper.scaleAndPosition(context.getMatrices(), x - 5, y + height, 0.5f);
+ DrawHelper.scaleAndPosition(graphics.pose(), x - 5, y + height, 0.5f);
String formattedMinVal = formatValue(minValue);
- context.drawText(mc.textRenderer, formattedMinVal, x - mc.textRenderer.getWidth(formattedMinVal), (int) (y + height - 4), 0xFFFFFFFF, true);
- DrawHelper.stopScaling(context.getMatrices());
+ graphics.drawString(mc.font, formattedMinVal, x - mc.font.width(formattedMinVal), (int) (y + height - 4), 0xFFFFFFFF, true);
+ DrawHelper.stopScaling(graphics.pose());
if(showGrid) x -= offset;
this.widgetBox.setDimensions(x, y, width + offset, height, shouldScale, GlobalConfig.get().getScale());
- DrawHelper.disableScissor();
+ // DrawHelper.disableScissor();
if (menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
}
@@ -332,12 +306,12 @@ public void createMenu() {
ContextMenuProperties properties = ContextMenuProperties.builder().build();
menu = new ContextMenu<>(getX(), (int) (getY() + widgetBox.getHeight()), properties);
- menu.addOption(new BooleanOption(Text.of("Show Grid"),
+ menu.addOption(new BooleanOption(Component.literal("Show Grid"),
() -> this.showGrid, value -> this.showGrid = value,
BooleanOption.BooleanType.YES_NO)
- .description(Text.of("Shows a grid and Y axis values"))
+ .description(Component.literal("Shows a grid and Y axis values"))
);
- menu.addOption(new DoubleOption(Text.of("Number of Grid Lines"),
+ menu.addOption(new DoubleOption(Component.literal("Number of Grid Lines"),
1, 25, 1,
() -> (double) this.gridLines, value -> {
this.setGridLines(value.intValue());
@@ -345,36 +319,35 @@ public void createMenu() {
}, menu)
.renderWhen(() -> this.showGrid)
);
- menu.addOption(new ColorOption(Text.of("Graph Line Color"),
+ menu.addOption(new ColorOption(Component.literal("Graph Line Color"),
() -> this.graphColor, value -> this.graphColor = value, menu)
- .description(Text.of("Specify the color you want for the graph's lines"))
+ .description(Component.literal("Specify the color you want for the graph's lines"))
);
- menu.addOption(new BooleanOption(Text.of("Rainbow Graph Line Color"),
+ menu.addOption(new BooleanOption(Component.literal("Rainbow Graph Line Color"),
() -> this.graphColorRainbow, value -> this.graphColorRainbow = value)
- .description(Text.of("Color your graph line with funny rainbow"))
+ .description(Component.literal("Color your graph line with funny rainbow"))
.withComplexity(Option.Complexity.Pro)
);
- menu.addOption(new ColorOption(Text.of("Graph Background Color"),
+ menu.addOption(new ColorOption(Component.literal("Graph Background Color"),
() -> this.backgroundColor, value -> this.backgroundColor = value, menu)
- .description(Text.of("Specify the color you want for the graph's background"))
+ .description(Component.literal("Specify the color you want for the graph's background"))
);
- menu.addOption(new DoubleOption(Text.of("Line Thickness"),
+ menu.addOption(new DoubleOption(Component.literal("Line Thickness"),
0.5f, 5.0f, 0.1f,
() -> (double) this.lineThickness, value -> this.lineThickness = value.floatValue(), menu)
);
}
private void computeOffset(){
- // The first text is usually the largest but a negative value may occupy more width so we check the first and last text.
+ // The first Component is usually the largest but a negative value may occupy more width so we check the first and last Component.
// Idk how this will break.
- if(mc.textRenderer == null) return;
String firstText = formatValue(maxValue - valueStep);
String lastText = formatValue(maxValue - (gridLines * valueStep));
offset = Math.max(
- (int) Math.ceil(mc.textRenderer.getWidth(firstText) * this.scale),
- (int) Math.ceil(mc.textRenderer.getWidth(lastText) * this.scale)
+ (int) Math.ceil(mc.font.width(firstText) * this.scale),
+ (int) Math.ceil(mc.font.width(lastText) * this.scale)
);
}
@@ -456,7 +429,7 @@ public void setGridLines(int gridLines) {
this.gridLines = gridLines;
this.stepY = height / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
- this.scale = (float) MathHelper.clamp((stepY / 9.5), 0.0f, 1.0f);
+ this.scale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
}
public boolean isShowGrid() {
@@ -490,7 +463,7 @@ public void onClose() {
}
@Override
- public void writeToTag(NbtCompound tag) {
+ public void writeToTag(CompoundTag tag) {
super.writeToTag(tag);
tag.putFloat("width", width);
tag.putFloat("height", height);
@@ -508,7 +481,7 @@ public void writeToTag(NbtCompound tag) {
}
@Override
- public void readFromTag(NbtCompound tag) {
+ public void readFromTag(CompoundTag tag) {
super.readFromTag(tag);
this.width = tag.getFloat("width").orElse(100f);
this.height = tag.getFloat("height").orElse(50f);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
index 9140d2c..48bd7ac 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
@@ -3,10 +3,10 @@
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.widget.Widget;
import com.tanishisherewith.dynamichud.widget.WidgetData;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NbtCompound;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
/**
* This is just an example widget, not supposed to be used.
@@ -25,21 +25,21 @@ public ItemWidget() {
}
@Override
- public void renderWidget(DrawContext context, int mouseX, int mouseY) {
- context.drawItem(item, x, y);
+ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
+ graphics.renderItem(item, x, y);
widgetBox.setDimensions(getX(), getY(), 16, 16, this.shouldScale, GlobalConfig.get().getScale());
}
@Override
- public void writeToTag(NbtCompound tag) {
+ public void writeToTag(CompoundTag tag) {
super.writeToTag(tag);
- tag.putInt("ItemID", Item.getRawId(item.getItem()));
+ tag.putInt("ItemID", Item.getId(item.getItem()));
}
@Override
- public void readFromTag(NbtCompound tag) {
+ public void readFromTag(CompoundTag tag) {
super.readFromTag(tag);
- item = Item.byRawId(tag.getInt("ItemID").orElse(0)).getDefaultStack();
+ item = Item.byId(tag.getInt("ItemID").orElse(0)).getDefaultInstance();
}
public void setItemStack(ItemStack item) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index f85a8d7..a286d51 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -8,21 +8,28 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ModernSkin;
import com.tanishisherewith.dynamichud.widget.DynamicValueWidget;
import com.tanishisherewith.dynamichud.widget.WidgetData;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.nbt.NbtCompound;
-import net.minecraft.text.Text;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.chat.Component;
+import javax.swing.*;
import java.awt.Color;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
public class TextWidget extends DynamicValueWidget implements ContextMenuProvider {
- public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Text on screen", TextWidget::new);
+ public static WidgetData DATA = new WidgetData<>("TextWidget", "Display Component on screen", TextWidget::new);
private ContextMenu> menu;
public Color textColor;
- protected boolean shadow; // Whether to draw a shadow behind the text
- protected boolean rainbow; // Whether to apply a rainbow effect to the text
+ protected boolean shadow; // Whether to draw a shadow behind the Component
+ protected boolean rainbow; // Whether to apply a rainbow effect to the Component
protected int rainbowSpeed = 2; //Speed of the rainbow effect
protected float rainbowSpread = 0.01f, rainbowSaturation = 1.0f, rainbowBrightness = 1.0f;
@@ -44,62 +51,98 @@ public TextWidget(String registryID, String registryKey, boolean shadow, boolean
}
public void createMenu() {
- menu = new ContextMenu<>(getX(), getY(),ContextMenuProperties.createGenericSimplified());
+ menu = new ContextMenu<>(getX(), getY(),ContextMenuProperties.builder().skin(new ModernSkin()).build());
- menu.addOption(new BooleanOption(Text.of("Shadow"),
+ menu.addOption(new BooleanOption(Component.literal("Shadow"),
() -> this.shadow, value -> this.shadow = value,
BooleanOption.BooleanType.ON_OFF)
- .description(Text.of("Adds shadow to your text"))
+ .description(Component.literal("Adds shadow to your Component"))
);
- menu.addOption(new BooleanOption(Text.of("Rainbow"),
+ menu.addOption(new BooleanOption(Component.literal("Rainbow"),
() -> this.rainbow, value -> this.rainbow = value,
BooleanOption.BooleanType.ON_OFF)
- .description(Text.of("Adds rainbow effect to your text"))
+ .description(Component.literal("Adds rainbow effect to your Component"))
);
- menu.addOption(new ColorOption(Text.of("Text Color"),
+ menu.addOption(new ColorOption(Component.literal("Component Color"),
() -> this.textColor, value -> this.textColor = value, menu)
- .description(Text.of("Specify the color you want to add to your text"))
+ .description(Component.literal("Specify the color you want to add to your Component"))
.renderWhen(() -> !this.rainbow)
);
- menu.addOption(new DoubleOption(Text.of("Rainbow Speed"),
+ menu.addOption(new DoubleOption(Component.literal("Rainbow Speed"),
1, 5.0f, 1,
() -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu)
.renderWhen(() -> this.rainbow)
);
- menu.addOption(new DoubleOption(Text.of("Rainbow Spread"),
+ menu.addOption(new DoubleOption(Component.literal("Rainbow Spread"),
0.001f, 0.15f, 0.001f,
() -> (double) this.rainbowSpread, value -> this.rainbowSpread = value.floatValue(), menu)
.renderWhen(() -> this.rainbow)
.withComplexity(Option.Complexity.Enhanced)
);
- menu.addOption(new DoubleOption(Text.of("Rainbow Saturation"),
+ menu.addOption(new DoubleOption(Component.literal("Rainbow Saturation"),
0, 1.0f, 0.1f,
() -> (double) this.rainbowSaturation, value -> this.rainbowSaturation = value.floatValue(), menu)
.renderWhen(() -> this.rainbow)
.withComplexity(Option.Complexity.Pro)
);
- menu.addOption(new DoubleOption(Text.of("Rainbow Brightness"),
+ menu.addOption(new DoubleOption(Component.literal("Rainbow Brightness"),
0, 1.0f, 0.01f,
() -> (double) this.rainbowBrightness, value -> this.rainbowBrightness = value.floatValue(), menu)
.renderWhen(() -> this.rainbow)
.withComplexity(Option.Complexity.Pro)
);
+ // Runnable Option
+ AtomicBoolean ran = new AtomicBoolean(false);
+ menu.addOption(new RunnableOption(Component.literal("Reset Position"),
+ ran::get, ran::set,
+ () -> this.setPosition(0, 0))
+ .description(Component.literal("Reset widget to default position")));
+
+ // List Option
+ AtomicReference style = new AtomicReference<>("Style1");
+ List styles = Arrays.asList("Style1", "Style2", "Style3");
+ menu.addOption(new ListOption<>(Component.literal("Text Style"),
+ style::get, style::set, styles)
+ .description(Component.literal("Choose a text style")));
+
+ // Enum Option
+ menu.addOption(new EnumOption<>(Component.literal("Alignment"),
+ () -> GroupLayout.Alignment.CENTER, value -> {}, GroupLayout.Alignment.values())
+ .description(Component.literal("Set text alignment")));
+
+ // Option Group
+ OptionGroup group = new OptionGroup(Component.literal("Display Options"));
+ group.addOption(new BooleanOption(Component.literal("Bold Text"),
+ () -> false, value -> {}, BooleanOption.BooleanType.YES_NO)
+ .description(Component.literal("Enable bold text")));
+ group.addOption(new DoubleOption(Component.literal("Font Size"),
+ 8.0, 24.0, 1.0f,
+ () -> 12.0, value -> {}, menu)
+ .description(Component.literal("Adjust font size")));
+ menu.addOption(group);
+
+ // SubMenu Option
+ SubMenuOption subMenu = (SubMenuOption) new SubMenuOption(Component.literal("Advanced Settings"), menu)
+ .description(Component.literal("Open advanced settings"));
+ subMenu.getSubMenu().addOption(new BooleanOption(Component.literal("Some Boolean"),
+ () -> false, value -> {}, BooleanOption.BooleanType.TRUE_FALSE)
+ .description(Component.literal("True/False")));
+ menu.addOption(subMenu);
}
@Override
- public void renderWidget(DrawContext drawContext, int mouseX, int mouseY) {
+ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
if (menu == null) return;
//int color = rainbow ? ColorHelper.getColorFromHue((System.currentTimeMillis() % (5000 * rainbowSpeed) / (5000f * rainbowSpeed))) : textColor.getRGB();
int color = textColor.getRGB();
if (valueSupplier != null) {
- String text = getValue();
+ String Component = getValue();
if (rainbow) {
- DrawHelper.drawChromaText(drawContext, text, getX() + 2, getY() + 2, rainbowSpeed / 2f, rainbowSaturation, rainbowBrightness, rainbowSpread, shadow);
+ DrawHelper.drawChromaText(graphics, Component, getX() + 2, getY() + 2, rainbowSpeed / 2f, rainbowSaturation, rainbowBrightness, rainbowSpread, shadow);
} else {
- drawContext.drawText(mc.textRenderer, text, getX() + 2, getY() + 2, color, shadow);
+ graphics.drawString(mc.font, Component, getX() + 2, getY() + 2, color, shadow);
}
- drawContext.draw();
- widgetBox.setDimensions(getX(), getY(), mc.textRenderer.getWidth(text) + 3, mc.textRenderer.fontHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
+ widgetBox.setDimensions(getX(), getY(), mc.font.width(Component) + 3, mc.font.lineHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
}
menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
@@ -118,7 +161,7 @@ public void onClose() {
}
@Override
- public void writeToTag(NbtCompound tag) {
+ public void writeToTag(CompoundTag tag) {
super.writeToTag(tag);
tag.putBoolean("Shadow", shadow);
tag.putBoolean("Rainbow", rainbow);
@@ -130,7 +173,7 @@ public void writeToTag(NbtCompound tag) {
}
@Override
- public void readFromTag(NbtCompound tag) {
+ public void readFromTag(CompoundTag tag) {
super.readFromTag(tag);
shadow = tag.getBoolean("Shadow").orElse(false);
rainbow = tag.getBoolean("Rainbow").orElse(false);
diff --git a/src/main/resources/dynamichud.mixins.json b/src/main/resources/dynamichud.mixins.json
index f60e286..caa9633 100644
--- a/src/main/resources/dynamichud.mixins.json
+++ b/src/main/resources/dynamichud.mixins.json
@@ -1,6 +1,5 @@
{
"required": true,
- "minVersion": "0.8",
"package": "com.tanishisherewith.dynamichud.mixins",
"compatibilityLevel": "JAVA_21",
"mixins": [
@@ -10,7 +9,11 @@
"defaultRequire": 1
},
"client": [
- "OptionsScreenMixin",
- "RenderLayerMixin"
- ]
+ "BufferBuilderMixin",
+ "MinecraftMixin",
+ "OptionsScreenMixin"
+ ],
+ "overwrites": {
+ "requireAnnotations": true
+ }
}
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index a6ef3cf..a416a25 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -26,7 +26,10 @@
]
},
"mixins": [
- "dynamichud.mixins.json"
+ {
+ "config": "dynamichud.mixins.json",
+ "environment": "client"
+ }
],
"depends": {
"fabricloader": ">=${loader_version}",
From a4e81749c18bd53e000ad74f798f5b0c928648e9 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sat, 11 Apr 2026 00:59:39 +0530
Subject: [PATCH 02/22] Fixed dynamicHUD button position
---
.../dynamichud/helpers/DrawHelper.java | 53 +++---
.../dynamichud/mixins/OptionsScreenMixin.java | 34 ++--
.../renderstates/GeometryRenderState.java | 3 +-
.../GradientShadowRenderState.java | 12 +-
.../InterpolatedCurveRenderState.java | 23 ++-
.../QuadColorRectRenderState.java | 8 +-
.../renderstates/RoundedRectRenderState.java | 168 +++++++++++++++---
.../dynamichud/utils/CustomRenderLayers.java | 24 ++-
.../contextmenu/skinsystem/ModernSkin.java | 4 +-
.../dynamichud/widgets/GraphWidget.java | 7 +-
10 files changed, 241 insertions(+), 95 deletions(-)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index e089219..5373dc4 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -1,7 +1,5 @@
package com.tanishisherewith.dynamichud.helpers;
-import com.mojang.blaze3d.systems.RenderSystem;
-import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.renderstates.GeometryRenderState;
import com.tanishisherewith.dynamichud.renderstates.QuadColorRectRenderState;
import com.tanishisherewith.dynamichud.renderstates.RoundedRectRenderState;
@@ -9,7 +7,6 @@
import com.tanishisherewith.dynamichud.widget.WidgetBox;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
-import net.minecraft.client.gui.navigation.ScreenPosition;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.network.chat.Component;
@@ -29,6 +26,12 @@
* Credits: HeliosClient
*/
public class DrawHelper {
+ public static final float[] SINA = {0,0.1736482f,0.3420201f,0.5f,0.6427876f,0.7660444f,0.8660254f,0.9396926f,0.9848077f,1,0.9848078f,0.9396927f,0.8660255f,0.7660446f,0.6427878f,0.5000002f,0.3420205f,0.1736485f,3.894144E-07f,-0.1736478f,-0.3420197f,-0.4999996f,-0.6427872f,-0.7660443f,-0.8660252f,-0.9396925f,-0.9848077f,-1,-0.9848078f,-0.9396928f,-0.8660257f,-0.7660449f,-0.6427881f,-0.5000006f,-0.3420208f,-0.1736489f,0,0.1736482f,0.3420201f,0.5f,0.6427876f,0.7660444f,0.8660254f,0.9396926f,0.9848077f};
+ public static final float[] COSA = new float[45];
+ static {
+ // Cosa is simply Sina shifted by 90 degrees (9 steps)
+ System.arraycopy(SINA, 9, COSA, 0, 36);
+ }
/**
* Draws a singular gradient rectangle on screen with the given parameters
@@ -51,7 +54,6 @@ public static void drawGradient(GuiGraphics g, float x, float y, float width, fl
g.guiRenderState.submitGuiElement(
new QuadColorRectRenderState(RenderPipelines.GUI,g.pose(),x,y,width,height,c,
- new ScreenRectangle((int) x, (int) y,(int)width,(int) height),
g.scissorStack.peek())
);
}
@@ -64,16 +66,24 @@ public static void enableScissor(WidgetBox box,GuiGraphics graphics) {
enableScissor((int) box.x, (int) box.y, (int) box.getWidth(), (int) box.getHeight(), mc.getWindow().getGuiScale(),graphics);
}
- public static void enableScissor(int x, int y, int width, int height, double scaleFactor, GuiGraphics graphics) {
+ public static void enableScissor(int x, int y, int width, int height, float scaleFactor, GuiGraphics graphics) {
+ scaleFactor = scaleFactor / mc.getWindow().getGuiScale();
int scissorX = (int) (x * scaleFactor);
int scissorY = (int) (y * scaleFactor);
int scissorWidth = (int) (width * scaleFactor);
int scissorHeight = (int) (height * scaleFactor);
- ScreenRectangle rect = new ScreenRectangle(x, y, width, height);
+ ScreenRectangle rect = new ScreenRectangle(scissorX, scissorY, scissorWidth, scissorHeight);
graphics.scissorStack.push(rect);
}
+ /**
+ * All coordinates by minecraft need to unscaled first and then scaled by our factor.
+ */
+ public static float scaleFactor(float scale) {
+ return scale / mc.getWindow().getGuiScale();
+ }
+
public static void disableScissor(GuiGraphics graphics) {
graphics.disableScissor();
@@ -158,10 +168,9 @@ public static void drawOutlineRoundedBox(GuiGraphics graphics, float x, float y,
int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
- CustomRenderLayers.ROUNDED_RECT_OUTLINE,
+ CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
graphics.pose(),
- x, y, width, height, thickness, intColors, radii, graphics.scissorStack.peek(),
- new ScreenRectangle(new ScreenPosition((int) x, (int) y), (int) width, (int) height)
+ x, y, width, height, thickness, intColors, radii, graphics.scissorStack.peek()
));
}
@@ -486,10 +495,9 @@ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y,
int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
- CustomRenderLayers.ROUNDED_RECT,
+ CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
graphics.pose(),
- x, y, width, height, 0f, intColors, radii, graphics.scissorStack.peek(),
- new ScreenRectangle(new ScreenPosition((int) x, (int) y), (int) width, (int) height)
+ x, y, width, height, -1f, intColors, radii, graphics.scissorStack.peek()
));
}
@@ -593,16 +601,9 @@ public static void drawOutlinedBox(GuiGraphics graphics, int x1, int y1, int x2,
graphics.fill(x2 - 1, y1 + 1, x2, y2 - 1, color);
}
- public static void unscaledProjection() {
- //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getWidth(), mc.getWindow().getHeight(), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
- }
-
- public static void scaledProjection() {
- //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, (float) (mc.getWindow().getWidth() / mc.getWindow().getGuiScale()), (float) (mc.getWindow().getFramebufferHeight() / mc.getWindow().getScaleFactor()), 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
- }
-
- public static void customScaledProjection(float scale) {
- //RenderSystem.setProjectionMatrix(new Matrix4f().setOrtho(0, mc.getWindow().getWidth() / scale, mc.getWindow().getHeight() / scale, 0, 1000, 21000), ProjectionType.ORTHOGRAPHIC);
+ public static void scaledProjection(float scale, GuiGraphics graphics) {
+ graphics.pose().pushMatrix();
+ graphics.pose().scale(scale/mc.getWindow().getGuiScale());
}
/**
@@ -624,6 +625,14 @@ public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y,
matrices.translate(-x, -y);
}
+ /**
+ * Creating bounds for Render states
+ */
+ public static ScreenRectangle createBounds(Matrix3x2fStack pose, ScreenRectangle scissor, float x, float y, float w, float h) {
+ ScreenRectangle bounds = new ScreenRectangle((int) x, (int) y, (int) w, (int) h).transformAxisAligned(pose);
+ return scissor == null ? bounds : scissor.intersection(bounds);
+ }
+
/**
* This method scales the matrices by the centre of the widget
*
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
index ba6887b..b778b05 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/OptionsScreenMixin.java
@@ -4,14 +4,15 @@
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
-import net.minecraft.client.gui.layouts.LayoutSettings;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.gui.screens.options.OptionsScreen;
import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -23,28 +24,41 @@ public abstract class OptionsScreenMixin extends Screen {
@Shadow
protected abstract Button openScreenButton(Component component, Supplier supplier);
- @Shadow
- @Final
- private HeaderAndFooterLayout layout;
-
protected OptionsScreenMixin(Component title) {
super(title);
}
+ @Unique
+ private LinearLayout header;
+
+ @Unique
+ private Button dhButton;
+
@Inject(
method = "init",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/layouts/LinearLayout;addChild(Lnet/minecraft/client/gui/layouts/LayoutElement;)Lnet/minecraft/client/gui/layouts/LayoutElement;",
- ordinal = 1 // this is where the FOV row is added
+ ordinal = 1, // this is where the FOV row is added
+ shift = At.Shift.AFTER
)
)
private void injectDHLayout(CallbackInfo ci, @Local(ordinal = 0) LinearLayout header) {
- LinearLayout dhLayout = header.addChild(LinearLayout.vertical(), layoutSettings -> layoutSettings.paddingLeft(-20));
+ this.header = header;
+ dhButton = openScreenButton(Component.literal("DH"), () -> GlobalConfig.get().createYACLGUI());
+ dhButton.setPosition(this.width / 2 - 150 - 24 - 8, header.getY() + header.getHeight() - 20);
+ dhButton.setSize(20,20);
+ this.addRenderableWidget(dhButton);
+ }
- Button dhButton = openScreenButton(Component.literal("DH"), () -> GlobalConfig.get().createYACLGUI());
- dhButton.setWidth(20);
- dhLayout.addChild(dhButton);
+ @Inject(
+ method = "repositionElements",
+ at = @At(value = "TAIL")
+ )
+ private void repositionElements(CallbackInfo ci) {
+ if(dhButton != null && header != null) {
+ dhButton.setPosition(this.width / 2 - 150 - 24 - 8, header.getY() + header.getHeight() - 20);
+ }
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
index 8926ee4..eb2106b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
@@ -17,8 +17,6 @@ public record GeometryRenderState(
@Nullable ScreenRectangle scissorArea
) implements GuiElementRenderState {
- public record VertexData(float x, float y, int color) {}
-
@Override
public void buildVertices(VertexConsumer consumer) {
for (int i = 0; i < vertices.length / 2; i++) {
@@ -31,6 +29,7 @@ public void buildVertices(VertexConsumer consumer) {
public TextureSetup textureSetup() {
return TextureSetup.noTexture();
}
+
@Override
public @Nullable ScreenRectangle bounds() {
return null;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
index 1e4af63..7a1375a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
@@ -2,10 +2,12 @@
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
+import org.joml.Matrix3x2fStack;
import org.joml.Matrix3x2fc;
import org.jspecify.annotations.NonNull;
@@ -17,8 +19,10 @@ public record GradientShadowRenderState(
float bottomY,
int startColor,
int endColor,
- Matrix3x2fc pose,
+ Matrix3x2fStack pose,
RenderPipeline pipeline,
+ int width,
+ int height,
@Nullable ScreenRectangle scissorArea
) implements GuiElementRenderState {
@@ -33,12 +37,12 @@ public void buildVertices(@NonNull VertexConsumer consumer) {
}
}
@Override
- public TextureSetup textureSetup() {
+ public @NonNull TextureSetup textureSetup() {
return TextureSetup.noTexture();
}
@Override
- public @org.jspecify.annotations.Nullable ScreenRectangle bounds() {
- return null;
+ public @Nullable ScreenRectangle bounds() {
+ return DrawHelper.createBounds(pose,scissorArea,points.getFirst()[0],points.getFirst()[1],width,height);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
index 96031ee..78d4dbc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
@@ -2,11 +2,12 @@
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fc;
+import org.joml.Matrix3x2fStack;
import org.jspecify.annotations.NonNull;
import java.util.List;
@@ -15,18 +16,16 @@ public record InterpolatedCurveRenderState(
List points,
float thickness,
int color,
- Matrix3x2fc pose,
+ Matrix3x2fStack pose,
RenderPipeline pipeline,
+ int width,
+ int height,
@Nullable ScreenRectangle scissorArea
) implements GuiElementRenderState {
@Override
public void buildVertices(@NonNull VertexConsumer consumer) {
- consumer.addVertexWith2DPose(pose, 10, 10).setColor(color);
- consumer.addVertexWith2DPose(pose, 100, 10).setColor(color);
- consumer.addVertexWith2DPose(pose, 10, 20).setColor(color);
- consumer.addVertexWith2DPose(pose, 100, 20).setColor(color);
- /*
+ consumer.setLineWidth(thickness);
for (int i = 0; i < points.size(); i++) {
float[] point = points.get(i);
float x = point[0];
@@ -37,23 +36,21 @@ public void buildVertices(@NonNull VertexConsumer consumer) {
float length = (float) Math.sqrt(dx * dx + dy * dy);
if (length == 0) continue;
- float offsetX = (thickness * 0.5f * dy) / length;
- float offsetY = (thickness * 0.5f * -dx) / length;
+ float offsetX = (dy) / length;
+ float offsetY = (-dx) / length;
consumer.addVertexWith2DPose(pose, x + offsetX, y + offsetY).setColor(color);
consumer.addVertexWith2DPose(pose, x - offsetX, y - offsetY).setColor(color);
}
-
- */
}
@Override
- public TextureSetup textureSetup() {
+ public @NonNull TextureSetup textureSetup() {
return TextureSetup.noTexture();
}
@Override
public @Nullable ScreenRectangle bounds() {
- return null;
+ return DrawHelper.createBounds(pose,scissorArea,points.getFirst()[0],points.getFirst()[1],width,height);
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
index 4921a73..4485440 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
@@ -2,23 +2,23 @@
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
-import org.joml.Matrix3x2f;
+import org.joml.Matrix3x2fStack;
import org.jspecify.annotations.Nullable;
import java.awt.*;
public record QuadColorRectRenderState(
RenderPipeline pipeline,
- Matrix3x2f pose,
+ Matrix3x2fStack pose,
float x,
float y,
float width,
float height,
int[] color,
- ScreenRectangle bounds,
ScreenRectangle scissorArea
) implements GuiElementRenderState {
@@ -37,6 +37,6 @@ public TextureSetup textureSetup() {
@Override
public @Nullable ScreenRectangle bounds() {
- return this.scissorArea != null ? this.scissorArea.intersection(bounds) : this.bounds;
+ return DrawHelper.createBounds(pose,scissorArea,x,y,width,height);
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
index 01a6788..f7141c3 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
@@ -2,56 +2,172 @@
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.vertex.VertexConsumer;
-import com.tanishisherewith.dynamichud.internal.IBufferBuilder;
-import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fc;
+import org.joml.Matrix3x2fStack;
import org.joml.Vector4f;
import org.jspecify.annotations.NonNull;
+import static com.tanishisherewith.dynamichud.helpers.DrawHelper.COSA;
+import static com.tanishisherewith.dynamichud.helpers.DrawHelper.SINA;
+
public record RoundedRectRenderState(
RenderPipeline pipeline,
- Matrix3x2fc pose,
- float x,
- float y,
- float width,
- float height,
+ Matrix3x2fStack pose, // Using Matrix3x2fc for 2D optimization
+ float x, float y,
+ float width, float height,
float thickness,
- int[] colors,
- Vector4f roundness,
- @Nullable ScreenRectangle scissorArea,
- @Nullable ScreenRectangle bounds
+ int[] colors, // [TL, BL, BR, TR]
+ Vector4f roundness, // [x=TL, y=TR, z=BR, w=BL]
+ @Nullable ScreenRectangle scissorArea
) implements GuiElementRenderState {
- @Override
+ @Override
public void buildVertices(@NonNull VertexConsumer consumer) {
- if (consumer instanceof IBufferBuilder builder) {
- float[][] uvs = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
- float[][] coords = {{x, y}, {x, y + height}, {x + width, y + height}, {x + width, y}};
+ if (thickness > 0) {
+ drawContinuousOutline(consumer);
+ } else {
+ drawFill(consumer);
+ }
+ }
+
+ private int averageColors(int[] c) {
+ int r = 0, g = 0, b = 0, a = 0;
+ for (int color : c) {
+ a += (color >> 24) & 0xFF;
+ r += (color >> 16) & 0xFF;
+ g += (color >> 8) & 0xFF;
+ b += color & 0xFF;
+ }
+ return (a / 4 << 24) | (r / 4 << 16) | (g / 4 << 8) | (b / 4);
+ }
+
+ private void drawFill(VertexConsumer consumer) {
+ float cx = x + (width / 2.0f);
+ float cy = y + (height / 2.0f);
+ float halfWidth = width * 0.5f;
+ float halfHeight = height * 0.5f;
- for (int i = 0; i < 4; i++) {
- consumer.addVertexWith2DPose(pose, coords[i][0], coords[i][1])
- .setColor(colors[i % colors.length])
- .setUv(uvs[i][0], uvs[i][1]);
+ // Start Fan at center
+ consumer.addVertexWith2DPose(pose, cx, cy).setColor(averageColors(colors));
+
+ // 1. Bottom-Right (Original i=0-9)
+ // Original logic: x0 = cx + (0.5f * dx), y0 = cy + (0.5f * dy)
+ float brRadius = roundness.z;
+ float dx = width - (brRadius * 2); // This is localized for the specific corner
+ float dy = height - (brRadius * 2);
+
+ float x0 = cx + (0.5f * (width - brRadius * 2));
+ float y0 = cy + (0.5f * (height - brRadius * 2));
+
+ if (brRadius > 0) {
+ for (int i = 0; i < 9; i++) {
+ // Using + for SINA to match your original: y = y0 + (r * sina[i])
+ consumer.addVertexWith2DPose(pose, x0 + (brRadius * COSA[i]), y0 + (brRadius * SINA[i])).setColor(colors[2]);
+ }
+ } else {
+ consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + halfHeight).setColor(colors[2]);
+ }
+
+ // 2. Bottom-Left (Original i=9-18)
+ float blRadius = roundness.w;
+ x0 = cx - (0.5f * (width - blRadius * 2));
+ y0 = cy + (0.5f * (height - blRadius * 2));
+ if (blRadius > 0) {
+ for (int i = 9; i < 18; i++) {
+ consumer.addVertexWith2DPose(pose, x0 + (blRadius * COSA[i]), y0 + (blRadius * SINA[i])).setColor(colors[1]);
+ }
+ } else {
+ consumer.addVertexWith2DPose(pose, cx - halfWidth, cy + halfHeight).setColor(colors[1]);
+ }
- builder.dynamicHUD$writeGenericFloats(CustomRenderLayers.ELM_WIDTH_HEIGHT, width, height);
+ // 3. Top-Left (Original i=18-27)
+ float tlRadius = roundness.x;
+ x0 = cx - (0.5f * (width - tlRadius * 2));
+ y0 = cy - (0.5f * (height - tlRadius * 2));
+ if (tlRadius > 0) {
+ for (int i = 18; i < 27; i++) {
+ consumer.addVertexWith2DPose(pose, x0 + (tlRadius * COSA[i]), y0 + (tlRadius * SINA[i])).setColor(colors[0]);
+ }
+ } else {
+ consumer.addVertexWith2DPose(pose, cx - halfWidth, cy - halfHeight).setColor(colors[0]);
+ }
- builder.dynamicHUD$writeGenericFloats(CustomRenderLayers.ELM_ROUNDNESS,
- roundness.x, roundness.y, roundness.z, roundness.w);
+ // 4. Top-Right (Original i=27-36)
+ float trRadius = roundness.y;
+ x0 = cx + (0.5f * (width - trRadius * 2));
+ y0 = cy - (0.5f * (height - trRadius * 2));
+ if (trRadius > 0) {
+ for (int i = 27; i < 36; i++) {
+ consumer.addVertexWith2DPose(pose, x0 + (trRadius * COSA[i]), y0 + (trRadius * SINA[i])).setColor(colors[3]);
}
+ } else {
+ consumer.addVertexWith2DPose(pose, cx + halfWidth, cy - halfHeight).setColor(colors[3]);
+ }
+
+ // 5. Final Closing Vertex (Matches your specific !BR logic)
+ if (roundness.z <= 0) {
+ consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + halfHeight).setColor(colors[2]);
+ } else {
+ // Your original: buf.vertex(ma, x, cy + (0.5f * dy), 0)
+ // x here was the last calculated x (cx + halfWidth)
+ consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + (0.5f * (height - brRadius * 2))).setColor(colors[2]);
+ }
+ }
+
+ private void drawContinuousOutline(VertexConsumer consumer) {
+ consumer.setLineWidth(thickness);
+ float innerShift = thickness;
+
+ // Quadrant 1: Top-Right (i=0-9)
+ float cx = x + width - roundness.y;
+ float cy = y + roundness.y;
+ walkArc(consumer, cx, cy, roundness.y, roundness.y - innerShift, colors[3], 0, 9);
+
+ // Quadrant 2: Top-Left (i=9-18)
+ cx = x + roundness.x;
+ cy = y + roundness.x;
+ walkArc(consumer, cx, cy, roundness.x, roundness.x - innerShift, colors[0], 9, 18);
+
+ // Quadrant 3: Bottom-Left (i=18-27)
+ cx = x + roundness.w;
+ cy = y + height - roundness.w;
+ walkArc(consumer, cx, cy, roundness.w, roundness.w - innerShift, colors[1], 18, 27);
+
+ // Quadrant 4: Bottom-Right (i=27-36)
+ cx = x + width - roundness.z;
+ cy = y + height - roundness.z;
+ walkArc(consumer, cx, cy, roundness.z, roundness.z - innerShift, colors[2], 27, 36);
+
+ // Close the loop back to the start of Quadrant 1
+ float startX = x + width;
+ float startY = y + roundness.y;
+ consumer.addVertexWith2DPose(pose, startX, startY).setColor(colors[3]);
+ consumer.addVertexWith2DPose(pose, startX - innerShift, startY).setColor(colors[3]);
+ }
+
+ /**
+ * Walks a specific corner arc, pushing vertices for both outer and inner radii.
+ */
+ private void walkArc(VertexConsumer c, float cx, float cy, float outerR, float innerR, int color, int start, int end) {
+ for (int i = start; i <= end; i++) {
+ // Outer Ring Vertex
+ c.addVertexWith2DPose(pose, cx + (outerR * COSA[i]), cy - (outerR * SINA[i])).setColor(color);
+ // Inner Ring Vertex
+ c.addVertexWith2DPose(pose, cx + (innerR * COSA[i]), cy - (innerR * SINA[i])).setColor(color);
}
}
@Override
- public TextureSetup textureSetup() {
+ public @NonNull TextureSetup textureSetup() {
return TextureSetup.noTexture();
}
@Override
- public @org.jspecify.annotations.Nullable ScreenRectangle bounds() {
- return this.scissorArea != null ? this.scissorArea.intersection(this.bounds) : this.bounds;
+ public @Nullable ScreenRectangle bounds() {
+ return DrawHelper.createBounds(pose,scissorArea,x,y,width,height);
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
index 5e395c3..d98fa06 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
@@ -17,10 +17,24 @@ public class CustomRenderLayers {
public static final RenderPipeline COLOR_LINE = RenderPipeline.builder()
.withLocation(Identifier.fromNamespaceAndPath("dynamichud", "color_line"))
.withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.DEBUG_LINES)
- .withFragmentShader(Identifier.withDefaultNamespace("position_color"))
- .withVertexShader(Identifier.withDefaultNamespace("position_color"))
+ .withFragmentShader(Identifier.withDefaultNamespace("core/position_color"))
+ .withVertexShader(Identifier.withDefaultNamespace("core/position_color"))
.build();
+ public static final RenderPipeline COLOR_TRIANGLES = RenderPipeline.builder()
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "color_triangles"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLES)
+ .withVertexShader(Identifier.withDefaultNamespace("core/position_color"))
+ .withFragmentShader(Identifier.withDefaultNamespace("core/position_color"))
+ .build();
+
+ public static RenderPipeline TRIANGLE_STRIP = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
+ .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_strip"))
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP)
+ .withBlend(BlendFunction.TRANSLUCENT)
+ .build()
+ );
+
// Width/Height in UV1
public static final VertexFormatElement ELM_WIDTH_HEIGHT =
new VertexFormatElement(1, 2, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.UV, 8);
@@ -76,12 +90,6 @@ public class CustomRenderLayers {
.withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
.build()
);
- public static RenderPipeline TRIANGLE_STRIP = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
- .withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_strip"))
- .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP)
- .withBlend(BlendFunction.TRANSLUCENT)
- .build()
- );
/*
private static final RenderPipeline ROUNDED = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index 6d3b809..ae2f21b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -135,7 +135,7 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
mouseY = (int) (mc.mouseHandler.ypos() / SCALE_FACTOR);
// Apply custom scaling to counteract Minecraft's default scaling
- DrawHelper.customScaledProjection(SCALE_FACTOR);
+ DrawHelper.scaledProjection(SCALE_FACTOR, graphics);
updateContextDimensions();
contextMenu.set(contextMenuX, contextMenuY, 0);
@@ -182,7 +182,7 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
renderToolTipText(graphics, mouseX, mouseY);
//Reset our scaling so minecraft runs normally\
- DrawHelper.scaledProjection();
+ DrawHelper.stopScaling(graphics.pose());
}
private void updateContextDimensions() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 574ae6c..f17a7b8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -167,17 +167,16 @@ private void drawInterpolatedCurve(GuiGraphics graphics, List points, i
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.QUADS_CUSTOM_BLEND, graphics.scissorStack.peek())
+ new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, (int) width, (int) height, graphics.scissorStack.peek())
);
}
-
// draw a gradient shadow under the curve
private void drawGradientShadow(GuiGraphics graphics, List points, float bottomY, int startColor, int endColor) {
if (points.size() < 2) return;
- graphics.guiRenderState.submitGuiElement(
- new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, graphics.scissorStack.peek())
+ graphics.guiRenderState.submitGuiElement(
+ new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, (int) width, (int) height, graphics.scissorStack.peek())
);
}
From 823921e573185b50cc02c0d949dc0227866574e9 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sun, 12 Apr 2026 16:49:30 +0530
Subject: [PATCH 03/22] Finally got rounded rectangles to work.
---
.../dynamichud/IntegrationTest.java | 1 +
.../dynamichud/helpers/DrawHelper.java | 6 +-
.../GradientShadowRenderState.java | 14 +-
.../InterpolatedCurveRenderState.java | 39 ++--
.../QuadColorRectRenderState.java | 5 +-
.../renderstates/RoundedRectRenderState.java | 195 ++++++------------
.../dynamichud/utils/CustomRenderLayers.java | 5 +-
.../dynamichud/widgets/GraphWidget.java | 104 +++++++---
8 files changed, 187 insertions(+), 182 deletions(-)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
index 1dd92c6..8b260b0 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
@@ -87,6 +87,7 @@ public void init() {
.setDraggable(true)
.setDisplay(true)
.showGrid(true)
+ .shouldScale(true)
.registryKey("FPS")
.registryID(registry.getId())
.build()
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index 5373dc4..1e7790c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -168,7 +168,7 @@ public static void drawOutlineRoundedBox(GuiGraphics graphics, float x, float y,
int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
- CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
+ RenderPipelines.DEBUG_QUADS,
graphics.pose(),
x, y, width, height, thickness, intColors, radii, graphics.scissorStack.peek()
));
@@ -465,7 +465,7 @@ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y,
* @param color Color of the rounded.fsh rectangle
*/
public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y, boolean TL, boolean TR, boolean BL, boolean BR, float width, float height, float radius, int color) {
- Vector4f radii = new Vector4f(TR ? radius : 0.0f, BR ? radius : 0.0f, TL ? radius : 0.0f, BL ? radius : 0.0f);
+ Vector4f radii = new Vector4f(TL ? radius : 0.0f, TR ? radius : 0.0f, BR ? radius : 0.0f, BL ? radius : 0.0f);
// Turns out Color class takes rgb by default not rgba
Color c = new Color(color, true);
@@ -495,7 +495,7 @@ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y,
int[] intColors = {tl.getRGB(),tr.getRGB(),br.getRGB(),bl.getRGB()};
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
- CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
+ RenderPipelines.DEBUG_QUADS,
graphics.pose(),
x, y, width, height, -1f, intColors, radii, graphics.scissorStack.peek()
));
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
index 7a1375a..1c177d8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
@@ -28,12 +28,16 @@ public record GradientShadowRenderState(
@Override
public void buildVertices(@NonNull VertexConsumer consumer) {
- for (float[] point : points) {
- float x = point[0];
- float y = point[1];
+ for (int i = 0; i < points.size() - 1; i++) {
+ float x1 = points.get(i)[0];
+ float y1 = points.get(i)[1];
+ float x2 = points.get(i + 1)[0];
+ float y2 = points.get(i + 1)[1];
- consumer.addVertexWith2DPose(pose, x, y).setColor(startColor);
- consumer.addVertexWith2DPose(pose, x, bottomY).setColor(endColor);
+ consumer.addVertexWith2DPose(pose, x1, y1).setColor(startColor); // Topleft
+ consumer.addVertexWith2DPose(pose, x1, bottomY).setColor(endColor); // Bottomleft
+ consumer.addVertexWith2DPose(pose, x2, bottomY).setColor(endColor); // Bottomright
+ consumer.addVertexWith2DPose(pose, x2, y2).setColor(startColor); // Topright
}
}
@Override
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
index 78d4dbc..07a9e7f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
@@ -26,21 +26,35 @@ public record InterpolatedCurveRenderState(
@Override
public void buildVertices(@NonNull VertexConsumer consumer) {
consumer.setLineWidth(thickness);
- for (int i = 0; i < points.size(); i++) {
- float[] point = points.get(i);
- float x = point[0];
- float y = point[1];
+ if (points.size() < 2) return;
- float dx = (i < points.size() - 1) ? points.get(i + 1)[0] - x : x - points.get(i - 1)[0];
- float dy = (i < points.size() - 1) ? points.get(i + 1)[1] - y : y - points.get(i - 1)[1];
+ // build individual QUADS
+ for (int i = 0; i < points.size() - 1; i++) {
+ float[] p1 = points.get(i);
+ float[] p2 = points.get(i + 1);
+
+ float x1 = p1[0];
+ float y1 = p1[1];
+ float x2 = p2[0];
+ float y2 = p2[1];
+
+ float dx = x2 - x1;
+ float dy = y2 - y1;
float length = (float) Math.sqrt(dx * dx + dy * dy);
if (length == 0) continue;
- float offsetX = (dy) / length;
- float offsetY = (-dx) / length;
+ // normals for line thickness
+ float offsetX = (thickness * 0.5f * dy) / length;
+ float offsetY = (thickness * 0.5f * -dx) / length;
- consumer.addVertexWith2DPose(pose, x + offsetX, y + offsetY).setColor(color);
- consumer.addVertexWith2DPose(pose, x - offsetX, y - offsetY).setColor(color);
+ //Topleft
+ consumer.addVertexWith2DPose(pose, x1 + offsetX, y1 + offsetY).setColor(color);
+ //Bottomleft
+ consumer.addVertexWith2DPose(pose, x1 - offsetX, y1 - offsetY).setColor(color);
+ //Bottomright
+ consumer.addVertexWith2DPose(pose, x2 - offsetX, y2 - offsetY).setColor(color);
+ //Topright
+ consumer.addVertexWith2DPose(pose, x2 + offsetX, y2 + offsetY).setColor(color);
}
}
@@ -51,6 +65,7 @@ public void buildVertices(@NonNull VertexConsumer consumer) {
@Override
public @Nullable ScreenRectangle bounds() {
- return DrawHelper.createBounds(pose,scissorArea,points.getFirst()[0],points.getFirst()[1],width,height);
+ if (points.isEmpty()) return null;
+ return DrawHelper.createBounds(pose, scissorArea, points.getFirst()[0], points.getFirst()[1], width, height);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
index 4485440..e02892e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
@@ -7,10 +7,9 @@
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.joml.Matrix3x2fStack;
+import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
-import java.awt.*;
-
public record QuadColorRectRenderState(
RenderPipeline pipeline,
Matrix3x2fStack pose,
@@ -31,7 +30,7 @@ public void buildVertices(VertexConsumer vertices) {
}
@Override
- public TextureSetup textureSetup() {
+ public @NonNull TextureSetup textureSetup() {
return TextureSetup.noTexture();
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
index f7141c3..4e39e3b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
@@ -16,149 +16,90 @@
public record RoundedRectRenderState(
RenderPipeline pipeline,
- Matrix3x2fStack pose, // Using Matrix3x2fc for 2D optimization
+ Matrix3x2fStack pose,
float x, float y,
float width, float height,
float thickness,
- int[] colors, // [TL, BL, BR, TR]
- Vector4f roundness, // [x=TL, y=TR, z=BR, w=BL]
+ int[] colors,
+ Vector4f roundness,
@Nullable ScreenRectangle scissorArea
) implements GuiElementRenderState {
- @Override
+ @Override
public void buildVertices(@NonNull VertexConsumer consumer) {
- if (thickness > 0) {
- drawContinuousOutline(consumer);
- } else {
- drawFill(consumer);
- }
- }
-
- private int averageColors(int[] c) {
- int r = 0, g = 0, b = 0, a = 0;
- for (int color : c) {
- a += (color >> 24) & 0xFF;
- r += (color >> 16) & 0xFF;
- g += (color >> 8) & 0xFF;
- b += color & 0xFF;
- }
- return (a / 4 << 24) | (r / 4 << 16) | (g / 4 << 8) | (b / 4);
- }
-
- private void drawFill(VertexConsumer consumer) {
- float cx = x + (width / 2.0f);
- float cy = y + (height / 2.0f);
- float halfWidth = width * 0.5f;
- float halfHeight = height * 0.5f;
-
- // Start Fan at center
- consumer.addVertexWith2DPose(pose, cx, cy).setColor(averageColors(colors));
-
- // 1. Bottom-Right (Original i=0-9)
- // Original logic: x0 = cx + (0.5f * dx), y0 = cy + (0.5f * dy)
- float brRadius = roundness.z;
- float dx = width - (brRadius * 2); // This is localized for the specific corner
- float dy = height - (brRadius * 2);
-
- float x0 = cx + (0.5f * (width - brRadius * 2));
- float y0 = cy + (0.5f * (height - brRadius * 2));
-
- if (brRadius > 0) {
- for (int i = 0; i < 9; i++) {
- // Using + for SINA to match your original: y = y0 + (r * sina[i])
- consumer.addVertexWith2DPose(pose, x0 + (brRadius * COSA[i]), y0 + (brRadius * SINA[i])).setColor(colors[2]);
+ float fX = 0, fY = 0, fIX = 0, fIY = 0;
+ int fC = 0;
+ float pX = 0, pY = 0, pIX = 0, pIY = 0;
+ int pC = 0;
+
+ float midX = x + (width * 0.5f);
+ float midY = y + (height * 0.5f);
+ int midC = (thickness <= 0) ? averageColors(colors) : 0;
+
+ // 9 steps per quadrant to match the 360 precomputed tables
+ for (int k = 0; k <= 36; k++) {
+ int i = k % 36;
+ float r, cx, cy;
+ int color;
+
+ // Quadrants:- 0-8:BR, 9-17:BL, 18-26:TL, 27-35:TR
+ if (i < 9) {
+ r = roundness.z; cx = x + width - r; cy = y + height - r; color = colors[2];
+ } else if (i < 18) {
+ r = roundness.w; cx = x + r; cy = y + height - r; color = colors[3];
+ } else if (i < 27) {
+ r = roundness.x; cx = x + r; cy = y + r; color = colors[0];
+ } else {
+ r = roundness.y; cx = x + width - r; cy = y + r; color = colors[1];
}
- } else {
- consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + halfHeight).setColor(colors[2]);
- }
- // 2. Bottom-Left (Original i=9-18)
- float blRadius = roundness.w;
- x0 = cx - (0.5f * (width - blRadius * 2));
- y0 = cy + (0.5f * (height - blRadius * 2));
- if (blRadius > 0) {
- for (int i = 9; i < 18; i++) {
- consumer.addVertexWith2DPose(pose, x0 + (blRadius * COSA[i]), y0 + (blRadius * SINA[i])).setColor(colors[1]);
- }
- } else {
- consumer.addVertexWith2DPose(pose, cx - halfWidth, cy + halfHeight).setColor(colors[1]);
- }
+ float cX = cx + (r * COSA[i]);
+ float cY = cy + (r * SINA[i]);
+ float cIX = 0, cIY = 0;
- // 3. Top-Left (Original i=18-27)
- float tlRadius = roundness.x;
- x0 = cx - (0.5f * (width - tlRadius * 2));
- y0 = cy - (0.5f * (height - tlRadius * 2));
- if (tlRadius > 0) {
- for (int i = 18; i < 27; i++) {
- consumer.addVertexWith2DPose(pose, x0 + (tlRadius * COSA[i]), y0 + (tlRadius * SINA[i])).setColor(colors[0]);
+ if (thickness > 0) {
+ // clamping inner radius to 0
+ float ir = Math.max(0, r - thickness);
+ cIX = cx + (ir * COSA[i]);
+ cIY = cy + (ir * SINA[i]);
}
- } else {
- consumer.addVertexWith2DPose(pose, cx - halfWidth, cy - halfHeight).setColor(colors[0]);
- }
- // 4. Top-Right (Original i=27-36)
- float trRadius = roundness.y;
- x0 = cx + (0.5f * (width - trRadius * 2));
- y0 = cy - (0.5f * (height - trRadius * 2));
- if (trRadius > 0) {
- for (int i = 27; i < 36; i++) {
- consumer.addVertexWith2DPose(pose, x0 + (trRadius * COSA[i]), y0 + (trRadius * SINA[i])).setColor(colors[3]);
+ if (k == 0) {
+ // Cache the first vertex set to ensure pixel-perfect loop closure
+ fX = cX; fY = cY; fIX = cIX; fIY = cIY; fC = color;
+ } else {
+ float tX = (k == 36) ? fX : cX;
+ float tY = (k == 36) ? fY : cY;
+ float tIX = (k == 36) ? fIX : cIX;
+ float tIY = (k == 36) ? fIY : cIY;
+ int tC = (k == 36) ? fC : color;
+
+ if (thickness > 0) {
+ consumer.addVertexWith2DPose(pose, pX, pY).setColor(pC);
+ consumer.addVertexWith2DPose(pose, pIX, pIY).setColor(pC);
+ consumer.addVertexWith2DPose(pose, tIX, tIY).setColor(tC);
+ consumer.addVertexWith2DPose(pose, tX, tY).setColor(tC);
+ } else {
+ consumer.addVertexWith2DPose(pose, midX, midY).setColor(midC);
+ consumer.addVertexWith2DPose(pose, pX, pY).setColor(pC);
+ consumer.addVertexWith2DPose(pose, tX, tY).setColor(tC);
+ consumer.addVertexWith2DPose(pose, tX, tY).setColor(tC);
+ }
}
- } else {
- consumer.addVertexWith2DPose(pose, cx + halfWidth, cy - halfHeight).setColor(colors[3]);
- }
- // 5. Final Closing Vertex (Matches your specific !BR logic)
- if (roundness.z <= 0) {
- consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + halfHeight).setColor(colors[2]);
- } else {
- // Your original: buf.vertex(ma, x, cy + (0.5f * dy), 0)
- // x here was the last calculated x (cx + halfWidth)
- consumer.addVertexWith2DPose(pose, cx + halfWidth, cy + (0.5f * (height - brRadius * 2))).setColor(colors[2]);
+ pX = cX; pY = cY; pIX = cIX; pIY = cIY; pC = color;
}
}
- private void drawContinuousOutline(VertexConsumer consumer) {
- consumer.setLineWidth(thickness);
- float innerShift = thickness;
-
- // Quadrant 1: Top-Right (i=0-9)
- float cx = x + width - roundness.y;
- float cy = y + roundness.y;
- walkArc(consumer, cx, cy, roundness.y, roundness.y - innerShift, colors[3], 0, 9);
-
- // Quadrant 2: Top-Left (i=9-18)
- cx = x + roundness.x;
- cy = y + roundness.x;
- walkArc(consumer, cx, cy, roundness.x, roundness.x - innerShift, colors[0], 9, 18);
-
- // Quadrant 3: Bottom-Left (i=18-27)
- cx = x + roundness.w;
- cy = y + height - roundness.w;
- walkArc(consumer, cx, cy, roundness.w, roundness.w - innerShift, colors[1], 18, 27);
-
- // Quadrant 4: Bottom-Right (i=27-36)
- cx = x + width - roundness.z;
- cy = y + height - roundness.z;
- walkArc(consumer, cx, cy, roundness.z, roundness.z - innerShift, colors[2], 27, 36);
-
- // Close the loop back to the start of Quadrant 1
- float startX = x + width;
- float startY = y + roundness.y;
- consumer.addVertexWith2DPose(pose, startX, startY).setColor(colors[3]);
- consumer.addVertexWith2DPose(pose, startX - innerShift, startY).setColor(colors[3]);
- }
-
- /**
- * Walks a specific corner arc, pushing vertices for both outer and inner radii.
- */
- private void walkArc(VertexConsumer c, float cx, float cy, float outerR, float innerR, int color, int start, int end) {
- for (int i = start; i <= end; i++) {
- // Outer Ring Vertex
- c.addVertexWith2DPose(pose, cx + (outerR * COSA[i]), cy - (outerR * SINA[i])).setColor(color);
- // Inner Ring Vertex
- c.addVertexWith2DPose(pose, cx + (innerR * COSA[i]), cy - (innerR * SINA[i])).setColor(color);
+ private int averageColors(int[] c) {
+ int r = 0, g = 0, b = 0, a = 0;
+ for (int color : c) {
+ a += (color >> 24) & 0xFF;
+ r += (color >> 16) & 0xFF;
+ g += (color >> 8) & 0xFF;
+ b += color & 0xFF;
}
+ return ((a / 4) << 24) | ((r / 4) << 16) | ((g / 4) << 8) | (b / 4);
}
@Override
@@ -168,6 +109,6 @@ private void walkArc(VertexConsumer c, float cx, float cy, float outerR, float i
@Override
public @Nullable ScreenRectangle bounds() {
- return DrawHelper.createBounds(pose,scissorArea,x,y,width,height);
+ return DrawHelper.createBounds(pose, scissorArea, x, y, width, height);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
index d98fa06..8291909 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/CustomRenderLayers.java
@@ -30,8 +30,7 @@ public class CustomRenderLayers {
public static RenderPipeline TRIANGLE_STRIP = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
.withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_strip"))
- .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP)
- .withBlend(BlendFunction.TRANSLUCENT)
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLES)
.build()
);
@@ -87,7 +86,7 @@ public class CustomRenderLayers {
public static RenderPipeline TRIANGLE_FAN_CUSTOM_BLEND = RenderPipelines.register(RenderPipeline.builder(RenderPipelines.GUI_SNIPPET)
.withLocation(Identifier.fromNamespaceAndPath("dynamichud", "pipeline/triangle_fan_custom_blend_func"))
.withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_FAN)
- .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
+ // .withBlend(new BlendFunction(SourceFactor.DST_ALPHA, DestFactor.ONE_MINUS_DST_ALPHA))
.build()
);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index f17a7b8..a9b0ac3 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -7,7 +7,6 @@
import com.tanishisherewith.dynamichud.renderstates.InterpolatedCurveRenderState;
import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
-import com.tanishisherewith.dynamichud.utils.Util;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
@@ -21,7 +20,6 @@
import com.tanishisherewith.dynamichud.widget.WidgetData;
import com.twelvemonkeys.lang.Validate;
import net.minecraft.client.gui.GuiGraphics;
-import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@@ -57,7 +55,7 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
private boolean autoUpdateRange = false;
private float stepY;
private float valueStep;
- private float scale;
+ private float valueScale;
int offset = -2;
public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) {
@@ -87,7 +85,7 @@ private void internal_init() {
this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
this.stepY = height / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
- this.scale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
+ this.valueScale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
computeOffset();
@@ -137,26 +135,72 @@ private List getInterpolatedPoints() {
if (dataPoints.length < 2) return points;
float xStep = width / (dataPoints.length - 1);
- for (int i = 0; i < dataPoints.length - 1; i++) {
- int index1 = (head + i) % dataPoints.length;
- int index2 = (head + i + 1) % dataPoints.length;
+ float range = Math.max(maxValue - minValue, 0.0001f);
+
+ //Pre-calculate Y coordinates
+ float[] yVals = new float[dataPoints.length];
+ for (int i = 0; i < dataPoints.length; i++) {
+ int index = (head + i) % dataPoints.length;
+ yVals[i] = y + height - ((dataPoints[index] - minValue) / range * height);
+ }
+
+ // Monotone Cubic Spline (Fritsch-Carlson) calculation
+ float[] m = new float[dataPoints.length];
+ for (int i = 0; i < dataPoints.length; i++) {
+ if (i == 0) {
+ m[i] = yVals[1] - yVals[0];
+ } else if (i == dataPoints.length - 1) {
+ m[i] = yVals[dataPoints.length - 1] - yVals[dataPoints.length - 2];
+ } else {
+ float sPrev = yVals[i] - yVals[i - 1];
+ float sNext = yVals[i + 1] - yVals[i];
+
+ if (sPrev * sNext <= 0) {
+ m[i] = 0; // Local peak/valley so clamp tangent to prevent overshoot
+ } else {
+ m[i] = (sPrev + sNext) / 2.0f;
+ // Clamp tangent magnitude to max 3x of smallest secant
+ float maxMag = 3.0f * Math.min(Math.abs(sPrev), Math.abs(sNext));
+ if (Math.abs(m[i]) > maxMag) {
+ m[i] = Math.signum(m[i]) * maxMag;
+ }
+ }
+ }
+ }
- float x1 = x + i * xStep;
- float y1 = y + height - ((dataPoints[index1] - minValue) / (maxValue - minValue) * height);
- float x2 = x + (i + 1) * xStep;
- float y2 = y + height - ((dataPoints[index2] - minValue) / (maxValue - minValue) * height);
+ //Generate curve with distance filtering to fix tearing
+ for (int i = 0; i < dataPoints.length - 1; i++) {
+ float y0 = yVals[i];
+ float y1 = yVals[i + 1];
+ float m0 = m[i];
+ float m1 = m[i + 1];
+ float x0 = x + i * xStep;
- // Add interpolated points using hermite spline (simplified)
- for (float t = 0; t <= 1; t += 0.03f) {
+ for (float t = 0; t <= 1.0f; t += 0.05f) {
float t2 = t * t;
float t3 = t2 * t;
+
+ // Hermite basis functions
float h00 = 2 * t3 - 3 * t2 + 1;
float h10 = t3 - 2 * t2 + t;
float h01 = -2 * t3 + 3 * t2;
-
- float px = h00 * x1 + h10 * xStep + h01 * x2;
- float py = h00 * y1 + h10 * (y2 - y1) + h01 * y2;
- points.add(new float[]{px, py});
+ float h11 = t3 - t2;
+
+ float px = x0 + t * xStep;
+ float py = h00 * y0 + h10 * m0 + h01 * y1 + h11 * m1;
+
+ // Vertex Simplifier: Only add point if it moved a safe distance.
+ // This prevents float-precision "divide by zero" errors when normals are
+ if (points.isEmpty()) {
+ points.add(new float[]{px, py});
+ } else {
+ float[] lastP = points.get(points.size() - 1);
+ float distSq = (px - lastP[0]) * (px - lastP[0]) + (py - lastP[1]) * (py - lastP[1]);
+ // Add only if distance is safe OR if it's the strict end of the segment
+ if (distSq > 0.5f || t >= 0.99f) {
+ points.add(new float[]{px, py});
+ }
+ }
}
}
return points;
@@ -167,7 +211,7 @@ private void drawInterpolatedCurve(GuiGraphics graphics, List points, i
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, (int) width, (int) height, graphics.scissorStack.peek())
+ new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.QUADS_CUSTOM_BLEND, (int) width, (int) height, graphics.scissorStack.peek())
);
}
@@ -176,7 +220,7 @@ private void drawGradientShadow(GuiGraphics graphics, List points, floa
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), CustomRenderLayers.TRIANGLE_STRIP, (int) width, (int) height, graphics.scissorStack.peek())
+ new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), RenderPipelines.DEBUG_QUADS, (int) width, (int) height, graphics.scissorStack.peek())
);
}
@@ -212,7 +256,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
// Draw grid lines and value markings
if (showGrid) {
- //TODO: The scale is too small when no. of grid lines is greater than 21 (20 is the barely visible threshold)
+ //TODO: The valueScale is too small when no. of grid lines is greater than 21 (20 is the barely visible threshold)
for (int i = 1; i <= gridLines; i++) {
float yPos = y + stepY * i;
@@ -222,11 +266,11 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
float value = maxValue - (i * valueStep);
String valueText = formatValue(value);
- float texWidth = mc.font.width(valueText) * scale;
+ float texWidth = mc.font.width(valueText) * valueScale;
//Scale the Component to its proper position and size with grid lines
- DrawHelper.scaleAndPosition(graphics.pose(), x - 2, yPos, scale);
- graphics.drawString(mc.font, valueText, Math.round(x + offset - texWidth), (int) (yPos - (mc.font.lineHeight * scale) / 2.0f), 0xFFFFFFFF, true);
+ DrawHelper.scaleAndPosition(graphics.pose(), x - 2, yPos, valueScale);
+ graphics.drawString(mc.font, valueText, Math.round(x + offset - texWidth), (int) (yPos - (mc.font.lineHeight * valueScale) / 2.0f), 0xFFFFFFFF, true);
DrawHelper.stopScaling(graphics.pose());
}
@@ -241,16 +285,18 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
}
}
- // Draw interpolated graph curve
List points = getInterpolatedPoints();
- drawInterpolatedCurve(graphics, points, graphColor.getRGB(), lineThickness);
// Draw shadow effect under the graph
drawGradientShadow(
graphics, points, y + height,
- ColorHelper.changeAlpha(graphColor, 50).getRGB(),
+ ColorHelper.changeAlpha(graphColor, 100).getRGB(),
0x00000000
);
+
+ // Draw interpolated graph curve
+ drawInterpolatedCurve(graphics, points, graphColor.getRGB(), lineThickness);
+
DrawHelper.drawChromaText(
graphics, label,
x + 5, y + 5,
@@ -345,8 +391,8 @@ private void computeOffset(){
String lastText = formatValue(maxValue - (gridLines * valueStep));
offset = Math.max(
- (int) Math.ceil(mc.font.width(firstText) * this.scale),
- (int) Math.ceil(mc.font.width(lastText) * this.scale)
+ (int) Math.ceil(mc.font.width(firstText) * this.valueScale),
+ (int) Math.ceil(mc.font.width(lastText) * this.valueScale)
);
}
@@ -428,7 +474,7 @@ public void setGridLines(int gridLines) {
this.gridLines = gridLines;
this.stepY = height / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
- this.scale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
+ this.valueScale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
}
public boolean isShowGrid() {
From 4ca5a1d4ffad2b5956cd4648d774ac517b9c0226 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sun, 12 Apr 2026 16:55:52 +0530
Subject: [PATCH 04/22] Refactor GlobalConfig.get().getScale()
---
.../com/tanishisherewith/dynamichud/DynamicHUD.java | 10 ++++++++++
.../com/tanishisherewith/dynamichud/widget/Widget.java | 5 +++--
.../dynamichud/widgets/GraphWidget.java | 4 ++--
.../dynamichud/widgets/ItemWidget.java | 3 ++-
.../dynamichud/widgets/TextWidget.java | 3 ++-
5 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
index 53dc955..43b9b99 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
@@ -70,4 +70,14 @@ public void onInitializeClient() {
ClientTickEvents.END_CLIENT_TICK.register(mc-> MouseColorQuery.processIfPending());
}
+
+ /**
+ * Get applied scale on all widgets, modified by YACL.
+ *
+ * From {@link GlobalConfig#getScale()}
+ * @return scale in float
+ */
+ public static float getGlobalScale() {
+ return GlobalConfig.get().getScale();
+ }
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
index 74d4c56..5c6a89c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud.widget;
+import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.internal.UID;
@@ -163,7 +164,7 @@ public final void render(GuiGraphics graphics, int mouseX, int mouseY) {
if (shouldScale) {
- DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), GlobalConfig.get().getScale());
+ DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), DynamicHUD.getGlobalScale());
}
renderWidget(graphics, mouseX, mouseY);
@@ -182,7 +183,7 @@ public final void renderInEditor(GuiGraphics graphics, int mouseX, int mouseY) {
drawWidgetBackground(graphics);
if (shouldScale) {
- DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), GlobalConfig.get().getScale());
+ DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), DynamicHUD.getGlobalScale());
}
renderWidgetInEditor(graphics, mouseX, mouseY);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index a9b0ac3..4ccd082 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -1,6 +1,6 @@
package com.tanishisherewith.dynamichud.widgets;
-import com.tanishisherewith.dynamichud.config.GlobalConfig;
+import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.renderstates.GradientShadowRenderState;
@@ -324,7 +324,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
if(showGrid) x -= offset;
- this.widgetBox.setDimensions(x, y, width + offset, height, shouldScale, GlobalConfig.get().getScale());
+ this.widgetBox.setDimensions(x, y, width + offset, height, shouldScale, DynamicHUD.getGlobalScale());
// DrawHelper.disableScissor();
if (menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
index 48bd7ac..edb1c71 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud.widgets;
+import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.widget.Widget;
import com.tanishisherewith.dynamichud.widget.WidgetData;
@@ -27,7 +28,7 @@ public ItemWidget() {
@Override
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
graphics.renderItem(item, x, y);
- widgetBox.setDimensions(getX(), getY(), 16, 16, this.shouldScale, GlobalConfig.get().getScale());
+ widgetBox.setDimensions(getX(), getY(), 16, 16, this.shouldScale, DynamicHUD.getGlobalScale());
}
@Override
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index a286d51..25beeca 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud.widgets;
+import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
@@ -142,7 +143,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
} else {
graphics.drawString(mc.font, Component, getX() + 2, getY() + 2, color, shadow);
}
- widgetBox.setDimensions(getX(), getY(), mc.font.width(Component) + 3, mc.font.lineHeight + 2, this.shouldScale, GlobalConfig.get().getScale());
+ widgetBox.setDimensions(getX(), getY(), mc.font.width(Component) + 3, mc.font.lineHeight + 2, this.shouldScale, DynamicHUD.getGlobalScale());
}
menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
From a546a2ffa87ce74dbe3711f2562fdef406c32351 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Wed, 17 Jun 2026 00:10:45 +0530
Subject: [PATCH 05/22] Better animations to context menu Patches for 1.21.11
Refactor to improve package names Made rounded rectangles and circles work
Fix mouse actions in context menu Improvements to library
---
.../dynamichud/helpers/ColorHelper.java | 4 +
.../dynamichud/helpers/DrawHelper.java | 59 ++--
.../animationhelper/AnimationProperty.java | 1 -
.../animations/MathAnimations.java | 2 +-
.../integration/IntegrationManager.java | 6 +-
.../dynamichud/mixins/BufferBuilderMixin.java | 5 +-
.../renderstates/GeometryRenderState.java | 24 +-
.../GradientShadowRenderState.java | 4 +-
.../InterpolatedCurveRenderState.java | 4 +-
.../QuadColorRectRenderState.java | 4 +-
.../renderstates/RoundedRectRenderState.java | 7 +-
.../utils/contextmenu/ContextMenu.java | 119 +++++--
.../contextmenu/ContextMenuProperties.java | 10 +
.../contextmenu/layout/LayoutEngine.java | 166 +++++++++
.../contextmenu/options/BooleanOption.java | 1 -
.../contextmenu/options/ColorOption.java | 11 +-
.../contextmenu/options/DoubleOption.java | 12 +-
.../utils/contextmenu/options/EnumOption.java | 4 +-
.../utils/contextmenu/options/ListOption.java | 4 +-
.../utils/contextmenu/options/Option.java | 1 +
.../contextmenu/options/OptionGroup.java | 18 +-
.../contextmenu/options/RunnableOption.java | 20 +-
.../contextmenu/options/SubMenuOption.java | 18 +-
.../options/coloroption/ColorGradient.java | 9 +-
.../ContextMenuScreen.java | 4 +-
.../ContextMenuScreenRegistry.java | 2 +-
.../factory}/ContextMenuScreenFactory.java | 2 +-
.../DefaultContextMenuScreenFactory.java | 3 +-
.../contextmenu/skinsystem/ClassicSkin.java | 150 ++-------
.../contextmenu/skinsystem/MinecraftSkin.java | 150 ++++++---
.../contextmenu/skinsystem/ModernSkin.java | 314 ++++++++----------
.../utils/contextmenu/skinsystem/Skin.java | 2 +-
.../dynamichud/widget/WidgetRenderer.java | 2 +-
.../dynamichud/widgets/GraphWidget.java | 10 +-
.../dynamichud/widgets/TextWidget.java | 82 ++---
35 files changed, 740 insertions(+), 494 deletions(-)
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/{contextmenuscreen => screen}/ContextMenuScreen.java (94%)
rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/{contextmenuscreen => screen}/ContextMenuScreenRegistry.java (77%)
rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/{contextmenuscreen => screen/factory}/ContextMenuScreenFactory.java (89%)
rename src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/{contextmenuscreen => screen/factory}/DefaultContextMenuScreenFactory.java (78%)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
index 1e59066..c6894ce 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/ColorHelper.java
@@ -37,6 +37,10 @@ public class ColorHelper {
public static int r, g, b, a;
+ // Used in [ClassicSkin.java]
+ public static Color DARK_RED = new Color(116, 0, 0);
+ public static Color DARK_GREEN = new Color(24, 132, 0, 226);
+
public ColorHelper(int r, int g, int b, int a) {
ColorHelper.r = r;
ColorHelper.g = g;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index 1e7790c..ffac337 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -5,6 +5,7 @@
import com.tanishisherewith.dynamichud.renderstates.RoundedRectRenderState;
import com.tanishisherewith.dynamichud.utils.CustomRenderLayers;
import com.tanishisherewith.dynamichud.widget.WidgetBox;
+import net.fabricmc.fabric.api.renderer.v1.render.RenderLayerHelper;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenRectangle;
@@ -13,6 +14,7 @@
import net.minecraft.util.ARGB;
import net.minecraft.util.Util;
import org.jetbrains.annotations.NotNull;
+import org.joml.Matrix3x2f;
import org.joml.Matrix3x2fStack;
import org.joml.Vector4f;
@@ -31,6 +33,7 @@ public class DrawHelper {
static {
// Cosa is simply Sina shifted by 90 degrees (9 steps)
System.arraycopy(SINA, 9, COSA, 0, 36);
+ System.arraycopy(SINA, 9, COSA, 36, 9);
}
/**
@@ -53,7 +56,7 @@ public static void drawGradient(GuiGraphics g, float x, float y, float width, fl
};
g.guiRenderState.submitGuiElement(
- new QuadColorRectRenderState(RenderPipelines.GUI,g.pose(),x,y,width,height,c,
+ new QuadColorRectRenderState(RenderPipelines.GUI,new Matrix3x2f(g.pose()),x,y,width,height,c,
g.scissorStack.peek())
);
}
@@ -169,7 +172,7 @@ public static void drawOutlineRoundedBox(GuiGraphics graphics, float x, float y,
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
RenderPipelines.DEBUG_QUADS,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
x, y, width, height, thickness, intColors, radii, graphics.scissorStack.peek()
));
}
@@ -236,7 +239,7 @@ public static void drawOutlineCircle(GuiGraphics graphics, float xCenter, float
graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
CustomRenderLayers.TRIANGLE_STRIP,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
verts, colors, graphics.scissorStack.peek()
));
}
@@ -250,25 +253,33 @@ public static void drawOutlineCircle(GuiGraphics graphics, float xCenter, float
* @param color color of the circle outline
*/
public static void drawFilledCircle(GuiGraphics graphics, float xCenter, float yCenter, float radius, int color) {
- int segments = 72; // 5-degree steps for smoothness
- float[] verts = new float[(segments + 2) * 2];
- int[] colors = new int[segments + 2];
-
- // Center point
- verts[0] = xCenter; verts[1] = yCenter;
- colors[0] = color;
-
- for (int i = 0; i <= segments; i++) {
- float rad = (float) Math.toRadians(i * 5);
- int idx = (i + 1) * 2;
- verts[idx] = xCenter + (float) Math.sin(rad) * radius;
- verts[idx + 1] = yCenter + (float) Math.cos(rad) * radius;
- colors[i + 1] = color;
+ int segments = 36;
+ float[] verts = new float[segments * 4 * 2];
+ int[] colors = new int[segments * 4];
+
+ int vIdx = 0;
+ int cIdx = 0;
+
+ for (int i = 0; i < segments; i++) {
+ float x1 = xCenter + SINA[i] * radius;
+ float y1 = yCenter + COSA[i] * radius;
+ float x2 = xCenter + SINA[i + 1] * radius;
+ float y2 = yCenter + COSA[i + 1] * radius;
+
+ verts[vIdx++] = xCenter; verts[vIdx++] = yCenter;
+ verts[vIdx++] = x1; verts[vIdx++] = y1;
+ verts[vIdx++] = x2; verts[vIdx++] = y2;
+ verts[vIdx++] = x2; verts[vIdx++] = y2;
+
+ colors[cIdx++] = color;
+ colors[cIdx++] = color;
+ colors[cIdx++] = color;
+ colors[cIdx++] = color;
}
graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
- CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
- graphics.pose(),
+ CustomRenderLayers.QUADS_CUSTOM_BLEND,
+ new Matrix3x2f(graphics.pose()),
verts, colors, graphics.scissorStack.peek()
));
}
@@ -324,7 +335,7 @@ public static void drawFilledGradientQuadrant(GuiGraphics graphics, float xCente
graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
verts, colors, graphics.scissorStack.peek()
));
}
@@ -364,7 +375,7 @@ public static void drawArc(GuiGraphics graphics, float xCenter, float yCenter, f
graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
CustomRenderLayers.TRIANGLE_FAN_CUSTOM_BLEND,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
verts, colors, graphics.scissorStack.peek()
));
}
@@ -399,7 +410,7 @@ public static void drawOutlineTriangle(GuiGraphics graphics, int x1, int y1, int
graphics.guiRenderState.submitGuiElement(new GeometryRenderState(
CustomRenderLayers.COLOR_LINE,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
vertices,
colors,
graphics.scissorStack.peek()
@@ -496,7 +507,7 @@ public static void drawRoundedRectangle(GuiGraphics graphics, float x, float y,
graphics.guiRenderState.submitGuiElement(new RoundedRectRenderState(
RenderPipelines.DEBUG_QUADS,
- graphics.pose(),
+ new Matrix3x2f(graphics.pose()),
x, y, width, height, -1f, intColors, radii, graphics.scissorStack.peek()
));
}
@@ -628,7 +639,7 @@ public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y,
/**
* Creating bounds for Render states
*/
- public static ScreenRectangle createBounds(Matrix3x2fStack pose, ScreenRectangle scissor, float x, float y, float w, float h) {
+ public static ScreenRectangle createBounds(Matrix3x2f pose, ScreenRectangle scissor, float x, float y, float w, float h) {
ScreenRectangle bounds = new ScreenRectangle((int) x, (int) y, (int) w, (int) h).transformAxisAligned(pose);
return scissor == null ? bounds : scissor.intersection(bounds);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
index 20a80b0..40a1b0b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
@@ -3,6 +3,5 @@
// AnimationProperty.java
public interface AnimationProperty {
T get();
-
void set(T value);
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
index 028e442..acdfccc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/MathAnimations.java
@@ -91,7 +91,7 @@ public static float lerp(float start, float end, long startTime, float duration)
/// Linear interpolation between values over time with easing
public static float lerp(float start, float end, long startTime, float duration, EasingType easing) {
float progress = (System.currentTimeMillis() - startTime) / duration;
- progress = Math.min(1, Math.max(0, progress)); // Clamp 0-1
+ progress = Math.clamp(progress, 0, 1);
return start + (end - start) * Easing.apply(easing, progress);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
index fbaa215..a264c1b 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/integration/IntegrationManager.java
@@ -32,7 +32,7 @@ public final class IntegrationManager {
public static final Map> FILE_MAP = new HashMap<>();
private static final List widgetRenderers = new ArrayList<>();
- private static boolean enableTestIntegration = false;
+ public static boolean IS_TEST_MODE = false;
public static void addWidgetRenderer(WidgetRenderer widgetRenderer) {
@@ -59,7 +59,7 @@ private static void checkToEnableTestIntegration() {
String[] args = FabricLoader.getInstance().getLaunchArguments(true);
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--dynamicHudTest") && i + 1 < args.length) {
- enableTestIntegration = Boolean.parseBoolean(args[i + 1]);
+ IS_TEST_MODE = Boolean.parseBoolean(args[i + 1]);
break;
}
}
@@ -72,7 +72,7 @@ public static void integrate() {
var integrations = new ArrayList<>(getRegisteredIntegrations());
- if (enableTestIntegration) {
+ if (IS_TEST_MODE) {
EntrypointContainer testIntegration = getTestIntegration();
if (testIntegration != null) {
integrations.add(testIntegration);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java b/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
index 8f2e442..0e25d22 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/mixins/BufferBuilderMixin.java
@@ -15,10 +15,7 @@ public abstract class BufferBuilderMixin implements VertexConsumer, IBufferBuild
@Shadow
protected abstract long beginElement(VertexFormatElement element);
- /**
- * The "Library" secret sauce.
- * This allows you to write N floats to a custom GENERIC element.
- */
+
@Unique
public VertexConsumer dynamicHUD$writeGenericFloats(VertexFormatElement element, float... values) {
long addr = this.beginElement(element);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
index eb2106b..2f5fbd8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GeometryRenderState.java
@@ -2,16 +2,17 @@
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fStack;
+import org.joml.Matrix3x2f;
// State for Geometric Shapes (Circles, Arcs, Fans)
public record GeometryRenderState(
RenderPipeline pipeline,
- Matrix3x2fStack pose,
+ Matrix3x2f pose,
float[] vertices, // Flat array: [x1, y1, x2, y2, ...]
int[] colors, // Parallel array of ARGB colors
@Nullable ScreenRectangle scissorArea
@@ -32,6 +33,23 @@ public TextureSetup textureSetup() {
@Override
public @Nullable ScreenRectangle bounds() {
- return null;
+ if (vertices == null || vertices.length < 2) return null;
+
+ float minX = Float.MAX_VALUE;
+ float minY = Float.MAX_VALUE;
+ float maxX = -Float.MAX_VALUE;
+ float maxY = -Float.MAX_VALUE;
+
+ for (int i = 0; i < vertices.length / 2; i++) {
+ float x = vertices[i * 2];
+ float y = vertices[i * 2 + 1];
+
+ if (x < minX) minX = x;
+ if (y < minY) minY = y;
+ if (x > maxX) maxX = x;
+ if (y > maxY) maxY = y;
+ }
+
+ return DrawHelper.createBounds(pose, scissorArea, minX, minY, maxX - minX, maxY - minY);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
index 1c177d8..5a0c3de 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/GradientShadowRenderState.java
@@ -7,7 +7,7 @@
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fStack;
+import org.joml.Matrix3x2f;
import org.joml.Matrix3x2fc;
import org.jspecify.annotations.NonNull;
@@ -19,7 +19,7 @@ public record GradientShadowRenderState(
float bottomY,
int startColor,
int endColor,
- Matrix3x2fStack pose,
+ Matrix3x2f pose,
RenderPipeline pipeline,
int width,
int height,
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
index 07a9e7f..f1addda 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/InterpolatedCurveRenderState.java
@@ -7,7 +7,7 @@
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fStack;
+import org.joml.Matrix3x2f;
import org.jspecify.annotations.NonNull;
import java.util.List;
@@ -16,7 +16,7 @@ public record InterpolatedCurveRenderState(
List points,
float thickness,
int color,
- Matrix3x2fStack pose,
+ Matrix3x2f pose,
RenderPipeline pipeline,
int width,
int height,
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
index e02892e..6edf7ca 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/QuadColorRectRenderState.java
@@ -6,13 +6,13 @@
import net.minecraft.client.gui.navigation.ScreenRectangle;
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
-import org.joml.Matrix3x2fStack;
+import org.joml.Matrix3x2f;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
public record QuadColorRectRenderState(
RenderPipeline pipeline,
- Matrix3x2fStack pose,
+ Matrix3x2f pose,
float x,
float y,
float width,
diff --git a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
index 4e39e3b..daf15eb 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/renderstates/RoundedRectRenderState.java
@@ -7,16 +7,19 @@
import net.minecraft.client.gui.render.TextureSetup;
import net.minecraft.client.gui.render.state.GuiElementRenderState;
import org.jetbrains.annotations.Nullable;
-import org.joml.Matrix3x2fStack;
+import org.joml.Matrix3x2f;
import org.joml.Vector4f;
import org.jspecify.annotations.NonNull;
import static com.tanishisherewith.dynamichud.helpers.DrawHelper.COSA;
import static com.tanishisherewith.dynamichud.helpers.DrawHelper.SINA;
+/**
+ * Using Matrix3x2f is essential for these shapes to be affected by MatrixStack changes.
+ */
public record RoundedRectRenderState(
RenderPipeline pipeline,
- Matrix3x2fStack pose,
+ Matrix3x2f pose,
float x, float y,
float width, float height,
float thickness,
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 65da6a9..f6b1860 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -2,11 +2,15 @@
import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.AnimationProperty;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.ValueAnimation;
import com.tanishisherewith.dynamichud.internal.System;
import com.tanishisherewith.dynamichud.utils.Input;
-import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenFactory;
-import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry;
-import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.DefaultContextMenuScreenFactory;
+import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutEngine;
+import com.tanishisherewith.dynamichud.utils.contextmenu.screen.factory.ContextMenuScreenFactory;
+import com.tanishisherewith.dynamichud.utils.contextmenu.screen.ContextMenuScreenRegistry;
+import com.tanishisherewith.dynamichud.utils.contextmenu.screen.factory.DefaultContextMenuScreenFactory;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
import com.tanishisherewith.dynamichud.widget.WidgetBox;
import net.minecraft.client.gui.GuiGraphics;
@@ -30,8 +34,9 @@ public class ContextMenu implements Input {
protected final List
> options = new ArrayList<>(); // The list of options in the context menu
protected final ContextMenuScreenFactory screenFactory;
public int x, y;
- // Width is counted while the options are being rendered.
- // FinalWidth is the width at the end of the count.
+
+ protected LayoutEngine layoutEngine;
+
protected int width = 0;
protected int height = 0, widgetHeight = 0;
protected boolean shouldDisplay = false;
@@ -39,6 +44,8 @@ public class ContextMenu implements Input {
protected Screen parentScreen = null;
protected boolean newScreenFlag = false;
+ private final ValueAnimation scaleAnimation;
+
@Nullable
private final ContextMenu> parentMenu;
@@ -61,6 +68,27 @@ public ContextMenu(int x, int y, @NotNull T properties, ContextMenuScreenFactory
this.darkerBackgroundColor = properties.getBackgroundColor().darker().darker().darker().darker().darker().darker();
this.parentMenu = parentMenu;
this.properties.getSkin().setContextMenu(this);
+ this.layoutEngine = new LayoutEngine();
+
+ this.scaleAnimation = new ValueAnimation(new AnimationProperty<>() {
+ @Override
+ public Float get() {
+ return scale;
+ }
+
+ @Override
+ public void set(Float value) {
+ scale = value;
+ }
+ }, 0.0f, 1.0f);
+ this.scaleAnimation.easing(EasingType.EASE_IN_CUBIC);
+ this.scaleAnimation.duration(280);
+ this.scaleAnimation.onComplete(() -> {
+ if (scale <= 0.0f && parentScreen != null && properties.getSkin().shouldCreateNewScreen()) {
+ DynamicHUD.MC.setScreen(parentScreen);
+ }
+ });
+
Screen dummy = screenFactory.create(this, properties);
System.registerInstance(new ContextMenuScreenRegistry(dummy.getClass()), DynamicHUD.MOD_ID);
@@ -71,18 +99,20 @@ public void addOption(Option> option) {
options.add(option);
}
- public void render(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {
+ public void render(GuiGraphics graphics, int xPos, int yPos, int mouseX, int mouseY) {
if (newScreenFlag && screenFactory != null) {
DynamicHUD.MC.setScreen(screenFactory.create(this, properties));
return;
}
- this.x = x;
- this.y = y + properties.getHeightOffset() + widgetHeight;
+ this.x = xPos;
+ this.y = yPos + properties.getHeightOffset() + widgetHeight;
+
update();
+
if (scale <= 0.0f || newScreenFlag) return;
- DrawHelper.scaleAndPosition(graphics.pose(), x, y, scale);
+ DrawHelper.scaleAndPosition(graphics.pose(), this.x + width/2.0f, this.y + height/2.0f, scale);
properties.getSkin().setContextMenu(this);
properties.getSkin().renderContextMenu(graphics, this, mouseX, mouseY);
@@ -91,19 +121,15 @@ public void render(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {
}
public void update() {
+ if (layoutEngine != null) {
+ layoutEngine.applyLayout(this);
+ }
if (!properties.enableAnimations()) {
- scale = 1.0f;
+ scale = shouldDisplay ? 1.0f : 0.0f;
return;
}
- // Update the scale
- if (shouldDisplay) {
- scale += 0.1f;
- } else {
- scale -= 0.1f;
- }
-
- scale = Math.clamp(scale, 0, 1.0f);
+ scaleAnimation.update();
}
public void close() {
@@ -112,8 +138,15 @@ public void close() {
for (Option> option : options) {
option.onClose();
}
- if (properties.getSkin().shouldCreateNewScreen() && scale <= 0 && parentScreen != null) {
- DynamicHUD.MC.setScreen(parentScreen);
+ if (properties.enableAnimations()) {
+ scaleAnimation.startValue(scale);
+ scaleAnimation.endValue(0.0f);
+ scaleAnimation.start();
+ } else {
+ scale = 0.0f;
+ if (properties.getSkin().shouldCreateNewScreen() && parentScreen != null) {
+ DynamicHUD.MC.setScreen(parentScreen);
+ }
}
}
@@ -124,6 +157,16 @@ public void open() {
if (properties.getSkin().shouldCreateNewScreen()) {
newScreenFlag = true;
}
+ if (properties.enableAnimations()) {
+ scaleAnimation.startValue(scale);
+ scaleAnimation.endValue(1.0f);
+ scaleAnimation.start();
+ } else {
+ scale = 0.0f;
+ if (properties.getSkin().shouldCreateNewScreen() && parentScreen != null) {
+ DynamicHUD.MC.setScreen(parentScreen);
+ }
+ }
}
public void toggleDisplay() {
@@ -146,11 +189,21 @@ public void resetAllOptions() {
}
}
+ public LayoutEngine getLayoutEngine() {
+ return layoutEngine;
+ }
+
+ public void setLayoutEngine(LayoutEngine layoutEngine) {
+ this.layoutEngine = layoutEngine;
+ }
+
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (!shouldDisplay) return false;
for (Option option : options) {
- option.getRenderer().mouseClicked(option, mouseX, mouseY, button);
+ if (option.shouldRender() && option.getRenderer().mouseClicked(option ,mouseX, mouseY, button)) {
+ return true;
+ }
}
return properties.getSkin().mouseClicked(this, mouseX, mouseY, button);
}
@@ -159,7 +212,9 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (!shouldDisplay) return false;
for (Option option : options) {
- option.getRenderer().mouseReleased(option, mouseX, mouseY, button);
+ if(option.shouldRender() && option.getRenderer().mouseReleased(option, mouseX, mouseY, button)){
+ return true;
+ }
}
return properties.getSkin().mouseReleased(this, mouseX, mouseY, button);
}
@@ -168,7 +223,9 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (!shouldDisplay) return false;
for (Option option : options) {
- option.getRenderer().mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
+ if(option.shouldRender() && option.getRenderer().mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY)){
+ return true;
+ }
}
return properties.getSkin().mouseDragged(this, mouseX, mouseY, button, deltaX, deltaY);
}
@@ -177,7 +234,9 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
public void keyPressed(int key, int scanCode, int modifiers) {
if (!shouldDisplay) return;
for (Option option : options) {
- option.getRenderer().keyPressed(option, key, scanCode, modifiers);
+ if(option.shouldRender()){
+ option.getRenderer().keyPressed(option, key, scanCode, modifiers);
+ }
}
properties.getSkin().keyPressed(this, key, scanCode, modifiers);
@@ -187,7 +246,9 @@ public void keyPressed(int key, int scanCode, int modifiers) {
public void keyReleased(int key, int scanCode, int modifiers) {
if (!shouldDisplay) return;
for (Option option : options) {
- option.getRenderer().keyReleased(option, key, scanCode, modifiers);
+ if(option.shouldRender()) {
+ option.getRenderer().keyReleased(option, key, scanCode, modifiers);
+ }
}
properties.getSkin().keyReleased(this, key, scanCode, modifiers);
@@ -197,7 +258,9 @@ public void keyReleased(int key, int scanCode, int modifiers) {
public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
if (!shouldDisplay) return;
for (Option option : options) {
- option.getRenderer().mouseScrolled(option, mouseX, mouseY, horizontalAmount, verticalAmount);
+ if(option.shouldRender()) {
+ option.getRenderer().mouseScrolled(option, mouseX, mouseY, horizontalAmount, verticalAmount);
+ }
}
properties.getSkin().mouseScrolled(this, mouseX, mouseY, horizontalAmount, verticalAmount);
}
@@ -206,7 +269,9 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount,
public void charTyped(char c, int modifiers) {
if (!shouldDisplay) return;
for (Option> option : options) {
- option.charTyped(c, modifiers);
+ if(option.shouldRender()) {
+ option.charTyped(c, modifiers);
+ }
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
index 3e45992..bbb23b9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenuProperties.java
@@ -10,6 +10,7 @@
*/
public class ContextMenuProperties {
protected Color backgroundColor = new Color(107, 112, 126, 124);
+ protected Color accentColor = new Color(104, 151, 187, 255); // Color.CYAN.darker().darker();
protected Color borderColor = Color.BLACK;
protected float borderWidth = 1f;
protected int padding = 5; // The amount of padding around the rectangle
@@ -91,6 +92,10 @@ public Skin getSkin() {
return skin;
}
+ public Color getAccentColor() {
+ return accentColor;
+ }
+
/**
* @return Cloned object of every property except skin
*/
@@ -144,6 +149,11 @@ public Builder backgroundColor(Color backgroundColor) {
return this;
}
+ public Builder accentColor(Color accentColor) {
+ properties.accentColor = accentColor;
+ return this;
+ }
+
public Builder borderColor(Color borderColor) {
properties.borderColor = borderColor;
return this;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
new file mode 100644
index 0000000..4f1d5f1
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
@@ -0,0 +1,166 @@
+package com.tanishisherewith.dynamichud.utils.contextmenu.layout;
+import com.tanishisherewith.dynamichud.DynamicHUD;
+import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
+import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Font;
+
+import java.util.List;
+
+public class LayoutEngine {
+ private int horizontalPadding = 8;
+ private int verticalPadding = 4;
+ private int itemSpacing = 2;
+ private int minWidth = 80;
+ private LayoutStrategy activeStrategy = new VerticalFlowStrategy();
+
+ public LayoutEngine() {}
+
+ public LayoutEngine(int horizontalPadding, int verticalPadding, int itemSpacing, int minWidth) {
+ this.horizontalPadding = horizontalPadding;
+ this.verticalPadding = verticalPadding;
+ this.itemSpacing = itemSpacing;
+ this.minWidth = minWidth;
+ }
+
+ @FunctionalInterface
+ public interface LayoutStrategy {
+ /**
+ * Computes dimensions and positions options within the context menu.
+ */
+ void layout(ContextMenu> menu, LayoutEngine engine);
+ }
+
+
+ /**
+ * Executes the currently active layout strategy to position and size options dynamically.
+ */
+ public void applyLayout(ContextMenu> menu) {
+ if (activeStrategy != null) {
+ activeStrategy.layout(menu, this);
+ }
+ }
+
+ /**
+ * Linear layout for skins that need to know their total dimensions
+ */
+ public void performSimpleLayout(ContextMenu> menu) {
+ if (menu == null) return;
+
+ Font font = Minecraft.getInstance().font;
+ List
> visibleOptions = menu.getProperties().getSkin().getOptions(menu);
+ int paddingValue = menu.getProperties().getPadding();
+
+ //width calculation
+ int maxInnerWidth = minWidth;
+ for (Option> option : visibleOptions) {
+ if (!option.shouldRender()) continue;
+
+ int preferredWidth = option.getWidth() > 0 ? option.getWidth() : font.width(option.getName());
+
+ maxInnerWidth = Math.max(maxInnerWidth, preferredWidth);
+ }
+
+ int totalMenuWidth = maxInnerWidth + (horizontalPadding * 2) + paddingValue;
+
+ int currentY = menu.getY() + verticalPadding + 3;
+ int currentX = menu.getX() + horizontalPadding;
+
+ // height calculation
+ for (Option> option : visibleOptions) {
+ if (!option.shouldRender()) continue;
+
+ int itemHeight = option.getHeight() > 0 ? option.getHeight() : font.lineHeight;
+
+ option.setWidth(totalMenuWidth - (horizontalPadding * 2) - paddingValue);
+ option.setHeight(itemHeight);
+ option.setPosition(currentX, currentY);
+
+ currentY += itemHeight + itemSpacing;
+ }
+
+ menu.setWidth(totalMenuWidth);
+ menu.setHeight(currentY - menu.getY());
+ }
+
+ /**
+ * Helper function for immediate layouts
+ * Automatically updates the option's dimensions and returns the updated Y position for the next element.
+ *
+ * @param option option to arrange.
+ * @param x start X coordinate.
+ * @param y start Y coordinate.
+ * @param targetWidth horizontal width for the option.
+ * @return next Y coordinate.
+ */
+ public int layoutOption(Option> option, int x, int y, int targetWidth) {
+ if (option == null || !option.shouldRender()) return y;
+
+ int itemHeight = option.getHeight() > 0 ? option.getHeight() : DynamicHUD.MC.font.lineHeight;
+
+ option.setPosition(x, y);
+ option.setWidth(targetWidth);
+ option.setHeight(itemHeight);
+
+ return y + itemHeight + itemSpacing;
+ }
+
+
+ public LayoutStrategy getActiveStrategy() {
+ return activeStrategy;
+ }
+
+ public void setActiveStrategy(LayoutStrategy activeStrategy) {
+ this.activeStrategy = activeStrategy;
+ }
+
+ public int getHorizontalPadding() { return horizontalPadding; }
+ public void setHorizontalPadding(int horizontalPadding) { this.horizontalPadding = horizontalPadding; }
+
+ public int getVerticalPadding() { return verticalPadding; }
+ public void setVerticalPadding(int verticalPadding) { this.verticalPadding = verticalPadding; }
+
+ public int getItemSpacing() { return itemSpacing; }
+ public void setItemSpacing(int itemSpacing) { this.itemSpacing = itemSpacing; }
+
+ public int getMinWidth() { return minWidth; }
+ public void setMinWidth(int minWidth) { this.minWidth = minWidth; }
+
+ /**
+ * Default layout strategy that arranges items in a single vertical column.
+ * Automatically scales the menu width to match the longest option.
+ */
+ public static class VerticalFlowStrategy implements LayoutStrategy {
+ @Override
+ public void layout(ContextMenu> menu, LayoutEngine engine) {
+ if (menu == null || menu.getProperties() == null) return;
+
+ Font font = Minecraft.getInstance().font;
+ List
> visibleOptions = menu.getProperties().getSkin().getOptions(menu);
+ int paddingValue = menu.getProperties().getPadding();
+
+ // width calc
+ int maxInnerWidth = engine.getMinWidth();
+ for (Option> option : visibleOptions) {
+ if (!option.shouldRender()) continue;
+ int preferredWidth = option.getWidth() > 0 ? option.getWidth() : font.width(option.getName());
+ maxInnerWidth = Math.max(maxInnerWidth, preferredWidth);
+ }
+
+ int totalMenuWidth = maxInnerWidth + (engine.getHorizontalPadding() * 2) + paddingValue;
+
+ // height calc
+ int currentY = menu.getY() + engine.getVerticalPadding() + 3;
+ int currentX = menu.getX() + engine.getHorizontalPadding();
+ int targetWidth = totalMenuWidth - (engine.getHorizontalPadding() * 2) - paddingValue;
+
+ for (Option> option : visibleOptions) {
+ if (!option.shouldRender()) continue;
+ currentY = engine.layoutOption(option, currentX, currentY, targetWidth);
+ }
+
+ menu.setWidth(totalMenuWidth);
+ menu.setHeight(currentY - menu.getY());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
index a4764d8..f0f0056 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/BooleanOption.java
@@ -15,7 +15,6 @@ public class BooleanOption extends Option {
public BooleanOption(Component name, Supplier getter, Consumer setter, BooleanType booleanType) {
super(name, getter, setter);
this.booleanType = booleanType;
- this.renderer.init(this);
}
public BooleanOption(Component name, Supplier getter, Consumer setter) {
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 c0f341d..9f4eb93 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
@@ -17,7 +17,6 @@ public ColorOption(Component name, Supplier getter, Consumer sette
super(name, getter, setter);
this.parentMenu = parentMenu;
this.colorGradient = new ColorGradient(x + this.parentMenu.getWidth(), y - 10, get(), this::set, 50, 100);
- this.renderer.init(this);
}
@Override
@@ -30,21 +29,19 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
} else {
colorGradient.close();
}
+ return true;
}
- colorGradient.mouseClicked(mouseX, mouseY, button);
- return super.mouseClicked(mouseX, mouseY, button);
+ return colorGradient.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
- colorGradient.mouseReleased(mouseX, mouseY, button);
- return super.mouseReleased(mouseX, mouseY, button);
+ return colorGradient.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
- colorGradient.mouseDragged(mouseX, mouseY, button);
- return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
+ return colorGradient.mouseDragged(mouseX, mouseY, button);
}
public ColorGradient getColorGradient() {
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 14208f4..e7e5d25 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
@@ -28,7 +28,6 @@ public DoubleOption(Component name, double minValue, double maxValue, float step
this.step = step;
this.parentMenu = parentMenu;
Validate.isTrue(this.step > 0.0f, "Step cannot be less than or equal to 0 (zero)");
- this.renderer.init(this);
}
public void drawSlider(GuiGraphics graphics, int sliderX, int sliderY, int sliderWidth, double handleX) {
@@ -43,8 +42,9 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (super.mouseClicked(mouseX, mouseY, button) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
step(mouseX);
isDragging = true;
+ return true;
}
- return true;
+ return false;
}
@Override
@@ -57,7 +57,7 @@ private void step(double mouseX) {
this.step(mouseX, x);
}
- public void step(double mouseX, double x) {
+ public void step(double mouseX, double x, double width) {
double newValue = minValue + (float) (mouseX - x) / width * (maxValue - minValue);
// Round the new value to the nearest step
newValue = Math.round(newValue / step) * step;
@@ -66,10 +66,16 @@ public void step(double mouseX, double x) {
}
+ public void step(double mouseX, double x) {
+ this.step(mouseX, x, width);
+ }
+
+
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (isMouseOver(mouseX, mouseY) && isDragging) {
step(mouseX);
+ return true;
}
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
index f71cee2..ffb0350 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
@@ -19,7 +19,6 @@ public EnumOption(Component name, Supplier getter, Consumer setter, E[] va
break;
}
}
- this.renderer.init(this);
}
@Override
@@ -39,8 +38,9 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
value = values[currentIndex];
}
set(value);
+ return true;
}
- return true;
+ return false;
}
public E[] getValues() {
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 d948664..f87a648 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
@@ -20,7 +20,6 @@ public ListOption(Component name, Supplier getter, Consumer setter, List getValues() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
index 137b4c6..2142ccc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
@@ -61,6 +61,7 @@ public void updateProperties(ContextMenuProperties properties) {
DynamicHUD.logger.error("Renderer not found for class: {} in the following skin: {}", this.getClass().getName(), properties.getSkin());
throw new RuntimeException();
}
+ this.renderer.init(this);
}
public void render(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
index ec68a50..33b0c5a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
@@ -71,10 +71,14 @@ public void render(GuiGraphics graphics, Option option, int x, int
public boolean mouseClicked(Option option2, double mouseX, double mouseY, int button) {
OptionGroup option = (OptionGroup) option2;
- for (Option subOption : option.getGroupOptions()) {
- subOption.getRenderer().mouseClicked(subOption, mouseX, mouseY, button);
+ if (option.isExpanded()) {
+ for (Option subOption : option.getGroupOptions()) {
+ if (subOption.getRenderer().mouseClicked(subOption, mouseX, mouseY, button)) {
+ return true;
+ }
+ }
}
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ return false;
}
@Override
@@ -82,9 +86,9 @@ public boolean mouseReleased(Option option2, double mouseX, double
OptionGroup option = (OptionGroup) option2;
for (Option subOption : option.getGroupOptions()) {
- subOption.getRenderer().mouseReleased(subOption, mouseX, mouseY, button);
+ if(subOption.getRenderer().mouseReleased(subOption, mouseX, mouseY, button)) return true;
}
- return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
+ return false;
}
@Override
@@ -92,9 +96,9 @@ public boolean mouseDragged(Option option2, double mouseX, double m
OptionGroup option = (OptionGroup) option2;
for (Option subOption : option.getGroupOptions()) {
- subOption.getRenderer().mouseDragged(subOption, mouseX, mouseY, button, deltaX, deltaY);
+ if(subOption.getRenderer().mouseDragged(subOption, mouseX, mouseY, button, deltaX, deltaY)) return true;
}
- return SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
+ return false;
}
@Override
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 ce18f5e..8605735 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
@@ -22,7 +22,6 @@ public RunnableOption(Component name, Supplier getter, Consumer SubMenuOption(Component name, ContextMe
this.subMenu = parentMenu.createSubMenu(parentMenu.x + parentMenu.getWidth(), this.y, properties.cloneSkin());
this.subMenu.getProperties().setHeightOffset(0);
this.subMenu.setVisible(get());
- this.renderer.init(this);
}
public SubMenuOption(Component name, ContextMenu> parentMenu, T properties) {
@@ -43,24 +42,25 @@ public SubMenuOption(Component name, ContextMe
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (super.mouseClicked(mouseX, mouseY, button)) {
- subMenu.toggleDisplay();
- set(subMenu.isVisible());
+ toggle();
return true;
}
- subMenu.mouseClicked(mouseX, mouseY, button);
- return false;
+ return subMenu.mouseClicked(mouseX, mouseY, button);
+ }
+
+ public void toggle(){
+ subMenu.toggleDisplay();
+ set(subMenu.isVisible());
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
- subMenu.mouseReleased(mouseX, mouseY, button);
- return super.mouseReleased(mouseX, mouseY, button);
+ return subMenu.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
- subMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
- return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
+ return subMenu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
public SubMenuOption getOption() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
index 14379a8..ed82651 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/coloroption/ColorGradient.java
@@ -1,7 +1,6 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.options.coloroption;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
-import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.MouseColorQuery;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
@@ -111,15 +110,16 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
return true;
}
- public void mouseReleased(double mouseX, double mouseY, int button) {
+ public boolean mouseReleased(double mouseX, double mouseY, int button) {
gradientSlider.onRelease(mouseX, mouseY, button);
gradientBox.onRelease(mouseX, mouseY, button);
alphaSlider.onRelease(mouseX, mouseY, button);
+ return false;
}
- public void mouseDragged(double mouseX, double mouseY, int button) {
+ public boolean mouseDragged(double mouseX, double mouseY, int button) {
if (!display) {
- return;
+ return false;
}
gradientSlider.onDrag(mouseX, mouseY, button);
gradientBox.setHue(gradientSlider.getHue());
@@ -127,6 +127,7 @@ public void mouseDragged(double mouseX, double mouseY, int button) {
alphaSlider.setColor(new Color(gradientBox.getColor(), true));
alphaSlider.onDrag(mouseX, mouseY, button);
onColorSelected.accept(alphaSlider.getColor());
+ return true;
}
public int getBoxSize() {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
similarity index 94%
rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java
rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
index eeba531..28c6cca 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
@@ -1,4 +1,4 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen;
+package com.tanishisherewith.dynamichud.utils.contextmenu.screen;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
@@ -13,7 +13,7 @@ public class ContextMenuScreen extends Screen {
ContextMenu> contextMenu;
ContextMenuProperties properties;
- protected ContextMenuScreen(ContextMenu> menu, ContextMenuProperties properties) {
+ public ContextMenuScreen(ContextMenu> menu, ContextMenuProperties properties) {
super(Component.literal("ContextMenu screen"));
this.contextMenu = menu;
this.properties = properties;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreenRegistry.java
similarity index 77%
rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreenRegistry.java
index 3e8ee1d..058548f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenRegistry.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreenRegistry.java
@@ -1,4 +1,4 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen;
+package com.tanishisherewith.dynamichud.utils.contextmenu.screen;
import net.minecraft.client.gui.screens.Screen;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/ContextMenuScreenFactory.java
similarity index 89%
rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java
rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/ContextMenuScreenFactory.java
index b66b0c7..66b60da 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/ContextMenuScreenFactory.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/ContextMenuScreenFactory.java
@@ -1,4 +1,4 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen;
+package com.tanishisherewith.dynamichud.utils.contextmenu.screen.factory;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/DefaultContextMenuScreenFactory.java
similarity index 78%
rename from src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java
rename to src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/DefaultContextMenuScreenFactory.java
index 1b0bbc9..589d38f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/contextmenuscreen/DefaultContextMenuScreenFactory.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/factory/DefaultContextMenuScreenFactory.java
@@ -1,7 +1,8 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen;
+package com.tanishisherewith.dynamichud.utils.contextmenu.screen.factory;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
+import com.tanishisherewith.dynamichud.utils.contextmenu.screen.ContextMenuScreen;
import net.minecraft.client.gui.screens.Screen;
/**
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
index 1298a56..89bbe7c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
@@ -1,5 +1,6 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem;
+import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
@@ -8,26 +9,23 @@
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
-import org.apache.logging.log4j.core.pattern.TextRenderer;
-import org.joml.Matrix3x2fStack;
import java.awt.*;
-
/**
* This is one of the Skins provided by DynamicHUD featuring the classic rendering,
* which should be used when you have a low amount of settings and want quicker way of changing the settings.
*/
public class ClassicSkin extends Skin {
+
public ClassicSkin() {
super();
-
addRenderer(BooleanOption.class, ClassicBooleanRenderer::new);
- addRenderer(DoubleOption.class, ClassicDoubleRenderer::new);
+ addRenderer(ColorOption.class, ClassicColorOptionRenderer::new);
addRenderer(EnumOption.class, ClassicEnumRenderer::new);
addRenderer(ListOption.class, ClassicListRenderer::new);
addRenderer(SubMenuOption.class, ClassicSubMenuRenderer::new);
addRenderer(RunnableOption.class, ClassicRunnableRenderer::new);
- addRenderer(ColorOption.class, ClassicColorOptionRenderer::new);
+ addRenderer(DoubleOption.class, ClassicDoubleRenderer::new);
setCreateNewScreen(false);
}
@@ -35,31 +33,24 @@ public ClassicSkin() {
@Override
public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu, int mouseX, int mouseY) {
this.contextMenu = contextMenu;
-
- Matrix3x2fStack matrices = graphics.pose();
ContextMenuProperties properties = contextMenu.getProperties();
- // Draw the background
+ if (contextMenu.getLayoutEngine() != null) {
+ contextMenu.getLayoutEngine().applyLayout(contextMenu);
+ }
+
drawBackground(graphics, contextMenu, properties);
- int yOffset = contextMenu.y + 3;
- int width = 10;
for (Option> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
- // Adjust mouse coordinates based on the scale
- if (contextMenu.getProperties().hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, contextMenu.x + 1, yOffset - 1, contextMenu.getWidth() - 2, option.getHeight())) {
- drawBackground(graphics, contextMenu, properties, yOffset - 1, contextMenu.getWidth(), option.getHeight() + 1, contextMenu.getProperties().getHoverColor().getRGB(), false);
+ if (properties.hoverEffect() && contextMenu.isMouseOver(mouseX, mouseY, option.getX() - 3, option.getY() - 1, contextMenu.getWidth() - 2, option.getHeight())) {
+ drawBackground(graphics, contextMenu, properties, option.getY() - 1, contextMenu.getWidth(), option.getHeight() + 1, properties.getHoverColor().getRGB(), false);
}
- option.render(graphics, contextMenu.x + 4, yOffset, mouseX, mouseY);
- width = Math.max(width, option.getWidth());
- yOffset += option.getHeight() + 1;
+ option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
}
- contextMenu.setWidth(width + properties.getPadding());
- contextMenu.setHeight(yOffset - contextMenu.y);
- // Draw the border if needed
if (properties.shouldDrawBorder()) {
drawBorder(graphics, contextMenu, properties);
}
@@ -71,74 +62,25 @@ private void drawBackground(GuiGraphics graphics, ContextMenu> contextMenu, Co
private void drawBackground(GuiGraphics graphics, ContextMenu> contextMenu, ContextMenuProperties properties, int yOffset, int width, int height, int color, boolean shadow) {
if (properties.roundedCorners()) {
- // Rounded
if (shadow) {
- DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
- contextMenu.x,
- yOffset,
- width,
- height,
- properties.getCornerRadius(),
- color,
- 150,
- 1,
- 1
- );
+ DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics, contextMenu.x, yOffset, width, height, properties.getCornerRadius(), color, 150, 1, 1);
} else {
- DrawHelper.drawRoundedRectangle(graphics,
- contextMenu.x,
- yOffset,
- width,
- height,
- properties.getCornerRadius(),
- color
- );
+ DrawHelper.drawRoundedRectangle(graphics, contextMenu.x, yOffset, width, height, properties.getCornerRadius(), color);
}
} else {
- // Normal
if (shadow) {
- DrawHelper.drawRectangleWithShadowBadWay(graphics,
- contextMenu.x,
- yOffset,
- width,
- height,
- color,
- 150,
- 1,
- 1
- );
+ DrawHelper.drawRectangleWithShadowBadWay(graphics, contextMenu.x, yOffset, width, height, color, 150, 1, 1);
} else {
- DrawHelper.drawRectangle(graphics,
- contextMenu.x,
- yOffset,
- width,
- height,
- color
- );
+ DrawHelper.drawRectangle(graphics, contextMenu.x, yOffset, width, height, color);
}
}
}
private void drawBorder(GuiGraphics graphics, ContextMenu> contextMenu, ContextMenuProperties properties) {
if (properties.roundedCorners()) {
- DrawHelper.drawOutlineRoundedBox(graphics,
- contextMenu.x,
- contextMenu.y,
- contextMenu.getWidth(),
- contextMenu.getHeight(),
- properties.getCornerRadius(),
- properties.getBorderWidth(),
- properties.getBorderColor().getRGB()
- );
+ DrawHelper.drawOutlineRoundedBox(graphics, contextMenu.x, contextMenu.y, contextMenu.getWidth(), contextMenu.getHeight(), properties.getCornerRadius(), properties.getBorderWidth(), properties.getBorderColor().getRGB());
} else {
- DrawHelper.drawOutlineBox(graphics,
- contextMenu.x,
- contextMenu.y,
- contextMenu.getWidth(),
- contextMenu.getHeight(),
- properties.getBorderWidth(),
- properties.getBorderColor().getRGB()
- );
+ DrawHelper.drawOutlineBox(graphics, contextMenu.x, contextMenu.y, contextMenu.getWidth(), contextMenu.getHeight(), properties.getBorderWidth(), properties.getBorderColor().getRGB());
}
}
@@ -147,13 +89,12 @@ public Skin clone() {
return new ClassicSkin();
}
+
public static class ClassicBooleanRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, BooleanOption option, int x, int y, int mouseX, int mouseY) {
- int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB();
+ int color = option.get() ? Color.GREEN.getRGB() : Color.RED.getRGB();
graphics.drawString(mc.font, option.name, x, y, color, false);
- option.setHeight(mc.font.lineHeight);
- option.setWidth(mc.font.width(option.name) + 1);
}
}
@@ -162,12 +103,10 @@ public static class ClassicColorOptionRenderer implements SkinRenderer> implements SkinRenderer> {
@Override
public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(mc.font.lineHeight + 1);
- option.setWidth(mc.font.width(option.name + ": " + option.value.name()) + 1);
-
graphics.drawString(mc.font, option.name.copy().append(": "), x, y, Color.WHITE.getRGB(), false);
- graphics.drawString(mc.font, option.value.name(), x + mc.font.width(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false);
+ graphics.drawString(mc.font, option.get().name(), x + mc.font.width(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false);
+ }
+ }
+
+ public static class ClassicListRenderer implements SkinRenderer> {
+ @Override
+ public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
+ graphics.drawString(mc.font, option.name.copy().append(": "), x, y + 1, Color.WHITE.getRGB(), false);
+ graphics.drawString(mc.font, option.get().toString(), x + mc.font.width(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false);
}
}
@@ -199,41 +143,25 @@ public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int
graphics.drawString(mc.font, option.name, x, y, color, false);
graphics.drawString(mc.font, option.getSubMenu().isVisible() ? "-" : "+", x + Math.max(option.getParentMenu().getWidth() - 12, mc.font.width(option.name) + 2), y, color, false);
- option.setHeight(mc.font.lineHeight);
- option.setWidth(mc.font.width(option.name) + 4);
-
option.getSubMenu().render(graphics, x + option.getParentMenu().getWidth(), y - 1, mouseX, mouseY);
}
}
public static class ClassicRunnableRenderer implements SkinRenderer {
- Color DARK_RED = new Color(116, 0, 0);
- Color DARK_GREEN = new Color(24, 132, 0, 226);
-
@Override
public void render(GuiGraphics graphics, RunnableOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(mc.font.lineHeight);
- option.setWidth(mc.font.width("Run: " + option.name));
- int color = option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB();
+ int color = option.value ? ColorHelper.DARK_GREEN.getRGB() : ColorHelper.DARK_RED.getRGB();
graphics.drawString(mc.font, Component.literal("Run: ").append(option.name), x, y, color, false);
}
}
- public class ClassicDoubleRenderer implements SkinRenderer {
+ public static class ClassicDoubleRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int mouseX, int mouseY) {
- option.setWidth(Math.max(35, contextMenu != null ? contextMenu.getWidth() - option.getProperties().getPadding() - 2 : 0));
- option.setHeight(16);
-
- // Draw the label
Font font = mc.font;
DrawHelper.scaleAndPosition(graphics.pose(), x, y, 0.7f);
Component labelText = option.name.copy().append(": " + String.format("%.1f", option.value));
- int labelWidth = font.width(labelText);
-
- option.setWidth(Math.max(option.getWidth(), labelWidth));
-
- graphics.drawString(font, labelText, x, y + 1, 0xFFFFFFFF,true);
+ graphics.drawString(font, labelText, x, y + 1, 0xFFFFFFFF, true);
DrawHelper.stopScaling(graphics.pose());
float handleWidth = 3;
@@ -241,10 +169,8 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
double handleX = x + (option.value - option.minValue) / (option.maxValue - option.minValue) * (option.getWidth() - handleWidth);
double handleY = y + font.lineHeight + 1 + ((2 - handleHeight) / 2);
- // Draw the slider
option.drawSlider(graphics, x, y + font.lineHeight + 1, option.getWidth(), handleX);
- // Draw the handle
DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
(float) handleX,
(float) handleY,
@@ -255,18 +181,6 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
90,
0.6f,
0.6f);
-
- }
- }
-
- public static class ClassicListRenderer implements SkinRenderer> {
- @Override
- public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(mc.font.lineHeight + 1);
- option.setWidth(mc.font.width(option.name + ": " + option.value.toString()) + 1);
-
- graphics.drawString(mc.font, option.name.copy().append(": "), x, y + 1, Color.WHITE.getRGB(), false);
- graphics.drawString(mc.font, option.value.toString(), x + mc.font.width(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false);
}
}
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
index 9aeb548..9266750 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
@@ -2,6 +2,9 @@
import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.AnimationProperty;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.ValueAnimation;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutContext;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
@@ -22,6 +25,9 @@
import java.util.List;
import java.util.function.IntSupplier;
+import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_GREEN;
+import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_RED;
+
/**
* This is one of the Skins provided by DynamicHUD featuring the minecraft-like style rendering.
* It runs on a separate screen and provides more complex features like scrolling and larger dimension.
@@ -33,26 +39,28 @@ public class MinecraftSkin extends Skin implements GroupableSkin {
Identifier.withDefaultNamespace("widget/button_disabled"),
Identifier.withDefaultNamespace("widget/button_highlighted")
);
- public static final int DEFAULT_SCROLLBAR_WIDTH = 8;
- public static final int DEFAULT_PANEL_WIDTH = 248;
- public static final int DEFAULT_PANEL_HEIGHT = 165;
public static final Identifier DEFAULT_BACKGROUND_PANEL = Identifier.withDefaultNamespace("textures/gui/demo_background.png");
public static final Identifier SCROLLER_TEXTURE = Identifier.withDefaultNamespace("widget/scroller");
public static final Identifier SCROLL_BAR_BACKGROUND = Identifier.withDefaultNamespace("widget/scroller_background");
public static final Identifier GROUP_BACKGROUND = Identifier.fromNamespaceAndPath(DynamicHUD.MOD_ID, "textures/minecraftskin/group_panel.png");
private final Identifier BACKGROUND_PANEL;
+
+ public static final int DEFAULT_SCROLLBAR_WIDTH = 8;
+ public static final int DEFAULT_PANEL_WIDTH = 248;
+ public static final int DEFAULT_PANEL_HEIGHT = 165;
private final int panelWidth;
private final int panelHeight;
- private PanelColor panelColor;
+ private final int groupPanelWidth = 60; // Width for the group panel
private int imageX, imageY;
private final ScrollHandler scrollHandler;
private List optionGroups;
private OptionGroup selectedGroup;
+
+ private PanelColor panelColor;
private final ScrollHandler groupScrollHandler;
- private final int groupPanelWidth = 60; // Width for the group panel
private final IntSupplier groupPanelX = () -> imageX - groupPanelWidth - 15;
public MinecraftSkin(PanelColor color) {
@@ -102,6 +110,19 @@ private void initOptionGroups() {
}
}
+ private int getOptionHeight(Option> option) {
+ if (option instanceof SubMenuOption) return 20;
+ if (option instanceof ColorOption colorOption) {
+ int baseHeight = 25;
+ if (colorOption.getColorGradient().shouldDisplay()) {
+ int colorGradientHeight = colorOption.getColorGradient().getBoxSize() + 10 + colorOption.getColorGradient().getGradientSlider().getHeight();
+ return baseHeight + colorGradientHeight;
+ }
+ return baseHeight;
+ }
+ return 25;
+ }
+
@Override
public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu, int mouseX, int mouseY) {
this.contextMenu = contextMenu;
@@ -185,13 +206,17 @@ private void renderOptionGroups(GuiGraphics graphics, int mouseX, int mouseY) {
private int renderSelectedGroupOptions(GuiGraphics graphics, int mouseX, int mouseY) {
int yOffset = imageY + 12 - scrollHandler.getScrollOffset();
+ int targetWidth = panelWidth - 25;
+
for (Option> option : selectedGroup.getGroupOptions()) {
if (!option.shouldRender()) continue;
- if (yOffset >= imageY - option.getHeight() && yOffset <= imageY + option.getHeight() + panelHeight) {
- option.render(graphics, imageX + 4, yOffset, mouseX, mouseY);
+ option.setHeight(getOptionHeight(option));
+ yOffset = contextMenu.getLayoutEngine().layoutOption(option, imageX + 4, yOffset, targetWidth);
+
+ if (option.getY() >= imageY - option.getHeight() && option.getY() <= imageY + option.getHeight() + panelHeight) {
+ option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
}
- yOffset += option.getHeight() + 1;
}
return yOffset;
}
@@ -390,21 +415,44 @@ public void render(GuiGraphics graphics, BooleanOption option, int x, int y, int
int color = option.value ? Color.GREEN.getRGB() : Color.RED.getRGB();
graphics.drawString(mc.font, Component, (int) (option.getX() + (width / 2.0f) - (mc.font.width(Component) / 2.0f)), y + 5, color, true);
- option.setHeight(25);
//Widths don't matter in this skin
option.setWidth(width);
}
+ }
+
+ public class MinecraftColorOptionRenderer implements SkinRenderer {
+ private ValueAnimation scaleAnimation;
+ private float scale = 0.0f;
@Override
- public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY, int button) {
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ public void init(ColorOption option) {
+ this.scaleAnimation = new ValueAnimation(new AnimationProperty<>() {
+ @Override
+ public Float get() {
+ return scale;
+ }
+
+ @Override
+ public void set(Float value) {
+ scale = value;
+ }
+ }, 0.0f, 1.0f);
+ scaleAnimation.easing(EasingType.EASE_OUT_BACK);
+ scaleAnimation.duration(200);
+ this.scaleAnimation.onComplete(() -> {
+ if (scale <= 0.0f) {
+ option.getColorGradient().close();
+ }
+ });
}
- }
- public class MinecraftColorOptionRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, ColorOption option, int x, int y, int mouseX, int mouseY) {
+ if (scaleAnimation != null) {
+ scaleAnimation.update();
+ }
+
graphics.drawString(mc.font, option.name, x + 15, y + 25 / 2 - 5, -1, true);
option.setPosition(x + panelWidth - 45, y);
@@ -423,26 +471,71 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
1,
1);
-
- option.setHeight(25);
option.setWidth(width);
if (option.getColorGradient().getColorPickerButton().isPicking()) {
- DrawHelper.disableScissor(graphics); // Disable scissor test for the colorpicker
+ DrawHelper.disableScissor(graphics);
}
- //TODO: WHAT IS THISSSSS
+
int colorGradientWidth = option.getColorGradient().getBoxSize() + option.getColorGradient().getAlphaSlider().getWidth() + option.getColorGradient().getColorPickerButton().getWidth();
- option.getColorGradient().render(graphics, x + panelWidth / 2 - colorGradientWidth / 2, y + 12, mouseX, mouseY);
+ int pickerX = x + panelWidth / 2 - colorGradientWidth / 2;
+ int pickerY = y + 12;
- if (option.getColorGradient().shouldDisplay()) {
+ if (scale > 0.0f) {
+ DrawHelper.scaleAndPosition(graphics.pose(), pickerX + colorGradientWidth / 2.0f, pickerY, scale);
+ option.getColorGradient().render(graphics, pickerX, pickerY, mouseX, mouseY);
+ DrawHelper.stopScaling(graphics.pose());
+ }
+
+ int baseHeight = 25;
+ if (option.getColorGradient().shouldDisplay() || (scaleAnimation != null && !scaleAnimation.isFinished())) {
int colorGradientHeight = option.getColorGradient().getBoxSize() + 10 + option.getColorGradient().getGradientSlider().getHeight();
- option.setHeight(option.getHeight() + colorGradientHeight);
+ option.setHeight(baseHeight + (int) (colorGradientHeight * scale));
+ } else {
+ option.setHeight(baseHeight);
}
if (option.getColorGradient().getColorPickerButton().isPicking()) {
DrawHelper.enableScissor(imageX, imageY + 2, panelWidth, panelHeight - 4, graphics);
}
}
+
+ @Override
+ public boolean mouseClicked(ColorOption option, double mouseX, double mouseY, int button) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX(), option.getY(), 20, 20)) {
+ boolean isOpening = !option.getColorGradient().shouldDisplay();
+ scaleAnimation.startValue(scale);
+ if (isOpening) {
+ option.getColorGradient().display();
+ scaleAnimation.endValue(1.0f);
+ } else {
+ scaleAnimation.endValue(0.0f);
+ }
+ scaleAnimation.start();
+ return true;
+ }
+
+ if (option.getColorGradient().shouldDisplay()) {
+ option.getColorGradient().mouseClicked(mouseX, mouseY, button);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean mouseDragged(ColorOption option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+ if (option.getColorGradient().shouldDisplay()) {
+ option.getColorGradient().mouseDragged(mouseX, mouseY, button);
+ }
+ return SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
+ }
+
+ @Override
+ public boolean mouseReleased(ColorOption option, double mouseX, double mouseY, int button) {
+ if (option.getColorGradient().shouldDisplay()) {
+ option.getColorGradient().mouseReleased(mouseX, mouseY, button);
+ }
+ return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
+ }
}
public class MinecraftDoubleRenderer implements SkinRenderer {
@@ -451,17 +544,11 @@ public class MinecraftDoubleRenderer implements SkinRenderer {
private static final Identifier HANDLE_TEXTURE = Identifier.withDefaultNamespace("widget/slider_handle");
private static final Identifier HANDLE_HIGHLIGHTED_TEXTURE = Identifier.withDefaultNamespace("widget/slider_handle_highlighted");
- @Override
- public void init(DoubleOption option) {
- SkinRenderer.super.init(option);
- }
-
@Override
public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int mouseX, int mouseY) {
graphics.drawString(mc.font, option.name, x + 15, y + 25 / 2 - 5, -1, true);
option.setWidth(panelWidth - 150);
- option.setHeight(25);
option.setPosition(x + panelWidth - 122, y);
double sliderX = option.getX() + ((option.value - option.minValue) / (option.maxValue - option.minValue)) * (option.getWidth() - 8);
@@ -477,11 +564,6 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
String formattedValue = String.format("%." + decimalPlaces + "f", option.value);
graphics.drawCenteredString(mc.font, formattedValue, option.getX() + option.getWidth() / 2, y + Math.round((float) mc.font.lineHeight /2), -1);
}
-
- @Override
- public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) {
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
- }
}
public class MinecraftEnumRenderer> implements SkinRenderer> {
@@ -499,7 +581,6 @@ private void calculateMaxWidth(EnumOption option) {
@Override
public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
calculateMaxWidth(option);
- option.setHeight(25);
option.setWidth(maxWidth);
graphics.drawString(mc.font, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
@@ -527,7 +608,6 @@ private void calculateMaxWidth(ListOption option) {
@Override
public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
calculateMaxWidth(option);
- option.setHeight(25);
option.setWidth(maxWidth);
graphics.drawString(mc.font, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
@@ -543,7 +623,6 @@ public void render(GuiGraphics graphics, ListOption option, int x, int y, int
public class MinecraftSubMenuRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(20);
option.setWidth(30);
graphics.drawString(mc.font, option.name, x + 15, y + 25 / 2 - 5, -1, true);
@@ -559,12 +638,9 @@ public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int
}
public class MinecraftRunnableRenderer implements SkinRenderer {
- Color DARK_RED = new Color(116, 0, 0);
- Color DARK_GREEN = new Color(24, 132, 0, 226);
@Override
public void render(GuiGraphics graphics, RunnableOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(25);
option.setWidth(26);
graphics.drawString(mc.font, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index ae2f21b..2ff9eec 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -22,12 +22,14 @@
import java.util.Arrays;
import java.util.List;
+import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_GREEN;
+import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_RED;
+
public class ModernSkin extends Skin implements GroupableSkin {
static Color DARK_GRAY = new Color(20, 20, 20, 229);
static Color DARKER_GRAY = new Color(10, 10, 10, 243);
static Color DARKER_GRAY_2 = new Color(12, 12, 12, 246);
- private final Color themeColor;
private final float radius;
private final Component defaultToolTipHeader;
private final Component defaultToolTipText;
@@ -39,12 +41,10 @@ public class ModernSkin extends Skin implements GroupableSkin {
private static int SCALE_FACTOR = 4;
private final ScrollHandler scrollHandler;
-
- public ModernSkin(Color themeColor, float radius, Component defaultToolTipHeader, Component defaultToolTipText) {
- this.themeColor = themeColor;
+ public ModernSkin(float radius, Component defaultToolTipHeader, Component defaultToolTipText) {
this.radius = radius;
- TOOLTIP_TEXT = defaultToolTipText;
- TOOLTIP_HEAD = defaultToolTipHeader;
+ this.TOOLTIP_TEXT = defaultToolTipText;
+ this.TOOLTIP_HEAD = defaultToolTipHeader;
this.defaultToolTipText = defaultToolTipText;
this.defaultToolTipHeader = defaultToolTipHeader;
@@ -61,21 +61,17 @@ public ModernSkin(Color themeColor, float radius, Component defaultToolTipHeader
setCreateNewScreen(true);
}
- public ModernSkin(Color themeColor, float radius) {
- this(themeColor, radius, Component.literal("Example Tip"), Component.literal("Hover over a setting to see its tool-tip (if present) here!"));
- }
-
- public ModernSkin(Color themeColor) {
- this(themeColor, 4);
+ public ModernSkin(float radius) {
+ this(radius, Component.literal("Example Tip"), Component.literal("Hover over a setting to see its tool-tip (if present) here!"));
}
public ModernSkin() {
- this(Color.CYAN.darker().darker());
+ this(4);
}
@Override
public LayoutContext.Offset getGroupIndent() {
- return new LayoutContext.Offset(2, 2);
+ return new LayoutContext.Offset(4, 4);
}
public void enableSkinScissor(GuiGraphics graphics) {
@@ -84,6 +80,24 @@ public void enableSkinScissor(GuiGraphics graphics) {
@Override
public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY) {
+ int targetWidth = (int) (width * 0.8f - 18);
+ renderGroup(graphics, group, groupX, groupY, targetWidth, mouseX, mouseY);
+ }
+ private int calcOptionHeight(Option> option) {
+ if (option instanceof BooleanOption || option instanceof DoubleOption) return 14;
+ if (option instanceof EnumOption || option instanceof ListOption) return mc.font.lineHeight + 2;
+ if (option instanceof SubMenuOption) return 16;
+ if (option instanceof RunnableOption) return mc.font.lineHeight + 6;
+ if (option instanceof ColorOption colorOption) {
+ return colorOption.getHeight() > 0 ? colorOption.getHeight() : 20;
+ }
+ if (option instanceof OptionGroup group) {
+ return group.isExpanded() ? group.getHeight() : 20;
+ }
+ return option.getHeight() > 0 ? option.getHeight() : mc.font.lineHeight;
+ }
+
+ public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int groupY, int targetWidth, int mouseX, int mouseY) {
mouseX = (int) (mc.mouseHandler.xpos() / SCALE_FACTOR);
mouseY = (int) (mc.mouseHandler.ypos() / SCALE_FACTOR);
@@ -101,11 +115,16 @@ public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int
if (group.isExpanded()) {
int yOffset = groupY + 16 + getGroupIndent().top();
+ int nestedIndent = getGroupIndent().left();
+ int subWidth = targetWidth - nestedIndent - 8;
+
for (Option> option : group.getGroupOptions()) {
if (!option.shouldRender()) continue;
- option.render(graphics, groupX + getGroupIndent().left(), yOffset, mouseX, mouseY);
- yOffset += option.getHeight() + 1;
+ // Position child option with layout engine
+ option.setHeight(calcOptionHeight(option));
+ yOffset = contextMenu.getLayoutEngine().layoutOption(option, groupX + nestedIndent, yOffset, subWidth);
+ option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
}
group.setHeight(yOffset - groupY);
@@ -116,8 +135,8 @@ public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int
private void drawScrollbar(GuiGraphics graphics) {
if (getMaxScrollOffset() > 0) {
- int scrollbarX = contextMenuX + width + 5; // Position at the right of the panel
- int scrollbarY = contextMenuY + 19; // Position below the header
+ int scrollbarX = contextMenuX + width + 5;
+ int scrollbarY = contextMenuY + 19;
int handleHeight = (int) ((float) (height - 23) * ((height - 23) / (float) contextMenu.getHeight()));
int handleY = scrollbarY + (int) ((float) ((height - 23) - handleHeight) * ((float) scrollHandler.getScrollOffset() / getMaxScrollOffset()));
@@ -128,33 +147,34 @@ private void drawScrollbar(GuiGraphics graphics) {
@Override
public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu, int mouseX, int mouseY) {
- //This is equivalent to "Auto" GUI scale in minecraft options
SCALE_FACTOR = mc.getWindow().calculateScale(0, mc.isEnforceUnicode());
+ this.contextMenu = contextMenu;
mouseX = (int) (mc.mouseHandler.xpos() / SCALE_FACTOR);
mouseY = (int) (mc.mouseHandler.ypos() / SCALE_FACTOR);
- // Apply custom scaling to counteract Minecraft's default scaling
DrawHelper.scaledProjection(SCALE_FACTOR, graphics);
updateContextDimensions();
contextMenu.set(contextMenuX, contextMenuY, 0);
- //Background
+ // Background
DrawHelper.drawRoundedRectangle(graphics,
contextMenuX, contextMenuY, width, height, radius, DARKER_GRAY.getRGB());
drawBackButton(graphics, mouseX, mouseY);
- //OptionStartX = Tool-Tip width + padding
int optionStartX = contextMenu.x + (int) (width * 0.2f) + 10;
+ int targetWidth = (int) (width * 0.8f - 18);
- //Background behind the options
+ // Background behind the options scroll area
DrawHelper.drawRoundedRectangle(graphics,
optionStartX, contextMenuY + 19, width * 0.8f - 14, height - 23, radius, DARK_GRAY.getRGB());
enableSkinScissor(graphics);
+
int yOffset = contextMenu.y + 19 + 3 - scrollHandler.getScrollOffset();
+
for (Option> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
@@ -162,14 +182,18 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
setTooltipText(option.name, option.description);
}
+ option.setHeight(calcOptionHeight(option));
+ int nextY = contextMenu.getLayoutEngine().layoutOption(option, optionStartX + 2, yOffset, targetWidth);
+
if (option instanceof OptionGroup group) {
- this.renderGroup(graphics, group, optionStartX + 2, yOffset, mouseX, mouseY);
+ this.renderGroup(graphics, group, optionStartX + 2, yOffset, targetWidth, mouseX, mouseY);
+ yOffset += group.getHeight() + contextMenu.getLayoutEngine().getItemSpacing();
} else {
- option.render(graphics, optionStartX + 2, yOffset, mouseX, mouseY);
+ option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
+ yOffset = nextY;
}
-
- yOffset += option.getHeight() + 1;
}
+
DrawHelper.disableScissor(graphics);
contextMenu.setWidth(width);
@@ -181,7 +205,6 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
renderToolTipText(graphics, mouseX, mouseY);
- //Reset our scaling so minecraft runs normally\
DrawHelper.stopScaling(graphics.pose());
}
@@ -199,7 +222,7 @@ public void drawBackButton(GuiGraphics graphics, int mouseX, int mouseY) {
int textWidth = mc.font.width(backText);
boolean isHoveringOver = isMouseOver(mouseX, mouseY, contextMenuX + 2, contextMenuY + 2, textWidth + 8, 14);
- int color = isHoveringOver ? themeColor.darker().getRGB() : themeColor.getRGB();
+ int color = isHoveringOver ? getThemeColor().darker().getRGB() : getThemeColor().getRGB();
DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
contextMenuX + 2, contextMenuY + 2, textWidth + 8, 14, radius, color, 125, 2, 2);
@@ -219,7 +242,6 @@ public void renderToolTipText(GuiGraphics graphics, int mouseX, int mouseY) {
float textScale = 0.8f;
- // Draw background
DrawHelper.drawRoundedRectangle(
graphics,
contextMenuX + 2,
@@ -243,7 +265,6 @@ public void renderToolTipText(GuiGraphics graphics, int mouseX, int mouseY) {
return;
}
- //Draw the head Component
graphics.drawString(
mc.font,
TOOLTIP_HEAD,
@@ -257,7 +278,6 @@ public void renderToolTipText(GuiGraphics graphics, int mouseX, int mouseY) {
DrawHelper.scaleAndPosition(graphics.pose(), contextMenuX + 4, tooltipY + 19, textScale);
- // Draw Component
int textY = tooltipY + 19;
for (FormattedCharSequence line : wrappedText) {
graphics.drawString(
@@ -277,8 +297,8 @@ public void renderToolTipText(GuiGraphics graphics, int mouseX, int mouseY) {
}
public void setTooltipText(Component head_text, Component tooltip_text) {
- TOOLTIP_TEXT = tooltip_text;
- TOOLTIP_HEAD = head_text;
+ this.TOOLTIP_TEXT = tooltip_text;
+ this.TOOLTIP_HEAD = head_text;
}
private int getMaxScrollOffset() {
@@ -309,19 +329,24 @@ public boolean mouseClicked(ContextMenu> menu, double mouseX, double mouseY, i
if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
int optionStartX = contextMenuX + (int) (width * 0.2f) + 10;
int yOffset = contextMenu.y + 22 - scrollHandler.getScrollOffset();
+ int spacing = contextMenu.getLayoutEngine().getItemSpacing();
+
for (Option> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
+ int optHeight = calcOptionHeight(option);
if (option instanceof OptionGroup group) {
+ Component groupText = group.name.copy().append(" " + (group.isExpanded() ? "-" : "+"));
if (isMouseOver(mouseX, mouseY, optionStartX + 2, yOffset,
- mc.font.width(group.name + " " + (group.isExpanded() ? "-" : "+")) + 6,
+ mc.font.width(groupText) + 6,
16)) {
group.setExpanded(!group.isExpanded());
- break;
+ return true;
}
+ yOffset += group.getHeight() + spacing;
+ } else {
+ yOffset += optHeight + spacing;
}
-
- yOffset += option.getHeight() + 1;
}
}
if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + 2, contextMenuY + 2, mc.font.width("< Back") + 8, 14)) {
@@ -344,7 +369,7 @@ public boolean mouseDragged(ContextMenu> menu, double mouseX, double mouseY, i
}
public Color getThemeColor() {
- return themeColor;
+ return contextMenu.getProperties().getAccentColor();
}
public class ModernBooleanRenderer implements SkinRenderer {
@@ -352,15 +377,7 @@ public class ModernBooleanRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, BooleanOption option, int x, int y, int mouseX, int mouseY) {
- int backgroundWidth = (int) (width * 0.8f - 14);
-
- option.setHeight(14);
- option.setPosition(x, y);
- option.setWidth(backgroundWidth);
-
- // Calculate the current progress of the animation
- int toggleBgX = x + backgroundWidth - 30;
- // Background
+ int toggleBgX = x + option.getWidth() - 30;
boolean active = option.get();
Color backgroundColor = active ? getThemeColor() : DARKER_GRAY;
Color hoveredColor = isMouseOver(mouseX, mouseY, toggleBgX, y + 2, 14, 7) ? backgroundColor.darker() : backgroundColor;
@@ -373,7 +390,6 @@ public void render(GuiGraphics graphics, BooleanOption option, int x, int y, int
125, 1, 1
);
- // Draw toggle circle
float startX = active ? toggleBgX + 4 : toggleBgX + 10;
float endX = active ? toggleBgX + 10 : toggleBgX + 4;
EasingType easingType = active ? EasingType.EASE_IN_CUBIC : EasingType.EASE_OUT_QUAD;
@@ -381,7 +397,6 @@ public void render(GuiGraphics graphics, BooleanOption option, int x, int y, int
DrawHelper.drawFilledCircle(graphics, toggleX, y + 2 + 3.3f, 2.8f, Color.WHITE.getRGB());
- // Draw option name
graphics.drawString(
mc.font,
option.name,
@@ -397,8 +412,7 @@ public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY,
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- int backgroundWidth = (int) (width * 0.8f - 14);
- int toggleBgX = option.getX() + backgroundWidth - 30;
+ int toggleBgX = option.getX() + option.getWidth() - 30;
if (isMouseOver(mouseX, mouseY, toggleBgX, option.getY(), 14, option.getHeight())) {
option.set(!option.get());
@@ -409,7 +423,6 @@ public boolean mouseClicked(BooleanOption option, double mouseX, double mouseY,
}
}
-
public class ModernColorOptionRenderer implements SkinRenderer {
private static final float ANIMATION_SPEED = 0.1f;
private float scale = 0f;
@@ -432,9 +445,6 @@ public void update(ColorOption option) {
public void render(GuiGraphics graphics, ColorOption option, int x, int y, int mouseX, int mouseY) {
update(option);
- int backgroundWidth = (int) (width * 0.8f - 14);
-
- // Draw option name
graphics.drawString(
mc.font,
option.name,
@@ -444,17 +454,12 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
false
);
- option.setWidth(20);
- option.setPosition(x, y);
-
-
int width = 20;
int shadowOpacity = Math.min(option.value.getAlpha(), 45);
- //The shape behind the preview
- Color behindColor = isMouseOver(mouseX, mouseY, x + backgroundWidth - width - 17, y + 1, width + 2, 14) ? getThemeColor().darker().darker() : getThemeColor();
+ Color behindColor = isMouseOver(mouseX, mouseY, x + option.getWidth() - width - 17, y + 1, width + 2, 14) ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
- x + backgroundWidth - width - 17,
+ x + option.getWidth() - width - 17,
y + 1,
width + 2,
14,
@@ -464,19 +469,17 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
1,
1);
- //The letter above the shape behind the preview
graphics.drawString(
mc.font,
option.getColorGradient().shouldDisplay() ? "^" : "v",
- x + backgroundWidth - 21,
+ x + option.getWidth() - 21,
y + 4,
-1,
false
);
- //Preview
DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
- x + backgroundWidth - width - 15,
+ x + option.getWidth() - width - 15,
y + 2,
width - 8,
12,
@@ -488,18 +491,17 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
int targetHeight = (int) (option.getColorGradient().getBoxSize() + option.getColorGradient().getGradientBox().getSize() * scale);
option.setHeight(option.getColorGradient().shouldDisplay() ? targetHeight : 20);
- option.setWidth(width);
if (option.getColorGradient().getColorPickerButton().isPicking()) {
- DrawHelper.disableScissor(graphics); //Disable scissor so the color picker preview works
+ DrawHelper.disableScissor(graphics);
}
- DrawHelper.scaleAndPosition(graphics.pose(), x + backgroundWidth / 2.0f, y, scale);
- option.getColorGradient().render(graphics, x + backgroundWidth / 2 - 50, y + 6, mouseX, mouseY);
+ DrawHelper.scaleAndPosition(graphics.pose(), x + option.getWidth() / 2.0f, y, scale);
+ option.getColorGradient().render(graphics, x + option.getWidth() / 2 - 50, y + 6, mouseX, mouseY);
DrawHelper.stopScaling(graphics.pose());
if (option.getColorGradient().getColorPickerButton().isPicking()) {
- enableSkinScissor(graphics); // re-enable the scissor
+ enableSkinScissor(graphics);
}
}
@@ -507,7 +509,7 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
public boolean mouseClicked(ColorOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX() + (int) (width * 0.8f - 14) - 37, option.getY(), 22, 16)) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX() + option.getWidth() - 37, option.getY(), 22, 16)) {
option.isVisible = !option.isVisible;
if (option.isVisible) {
option.getColorGradient().display();
@@ -517,35 +519,32 @@ public boolean mouseClicked(ColorOption option, double mouseX, double mouseY, in
}
return true;
}
- option.getColorGradient().mouseClicked(mouseX, mouseY, button);
- return false;
+ return option.getColorGradient().mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(ColorOption option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- option.getColorGradient().mouseDragged(mouseX, mouseY, button);
- return SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
+ return option.getColorGradient().mouseDragged(mouseX, mouseY, button) && SkinRenderer.super.mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY);
}
@Override
public boolean mouseReleased(ColorOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- option.getColorGradient().mouseReleased(mouseX, mouseY, button);
-
- return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
+ return option.getColorGradient().mouseReleased(mouseX, mouseY, button) && SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
}
}
public class ModernDoubleRenderer implements SkinRenderer {
private double displayValue;
private static final float ANIMATION_SPEED = 0.1f;
+ int sliderBackgroundWidth = 120;
+ int sliderBackgroundHeight = 2;
@Override
public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int mouseX, int mouseY) {
- // Draw option name
graphics.drawString(
mc.font,
option.name,
@@ -554,44 +553,31 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
-1,
false
);
+ int sliderX = x + option.getWidth() - sliderBackgroundWidth - 10;
- int backgroundWidth = (int) (width * 0.8f - 14);
- int sliderBackgroundWidth = 120;
- int sliderBackgroundHeight = 2;
- int sliderX = x + backgroundWidth - sliderBackgroundWidth - 10;
-
- option.setPosition(x, y);
- option.setWidth(sliderBackgroundWidth);
- option.setHeight(14);
-
- // Smoothly interpolate to the new value
displayValue = Mth.lerp(ANIMATION_SPEED, displayValue, option.get());
- // Background
DrawHelper.drawRoundedRectangle(
graphics,
sliderX, y, sliderBackgroundWidth, sliderBackgroundHeight, 1, DARKER_GRAY.getRGB()
);
- // Active fill
- int activeFillWidth = (int) ((displayValue - option.minValue) / (option.maxValue - option.minValue) * option.getWidth());
+ int activeFillWidth = (int) ((displayValue - option.minValue) / (option.maxValue - option.minValue) * sliderBackgroundWidth);
Color fillColor = isMouseOver(mouseX, mouseY, sliderX, y, sliderBackgroundWidth, sliderBackgroundHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangle(
graphics,
sliderX, y, activeFillWidth, sliderBackgroundHeight, 2, fillColor.getRGB()
);
- // Draw slider handle
float sliderHandleX = sliderX + activeFillWidth - 5;
DrawHelper.drawFilledCircle(graphics, sliderHandleX + 5, y + 1, 2, Color.WHITE.getRGB());
- // Draw value Component
- String Component = String.format("%.2f", displayValue);
- DrawHelper.scaleAndPosition(graphics.pose(), sliderX + 120 - mc.font.width(Component), y + 7, 0.6f);
+ String label = String.format("%.2f", displayValue);
+ DrawHelper.scaleAndPosition(graphics.pose(), sliderX + sliderBackgroundWidth - mc.font.width(label), y + 7, 0.6f);
graphics.drawString(
mc.font,
- Component,
- sliderX + sliderBackgroundWidth + 10 - mc.font.width(Component),
+ label,
+ sliderX + sliderBackgroundWidth + 10 - mc.font.width(label),
y + 2,
-1,
true
@@ -603,7 +589,8 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, option.getX() + (int) (width * 0.8f - 14) - 125, option.getY() - 1, option.getWidth() + 2, option.getHeight() + 1)) {
+ int sliderX = option.getX() + option.getWidth() - sliderBackgroundWidth - 10;
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, sliderX - 2, option.getY() - 1, sliderBackgroundWidth + 4, option.getHeight() + 1)) {
option.setDragging(true);
return true;
}
@@ -614,10 +601,8 @@ public boolean mouseClicked(DoubleOption option, double mouseX, double mouseY, i
public boolean mouseDragged(DoubleOption option, double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (option.isDragging()) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
- int backgroundWidth = (int) (width * 0.8f - 14);
- int sliderBackgroundWidth = 120;
- int sliderX = option.getX() + backgroundWidth - sliderBackgroundWidth - 10;
- option.step(mouseX, sliderX);
+ int sliderX = option.getX() + option.getWidth() - sliderBackgroundWidth - 10;
+ option.step(mouseX, sliderX, sliderBackgroundWidth);
return true;
}
return false;
@@ -636,25 +621,23 @@ public boolean mouseReleased(DoubleOption option, double mouseX, double mouseY,
public class ModernEnumRenderer> implements SkinRenderer> {
@Override
public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
- // Set dimensions for the main label and dropdown area
option.setHeight(mc.font.lineHeight + 2);
- // Draw main option name and selected option
Component mainLabel = option.name.copy().append(": ");
String selectedOption = option.get().toString();
graphics.drawString(mc.font, mainLabel, x + 4, y + 2, -1, false);
- Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
+ boolean isMouseOverText = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
+ Color fillColor = isMouseOverText ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangle(
graphics,
x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2, 2,
fillColor.getRGB()
);
- // "<" and ">" buttons
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int leftX = x + contextMenuWidth - 30;
+
+ int leftX = x + option.getWidth() - 30;
boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
- // Shadow
+
DrawHelper.drawRoundedRectangle(
graphics,
leftX + 1, y + 3,
@@ -686,7 +669,7 @@ public void render(GuiGraphics graphics, EnumOption option, int x, int y, int
graphics.drawString(mc.font, "<", leftX + mc.font.width("<") / 2 + 1, y + 3, -1, false);
graphics.drawString(mc.font, ">", leftX + mc.font.width("<") + 7 + mc.font.width(">") / 2, y + 3, -1, false);
- graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), false);
+ graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), isMouseOverText);
}
@Override
@@ -698,13 +681,10 @@ public boolean mouseClicked(EnumOption option, double mouseX, double mouseY,
int x = option.getX();
int y = option.getY();
- String mainLabel = option.name + ": ";
+ Component mainLabel = option.name.copy().append(": ");
String selectedOption = option.get().toString();
- // Check if the main label is clicked to cycle
- // "<" and ">" buttons
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int leftX = x + contextMenuWidth - 30;
+ int leftX = x + option.getWidth() - 30;
boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
boolean hoveredOverMainLabel = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
@@ -714,47 +694,41 @@ public boolean mouseClicked(EnumOption option, double mouseX, double mouseY,
int index = Arrays.asList(values).indexOf(option.value);
if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || hoveredOverLeft) {
- // Cycle forward
E nextVal = values[(index + 1) % values.length];
option.set(nextVal);
} else if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT || hoveredOverRight) {
- // Cycle backward with wrap-around
E nextVal = values[(index - 1 + values.length) % values.length];
option.set(nextVal);
+ } else {
+ return false;
}
return true;
}
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ return false;
}
-
}
public class ModernListRenderer implements SkinRenderer> {
-
@Override
public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
-
- // Set dimensions for the main label and dropdown area
option.setHeight(mc.font.lineHeight + 2);
- // Draw main option name and selected option
Component mainLabel = option.name.copy().append(": ");
String selectedOption = option.get().toString();
graphics.drawString(mc.font, mainLabel, x + 4, y + 2, -1, false);
- Color fillColor = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2) ? getThemeColor().darker().darker() : getThemeColor();
+ boolean isMouseOverText = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
+ Color fillColor = isMouseOverText ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangle(
graphics,
x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2, 2,
fillColor.getRGB()
);
- // "<" and ">" buttons
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int leftX = x + contextMenuWidth - 30;
+ int leftX = x + option.getWidth() - 30;
boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
- // Shadow
+
DrawHelper.drawRoundedRectangle(
graphics,
leftX + 1, y + 3,
@@ -786,77 +760,62 @@ public void render(GuiGraphics graphics, ListOption option, int x, int y, int
graphics.drawString(mc.font, "<", leftX + mc.font.width("<") / 2 + 1, y + 3, -1, false);
graphics.drawString(mc.font, ">", leftX + mc.font.width("<") + 7 + mc.font.width(">") / 2, y + 3, -1, false);
- graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), false);
+ graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), isMouseOverText);
}
@Override
public boolean mouseClicked(ListOption option, double mouseX, double mouseY, int button) {
if (option.getValues().isEmpty()) return false;
- mouseX /= SCALE_FACTOR;
- mouseY /= SCALE_FACTOR;
+ mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
+ mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
int x = option.getX();
int y = option.getY();
Component mainLabel = option.name.copy().append(": ");
String selectedOption = option.get().toString();
- // Calculate positions
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int leftX = x + contextMenuWidth - 30;
-
- // Check hover states
+ int leftX = x + option.getWidth() - 30;
boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
boolean hoveredOverMainLabel = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
- // Check if any area is clicked
if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) {
List values = option.getValues();
int currentIndex = values.indexOf(option.value);
int nextIndex;
- // Determine the next index based on the button clicked
if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || hoveredOverLeft) {
- nextIndex = (currentIndex + 1) % values.size(); // Cycle forward
+ nextIndex = (currentIndex + 1) % values.size();
} else if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT || hoveredOverRight) {
- nextIndex = (currentIndex - 1 + values.size()) % values.size(); // Cycle backward
+ nextIndex = (currentIndex - 1 + values.size()) % values.size();
} else {
- return false; // No valid click
+ return false;
}
option.set(values.get(nextIndex));
return true;
}
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ return false;
}
}
public class ModernSubMenuRenderer implements SkinRenderer {
@Override
public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int mouseX, int mouseY) {
- mouseX = (int) (mc.mouseHandler.xpos() / SCALE_FACTOR);
- mouseY = (int) (mc.mouseHandler.ypos() / SCALE_FACTOR);
-
- String Component = "Open";
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int xPos = x + 4 + contextMenuWidth - 40;
+ String textLabel = "Open";
+ int xPos = x + option.getWidth() - 40;
- option.setPosition(xPos - 1, y);
- option.setWidth(mc.font.width(Component) + 5);
option.setHeight(16);
graphics.drawString(mc.font, option.name, x + 4, y + 4, -1, false);
-
- graphics.drawString(mc.font, Component, xPos + 2, y + 4, Color.WHITE.getRGB(), true);
-
- Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(Component) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
+ Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(textLabel) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangleWithShadowBadWay(
graphics,
xPos - 1, y + 1,
- mc.font.width(Component) + 5, mc.font.lineHeight + 4,
+ mc.font.width(textLabel) + 5, mc.font.lineHeight + 4,
2,
fillColor.getRGB(),
180,
@@ -866,12 +825,14 @@ public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int
DrawHelper.drawOutlineRoundedBox(
graphics,
xPos - 1, y + 1,
- mc.font.width(Component) + 5, mc.font.lineHeight + 4,
+ mc.font.width(textLabel) + 5, mc.font.lineHeight + 4,
2,
0.7f,
Color.WHITE.getRGB()
);
+ graphics.drawString(mc.font, textLabel, xPos + 2, y + 4, Color.WHITE.getRGB(), true);
+
option.getSubMenu().render(graphics, x + option.getParentMenu().getWidth(), y, mouseX, mouseY);
}
@@ -893,58 +854,61 @@ public boolean mouseDragged(SubMenuOption option, double mouseX, double mouseY,
public boolean mouseReleased(SubMenuOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
+ return isMouseOver(mouseX, mouseY, option.getX() + option.getWidth() - 40 + 2, option.getY() + 4, mc.font.width("Open") + 5, mc.font.lineHeight + 4);
}
@Override
public boolean mouseClicked(SubMenuOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ if(isMouseOver(mouseX, mouseY, option.getX() + option.getWidth() - 40 + 2, option.getY() + 4, mc.font.width("Open") + 5, mc.font.lineHeight + 4)){
+ option.toggle();
+ return true;
+ }
+ return false;
}
}
public class ModernRunnableRenderer implements SkinRenderer {
- Color DARK_RED = new Color(116, 0, 0);
- Color DARK_GREEN = new Color(24, 132, 0, 226);
-
@Override
public void render(GuiGraphics graphics, RunnableOption option, int x, int y, int mouseX, int mouseY) {
- String Component = "Run â–¶";
- int contextMenuWidth = (int) (width * 0.8f - 14);
- int xPos = x + 4 + contextMenuWidth - 45;
+ String labelText = "Run â–¶";
+ int xPos = x + option.getWidth() - 45;
- option.setPosition(xPos - 1, y);
- option.setWidth(mc.font.width(Component) + 5);
option.setHeight(mc.font.lineHeight + 6);
graphics.drawString(mc.font, option.name, x + 4, y + 4, -1, false);
- graphics.drawString(mc.font, Component, xPos + 2, y + 4, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true);
-
- Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(Component) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
+ Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(labelText) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangleWithShadowBadWay(
graphics,
xPos - 1, y + 1,
- mc.font.width(Component) + 5, mc.font.lineHeight + 4,
+ mc.font.width(labelText) + 5, mc.font.lineHeight + 4,
2,
fillColor.getRGB(),
180,
1,
1
);
+
+ graphics.drawString(mc.font, labelText, xPos + 2, y + 4, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true);
}
@Override
public boolean mouseClicked(RunnableOption option, double mouseX, double mouseY, int button) {
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- return SkinRenderer.super.mouseClicked(option, mouseX, mouseY, button);
+ if(isMouseOver(mouseX, mouseY, option.getX() + option.getWidth() - 45 + 2, option.getY() + 4, mc.font.width("Run â–¶") + 5, mc.font.lineHeight + 4)){
+ option.toggle();
+ return true;
+ }
+ return false;
}
}
+
@Override
public Skin clone() {
- return new ModernSkin(themeColor,radius,defaultToolTipHeader,defaultToolTipText);
+ return new ModernSkin(radius, defaultToolTipHeader, defaultToolTipText);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
index 03f8a60..dc4997d 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/Skin.java
@@ -70,7 +70,7 @@ protected List
> flattenOptions(List
> options) {
return flattened;
}
- protected List
> getOptions(ContextMenu> menu) {
+ public List
> getOptions(ContextMenu> menu) {
return supportsGroups() ? menu.getOptions() : flattenOptions(menu.getOptions());
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
index cd6df72..05d10a7 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetRenderer.java
@@ -5,7 +5,7 @@
import com.tanishisherewith.dynamichud.internal.System;
import com.tanishisherewith.dynamichud.screens.AbstractMoveableScreen;
import com.tanishisherewith.dynamichud.utils.Input;
-import com.tanishisherewith.dynamichud.utils.contextmenu.contextmenuscreen.ContextMenuScreenRegistry;
+import com.tanishisherewith.dynamichud.utils.contextmenu.screen.ContextMenuScreenRegistry;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.PauseScreen;
import net.minecraft.client.gui.screens.Screen;
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 4ccd082..58d568f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -15,6 +15,7 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.options.ColorOption;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.DoubleOption;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin;
import com.tanishisherewith.dynamichud.widget.DynamicValueWidget;
import com.tanishisherewith.dynamichud.widget.WidgetBox;
import com.tanishisherewith.dynamichud.widget.WidgetData;
@@ -23,6 +24,7 @@
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
+import org.joml.Matrix3x2f;
import java.awt.*;
import java.util.ArrayList;
@@ -211,7 +213,7 @@ private void drawInterpolatedCurve(GuiGraphics graphics, List points, i
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new InterpolatedCurveRenderState(points, thickness, color, graphics.pose(), CustomRenderLayers.QUADS_CUSTOM_BLEND, (int) width, (int) height, graphics.scissorStack.peek())
+ new InterpolatedCurveRenderState(points, thickness, color, new Matrix3x2f(graphics.pose()), CustomRenderLayers.QUADS_CUSTOM_BLEND, (int) width, (int) height, graphics.scissorStack.peek())
);
}
@@ -220,7 +222,7 @@ private void drawGradientShadow(GuiGraphics graphics, List points, floa
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new GradientShadowRenderState(points,bottomY, startColor, endColor, graphics.pose(), RenderPipelines.DEBUG_QUADS, (int) width, (int) height, graphics.scissorStack.peek())
+ new GradientShadowRenderState(points,bottomY, startColor, endColor, new Matrix3x2f(graphics.pose()), RenderPipelines.DEBUG_QUADS, (int) width, (int) height, graphics.scissorStack.peek())
);
}
@@ -274,7 +276,6 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
DrawHelper.stopScaling(graphics.pose());
}
- // Update the offsets for the rest of the elements drawn.
x += offset;
// Draw vertical grid lines (time axis)
@@ -294,7 +295,6 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
0x00000000
);
- // Draw interpolated graph curve
drawInterpolatedCurve(graphics, points, graphColor.getRGB(), lineThickness);
DrawHelper.drawChromaText(
@@ -348,7 +348,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
}
public void createMenu() {
- ContextMenuProperties properties = ContextMenuProperties.builder().build();
+ ContextMenuProperties properties = ContextMenuProperties.builder().skin(new MinecraftSkin(MinecraftSkin.PanelColor.FOREST_GREEN)).build();
menu = new ContextMenu<>(getX(), (int) (getY() + widgetBox.getHeight()), properties);
menu.addOption(new BooleanOption(Component.literal("Show Grid"),
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 25beeca..2ad95fb 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -3,6 +3,7 @@
import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
+import com.tanishisherewith.dynamichud.integration.IntegrationManager;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuManager;
@@ -92,43 +93,50 @@ public void createMenu() {
.renderWhen(() -> this.rainbow)
.withComplexity(Option.Complexity.Pro)
);
- // Runnable Option
- AtomicBoolean ran = new AtomicBoolean(false);
- menu.addOption(new RunnableOption(Component.literal("Reset Position"),
- ran::get, ran::set,
- () -> this.setPosition(0, 0))
- .description(Component.literal("Reset widget to default position")));
-
- // List Option
- AtomicReference style = new AtomicReference<>("Style1");
- List styles = Arrays.asList("Style1", "Style2", "Style3");
- menu.addOption(new ListOption<>(Component.literal("Text Style"),
- style::get, style::set, styles)
- .description(Component.literal("Choose a text style")));
-
- // Enum Option
- menu.addOption(new EnumOption<>(Component.literal("Alignment"),
- () -> GroupLayout.Alignment.CENTER, value -> {}, GroupLayout.Alignment.values())
- .description(Component.literal("Set text alignment")));
-
- // Option Group
- OptionGroup group = new OptionGroup(Component.literal("Display Options"));
- group.addOption(new BooleanOption(Component.literal("Bold Text"),
- () -> false, value -> {}, BooleanOption.BooleanType.YES_NO)
- .description(Component.literal("Enable bold text")));
- group.addOption(new DoubleOption(Component.literal("Font Size"),
- 8.0, 24.0, 1.0f,
- () -> 12.0, value -> {}, menu)
- .description(Component.literal("Adjust font size")));
- menu.addOption(group);
-
- // SubMenu Option
- SubMenuOption subMenu = (SubMenuOption) new SubMenuOption(Component.literal("Advanced Settings"), menu)
- .description(Component.literal("Open advanced settings"));
- subMenu.getSubMenu().addOption(new BooleanOption(Component.literal("Some Boolean"),
- () -> false, value -> {}, BooleanOption.BooleanType.TRUE_FALSE)
- .description(Component.literal("True/False")));
- menu.addOption(subMenu);
+ if(IntegrationManager.IS_TEST_MODE) {
+ // Runnable Option
+ AtomicBoolean ran = new AtomicBoolean(false);
+ menu.addOption(new RunnableOption(Component.literal("Reset Position"),
+ ran::get, ran::set,
+ () -> this.setPosition(0, 0))
+ .description(Component.literal("Reset widget to default position")));
+
+ // List Option
+ AtomicReference style = new AtomicReference<>("Style1");
+ List styles = Arrays.asList("Style1", "Style2", "Style3");
+ menu.addOption(new ListOption<>(Component.literal("Text Style"),
+ style::get, style::set, styles)
+ .description(Component.literal("Choose a text style")));
+
+ // Enum Option
+ AtomicReference align = new AtomicReference<>(GroupLayout.Alignment.CENTER);
+
+ menu.addOption(new EnumOption<>(Component.literal("Alignment"),
+ align::get, align::set, GroupLayout.Alignment.values())
+ .description(Component.literal("Set text alignment")));
+
+ // Option Group
+ OptionGroup group = new OptionGroup(Component.literal("Display Options"));
+ group.addOption(new BooleanOption(Component.literal("Bold Text"),
+ () -> false, value -> {
+ }, BooleanOption.BooleanType.YES_NO)
+ .description(Component.literal("Enable bold text")));
+ group.addOption(new DoubleOption(Component.literal("Font Size"),
+ 8.0, 24.0, 1.0f,
+ () -> 12.0, value -> {
+ }, menu).description(Component.literal("Adjust font size")));
+
+ menu.addOption(group);
+
+ // SubMenu Option
+ SubMenuOption subMenu = (SubMenuOption) new SubMenuOption(Component.literal("Advanced Settings"), menu)
+ .description(Component.literal("Open advanced settings"));
+ subMenu.getSubMenu().addOption(new BooleanOption(Component.literal("Some Boolean"),
+ () -> false, value -> {
+ }, BooleanOption.BooleanType.TRUE_FALSE)
+ .description(Component.literal("True/False")));
+ menu.addOption(subMenu);
+ }
}
@Override
From a2a9665cf8f6f331916a1d6081544f40b3496129 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Wed, 17 Jun 2026 17:00:06 +0530
Subject: [PATCH 06/22] Replaced ListOption and EnumOption with CycleOption
Removed LayoutContext Added animations in ModernSkin New SquishAnimator Fixed
some issues in GraphWidget
---
.../dynamichud/helpers/DrawHelper.java | 6 +-
.../animations/SquishAnimator.java | 41 +++
.../animations/ValueAnimation.java | 5 +
.../utils/contextmenu/ContextMenu.java | 7 +-
.../contextmenu/layout/LayoutContext.java | 60 -----
.../contextmenu/layout/LayoutEngine.java | 73 ++----
.../contextmenu/options/CycleOption.java | 60 +++++
.../utils/contextmenu/options/EnumOption.java | 49 ----
.../utils/contextmenu/options/ListOption.java | 50 ----
.../contextmenu/options/OptionGroup.java | 1 +
.../contextmenu/screen/ContextMenuScreen.java | 3 +-
.../contextmenu/skinsystem/ClassicSkin.java | 21 +-
.../contextmenu/skinsystem/MinecraftSkin.java | 50 +---
.../contextmenu/skinsystem/ModernSkin.java | 243 +++++++++---------
.../skinsystem/interfaces/GroupableSkin.java | 4 +-
.../utils/handlers/ScrollHandler.java | 4 +-
.../dynamichud/widgets/GraphWidget.java | 15 +-
.../dynamichud/widgets/TextWidget.java | 19 +-
18 files changed, 297 insertions(+), 414 deletions(-)
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/SquishAnimator.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
create mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/CycleOption.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
delete mode 100644 src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
index ffac337..139d632 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/DrawHelper.java
@@ -625,12 +625,11 @@ public static void scaledProjection(float scale, GuiGraphics graphics) {
* @param scale Scale the matrices
*/
public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y, float scale) {
- matrices.pushMatrix(); // Save the current transformation state
+ matrices.pushMatrix();
// Translate the origin back to the desired position
matrices.translate(x, y);
- // Scale the matrix
matrices.scale(scale, scale);
matrices.translate(-x, -y);
@@ -654,12 +653,11 @@ public static ScreenRectangle createBounds(Matrix3x2f pose, ScreenRectangle scis
* @param scale Scale the matrices
*/
public static void scaleAndPosition(Matrix3x2fStack matrices, float x, float y, float width, float height, float scale) {
- matrices.pushMatrix(); // Save the current transformation state
+ matrices.pushMatrix();
// Translate the origin back to the desired position
matrices.translate(x + width / 2.0f, y + height / 2.0f);
- // Scale the matrix
matrices.scale(scale, scale);
matrices.translate(-(x + width / 2.0f), -(y + height / 2.0f));
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/SquishAnimator.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/SquishAnimator.java
new file mode 100644
index 0000000..9f9e403
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/SquishAnimator.java
@@ -0,0 +1,41 @@
+package com.tanishisherewith.dynamichud.helpers.animationhelper.animations;
+
+import com.tanishisherewith.dynamichud.helpers.animationhelper.AnimationProperty;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
+
+public class SquishAnimator {
+ private final ValueAnimation animation;
+ private final AnimationProperty property;
+ private boolean isPressed = false;
+ private float normalScale;
+ private float pressedScale;
+
+ public SquishAnimator(float normalScale, float pressedScale) {
+ this.normalScale = normalScale;
+ this.pressedScale = pressedScale;
+ this.property = new AnimationProperty<>() {
+ private float val = normalScale;
+ public Float get() { return val; }
+ public void set(Float v) { val = v; }
+ };
+
+ this.animation = new ValueAnimation(property, normalScale, pressedScale);
+ this.animation.easing(EasingType.EASE_OUT_BACK);
+ this.animation.duration(125);
+ }
+ public SquishAnimator(){
+ this(1.0f,0.95f);
+ }
+
+ public void update(boolean pressed) {
+ if (this.isPressed != pressed) {
+ this.isPressed = pressed;
+ animation.startValue(property.get());
+ animation.endValue(pressed ? pressedScale : normalScale);
+ animation.start();
+ }
+ animation.update();
+ }
+
+ public float getScale() { return property.get(); }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java
index 9d19d3b..c984e44 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/animations/ValueAnimation.java
@@ -17,6 +17,7 @@ public ValueAnimation(AnimationProperty property, float start, float end,
this.startValue = start;
this.endValue = end;
this.easing = easingType;
+ this.value = startValue;
}
public ValueAnimation(AnimationProperty property, float start, float end) {
@@ -44,6 +45,10 @@ public ValueAnimation endValue(float endValue) {
return this;
}
+ public void setValue(float value) {
+ this.value = value;
+ }
+
public float getValue() {
return value;
}
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 f6b1860..b75fe93 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -112,7 +112,7 @@ public void render(GuiGraphics graphics, int xPos, int yPos, int mouseX, int mou
if (scale <= 0.0f || newScreenFlag) return;
- DrawHelper.scaleAndPosition(graphics.pose(), this.x + width/2.0f, this.y + height/2.0f, scale);
+ DrawHelper.scaleAndPosition(graphics.pose(), this.x, this.y,this.width,this.height, scale);
properties.getSkin().setContextMenu(this);
properties.getSkin().renderContextMenu(graphics, this, mouseX, mouseY);
@@ -124,6 +124,7 @@ public void update() {
if (layoutEngine != null) {
layoutEngine.applyLayout(this);
}
+
if (!properties.enableAnimations()) {
scale = shouldDisplay ? 1.0f : 0.0f;
return;
@@ -212,8 +213,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (!shouldDisplay) return false;
for (Option option : options) {
- if(option.shouldRender() && option.getRenderer().mouseReleased(option, mouseX, mouseY, button)){
- return true;
+ if(option.shouldRender()){
+ option.getRenderer().mouseReleased(option, mouseX, mouseY, button);
}
}
return properties.getSkin().mouseReleased(this, mouseX, mouseY, button);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
deleted file mode 100644
index a20ce5f..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutContext.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.layout;
-
-import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
-
-//This was supposed to be used for something bigger but that got scraped.
-public record LayoutContext(Offset indent, Option> parentOption) {
- public LayoutContext() {
- this(Offset.zero(), null);
- }
-
- // Builder-style methods for creating new contexts
- public LayoutContext withIndent(Offset indent) {
- return new LayoutContext(indent, this.parentOption);
- }
-
- public LayoutContext withParent(Option> parent) {
- return new LayoutContext(this.indent, parent);
- }
-
- public LayoutContext addIndent(Offset additionalIndent) {
- return new LayoutContext(
- this.indent.add(additionalIndent),
- this.parentOption
- );
- }
-
- // Utility methods for calculating positions
- public int getEffectiveX(int baseX) {
- return baseX + indent.left;
- }
-
- public int getEffectiveY(int baseY) {
- return baseY + indent.top;
- }
-
- public int getEffectiveWidth(int baseWidth) {
- return baseWidth + indent.left;
- }
-
- public int getEffectiveHeight(int baseHeight) {
- return baseHeight + indent.top;
- }
-
- public record Offset(int left, int top) {
- public Offset(int all) {
- this(all, all);
- }
-
- public static Offset zero() {
- return new Offset(0);
- }
-
- public Offset add(Offset other) {
- return new Offset(
- this.left + other.left,
- this.top + other.top
- );
- }
- }
-}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
index 4f1d5f1..7009c54 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/layout/LayoutEngine.java
@@ -1,9 +1,13 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.layout;
import com.tanishisherewith.dynamichud.DynamicHUD;
+import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.GuiGraphics;
+import org.joml.Vector2d;
import java.util.List;
@@ -12,15 +16,20 @@ public class LayoutEngine {
private int verticalPadding = 4;
private int itemSpacing = 2;
private int minWidth = 80;
- private LayoutStrategy activeStrategy = new VerticalFlowStrategy();
+ private LayoutStrategy activeStrategy;
public LayoutEngine() {}
public LayoutEngine(int horizontalPadding, int verticalPadding, int itemSpacing, int minWidth) {
+ this(horizontalPadding,verticalPadding,itemSpacing,minWidth,new VerticalFlowStrategy());
+ }
+
+ public LayoutEngine(int horizontalPadding, int verticalPadding, int itemSpacing, int minWidth, LayoutStrategy layoutStrategy) {
this.horizontalPadding = horizontalPadding;
this.verticalPadding = verticalPadding;
this.itemSpacing = itemSpacing;
this.minWidth = minWidth;
+ this.activeStrategy = layoutStrategy;
}
@FunctionalInterface
@@ -31,7 +40,6 @@ public interface LayoutStrategy {
void layout(ContextMenu> menu, LayoutEngine engine);
}
-
/**
* Executes the currently active layout strategy to position and size options dynamically.
*/
@@ -41,48 +49,6 @@ public void applyLayout(ContextMenu> menu) {
}
}
- /**
- * Linear layout for skins that need to know their total dimensions
- */
- public void performSimpleLayout(ContextMenu> menu) {
- if (menu == null) return;
-
- Font font = Minecraft.getInstance().font;
- List
> visibleOptions = menu.getProperties().getSkin().getOptions(menu);
- int paddingValue = menu.getProperties().getPadding();
-
- //width calculation
- int maxInnerWidth = minWidth;
- for (Option> option : visibleOptions) {
- if (!option.shouldRender()) continue;
-
- int preferredWidth = option.getWidth() > 0 ? option.getWidth() : font.width(option.getName());
-
- maxInnerWidth = Math.max(maxInnerWidth, preferredWidth);
- }
-
- int totalMenuWidth = maxInnerWidth + (horizontalPadding * 2) + paddingValue;
-
- int currentY = menu.getY() + verticalPadding + 3;
- int currentX = menu.getX() + horizontalPadding;
-
- // height calculation
- for (Option> option : visibleOptions) {
- if (!option.shouldRender()) continue;
-
- int itemHeight = option.getHeight() > 0 ? option.getHeight() : font.lineHeight;
-
- option.setWidth(totalMenuWidth - (horizontalPadding * 2) - paddingValue);
- option.setHeight(itemHeight);
- option.setPosition(currentX, currentY);
-
- currentY += itemHeight + itemSpacing;
- }
-
- menu.setWidth(totalMenuWidth);
- menu.setHeight(currentY - menu.getY());
- }
-
/**
* Helper function for immediate layouts
* Automatically updates the option's dimensions and returns the updated Y position for the next element.
@@ -133,7 +99,7 @@ public void setActiveStrategy(LayoutStrategy activeStrategy) {
public static class VerticalFlowStrategy implements LayoutStrategy {
@Override
public void layout(ContextMenu> menu, LayoutEngine engine) {
- if (menu == null || menu.getProperties() == null) return;
+ if (menu == null) return;
Font font = Minecraft.getInstance().font;
List
> visibleOptions = menu.getProperties().getSkin().getOptions(menu);
@@ -163,4 +129,21 @@ public void layout(ContextMenu> menu, LayoutEngine engine) {
menu.setHeight(currentY - menu.getY());
}
}
+
+ public record Offset(int left, int top) {
+ public Offset(int all) {
+ this(all, all);
+ }
+
+ public static Offset zero() {
+ return new Offset(0);
+ }
+
+ public Offset add(Offset other) {
+ return new Offset(
+ this.left + other.left,
+ this.top + other.top
+ );
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/CycleOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/CycleOption.java
new file mode 100644
index 0000000..fa3a158
--- /dev/null
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/CycleOption.java
@@ -0,0 +1,60 @@
+package com.tanishisherewith.dynamichud.utils.contextmenu.options;
+
+import net.minecraft.network.chat.Component;
+import org.lwjgl.glfw.GLFW;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class CycleOption extends Option {
+ protected final List values;
+ protected int currentIndex;
+
+ @SafeVarargs
+ public CycleOption(Component name, Supplier getter, Consumer setter, T... values) {
+ this(name, getter, setter, Arrays.asList(values));
+ }
+
+ public CycleOption(Component name, Supplier getter, Consumer setter, List values) {
+ super(name, getter, setter);
+ this.values = values;
+ this.currentIndex = values.indexOf(value);
+ if (currentIndex == -1) {
+ for (int i = 0; i < values.size(); i++) {
+ if (values.get(i).toString().equals(value)) {
+ currentIndex = i;
+ break;
+ }
+ }
+ }
+ }
+
+ public void cycle(int direction) {
+ currentIndex = (currentIndex + direction + values.size()) % values.size();
+ if (currentIndex < 0) currentIndex += values.size();
+
+ set(values.get(currentIndex));
+ }
+
+ public T getCurrentValue() { return value; }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (super.mouseClicked(mouseX, mouseY, button)) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
+ cycle(1);
+ } else if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
+ cycle(-1);
+ }
+ set(value);
+ return true;
+ }
+ return false;
+ }
+
+ public List getValues() {
+ return values;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
deleted file mode 100644
index ffb0350..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/EnumOption.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.options;
-
-import net.minecraft.network.chat.Component;
-
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-public class EnumOption> extends Option {
- private final E[] values;
- private int currentIndex = 0;
-
- public EnumOption(Component name, Supplier getter, Consumer setter, E[] values) {
- super(name, getter, setter);
- this.values = values;
- this.value = get();
- for (int i = 0; i < values.length; i++) {
- if (values[i] == value) {
- currentIndex = i;
- break;
- }
- }
- }
-
- @Override
- public boolean mouseClicked(double mouseX, double mouseY, int button) {
- if (super.mouseClicked(mouseX, mouseY, button)) {
- 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;
- }
- return false;
- }
-
- public E[] getValues() {
- return values;
- }
-}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
deleted file mode 100644
index f87a648..0000000
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/ListOption.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.tanishisherewith.dynamichud.utils.contextmenu.options;
-
-import net.minecraft.network.chat.Component;
-
-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 ListOption(Component name, Supplier getter, Consumer setter, List values) {
- super(name, getter, setter);
- 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 boolean mouseClicked(double mouseX, double mouseY, int button) {
- if (super.mouseClicked(mouseX, mouseY, button)) {
- 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;
- }
- return false;
- }
-
- public List getValues() {
- return values;
- }
-}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
index 33b0c5a..b10cd69 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
@@ -10,6 +10,7 @@
import java.util.List;
// A group is just another type of Option that contains other options
+@SuppressWarnings({"rawtypes", "unchecked"})
public class OptionGroup extends Option {
private final List
> groupOptions = new ArrayList<>();
protected boolean expanded; // Skins can choose to use this or ignore it
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
index 28c6cca..2a8f89f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
@@ -8,6 +8,7 @@
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.network.chat.Component;
+import org.jspecify.annotations.NonNull;
public class ContextMenuScreen extends Screen {
ContextMenu> contextMenu;
@@ -41,7 +42,7 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
}
@Override
- public void renderBackground(GuiGraphics guiGraphics, int i, int j, float f) {
+ public void renderBackground(@NonNull GuiGraphics guiGraphics, int i, int j, float f) {
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
index 89bbe7c..39b51ec 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ClassicSkin.java
@@ -21,8 +21,7 @@ public ClassicSkin() {
super();
addRenderer(BooleanOption.class, ClassicBooleanRenderer::new);
addRenderer(ColorOption.class, ClassicColorOptionRenderer::new);
- addRenderer(EnumOption.class, ClassicEnumRenderer::new);
- addRenderer(ListOption.class, ClassicListRenderer::new);
+ addRenderer(CycleOption.class, ClassicCycleRenderer::new);
addRenderer(SubMenuOption.class, ClassicSubMenuRenderer::new);
addRenderer(RunnableOption.class, ClassicRunnableRenderer::new);
addRenderer(DoubleOption.class, ClassicDoubleRenderer::new);
@@ -35,10 +34,6 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
this.contextMenu = contextMenu;
ContextMenuProperties properties = contextMenu.getProperties();
- if (contextMenu.getLayoutEngine() != null) {
- contextMenu.getLayoutEngine().applyLayout(contextMenu);
- }
-
drawBackground(graphics, contextMenu, properties);
for (Option> option : getOptions(contextMenu)) {
@@ -120,19 +115,11 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
}
}
- public static class ClassicEnumRenderer> implements SkinRenderer> {
+ public static class ClassicCycleRenderer implements SkinRenderer> {
@Override
- public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
+ public void render(GuiGraphics graphics, CycleOption option, int x, int y, int mouseX, int mouseY) {
graphics.drawString(mc.font, option.name.copy().append(": "), x, y, Color.WHITE.getRGB(), false);
- graphics.drawString(mc.font, option.get().name(), x + mc.font.width(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false);
- }
- }
-
- public static class ClassicListRenderer implements SkinRenderer> {
- @Override
- public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
- graphics.drawString(mc.font, option.name.copy().append(": "), x, y + 1, Color.WHITE.getRGB(), false);
- graphics.drawString(mc.font, option.get().toString(), x + mc.font.width(option.name + ": ") + 1, y + 1, Color.CYAN.getRGB(), false);
+ graphics.drawString(mc.font, option.get().toString(), x + mc.font.width(option.name + ": ") + 1, y, Color.CYAN.getRGB(), false);
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
index 9266750..0275199 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/MinecraftSkin.java
@@ -6,7 +6,7 @@
import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.ValueAnimation;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
-import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutContext;
+import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutEngine;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.GroupableSkin;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer;
@@ -49,9 +49,9 @@ public class MinecraftSkin extends Skin implements GroupableSkin {
public static final int DEFAULT_SCROLLBAR_WIDTH = 8;
public static final int DEFAULT_PANEL_WIDTH = 248;
public static final int DEFAULT_PANEL_HEIGHT = 165;
- private final int panelWidth;
- private final int panelHeight;
- private final int groupPanelWidth = 60; // Width for the group panel
+ private int panelWidth;
+ private int panelHeight;
+ private int groupPanelWidth = 60; // Width for the group panel
private int imageX, imageY;
private final ScrollHandler scrollHandler;
@@ -68,12 +68,12 @@ public MinecraftSkin(PanelColor color) {
this.panelColor = color;
addRenderer(BooleanOption.class, MinecraftBooleanRenderer::new);
addRenderer(DoubleOption.class, MinecraftDoubleRenderer::new);
- addRenderer(EnumOption.class, MinecraftEnumRenderer::new);
- addRenderer(ListOption.class, MinecraftListRenderer::new);
+ addRenderer(CycleOption.class, MinecraftCycleRenderer::new);
addRenderer(SubMenuOption.class, MinecraftSubMenuRenderer::new);
addRenderer(RunnableOption.class, MinecraftRunnableRenderer::new);
addRenderer(ColorOption.class, MinecraftColorOptionRenderer::new);
+ // if in case of different texture support.
this.panelHeight = DEFAULT_PANEL_HEIGHT;
this.panelWidth = DEFAULT_PANEL_WIDTH;
this.BACKGROUND_PANEL = DEFAULT_BACKGROUND_PANEL;
@@ -322,8 +322,8 @@ public boolean mouseDragged(ContextMenu> menu, double mouseX, double mouseY, i
}
@Override
- public LayoutContext.Offset getGroupIndent() {
- return LayoutContext.Offset.zero();
+ public LayoutEngine.Offset getGroupIndent() {
+ return LayoutEngine.Offset.zero();
}
public void setPanelColor(PanelColor panelColor) {
@@ -557,7 +557,6 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, option.isMouseOver(mouseX, mouseY) ? HIGHLIGHTED_TEXTURE : TEXTURE, option.getX(), y, option.getWidth(), 20);
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, isMouseOverHandle ? HANDLE_HIGHLIGHTED_TEXTURE : HANDLE_TEXTURE, (int) Math.round(sliderX), y, 8, 20);
- // Determine the number of decimal places in option.step
int decimalPlaces = String.valueOf(option.step).split("\\.")[1].length();
// Format option.value to the determined number of decimal places
@@ -566,37 +565,10 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
}
}
- public class MinecraftEnumRenderer> implements SkinRenderer> {
+ public class MinecraftCycleRenderer implements SkinRenderer> {
private int maxWidth = 50;
- private void calculateMaxWidth(EnumOption option) {
- for (E enumConstant : option.getValues()) {
- int width = mc.font.width(enumConstant.name()) + 5;
- if (width > maxWidth) {
- maxWidth = width;
- }
- }
- }
-
- @Override
- public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
- calculateMaxWidth(option);
- option.setWidth(maxWidth);
-
- graphics.drawString(mc.font, option.name.copy().append(": "), x + 15, y + 25 / 2 - 5, -1, true);
-
- option.setPosition(x + panelWidth - maxWidth - 25, y);
-
- graphics.blitSprite(RenderPipelines.GUI_TEXTURED, TEXTURES.get(true, option.isMouseOver(mouseX, mouseY)), option.getX(), y, maxWidth, 20);
- String Component = option.get().toString();
- graphics.drawString(mc.font, Component, option.getX() + maxWidth / 2 - mc.font.width(Component) / 2, y + 5, Color.CYAN.getRGB(), true);
- }
- }
-
- public class MinecraftListRenderer implements SkinRenderer> {
- private int maxWidth = 50;
-
- private void calculateMaxWidth(ListOption option) {
+ private void calculateMaxWidth(CycleOption option) {
for (E listValues : option.getValues()) {
int width = mc.font.width(listValues.toString()) + 5;
if (width > maxWidth) {
@@ -606,7 +578,7 @@ private void calculateMaxWidth(ListOption option) {
}
@Override
- public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
+ public void render(GuiGraphics graphics, CycleOption option, int x, int y, int mouseX, int mouseY) {
calculateMaxWidth(option);
option.setWidth(maxWidth);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index 2ff9eec..5e15ec5 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -2,10 +2,13 @@
import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.AnimationProperty;
import com.tanishisherewith.dynamichud.helpers.animationhelper.EasingType;
import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.MathAnimations;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.SquishAnimator;
+import com.tanishisherewith.dynamichud.helpers.animationhelper.animations.ValueAnimation;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenu;
-import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutContext;
+import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutEngine;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.GroupableSkin;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces.SkinRenderer;
@@ -19,7 +22,6 @@
import org.lwjgl.glfw.GLFW;
import java.awt.*;
-import java.util.Arrays;
import java.util.List;
import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_GREEN;
@@ -50,8 +52,7 @@ public ModernSkin(float radius, Component defaultToolTipHeader, Component defaul
addRenderer(BooleanOption.class, ModernBooleanRenderer::new);
addRenderer(DoubleOption.class, ModernDoubleRenderer::new);
- addRenderer(EnumOption.class, ModernEnumRenderer::new);
- addRenderer(ListOption.class, ModernListRenderer::new);
+ addRenderer(CycleOption.class, ModernCycleRenderer::new);
addRenderer(SubMenuOption.class, ModernSubMenuRenderer::new);
addRenderer(RunnableOption.class, ModernRunnableRenderer::new);
addRenderer(ColorOption.class, ModernColorOptionRenderer::new);
@@ -70,8 +71,8 @@ public ModernSkin() {
}
@Override
- public LayoutContext.Offset getGroupIndent() {
- return new LayoutContext.Offset(4, 4);
+ public LayoutEngine.Offset getGroupIndent() {
+ return new LayoutEngine.Offset(4, 4);
}
public void enableSkinScissor(GuiGraphics graphics) {
@@ -85,7 +86,7 @@ public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int
}
private int calcOptionHeight(Option> option) {
if (option instanceof BooleanOption || option instanceof DoubleOption) return 14;
- if (option instanceof EnumOption || option instanceof ListOption) return mc.font.lineHeight + 2;
+ if (option instanceof CycleOption) return mc.font.lineHeight + 2;
if (option instanceof SubMenuOption) return 16;
if (option instanceof RunnableOption) return mc.font.lineHeight + 6;
if (option instanceof ColorOption colorOption) {
@@ -173,7 +174,7 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
enableSkinScissor(graphics);
- int yOffset = contextMenu.y + 19 + 3 - scrollHandler.getScrollOffset();
+ int yPos = contextMenu.y + 22 - scrollHandler.getScrollOffset();
for (Option> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
@@ -183,21 +184,21 @@ public void renderContextMenu(GuiGraphics graphics, ContextMenu> contextMenu,
}
option.setHeight(calcOptionHeight(option));
- int nextY = contextMenu.getLayoutEngine().layoutOption(option, optionStartX + 2, yOffset, targetWidth);
+ int nextY = contextMenu.getLayoutEngine().layoutOption(option, optionStartX + 2, yPos, targetWidth);
if (option instanceof OptionGroup group) {
- this.renderGroup(graphics, group, optionStartX + 2, yOffset, targetWidth, mouseX, mouseY);
- yOffset += group.getHeight() + contextMenu.getLayoutEngine().getItemSpacing();
+ this.renderGroup(graphics, group, optionStartX + 2, yPos, mouseX, mouseY);
+ yPos += group.getHeight() + contextMenu.getLayoutEngine().getItemSpacing();
} else {
option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
- yOffset = nextY;
+ yPos = nextY;
}
}
DrawHelper.disableScissor(graphics);
contextMenu.setWidth(width);
- contextMenu.setHeight(yOffset - (contextMenu.y + 19 + 3 - scrollHandler.getScrollOffset()) + 4);
+ contextMenu.setHeight(yPos - (contextMenu.y + 26 - scrollHandler.getScrollOffset()));
scrollHandler.updateScrollOffset(getMaxScrollOffset());
@@ -322,13 +323,13 @@ public boolean mouseClicked(ContextMenu> menu, double mouseX, double mouseY, i
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY, 7, height)) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY + 19, 7, height)) {
scrollHandler.startDragging(mouseY);
}
if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT) {
int optionStartX = contextMenuX + (int) (width * 0.2f) + 10;
- int yOffset = contextMenu.y + 22 - scrollHandler.getScrollOffset();
+ int yPos = contextMenu.y + 22 - scrollHandler.getScrollOffset();
int spacing = contextMenu.getLayoutEngine().getItemSpacing();
for (Option> option : getOptions(contextMenu)) {
@@ -337,15 +338,15 @@ public boolean mouseClicked(ContextMenu> menu, double mouseX, double mouseY, i
int optHeight = calcOptionHeight(option);
if (option instanceof OptionGroup group) {
Component groupText = group.name.copy().append(" " + (group.isExpanded() ? "-" : "+"));
- if (isMouseOver(mouseX, mouseY, optionStartX + 2, yOffset,
+ if (isMouseOver(mouseX, mouseY, optionStartX + 2, yPos,
mc.font.width(groupText) + 6,
16)) {
group.setExpanded(!group.isExpanded());
return true;
}
- yOffset += group.getHeight() + spacing;
+ yPos += group.getHeight() + spacing;
} else {
- yOffset += optHeight + spacing;
+ yPos += optHeight + spacing;
}
}
}
@@ -362,7 +363,7 @@ public boolean mouseDragged(ContextMenu> menu, double mouseX, double mouseY, i
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY, 7, height)) {
+ if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT && isMouseOver(mouseX, mouseY, contextMenuX + width - 5, contextMenuY + 19, 7, height)) {
scrollHandler.updateScrollPosition(mouseY);
}
return super.mouseDragged(menu, mouseX, mouseY, button, deltaX, deltaY);
@@ -427,6 +428,8 @@ public class ModernColorOptionRenderer implements SkinRenderer {
private static final float ANIMATION_SPEED = 0.1f;
private float scale = 0f;
private boolean display = false;
+ private final SquishAnimator animator = new SquishAnimator();
+
public void update(ColorOption option) {
if (option.getColorGradient().shouldDisplay() && display) {
@@ -457,7 +460,13 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
int width = 20;
int shadowOpacity = Math.min(option.value.getAlpha(), 45);
- Color behindColor = isMouseOver(mouseX, mouseY, x + option.getWidth() - width - 17, y + 1, width + 2, 14) ? getThemeColor().darker().darker() : getThemeColor();
+ boolean isHovering = isMouseOver(mouseX, mouseY, x + option.getWidth() - width - 17, y + 1, width + 2, 14);
+ boolean isDown = isHovering && GLFW.glfwGetMouseButton(mc.getWindow().handle(), GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS;
+ animator.update(isDown);
+
+ Color behindColor = isHovering ? getThemeColor().darker().darker() : getThemeColor();
+ DrawHelper.scaleAndPosition(graphics.pose(), x + option.getWidth() - width - 17, y + 1,width + 2, 14, scale);
+
DrawHelper.drawRoundedRectangleWithShadowBadWay(graphics,
x + option.getWidth() - width - 17,
y + 1,
@@ -489,6 +498,8 @@ public void render(GuiGraphics graphics, ColorOption option, int x, int y, int m
1,
1);
+ DrawHelper.stopScaling(graphics.pose());
+
int targetHeight = (int) (option.getColorGradient().getBoxSize() + option.getColorGradient().getGradientBox().getSize() * scale);
option.setHeight(option.getColorGradient().shouldDisplay() ? targetHeight : 20);
@@ -572,7 +583,10 @@ public void render(GuiGraphics graphics, DoubleOption option, int x, int y, int
float sliderHandleX = sliderX + activeFillWidth - 5;
DrawHelper.drawFilledCircle(graphics, sliderHandleX + 5, y + 1, 2, Color.WHITE.getRGB());
- String label = String.format("%.2f", displayValue);
+ int decimalPlaces = String.valueOf(option.step).split("\\.")[1].length();
+
+ // Format option.value to the determined number of decimal places
+ String label = String.format("%." + decimalPlaces + "f", displayValue);
DrawHelper.scaleAndPosition(graphics.pose(), sliderX + sliderBackgroundWidth - mc.font.width(label), y + 7, 0.6f);
graphics.drawString(
mc.font,
@@ -612,159 +626,106 @@ public boolean mouseDragged(DoubleOption option, double mouseX, double mouseY, i
public boolean mouseReleased(DoubleOption option, double mouseX, double mouseY, int button) {
if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
option.setDragging(false);
- return true;
}
return false;
}
}
- public class ModernEnumRenderer> implements SkinRenderer> {
+ public class ModernCycleRenderer implements SkinRenderer> {
+ private final SquishAnimator textAnim = new SquishAnimator();
+ private final SquishAnimator leftAnim = new SquishAnimator(1.0f,0.9f);
+ private final SquishAnimator rightAnim = new SquishAnimator(1.0f,0.9f);
+
@Override
- public void render(GuiGraphics graphics, EnumOption option, int x, int y, int mouseX, int mouseY) {
+ public void render(GuiGraphics graphics, CycleOption option, int x, int y, int mouseX, int mouseY) {
option.setHeight(mc.font.lineHeight + 2);
Component mainLabel = option.name.copy().append(": ");
- String selectedOption = option.get().toString();
graphics.drawString(mc.font, mainLabel, x + 4, y + 2, -1, false);
- boolean isMouseOverText = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
- Color fillColor = isMouseOverText ? getThemeColor().darker().darker() : getThemeColor();
- DrawHelper.drawRoundedRectangle(
- graphics,
- x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2, 2,
- fillColor.getRGB()
- );
-
- int leftX = x + option.getWidth() - 30;
- boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
- boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
-
- DrawHelper.drawRoundedRectangle(
- graphics,
- leftX + 1, y + 3,
- (mc.font.width("<") * 2) + 10, mc.font.lineHeight, 2,
- ColorHelper.changeAlpha(Color.BLACK, 128).getRGB()
- );
- DrawHelper.drawRoundedRectangle(
- graphics,
- leftX, y + 2,
- true, false, true, false,
- mc.font.width("<") + 5, mc.font.lineHeight, 2,
- hoveredOverLeft ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
- );
- DrawHelper.drawRoundedRectangle(
- graphics,
- leftX + mc.font.width("<") + 6, y + 2,
- false, true, false, true,
- mc.font.width(">") + 5, mc.font.lineHeight, 2,
- hoveredOverRight ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
- );
- DrawHelper.drawVerticalLine(
- graphics,
- leftX + mc.font.width("<") + 5,
- y + 2,
- mc.font.lineHeight,
- 0.7f,
- Color.WHITE.getRGB()
- );
- graphics.drawString(mc.font, "<", leftX + mc.font.width("<") / 2 + 1, y + 3, -1, false);
- graphics.drawString(mc.font, ">", leftX + mc.font.width("<") + 7 + mc.font.width(">") / 2, y + 3, -1, false);
-
- graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), isMouseOverText);
- }
-
- @Override
- public boolean mouseClicked(EnumOption option, double mouseX, double mouseY, int button) {
- if (option.getValues().length == 0) return false;
-
- mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
- mouseY = mc.mouseHandler.ypos() / SCALE_FACTOR;
- int x = option.getX();
- int y = option.getY();
- Component mainLabel = option.name.copy().append(": ");
String selectedOption = option.get().toString();
int leftX = x + option.getWidth() - 30;
- boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
- boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
- boolean hoveredOverMainLabel = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
- if (hoveredOverLeft || hoveredOverRight || hoveredOverMainLabel) {
- E[] values = option.getValues();
- int index = Arrays.asList(values).indexOf(option.value);
+ int mainLabelWidth = mc.font.width(mainLabel);
+ int selectedOptionWidth = mc.font.width(selectedOption);
+ int leftWidth = mc.font.width("<");
+ int rightWidth = mc.font.width(">");
- if (button == GLFW.GLFW_MOUSE_BUTTON_LEFT || hoveredOverLeft) {
- E nextVal = values[(index + 1) % values.length];
- option.set(nextVal);
- } else if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT || hoveredOverRight) {
- E nextVal = values[(index - 1 + values.length) % values.length];
- option.set(nextVal);
- } else {
- return false;
- }
- return true;
- }
+ boolean hoveredOverText = isMouseOver(mouseX, mouseY, x + 4 + mainLabelWidth, y, selectedOptionWidth + 5, mc.font.lineHeight + 2);
+ boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, leftWidth + 5, mc.font.lineHeight);
+ boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + leftWidth + 6, y, rightWidth + 5, mc.font.lineHeight);
- return false;
- }
- }
+ boolean isPressed = GLFW.glfwGetMouseButton(mc.getWindow().handle(), GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS || GLFW.glfwGetMouseButton(mc.getWindow().handle(), GLFW.GLFW_MOUSE_BUTTON_RIGHT) == GLFW.GLFW_PRESS;
+ boolean isClickingOnText = hoveredOverText && isPressed;
+ boolean isClickingOnLeft = hoveredOverLeft && isPressed;
+ boolean isClickingOnRight = hoveredOverRight && isPressed;
- public class ModernListRenderer implements SkinRenderer> {
- @Override
- public void render(GuiGraphics graphics, ListOption option, int x, int y, int mouseX, int mouseY) {
- option.setHeight(mc.font.lineHeight + 2);
+ textAnim.update(isClickingOnText);
+ leftAnim.update(isClickingOnLeft);
+ rightAnim.update(isClickingOnRight);
- Component mainLabel = option.name.copy().append(": ");
- String selectedOption = option.get().toString();
- graphics.drawString(mc.font, mainLabel, x + 4, y + 2, -1, false);
- boolean isMouseOverText = isMouseOver(mouseX, mouseY, x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2);
- Color fillColor = isMouseOverText ? getThemeColor().darker().darker() : getThemeColor();
+ DrawHelper.scaleAndPosition(graphics.pose(),x + 4 + mainLabelWidth, y, selectedOptionWidth + 5, mc.font.lineHeight + 2, textAnim.getScale());
+
+ Color fillColor = hoveredOverText ? getThemeColor().darker().darker() : getThemeColor();
DrawHelper.drawRoundedRectangle(
graphics,
- x + 4 + mc.font.width(mainLabel), y, mc.font.width(selectedOption) + 5, mc.font.lineHeight + 2, 2,
+ x + 4 + mainLabelWidth, y, selectedOptionWidth + 5, mc.font.lineHeight + 2, 2,
fillColor.getRGB()
);
+ graphics.drawString(mc.font, selectedOption, x + 6 + mainLabelWidth, y + 2, Color.WHITE.getRGB(), hoveredOverText);
- int leftX = x + option.getWidth() - 30;
- boolean hoveredOverLeft = isMouseOver(mouseX, mouseY, leftX, y, mc.font.width("<") + 5, mc.font.lineHeight);
- boolean hoveredOverRight = isMouseOver(mouseX, mouseY, leftX + mc.font.width("<") + 6, y, mc.font.width(">") + 5, mc.font.lineHeight);
+ DrawHelper.stopScaling(graphics.pose());
+ //Shadow
DrawHelper.drawRoundedRectangle(
graphics,
leftX + 1, y + 3,
- (mc.font.width("<") * 2) + 10, mc.font.lineHeight, 2,
+ (leftWidth * 2) + 10, mc.font.lineHeight, 2,
ColorHelper.changeAlpha(Color.BLACK, 128).getRGB()
);
+
+ DrawHelper.scaleAndPosition(graphics.pose(),leftX, y + 2, leftWidth + 5, mc.font.lineHeight, leftAnim.getScale());
+
DrawHelper.drawRoundedRectangle(
graphics,
leftX, y + 2,
true, false, true, false,
- mc.font.width("<") + 5, mc.font.lineHeight, 2,
+ leftWidth + 5, mc.font.lineHeight, 2,
hoveredOverLeft ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
);
+ graphics.drawString(mc.font, "<", leftX + leftWidth / 2 + 1, y + 3, -1, false);
+
+ DrawHelper.stopScaling(graphics.pose());
+
+ DrawHelper.scaleAndPosition(graphics.pose(),leftX + leftWidth + 6, y + 2, rightWidth + 5, mc.font.lineHeight, rightAnim.getScale());
+
DrawHelper.drawRoundedRectangle(
graphics,
- leftX + mc.font.width("<") + 6, y + 2,
+ leftX + leftWidth + 6, y + 2,
false, true, false, true,
- mc.font.width(">") + 5, mc.font.lineHeight, 2,
+ rightWidth + 5, mc.font.lineHeight, 2,
hoveredOverRight ? getThemeColor().darker().darker().getRGB() : getThemeColor().getRGB()
);
+ graphics.drawString(mc.font, ">", leftX + leftWidth + 7 + rightWidth / 2, y + 3, -1, false);
+ DrawHelper.stopScaling(graphics.pose());
+
+ //todo: unsure whether to keep this or not? it removes the 3D illusion
+ /*
DrawHelper.drawVerticalLine(
graphics,
- leftX + mc.font.width("<") + 5,
+ leftX + leftWidth + 5,
y + 2,
mc.font.lineHeight,
- 0.7f,
+ 1f,
Color.WHITE.getRGB()
);
- graphics.drawString(mc.font, "<", leftX + mc.font.width("<") / 2 + 1, y + 3, -1, false);
- graphics.drawString(mc.font, ">", leftX + mc.font.width("<") + 7 + mc.font.width(">") / 2, y + 3, -1, false);
- graphics.drawString(mc.font, selectedOption, x + 6 + mc.font.width(mainLabel), y + 2, Color.LIGHT_GRAY.getRGB(), isMouseOverText);
+ */
}
@Override
- public boolean mouseClicked(ListOption option, double mouseX, double mouseY, int button) {
+ public boolean mouseClicked(CycleOption option, double mouseX, double mouseY, int button) {
if (option.getValues().isEmpty()) return false;
mouseX = mc.mouseHandler.xpos() / SCALE_FACTOR;
@@ -802,6 +763,8 @@ public boolean mouseClicked(ListOption option, double mouseX, double mouseY,
}
public class ModernSubMenuRenderer implements SkinRenderer {
+ private final SquishAnimator animator = new SquishAnimator();
+
@Override
public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int mouseX, int mouseY) {
String textLabel = "Open";
@@ -809,9 +772,18 @@ public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int
option.setHeight(16);
+
+ float width = mc.font.width(textLabel) + 5;
+
+ boolean isHovering = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, width, mc.font.lineHeight + 4);
+ boolean isDown = isHovering && GLFW.glfwGetMouseButton(mc.getWindow().handle(), GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS;
+ animator.update(isDown);
+
graphics.drawString(mc.font, option.name, x + 4, y + 4, -1, false);
- Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(textLabel) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
+ Color fillColor = isHovering ? getThemeColor().darker().darker() : getThemeColor();
+
+ DrawHelper.scaleAndPosition(graphics.pose(),x,y,width, mc.font.lineHeight + 4, animator.getScale());
DrawHelper.drawRoundedRectangleWithShadowBadWay(
graphics,
xPos - 1, y + 1,
@@ -833,6 +805,9 @@ public void render(GuiGraphics graphics, SubMenuOption option, int x, int y, int
graphics.drawString(mc.font, textLabel, xPos + 2, y + 4, Color.WHITE.getRGB(), true);
+ DrawHelper.stopScaling(graphics.pose());
+
+
option.getSubMenu().render(graphics, x + option.getParentMenu().getWidth(), y, mouseX, mouseY);
}
@@ -870,6 +845,8 @@ public boolean mouseClicked(SubMenuOption option, double mouseX, double mouseY,
}
public class ModernRunnableRenderer implements SkinRenderer {
+ private final SquishAnimator animator = new SquishAnimator();
+
@Override
public void render(GuiGraphics graphics, RunnableOption option, int x, int y, int mouseX, int mouseY) {
String labelText = "Run â–¶";
@@ -877,14 +854,22 @@ public void render(GuiGraphics graphics, RunnableOption option, int x, int y, in
option.setHeight(mc.font.lineHeight + 6);
+ boolean isHovering = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, width, mc.font.lineHeight + 4);
+ boolean isDown = isHovering && GLFW.glfwGetMouseButton(mc.getWindow().handle(), GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS;
+ animator.update(isDown);
+
graphics.drawString(mc.font, option.name, x + 4, y + 4, -1, false);
- Color fillColor = isMouseOver(mouseX, mouseY, xPos + 2, y + 4, mc.font.width(labelText) + 5, mc.font.lineHeight + 4) ? getThemeColor().darker().darker() : getThemeColor();
+ float width = mc.font.width(labelText) + 5;
+
+ Color fillColor = isHovering ? getThemeColor().darker().darker() : getThemeColor();
+
+ DrawHelper.scaleAndPosition(graphics.pose(),xPos - 1, y + 1,width, mc.font.lineHeight + 4, animator.getScale());
DrawHelper.drawRoundedRectangleWithShadowBadWay(
graphics,
xPos - 1, y + 1,
- mc.font.width(labelText) + 5, mc.font.lineHeight + 4,
+ width, mc.font.lineHeight + 4,
2,
fillColor.getRGB(),
180,
@@ -893,6 +878,7 @@ public void render(GuiGraphics graphics, RunnableOption option, int x, int y, in
);
graphics.drawString(mc.font, labelText, xPos + 2, y + 4, option.value ? DARK_GREEN.getRGB() : DARK_RED.getRGB(), true);
+ DrawHelper.stopScaling(graphics.pose());
}
@Override
@@ -905,6 +891,11 @@ public boolean mouseClicked(RunnableOption option, double mouseX, double mouseY,
}
return false;
}
+
+ @Override
+ public boolean mouseReleased(RunnableOption option, double mouseX, double mouseY, int button) {
+ return SkinRenderer.super.mouseReleased(option, mouseX, mouseY, button);
+ }
}
@Override
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
index 6319f77..6a7486c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/interfaces/GroupableSkin.java
@@ -1,11 +1,11 @@
package com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.interfaces;
-import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutContext;
+import com.tanishisherewith.dynamichud.utils.contextmenu.layout.LayoutEngine;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.OptionGroup;
import net.minecraft.client.gui.GuiGraphics;
public interface GroupableSkin {
- LayoutContext.Offset getGroupIndent();
+ LayoutEngine.Offset getGroupIndent();
void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int groupY, int mouseX, int mouseY);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
index 4d10ae4..62e54f8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/handlers/ScrollHandler.java
@@ -48,10 +48,8 @@ public void updateScrollPosition(double mouseY) {
// Calculate the difference in mouse Y position
double deltaY = lastMouseY - mouseY;
- // Update the scroll offset based on the mouse movement
- scrollOffset = Math.clamp(scrollOffset - (int) (deltaY * SCROLL_SPEED), 0, maxScrollOffset);
+ scrollOffset = Math.clamp(scrollOffset - (int) deltaY, 0, maxScrollOffset);
- // Update the last mouse position
lastMouseY = mouseY;
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index 58d568f..c8ccfdc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -239,7 +239,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
// DrawHelper.enableScissor(widgetBox);
- // Draw gradient background with rounded.fsh corners
+ // Draw gradient background with rounded corners
if (!isInEditor) {
DrawHelper.drawRoundedRectangle(
graphics,
@@ -352,7 +352,10 @@ public void createMenu() {
menu = new ContextMenu<>(getX(), (int) (getY() + widgetBox.getHeight()), properties);
menu.addOption(new BooleanOption(Component.literal("Show Grid"),
- () -> this.showGrid, value -> this.showGrid = value,
+ () -> this.showGrid, value -> {
+ this.showGrid = value;
+ this.computeOffset();
+ },
BooleanOption.BooleanType.YES_NO)
.description(Component.literal("Shows a grid and Y axis values"))
);
@@ -360,7 +363,7 @@ public void createMenu() {
1, 25, 1,
() -> (double) this.gridLines, value -> {
this.setGridLines(value.intValue());
- computeOffset();
+ this.computeOffset();
}, menu)
.renderWhen(() -> this.showGrid)
);
@@ -384,9 +387,13 @@ public void createMenu() {
}
private void computeOffset(){
+ if(!showGrid) {
+ offset = 0;
+ return;
+ }
+
// The first Component is usually the largest but a negative value may occupy more width so we check the first and last Component.
// Idk how this will break.
-
String firstText = formatValue(maxValue - valueStep);
String lastText = formatValue(maxValue - (gridLines * valueStep));
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 2ad95fb..9fccebe 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -1,7 +1,6 @@
package com.tanishisherewith.dynamichud.widgets;
import com.tanishisherewith.dynamichud.DynamicHUD;
-import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.integration.IntegrationManager;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
@@ -10,7 +9,6 @@
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProperties;
import com.tanishisherewith.dynamichud.utils.contextmenu.ContextMenuProvider;
import com.tanishisherewith.dynamichud.utils.contextmenu.options.*;
-import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.MinecraftSkin;
import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.ModernSkin;
import com.tanishisherewith.dynamichud.widget.DynamicValueWidget;
import com.tanishisherewith.dynamichud.widget.WidgetData;
@@ -55,6 +53,8 @@ public TextWidget(String registryID, String registryKey, boolean shadow, boolean
public void createMenu() {
menu = new ContextMenu<>(getX(), getY(),ContextMenuProperties.builder().skin(new ModernSkin()).build());
+ // if(IntegrationManager.IS_TEST_MODE) menu.setLayoutEngine(new LayoutEngine(20,20,20,80));
+
menu.addOption(new BooleanOption(Component.literal("Shadow"),
() -> this.shadow, value -> this.shadow = value,
BooleanOption.BooleanType.ON_OFF)
@@ -71,7 +71,7 @@ public void createMenu() {
.renderWhen(() -> !this.rainbow)
);
menu.addOption(new DoubleOption(Component.literal("Rainbow Speed"),
- 1, 5.0f, 1,
+ 1, 5, 1,
() -> (double) this.rainbowSpeed, value -> this.rainbowSpeed = value.intValue(), menu)
.renderWhen(() -> this.rainbow)
);
@@ -101,19 +101,16 @@ public void createMenu() {
() -> this.setPosition(0, 0))
.description(Component.literal("Reset widget to default position")));
- // List Option
AtomicReference style = new AtomicReference<>("Style1");
+ AtomicReference align = new AtomicReference<>(GroupLayout.Alignment.CENTER);
+
+ // List Option
List styles = Arrays.asList("Style1", "Style2", "Style3");
- menu.addOption(new ListOption<>(Component.literal("Text Style"),
- style::get, style::set, styles)
- .description(Component.literal("Choose a text style")));
+ menu.addOption(new CycleOption<>(Component.literal("Text Style"), style::get, style::set, styles));
// Enum Option
- AtomicReference align = new AtomicReference<>(GroupLayout.Alignment.CENTER);
+ menu.addOption(new CycleOption<>(Component.literal("Alignment"), align::get, align::set, GroupLayout.Alignment.values()));
- menu.addOption(new EnumOption<>(Component.literal("Alignment"),
- align::get, align::set, GroupLayout.Alignment.values())
- .description(Component.literal("Set text alignment")));
// Option Group
OptionGroup group = new OptionGroup(Component.literal("Display Options"));
From a00b3274e7a853565a52a862d84a5a0534af98bd Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Fri, 19 Jun 2026 02:33:29 +0530
Subject: [PATCH 07/22] Added Local Widget and ContextMenu scaling Rename
ShouldScale to canScale All scalable widgets can be scaled by holding CTRL
and scrolling up or down.
---
.../dynamichud/IntegrationTest.java | 4 +-
.../utils/contextmenu/ContextMenu.java | 56 +++++++----
.../contextmenu/options/RunnableOption.java | 1 +
.../contextmenu/screen/ContextMenuScreen.java | 4 +-
.../dynamichud/widget/Widget.java | 64 ++++++++-----
.../dynamichud/widget/WidgetBox.java | 92 +++++++++++-------
.../dynamichud/widgets/GraphWidget.java | 93 ++++++++-----------
.../dynamichud/widgets/ItemWidget.java | 4 +-
.../dynamichud/widgets/TextWidget.java | 7 +-
9 files changed, 184 insertions(+), 141 deletions(-)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
index 8b260b0..51d4b77 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
@@ -75,8 +75,8 @@ public void init() {
.label("FPS Chart")
.graphColor(Color.CYAN)
.anchor(Widget.Anchor.CENTER)
- .height(100)
- .width(150)
+ .gWidth(100)
+ .gHeight(150)
.gridLines(10)
.backgroundColor(Color.DARK_GRAY)
.lineThickness(1f)
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 b75fe93..2b6c3ea 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -40,9 +40,10 @@ public class ContextMenu implements Input {
protected int width = 0;
protected int height = 0, widgetHeight = 0;
protected boolean shouldDisplay = false;
- protected float scale = 0.0f;
+ protected float animScale = 0.0f;
protected Screen parentScreen = null;
protected boolean newScreenFlag = false;
+ protected float menuScale = 1.0f;
private final ValueAnimation scaleAnimation;
@@ -73,18 +74,18 @@ public ContextMenu(int x, int y, @NotNull T properties, ContextMenuScreenFactory
this.scaleAnimation = new ValueAnimation(new AnimationProperty<>() {
@Override
public Float get() {
- return scale;
+ return animScale;
}
@Override
public void set(Float value) {
- scale = value;
+ animScale = value;
}
}, 0.0f, 1.0f);
this.scaleAnimation.easing(EasingType.EASE_IN_CUBIC);
this.scaleAnimation.duration(280);
this.scaleAnimation.onComplete(() -> {
- if (scale <= 0.0f && parentScreen != null && properties.getSkin().shouldCreateNewScreen()) {
+ if (animScale <= 0.0f && parentScreen != null && properties.getSkin().shouldCreateNewScreen()) {
DynamicHUD.MC.setScreen(parentScreen);
}
});
@@ -99,6 +100,14 @@ public void addOption(Option> option) {
options.add(option);
}
+ public float getMenuScale() {
+ return animScale * menuScale;
+ }
+
+ public void setMenuScale(float menuScale) {
+ this.menuScale = Math.clamp(menuScale, 0.3f, 2.0f);
+ }
+
public void render(GuiGraphics graphics, int xPos, int yPos, int mouseX, int mouseY) {
if (newScreenFlag && screenFactory != null) {
DynamicHUD.MC.setScreen(screenFactory.create(this, properties));
@@ -110,12 +119,12 @@ public void render(GuiGraphics graphics, int xPos, int yPos, int mouseX, int mou
update();
- if (scale <= 0.0f || newScreenFlag) return;
+ if (animScale <= 0.0f || newScreenFlag) return;
- DrawHelper.scaleAndPosition(graphics.pose(), this.x, this.y,this.width,this.height, scale);
+ DrawHelper.scaleAndPosition(graphics.pose(), this.x, this.y,this.width,this.height, getMenuScale());
properties.getSkin().setContextMenu(this);
- properties.getSkin().renderContextMenu(graphics, this, mouseX, mouseY);
+ properties.getSkin().renderContextMenu(graphics, this, getTMouseX(mouseX), getTMouseY(mouseY));
DrawHelper.stopScaling(graphics.pose());
}
@@ -126,7 +135,7 @@ public void update() {
}
if (!properties.enableAnimations()) {
- scale = shouldDisplay ? 1.0f : 0.0f;
+ animScale = shouldDisplay ? 1.0f : 0.0f;
return;
}
@@ -140,11 +149,11 @@ public void close() {
option.onClose();
}
if (properties.enableAnimations()) {
- scaleAnimation.startValue(scale);
+ scaleAnimation.startValue(animScale);
scaleAnimation.endValue(0.0f);
scaleAnimation.start();
} else {
- scale = 0.0f;
+ animScale = 0.0f;
if (properties.getSkin().shouldCreateNewScreen() && parentScreen != null) {
DynamicHUD.MC.setScreen(parentScreen);
}
@@ -159,11 +168,11 @@ public void open() {
newScreenFlag = true;
}
if (properties.enableAnimations()) {
- scaleAnimation.startValue(scale);
+ scaleAnimation.startValue(animScale);
scaleAnimation.endValue(1.0f);
scaleAnimation.start();
} else {
- scale = 0.0f;
+ animScale = 0.0f;
if (properties.getSkin().shouldCreateNewScreen() && parentScreen != null) {
DynamicHUD.MC.setScreen(parentScreen);
}
@@ -178,6 +187,14 @@ public void toggleDisplay() {
}
}
+ protected int getTMouseX(double mouseX) {
+ return (int) ((mouseX - getX()) / getMenuScale() + getX());
+ }
+
+ protected int getTMouseY(double mouseY) {
+ return (int) ((mouseY - getY()) / getMenuScale() + getY());
+ }
+
public void toggleDisplay(WidgetBox widgetBox, double mouseX, double mouseY, int button) {
if (button == GLFW.GLFW_MOUSE_BUTTON_RIGHT && widgetBox.isMouseOver(mouseX, mouseY)) {
toggleDisplay();
@@ -201,8 +218,9 @@ public void setLayoutEngine(LayoutEngine layoutEngine) {
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (!shouldDisplay) return false;
+
for (Option option : options) {
- if (option.shouldRender() && option.getRenderer().mouseClicked(option ,mouseX, mouseY, button)) {
+ if (option.shouldRender() && option.getRenderer().mouseClicked(option ,getTMouseX(mouseX), getTMouseY(mouseY), button)) {
return true;
}
}
@@ -214,7 +232,7 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
if (!shouldDisplay) return false;
for (Option option : options) {
if(option.shouldRender()){
- option.getRenderer().mouseReleased(option, mouseX, mouseY, button);
+ option.getRenderer().mouseReleased(option, getTMouseX(mouseX), getTMouseY(mouseY), button);
}
}
return properties.getSkin().mouseReleased(this, mouseX, mouseY, button);
@@ -223,8 +241,12 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
if (!shouldDisplay) return false;
+
+ double tDeltaX = deltaX / getMenuScale();
+ double tDeltaY = deltaY / getMenuScale();
+
for (Option option : options) {
- if(option.shouldRender() && option.getRenderer().mouseDragged(option, mouseX, mouseY, button, deltaX, deltaY)){
+ if(option.shouldRender() && option.getRenderer().mouseDragged(option, getTMouseX(mouseX), getTMouseY(mouseY), button, tDeltaX, tDeltaY)){
return true;
}
}
@@ -327,10 +349,6 @@ public ContextMenu createSubMenu(int x, int
return new ContextMenu<>(x, y, properties, screenFactory, this);
}
- public float getScale() {
- return scale;
- }
-
public boolean isVisible() {
return shouldDisplay;
}
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 8605735..21a5ed0 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
@@ -37,6 +37,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
}
return false;
}
+
public void toggle(){
set(true);
try {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
index 2a8f89f..4ef4d73 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/screen/ContextMenuScreen.java
@@ -29,14 +29,14 @@ public void added() {
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
contextMenu.update();
- DrawHelper.scaleAndPosition(graphics.pose(), (float) width / 2, (float) height / 2, contextMenu.getScale());
+ DrawHelper.scaleAndPosition(graphics.pose(), (float) width / 2, (float) height / 2, contextMenu.getMenuScale());
properties.getSkin().setContextMenu(contextMenu);
properties.getSkin().renderContextMenu(graphics, contextMenu, mouseX, mouseY);
DrawHelper.stopScaling(graphics.pose());
- if (contextMenu.getScale() <= 0 && !contextMenu.isVisible()) {
+ if (contextMenu.getMenuScale() <= 0 && !contextMenu.isVisible()) {
contextMenu.close();
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
index 5c6a89c..7e8a8b6 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
@@ -9,6 +9,7 @@
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
+import net.minecraft.util.Mth;
import org.lwjgl.glfw.GLFW;
public abstract class Widget implements Input {
@@ -47,7 +48,7 @@ public abstract class Widget implements Input {
// Absolute position of the widget on screen in pixels.
protected int x, y;
- protected boolean shouldScale = true;
+ protected boolean canScale = true;
protected Anchor anchor; // The chosen anchor point
@@ -94,13 +95,12 @@ public int getY() {
return y;
}
- public float getWidth() {
- return widgetBox.getWidth();
+ public float getScale() {
+ return canScale ? widgetBox.getScale() * DynamicHUD.getGlobalScale() : 1.0f;
}
- public float getHeight() {
- return widgetBox.getHeight();
- }
+ public float getWidth() { return widgetBox.getWidth(); }
+ public float getHeight() { return widgetBox.getHeight(); }
private void calculateOffset(int initialX, int initialY, int screenWidth, int screenHeight) {
int anchorX = getAnchorX(screenWidth);
@@ -163,12 +163,12 @@ public final void render(GuiGraphics graphics, int mouseX, int mouseY) {
if (!isVisible()) return;
- if (shouldScale) {
- DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), DynamicHUD.getGlobalScale());
+ if (canScale) {
+ DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), getScale());
}
renderWidget(graphics, mouseX, mouseY);
- if (shouldScale) {
+ if (canScale) {
DrawHelper.stopScaling(graphics.pose());
}
clampPosition();
@@ -182,12 +182,12 @@ public final void renderInEditor(GuiGraphics graphics, int mouseX, int mouseY) {
drawWidgetBackground(graphics);
- if (shouldScale) {
- DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), DynamicHUD.getGlobalScale());
+ if (canScale) {
+ DrawHelper.scaleAndPosition(graphics.pose(), getX(), getY(), getScale());
}
renderWidgetInEditor(graphics, mouseX, mouseY);
- if (shouldScale) {
+ if (canScale) {
DrawHelper.stopScaling(graphics.pose());
}
clampPosition();
@@ -216,6 +216,14 @@ private void renderWidgetInEditor(GuiGraphics graphics, int mouseX, int mouseY)
renderWidget(graphics, mouseX, mouseY);
}
+ protected int getTransformedMouseX(double mouseX) {
+ return (int) ((mouseX - getX()) / getScale() + getX());
+ }
+
+ protected int getTransformedMouseY(double mouseY) {
+ return (int) ((mouseY - getY()) / getScale() + getY());
+ }
+
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
@@ -233,8 +241,8 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
/* Input related methods. Override with **super call** to add your own input-based code like contextMenu */
public void clampPosition() {
- this.x = (int) org.joml.Math.clamp(this.x, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
- this.y = (int) org.joml.Math.clamp(this.y, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
+ this.x = (int) Mth.clamp(this.x, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
+ this.y = (int) Mth.clamp(this.y, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
}
@Override
@@ -261,8 +269,8 @@ public boolean mouseDragged(double mouseX, double mouseY, int button, double del
newY = (newY / snapBoxHeight) * snapBoxHeight;
}
- this.x = (int) org.joml.Math.clamp(newX, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
- this.y = (int) org.joml.Math.clamp(newY, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
+ this.x = (int) Mth.clamp(newX, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
+ this.y = (int) Mth.clamp(newY, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
calculateOffset(x, y, mc.getWindow().getGuiScaledWidth(), mc.getWindow().getGuiScaledHeight()); // Set initial offset
@@ -285,6 +293,12 @@ public boolean mouseReleased(double mouseX, double mouseY, int button) {
*/
@Override
public void mouseScrolled(double mouseX, double mouseY, double vAmount, double hAmount) {
+ if (canScale && widgetBox.isMouseOver(mouseX,mouseY) && GLFW.glfwGetKey(mc.getWindow().handle(),GLFW.GLFW_KEY_LEFT_CONTROL) == GLFW.GLFW_PRESS) {
+ widgetBox.setScale(widgetBox.getScale() + (float) vAmount * 0.05f);
+
+ clampPosition();
+ calculateOffset(x, y, mc.getWindow().getGuiScaledWidth(), mc.getWindow().getGuiScaledHeight());
+ }
}
@Override
@@ -309,7 +323,6 @@ public void onClose() {
/**
* Displays a faint grayish background if enabled or faint reddish background if disabled.
- * Drawn with 2 pixel offset to all sides
*/
protected void drawWidgetBackground(GuiGraphics graphics) {
int backgroundColor = this.isVisible() ? GlobalConfig.get().getHudActiveColor().getRGB() : GlobalConfig.get().getHudInactiveColor().getRGB();
@@ -330,6 +343,10 @@ protected void setTooltipText(Component Component) {
this.tooltipText = Component;
}
+ public void setWidgetScale(float widgetScale) {
+ widgetBox.setScale(widgetScale);
+ }
+
public void readFromTag(CompoundTag tag) {
modId = tag.getString("modId").orElse("unknown");
uid = tag.contains("UID") ? new UID(tag.getString("UID").get()) : UID.generate();
@@ -340,7 +357,9 @@ public void readFromTag(CompoundTag tag) {
offsetY = tag.getInt("offsetY").orElse(0);
isVisible = tag.getBoolean("isVisible").orElse(true);
isDraggable = tag.getBoolean("isDraggable").orElse(true);
- shouldScale = tag.getBoolean("shouldScale").orElse(true);
+ canScale = tag.getBoolean("canScale").orElse(true);
+
+ widgetBox.setScale(tag.getFloat("widgetScale").orElse(1.0f));
}
/**
@@ -353,7 +372,8 @@ public void writeToTag(CompoundTag tag) {
tag.putString("modId", modId);
tag.putString("UID", uid.getUniqueID());
tag.putBoolean("isDraggable", isDraggable);
- tag.putBoolean("shouldScale", shouldScale);
+ tag.putBoolean("canScale", canScale);
+ tag.putFloat("widgetScale", widgetBox.getScale());
// tag.putInt("x", x);
// tag.putInt("y", y);
tag.putString("anchor", anchor.name());
@@ -374,8 +394,8 @@ public void setUid(UID uid) {
this.uid = uid;
}
- public void setShouldScale(boolean shouldScale) {
- this.shouldScale = shouldScale;
+ public void setCanScale(boolean canScale) {
+ this.canScale = canScale;
}
public String getModId() {
@@ -393,7 +413,7 @@ public String toString() {
", isVisible=" + isVisible +
", isDraggable=" + isDraggable +
", shiftDown=" + isShiftDown +
- ", shouldScale=" + shouldScale +
+ ", canScale=" + canScale +
'}';
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
index e12da3f..8cd8cc5 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/WidgetBox.java
@@ -1,19 +1,33 @@
package com.tanishisherewith.dynamichud.widget;
+import com.tanishisherewith.dynamichud.DynamicHUD;
+import net.minecraft.util.Mth;
+
public class WidgetBox {
public float x, y;
- private float width;
- private float height;
+ private float width, rawWidth;
+ private float height, rawHeight;
+ protected float scale;
- public WidgetBox(int x, int y, int width, int height) {
+ public WidgetBox(float x, float y, float width, float height, float scale) {
this.x = x;
this.y = y;
- this.width = width;
- this.height = height;
+ this.width = width * scale;
+ this.height = height * scale;
+ this.rawWidth = width;
+ this.rawHeight = height;
+ this.scale = scale;
+ }
+
+ public WidgetBox(float x, float y, float width, float height) {
+ this(x,y,width,height,1.0f);
}
+ /**
+ * Checks if the mouse is over the box, accounting for its scale factor.
+ */
public boolean isMouseOver(double mouseX, double mouseY) {
- return mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height;
+ return mouseX >= x && mouseX <= x + this.width && mouseY >= y && mouseY <= y + this.height;
}
public float getWidth() {
@@ -24,45 +38,57 @@ 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;
- }
+ public boolean intersects(WidgetBox other, float myScale, float otherScale) {
+ float myWidth = this.width * myScale;
+ float myHeight = this.height * myScale;
+ float oWidth = other.width * otherScale;
+ float oHeight = other.height * otherScale;
- // Check if this box is to the left of the other box
- if (this.x + this.width < other.x) {
- return false;
- }
+ return this.x < other.x + oWidth && this.x + myWidth > other.x &&
+ this.y < other.y + oHeight && this.y + myHeight > other.y;
+ }
- // Check if this box is below the other box
- if (this.y > other.y + other.height) {
- return false;
- }
+ public void setScale(float scale) {
+ this.scale = Mth.clamp(scale, 0.2f, 10.0f);
+ }
- // 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 float getScale() {
+ return scale * DynamicHUD.getGlobalScale();
}
- public void setDimensionsNoScale(float x, float y, float width, float height) {
- this.x = x;
- this.y = y;
- this.height = height;
- this.width = width;
+ public float getRawWidth() {
+ return rawWidth;
+ }
+
+ public float getRawHeight() {
+ return rawHeight;
}
- public void setDimensions(float x, float y, float width, float height, boolean shouldScale, float scale) {
+ private void setDimensions(float x, float y, float width, float height, boolean shouldScale, float scale) {
this.x = x;
this.y = y;
this.height = height * (shouldScale ? scale : 1.0f);
this.width = width * (shouldScale ? scale : 1.0f);
+ this.rawWidth = width;
+ this.rawHeight = height;
+ }
+
+ private void setSize(float width, float height, boolean shouldScale, float scale) {
+ if (width >= 0) {
+ this.width = (float) Math.ceil(width * (shouldScale ? scale : 1.0f));
+ this.rawWidth = width;
+ }
+ if (height >= 0) {
+ this.height = (float) Math.ceil(height * (shouldScale ? scale : 1.0f));
+ this.rawHeight = height;
+ }
+ }
+
+ public void setDimensions(float x, float y, float width, float height, boolean shouldScale) {
+ this.setDimensions(x,y,width,height,shouldScale,getScale());
}
- 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));
+ public void setSize(float width, float height, boolean shouldScale) {
+ this.setSize(width,height,shouldScale,getScale());
}
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index c8ccfdc..cb23beb 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -1,6 +1,5 @@
package com.tanishisherewith.dynamichud.widgets;
-import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.helpers.ColorHelper;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.renderstates.GradientShadowRenderState;
@@ -50,8 +49,8 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
private float lineThickness;
private boolean showGrid;
private int gridLines;
- private float width;
- private float height;
+ private float gWidth;
+ private float gHeight;
private String label;
/// Automatically update the min and max of the graph
private boolean autoUpdateRange = false;
@@ -60,10 +59,10 @@ public class GraphWidget extends DynamicValueWidget implements ContextMenuProvid
private float valueScale;
int offset = -2;
- public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float width, float height, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) {
+ public GraphWidget(String registryID, String registryKey, String modId, Anchor anchor, float gWidth, float gHeight, int maxDataPoints, float minValue, float maxValue, Color graphColor, Color backgroundColor, float lineThickness, boolean showGrid, int gridLines, String label) {
super(DATA, modId, anchor, registryID, registryKey);
- this.width = width;
- this.height = height;
+ this.gWidth = gWidth;
+ this.gHeight = gHeight;
this.maxDataPoints = maxDataPoints;
this.graphColor = graphColor;
this.backgroundColor = backgroundColor;
@@ -84,8 +83,8 @@ private void internal_init() {
Validate.isTrue(maxDataPoints > 2, "MaxDataPoints should be more than 2.");
this.dataPoints = new float[maxDataPoints];
this.label = label.trim();
- this.widgetBox = new WidgetBox(x, y, (int) width, (int) height);
- this.stepY = height / (gridLines + 1);
+ this.widgetBox = new WidgetBox(x, y, (int) gWidth, (int) gHeight);
+ this.stepY = gHeight / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
this.valueScale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
@@ -136,14 +135,14 @@ private List getInterpolatedPoints() {
List points = new ArrayList<>();
if (dataPoints.length < 2) return points;
- float xStep = width / (dataPoints.length - 1);
+ float xStep = gWidth / (dataPoints.length - 1);
float range = Math.max(maxValue - minValue, 0.0001f);
//Pre-calculate Y coordinates
float[] yVals = new float[dataPoints.length];
for (int i = 0; i < dataPoints.length; i++) {
int index = (head + i) % dataPoints.length;
- yVals[i] = y + height - ((dataPoints[index] - minValue) / range * height);
+ yVals[i] = y + gHeight - ((dataPoints[index] - minValue) / range * gHeight);
}
// Monotone Cubic Spline (Fritsch-Carlson) calculation
@@ -213,7 +212,7 @@ private void drawInterpolatedCurve(GuiGraphics graphics, List points, i
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new InterpolatedCurveRenderState(points, thickness, color, new Matrix3x2f(graphics.pose()), CustomRenderLayers.QUADS_CUSTOM_BLEND, (int) width, (int) height, graphics.scissorStack.peek())
+ new InterpolatedCurveRenderState(points, thickness, color, new Matrix3x2f(graphics.pose()), CustomRenderLayers.QUADS_CUSTOM_BLEND, (int) gWidth, (int) gHeight, graphics.scissorStack.peek())
);
}
@@ -222,7 +221,7 @@ private void drawGradientShadow(GuiGraphics graphics, List points, floa
if (points.size() < 2) return;
graphics.guiRenderState.submitGuiElement(
- new GradientShadowRenderState(points,bottomY, startColor, endColor, new Matrix3x2f(graphics.pose()), RenderPipelines.DEBUG_QUADS, (int) width, (int) height, graphics.scissorStack.peek())
+ new GradientShadowRenderState(points,bottomY, startColor, endColor, new Matrix3x2f(graphics.pose()), RenderPipelines.DEBUG_QUADS, (int) gWidth, (int) gHeight, graphics.scissorStack.peek())
);
}
@@ -249,8 +248,8 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
true,
false,
false,
- width,
- height,
+ gWidth,
+ gHeight,
4,
backgroundColor.getRGB()
);
@@ -262,7 +261,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
for (int i = 1; i <= gridLines; i++) {
float yPos = y + stepY * i;
- DrawHelper.drawHorizontalLine(graphics, x + offset, width, yPos, 0.5f, 0x4DFFFFFF); // Semi-transparent white
+ DrawHelper.drawHorizontalLine(graphics, x + offset, gWidth, yPos, 0.5f, 0x4DFFFFFF); // Semi-transparent white
// Draw value labels on the left axis
float value = maxValue - (i * valueStep);
@@ -279,10 +278,10 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
x += offset;
// Draw vertical grid lines (time axis)
- float stepX = width / 5; // 5 vertical lines
+ float stepX = gWidth / 5; // 5 vertical lines
for (int i = 1; i < 5; i++) {
float xPos = x + stepX * i;
- DrawHelper.drawVerticalLine(graphics, xPos, y, height, 0.5f, 0x4DFFFFFF);
+ DrawHelper.drawVerticalLine(graphics, xPos, y, gHeight, 0.5f, 0x4DFFFFFF);
}
}
@@ -290,7 +289,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
// Draw shadow effect under the graph
drawGradientShadow(
- graphics, points, y + height,
+ graphics, points, y + gHeight,
ColorHelper.changeAlpha(graphColor, 100).getRGB(),
0x00000000
);
@@ -305,26 +304,26 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
// Draw axes
- DrawHelper.drawHorizontalLine(graphics, x, width, y + height - 1, 1.0f, 0xFFFFFFFF); // X-axis
- DrawHelper.drawVerticalLine(graphics, x, y, height, 1.0f, 0xFFFFFFFF); // Y-axis
+ DrawHelper.drawHorizontalLine(graphics, x, gWidth, y + gHeight - 1, 1.0f, 0xFFFFFFFF); // X-axis
+ DrawHelper.drawVerticalLine(graphics, x, y, gHeight, 1.0f, 0xFFFFFFFF); // Y-axis
// Draw min and max value labels with formatted values
/*
DrawHelper.scaleAndPosition(context.getMatrices(),x - 5,y,0.5f);
String formattedMaxVal = formatValue(maxValue);
- context.drawText(mc.font, formattedMaxVal, x - 5 - mc.font.width(formattedMaxVal), y - 4, 0xFFFFFFFF, true);
+ context.drawText(mc.font, formattedMaxVal, x - 5 - mc.font.gWidth(formattedMaxVal), y - 4, 0xFFFFFFFF, true);
DrawHelper.stopScaling(context.getMatrices());
*/
- DrawHelper.scaleAndPosition(graphics.pose(), x - 5, y + height, 0.5f);
+ DrawHelper.scaleAndPosition(graphics.pose(), x - 5, y + gHeight, 0.5f);
String formattedMinVal = formatValue(minValue);
- graphics.drawString(mc.font, formattedMinVal, x - mc.font.width(formattedMinVal), (int) (y + height - 4), 0xFFFFFFFF, true);
+ graphics.drawString(mc.font, formattedMinVal, x - mc.font.width(formattedMinVal), (int) (y + gHeight - 4), 0xFFFFFFFF, true);
DrawHelper.stopScaling(graphics.pose());
if(showGrid) x -= offset;
- this.widgetBox.setDimensions(x, y, width + offset, height, shouldScale, DynamicHUD.getGlobalScale());
+ this.widgetBox.setDimensions(x, y, gWidth + offset, gHeight, canScale);
// DrawHelper.disableScissor();
if (menu != null) menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
@@ -392,7 +391,7 @@ private void computeOffset(){
return;
}
- // The first Component is usually the largest but a negative value may occupy more width so we check the first and last Component.
+ // The first Component is usually the largest but a negative value may occupy more gWidth so we check the first and last Component.
// Idk how this will break.
String firstText = formatValue(maxValue - valueStep);
String lastText = formatValue(maxValue - (gridLines * valueStep));
@@ -455,31 +454,13 @@ public void setLabel(String label) {
this.label = label;
}
- @Override
- public float getHeight() {
- return height;
- }
-
- public void setHeight(float height) {
- this.height = height;
- }
-
- @Override
- public float getWidth() {
- return width;
- }
-
- public void setWidth(float width) {
- this.width = width;
- }
-
public int getGridLines() {
return gridLines;
}
public void setGridLines(int gridLines) {
this.gridLines = gridLines;
- this.stepY = height / (gridLines + 1);
+ this.stepY = gHeight / (gridLines + 1);
this.valueStep = (maxValue - minValue) / (gridLines + 1);
this.valueScale = (float) Math.clamp((stepY / 9.5), 0.0f, 1.0f);
}
@@ -517,8 +498,8 @@ public void onClose() {
@Override
public void writeToTag(CompoundTag tag) {
super.writeToTag(tag);
- tag.putFloat("width", width);
- tag.putFloat("height", height);
+ tag.putFloat("gWidth", gWidth);
+ tag.putFloat("gHeight", gHeight);
tag.putInt("maxDataPoints", maxDataPoints);
tag.putFloat("minValue", minValue);
tag.putFloat("maxValue", maxValue);
@@ -535,8 +516,8 @@ public void writeToTag(CompoundTag tag) {
@Override
public void readFromTag(CompoundTag tag) {
super.readFromTag(tag);
- this.width = tag.getFloat("width").orElse(100f);
- this.height = tag.getFloat("height").orElse(50f);
+ this.gWidth = tag.getFloat("gWidth").orElse(100f);
+ this.gHeight = tag.getFloat("gHeight").orElse(50f);
this.maxDataPoints = tag.getInt("maxDataPoints").orElse(100);
this.minValue = tag.getFloat("minValue").orElse(0f);
this.maxValue = tag.getFloat("maxValue").orElse(1f);
@@ -563,8 +544,8 @@ public ContextMenu> getContextMenu() {
public static class GraphWidgetBuilder extends DynamicValueWidgetBuilder {
private Anchor anchor = Anchor.CENTER;
- private float width = 100;
- private float height = 50;
+ private float gWidth = 100;
+ private float gHeight = 50;
private int maxDataPoints = 50;
private float minValue = 0;
private float maxValue = 100;
@@ -588,13 +569,13 @@ public GraphWidgetBuilder anchor(Anchor anchor) {
return this;
}
- public GraphWidgetBuilder width(float width) {
- this.width = width;
+ public GraphWidgetBuilder gWidth(float gWidth) {
+ this.gWidth = gWidth;
return this;
}
- public GraphWidgetBuilder height(float height) {
- this.height = height;
+ public GraphWidgetBuilder gHeight(float gHeight) {
+ this.gHeight = gHeight;
return this;
}
@@ -645,10 +626,10 @@ protected GraphWidgetBuilder self() {
@Override
public GraphWidget build() {
- GraphWidget widget = new GraphWidget(registryID, registryKey, modID, anchor, width, height, maxDataPoints, minValue, maxValue, graphColor, backgroundColor, lineThickness, showGrid, gridLines, label);
+ GraphWidget widget = new GraphWidget(registryID, registryKey, modID, anchor, gWidth, gHeight, maxDataPoints, minValue, maxValue, graphColor, backgroundColor, lineThickness, showGrid, gridLines, label);
widget.setPosition(x, y);
widget.setDraggable(isDraggable);
- widget.setShouldScale(shouldScale);
+ widget.setCanScale(shouldScale);
widget.isVisible = display;
return widget;
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
index edb1c71..e7fb3b2 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/ItemWidget.java
@@ -1,7 +1,5 @@
package com.tanishisherewith.dynamichud.widgets;
-import com.tanishisherewith.dynamichud.DynamicHUD;
-import com.tanishisherewith.dynamichud.config.GlobalConfig;
import com.tanishisherewith.dynamichud.widget.Widget;
import com.tanishisherewith.dynamichud.widget.WidgetData;
import net.minecraft.client.gui.GuiGraphics;
@@ -28,7 +26,7 @@ public ItemWidget() {
@Override
public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
graphics.renderItem(item, x, y);
- widgetBox.setDimensions(getX(), getY(), 16, 16, this.shouldScale, DynamicHUD.getGlobalScale());
+ widgetBox.setDimensions(getX(), getY(), 16, 16, this.canScale);
}
@Override
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
index 9fccebe..8f741dc 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/TextWidget.java
@@ -1,6 +1,5 @@
package com.tanishisherewith.dynamichud.widgets;
-import com.tanishisherewith.dynamichud.DynamicHUD;
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.integration.IntegrationManager;
import com.tanishisherewith.dynamichud.utils.DynamicValueRegistry;
@@ -148,10 +147,10 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
} else {
graphics.drawString(mc.font, Component, getX() + 2, getY() + 2, color, shadow);
}
- widgetBox.setDimensions(getX(), getY(), mc.font.width(Component) + 3, mc.font.lineHeight + 2, this.shouldScale, DynamicHUD.getGlobalScale());
+ widgetBox.setDimensions(getX(), getY(), mc.font.width(Component) + 3, mc.font.lineHeight + 2, this.canScale);
}
- menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
+ menu.set(getX(), getY(), (int) Math.ceil(getHeight()));
}
@Override
@@ -236,7 +235,7 @@ public TextWidget build() {
widget.setPosition(x, y);
widget.setDraggable(isDraggable);
- widget.setShouldScale(shouldScale);
+ widget.setCanScale(shouldScale);
return widget;
}
}
From 2c5ae72b43f194b08f8583279d1d5b96e3fbcb59 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sat, 20 Jun 2026 13:46:06 +0530
Subject: [PATCH 08/22] OptionGroup animation in ModernSkin A slight fix to Y
axis of GraphWidget Anchor default to TOP_LEFT Anchor function refactor Some
more docs
---
.../dynamichud/DynamicHUD.java | 2 +-
.../dynamichud/IntegrationTest.java | 4 +-
.../animationhelper/AnimationProperty.java | 2 +-
.../contextmenu/skinsystem/ModernSkin.java | 94 ++++++++++++++++---
.../dynamichud/widget/DynamicValueWidget.java | 2 +-
.../dynamichud/widget/Widget.java | 58 +++++++-----
.../dynamichud/widgets/GraphWidget.java | 30 +++---
7 files changed, 133 insertions(+), 59 deletions(-)
diff --git a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
index 43b9b99..480605e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/DynamicHUD.java
@@ -60,7 +60,7 @@ public void onInitializeClient() {
* Using the fabric event {@link HudElementRegistry} 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.
*/
- HudElementRegistryImpl.attachElementAfter(VanillaHudElements.MISC_OVERLAYS,
+ HudElementRegistryImpl.attachElementBefore(VanillaHudElements.MISC_OVERLAYS,
Identifier.fromNamespaceAndPath("dynamichud","hudrender_callback"),
(graphics, tickCounter) -> {
for (WidgetRenderer widgetRenderer : IntegrationManager.getWidgetRenderers()) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
index 51d4b77..71f0bf9 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/IntegrationTest.java
@@ -74,7 +74,7 @@ public void init() {
.setY(100)
.label("FPS Chart")
.graphColor(Color.CYAN)
- .anchor(Widget.Anchor.CENTER)
+ .anchor(Widget.Anchor._default())
.gWidth(100)
.gHeight(150)
.gridLines(10)
@@ -85,7 +85,7 @@ public void init() {
.minValue(30)
.setModID(DynamicHUD.MOD_ID)
.setDraggable(true)
- .setDisplay(true)
+ .setIsVisible(true)
.showGrid(true)
.shouldScale(true)
.registryKey("FPS")
diff --git a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
index 40a1b0b..53eab9d 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/helpers/animationhelper/AnimationProperty.java
@@ -1,6 +1,6 @@
package com.tanishisherewith.dynamichud.helpers.animationhelper;
-// AnimationProperty.java
+// Use this to set/get the variable on which the animation should apply to
public interface AnimationProperty {
T get();
void set(T value);
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
index 5e15ec5..975e4a8 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/skinsystem/ModernSkin.java
@@ -22,7 +22,9 @@
import org.lwjgl.glfw.GLFW;
import java.awt.*;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_GREEN;
import static com.tanishisherewith.dynamichud.helpers.ColorHelper.DARK_RED;
@@ -42,6 +44,7 @@ public class ModernSkin extends Skin implements GroupableSkin {
private Component TOOLTIP_HEAD;
private static int SCALE_FACTOR = 4;
private final ScrollHandler scrollHandler;
+ private final Map groupAnimations = new HashMap<>();
public ModernSkin(float radius, Component defaultToolTipHeader, Component defaultToolTipText) {
this.radius = radius;
@@ -98,13 +101,41 @@ private int calcOptionHeight(Option> option) {
return option.getHeight() > 0 ? option.getHeight() : mc.font.lineHeight;
}
+ private int computeGroupFullHeight(OptionGroup group, int groupX, int groupY, int targetWidth) {
+ // If collapsed, just return 20 (the header height)
+ if (!group.isExpanded()) return 20;
+
+ int yOffset = groupY + 16 + getGroupIndent().top(); // header height + indent
+ int nestedIndent = getGroupIndent().left();
+ int subWidth = targetWidth - nestedIndent - 8;
+
+ for (Option> option : group.getGroupOptions()) {
+ if (!option.shouldRender()) continue;
+ option.setHeight(calcOptionHeight(option));
+ yOffset = contextMenu.getLayoutEngine().layoutOption(option, groupX + nestedIndent, yOffset, subWidth);
+ }
+ return yOffset - groupY; // total height
+ }
+
+ // Adds a nice animation while opening and closing
public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int groupY, int targetWidth, int mouseX, int mouseY) {
- mouseX = (int) (mc.mouseHandler.xpos() / SCALE_FACTOR);
- mouseY = (int) (mc.mouseHandler.ypos() / SCALE_FACTOR);
+ GroupAnimData animData = groupAnimations.computeIfAbsent(group, g -> new GroupAnimData(20f));
+ AnimationProperty heightProp = animData.property;
+ if (group.isExpanded() && heightProp.get() <= 20f) {
+ int fullHeight = computeGroupFullHeight(group, groupX, groupY, targetWidth);
+ heightProp.set((float) fullHeight);
+ }
+
+ if (animData.animation != null) {
+ animData.animation.update();
+ }
+
+ float animatedHeight = heightProp.get();
+ int groupHeight = Math.round(animatedHeight);
- if (group.isExpanded() && group.getHeight() > 20) {
+ if (group.isExpanded() && groupHeight > 20) {
DrawHelper.drawRoundedRectangle(graphics,
- groupX + 1, groupY + 14, width - groupX - 8 + contextMenuX, group.getHeight() - 16, radius, DARKER_GRAY_2.getRGB());
+ groupX + 1, groupY + 14, width - groupX - 8 + contextMenuX, groupHeight - 16, radius, DARKER_GRAY_2.getRGB());
}
Component groupText = group.name.copy().append(" " + (group.isExpanded() ? "-" : "+"));
@@ -114,24 +145,29 @@ public void renderGroup(GuiGraphics graphics, OptionGroup group, int groupX, int
graphics.drawString(mc.font, groupText, groupX + 4, groupY + 4, -1, true);
- if (group.isExpanded()) {
+ if (group.isExpanded() && groupHeight > 20) {
+ int clipX = groupX + 1;
+ int clipY = groupY + 16;
+ int clipWidth = targetWidth + getGroupIndent().left() + 8;
+ int clipHeight = groupHeight - 16;
+ DrawHelper.enableScissor(clipX, clipY, clipWidth, clipHeight, SCALE_FACTOR, graphics);
+
int yOffset = groupY + 16 + getGroupIndent().top();
int nestedIndent = getGroupIndent().left();
int subWidth = targetWidth - nestedIndent - 8;
for (Option> option : group.getGroupOptions()) {
if (!option.shouldRender()) continue;
-
- // Position child option with layout engine
option.setHeight(calcOptionHeight(option));
yOffset = contextMenu.getLayoutEngine().layoutOption(option, groupX + nestedIndent, yOffset, subWidth);
option.render(graphics, option.getX(), option.getY(), mouseX, mouseY);
}
- group.setHeight(yOffset - groupY);
- } else {
- group.setHeight(20);
+ DrawHelper.disableScissor(graphics);
}
+
+ // actual height for layout
+ group.setHeight(groupHeight);
}
private void drawScrollbar(GuiGraphics graphics) {
@@ -334,14 +370,30 @@ public boolean mouseClicked(ContextMenu> menu, double mouseX, double mouseY, i
for (Option> option : getOptions(contextMenu)) {
if (!option.shouldRender()) continue;
-
int optHeight = calcOptionHeight(option);
if (option instanceof OptionGroup group) {
Component groupText = group.name.copy().append(" " + (group.isExpanded() ? "-" : "+"));
if (isMouseOver(mouseX, mouseY, optionStartX + 2, yPos,
- mc.font.width(groupText) + 6,
- 16)) {
- group.setExpanded(!group.isExpanded());
+ mc.font.width(groupText) + 6, 16)) {
+ boolean willBeExpanded = !group.isExpanded();
+ group.setExpanded(willBeExpanded);
+
+ GroupAnimData animData = groupAnimations.computeIfAbsent(group, g -> new GroupAnimData(20f));
+ AnimationProperty heightProp = animData.property;
+ float current = heightProp.get();
+ float target;
+ if (willBeExpanded) {
+ int targetWidthForGroup = (int) (width * 0.8f - 18);
+ int fullHeight = computeGroupFullHeight(group, optionStartX + 2, yPos, targetWidthForGroup);
+ target = Math.max(fullHeight, 20);
+ } else {
+ target = 20f;
+ }
+
+ ValueAnimation anim = new ValueAnimation(heightProp, current, target, EasingType.EASE_OUT_QUAD);
+ anim.duration(200);
+ anim.start();
+ animData.animation = anim;
return true;
}
yPos += group.getHeight() + spacing;
@@ -902,4 +954,18 @@ public boolean mouseReleased(RunnableOption option, double mouseX, double mouseY
public Skin clone() {
return new ModernSkin(radius, defaultToolTipHeader, defaultToolTipText);
}
+
+
+ private static class GroupAnimData {
+ AnimationProperty property;
+ ValueAnimation animation;
+
+ GroupAnimData(float initial) {
+ property = new AnimationProperty() {
+ private float value = initial;
+ @Override public Float get() { return value; }
+ @Override public void set(Float v) { value = v; }
+ };
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
index 18cc7b9..10a880f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/DynamicValueWidget.java
@@ -19,7 +19,7 @@ public abstract class DynamicValueWidget extends Widget {
protected Supplier> valueSupplier;
public DynamicValueWidget(WidgetData> data, String modID, String registryID, String registryKey) {
- this(data, modID, Anchor.CENTER, registryID, registryKey);
+ this(data, modID, Anchor._default(), registryID, registryKey);
}
public DynamicValueWidget(WidgetData> data, String modId, Anchor anchor, String registryID, String registryKey) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
index 7e8a8b6..ef2955c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widget/Widget.java
@@ -5,6 +5,7 @@
import com.tanishisherewith.dynamichud.helpers.DrawHelper;
import com.tanishisherewith.dynamichud.internal.UID;
import com.tanishisherewith.dynamichud.utils.Input;
+import com.tanishisherewith.dynamichud.widgets.GraphWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.nbt.CompoundTag;
@@ -12,6 +13,12 @@
import net.minecraft.util.Mth;
import org.lwjgl.glfw.GLFW;
+/**
+ * This is the base Widget class that handles the rendering, scaling, dragging, anchoring and positioning of the Widget.
+ *
+ * Default fields are made to help with all the basic functions of a widget.
+ * Main fields include: {@link #uid},{@link #isVisible},{@link #isDraggable},{@link #canScale},{@link #isInEditor},{@link #widgetBox},{@link #DATA}
+ */
public abstract class Widget implements Input {
public static Minecraft mc = Minecraft.getInstance();
public WidgetData> DATA;
@@ -59,12 +66,12 @@ public abstract class Widget implements Input {
protected int offsetX, offsetY; // Offset from the anchor point
public Widget(WidgetData> DATA, String modId) {
- this(DATA, modId, Anchor.CENTER);
+ this(DATA, modId, Anchor._default());
}
public Widget(WidgetData> DATA, String modId, Anchor anchor) {
this.DATA = DATA;
- widgetBox = new WidgetBox(0, 0, 0, 0);
+ this.widgetBox = new WidgetBox(0, 0, 0, 0);
this.modId = modId;
this.anchor = anchor;
this.tooltipText = Component.literal(DATA.description());
@@ -216,14 +223,6 @@ private void renderWidgetInEditor(GuiGraphics graphics, int mouseX, int mouseY)
renderWidget(graphics, mouseX, mouseY);
}
- protected int getTransformedMouseX(double mouseX) {
- return (int) ((mouseX - getX()) / getScale() + getX());
- }
-
- protected int getTransformedMouseY(double mouseY) {
- return (int) ((mouseY - getY()) / getScale() + getY());
- }
-
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (widgetBox.isMouseOver(mouseX, mouseY) && button == GLFW.GLFW_MOUSE_BUTTON_LEFT) {
@@ -238,13 +237,13 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
return false;
}
- /* Input related methods. Override with **super call** to add your own input-based code like contextMenu */
-
public void clampPosition() {
this.x = (int) Mth.clamp(this.x, 0, mc.getWindow().getGuiScaledWidth() - getWidth());
this.y = (int) Mth.clamp(this.y, 0, mc.getWindow().getGuiScaledHeight() - getHeight());
}
+ /** Input related methods. Override with **super call** to add your own input-based code like contextMenu **/
+
@Override
public final boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
return false;
@@ -352,9 +351,9 @@ public void readFromTag(CompoundTag tag) {
uid = tag.contains("UID") ? new UID(tag.getString("UID").get()) : UID.generate();
// x = tag.getInt("x");
// y = tag.getInt("y");
- anchor = Anchor.valueOf(tag.getString("anchor").orElse("CENTER"));
- offsetX = tag.getInt("offsetX").orElse(0);
- offsetY = tag.getInt("offsetY").orElse(0);
+ anchor = Anchor.valueOf(tag.getString("anchor").orElse("TOP_LEFT"));
+ offsetX = tag.getIntOr("offsetX", 0);
+ offsetY = tag.getIntOr("offsetY",0);
isVisible = tag.getBoolean("isVisible").orElse(true);
isDraggable = tag.getBoolean("isDraggable").orElse(true);
canScale = tag.getBoolean("canScale").orElse(true);
@@ -390,10 +389,6 @@ public WidgetBox getWidgetBox() {
return widgetBox;
}
- public void setUid(UID uid) {
- this.uid = uid;
- }
-
public void setCanScale(boolean canScale) {
this.canScale = canScale;
}
@@ -417,16 +412,26 @@ public String toString() {
'}';
}
- public enum Anchor {TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CENTER}
+ public enum Anchor {
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+ CENTER;
+
+ public static Anchor _default(){
+ return TOP_LEFT;
+ }
+ }
public abstract static class WidgetBuilder {
protected int x;
protected int y;
- protected boolean display = true;
+ protected boolean isVisible = true;
protected boolean isDraggable = true;
protected boolean shouldScale = true;
protected String modID = "unknown";
-
+ protected Anchor anchor = Anchor._default();
/**
* X Position of the widget of the scaled screen.
@@ -444,8 +449,8 @@ public T setY(int y) {
return self();
}
- public T setDisplay(boolean display) {
- this.display = display;
+ public T setIsVisible(boolean isVisible) {
+ this.isVisible = isVisible;
return self();
}
@@ -464,6 +469,11 @@ public T setModID(String modID) {
return self();
}
+ public T anchor(Anchor anchor) {
+ this.anchor = anchor;
+ return self();
+ }
+
/**
* Method to be overridden in subclasses to return "this" correctly
*/
diff --git a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
index cb23beb..8b3782f 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/widgets/GraphWidget.java
@@ -94,12 +94,12 @@ private void internal_init() {
}
public GraphWidget() {
- this(DynamicValueRegistry.GLOBAL_ID, "unknown", "unknown", Anchor.CENTER, 0, 0, 5, 0, 10, Color.RED, Color.GREEN, 0, false, 0, "empty");
+ this(DynamicValueRegistry.GLOBAL_ID, "unknown", "unknown", Anchor._default(), 0, 0, 5, 0, 10, Color.RED, Color.GREEN, 0, false, 0, "empty");
}
@Override
public void init() {
- // Initialize the buffer with minValue, mimicking ArrayList behavior
+ // init the buffer with minValue
for (int i = 0; i < maxDataPoints; i++) {
dataPoints[i] = minValue;
}
@@ -270,7 +270,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
float texWidth = mc.font.width(valueText) * valueScale;
//Scale the Component to its proper position and size with grid lines
- DrawHelper.scaleAndPosition(graphics.pose(), x - 2, yPos, valueScale);
+ DrawHelper.scaleAndPosition(graphics.pose(), x - 2, yPos,texWidth,mc.font.lineHeight * valueScale, valueScale);
graphics.drawString(mc.font, valueText, Math.round(x + offset - texWidth), (int) (yPos - (mc.font.lineHeight * valueScale) / 2.0f), 0xFFFFFFFF, true);
DrawHelper.stopScaling(graphics.pose());
}
@@ -318,7 +318,7 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
DrawHelper.scaleAndPosition(graphics.pose(), x - 5, y + gHeight, 0.5f);
String formattedMinVal = formatValue(minValue);
- graphics.drawString(mc.font, formattedMinVal, x - mc.font.width(formattedMinVal), (int) (y + gHeight - 4), 0xFFFFFFFF, true);
+ graphics.drawString(mc.font, formattedMinVal, (int) (x - mc.font.width(formattedMinVal)), (int) (y + gHeight - 4), 0xFFFFFFFF, true);
DrawHelper.stopScaling(graphics.pose());
if(showGrid) x -= offset;
@@ -331,12 +331,16 @@ public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY) {
// format large values (like: 1000 -> 1K, 1000000 -> 1M)
private String formatValue(float value) {
- if (Math.abs(value) >= 1_000_000) {
- return String.format("%.1fM", value / 1_000_000).trim();
- } else if (Math.abs(value) >= 1_000) {
- return String.format("%.1fK", value / 1_000).trim();
+ float absVal = Math.abs(value);
+
+ if (absVal >= 1_000_000) {
+ long rounded = Math.round(value / 1_000_000f);
+ return String.format("%dM", rounded);
+ } else if (absVal >= 1_000) {
+ long rounded = Math.round(value / 1_000f);
+ return String.format("%dK", rounded);
} else {
- return String.format("%.0f", value).trim();
+ return String.format("%d", (int) value);
}
}
@@ -543,7 +547,6 @@ public ContextMenu> getContextMenu() {
}
public static class GraphWidgetBuilder extends DynamicValueWidgetBuilder {
- private Anchor anchor = Anchor.CENTER;
private float gWidth = 100;
private float gHeight = 50;
private int maxDataPoints = 50;
@@ -564,11 +567,6 @@ public GraphWidgetBuilder label(String label) {
return this;
}
- public GraphWidgetBuilder anchor(Anchor anchor) {
- this.anchor = anchor;
- return this;
- }
-
public GraphWidgetBuilder gWidth(float gWidth) {
this.gWidth = gWidth;
return this;
@@ -630,7 +628,7 @@ public GraphWidget build() {
widget.setPosition(x, y);
widget.setDraggable(isDraggable);
widget.setCanScale(shouldScale);
- widget.isVisible = display;
+ widget.isVisible = isVisible;
return widget;
}
}
From 20ebf289d279e12a84b661452fd9879920a217c9 Mon Sep 17 00:00:00 2001
From: tanishisherewith <120117618+tanishisherewithhh@users.noreply.github.com>
Date: Sat, 20 Jun 2026 20:22:00 +0530
Subject: [PATCH 09/22] Added search to ModernSkin Added Fuzzy Score and apache
library Fixed inconsistent height in ModernSkin Fixed charTyped missing call
in ContextMenu
---
build.gradle | 3 +
.../screens/AbstractMoveableScreen.java | 7 +-
.../dynamichud/utils/Util.java | 92 ++++++++
.../utils/contextmenu/ContextMenu.java | 7 +-
.../utils/contextmenu/options/Option.java | 2 +-
.../contextmenu/options/OptionGroup.java | 1 +
.../contextmenu/screen/ContextMenuScreen.java | 7 +
.../contextmenu/skinsystem/ModernSkin.java | 197 +++++++++++++-----
.../utils/contextmenu/skinsystem/Skin.java | 5 +-
.../utils/handlers/ScrollHandler.java | 4 +
10 files changed, 267 insertions(+), 58 deletions(-)
diff --git a/build.gradle b/build.gradle
index 8d9cd23..a9b435e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,6 +36,9 @@ dependencies {
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}"
+
+ //fuzzyscore
+ implementation 'org.apache.commons:commons-text:1.12.0'
}
processResources {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
index 5dcf628..8b2860a 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/screens/AbstractMoveableScreen.java
@@ -8,11 +8,13 @@
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.packs.PackSelectionScreen;
import net.minecraft.client.input.CharacterEvent;
import net.minecraft.client.input.KeyEvent;
import net.minecraft.client.input.MouseButtonEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.vehicle.minecart.Minecart;
+import org.apache.commons.lang3.StringUtils;
import org.jspecify.annotations.NonNull;
import org.lwjgl.glfw.GLFW;
@@ -59,8 +61,9 @@ public boolean mouseClicked(MouseButtonEvent event, boolean bl) {
@Override
public boolean charTyped(CharacterEvent event) {
- widgetRenderer.charTyped((char) event.codepoint(), event.modifiers());
- ContextMenuManager.getInstance().charTyped((char) event.codepoint(), event.modifiers());
+ char c = Character.toString(event.codepoint()).charAt(0);
+ widgetRenderer.charTyped(c, event.modifiers());
+ ContextMenuManager.getInstance().charTyped(c, event.modifiers());
return super.charTyped(event);
}
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
index c6ae850..323b578 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/Util.java
@@ -1,6 +1,12 @@
package com.tanishisherewith.dynamichud.utils;
import com.tanishisherewith.dynamichud.DynamicHUD;
+import com.tanishisherewith.dynamichud.utils.contextmenu.options.Option;
+import com.tanishisherewith.dynamichud.utils.contextmenu.options.OptionGroup;
+import com.tanishisherewith.dynamichud.utils.contextmenu.skinsystem.Skin;
+import org.apache.commons.text.similarity.FuzzyScore;
+
+import java.util.*;
public class Util {
public static Quadrant getQuadrant(int x, int y) {
@@ -36,6 +42,92 @@ public static boolean warnIfTrue(boolean expression, String message, Object... o
return expression;
}
+ /**
+ * Returns a list of options sorted by higher fuzzy score from the query string.
+ */
+ public static List
> getSearchResults(String query, int minimumScore, List
> options) {
+ if(options.isEmpty()) return new ArrayList<>();
+
+ if (query == null || query.trim().isEmpty()) {
+ return new ArrayList<>(options);
+ }
+
+ FuzzyScore FUZZY_SCORE = new FuzzyScore(Locale.ENGLISH);
+
+ String lowerQuery = query.toLowerCase().trim();
+ Map
, Integer> scoreMap = new HashMap<>();
+
+ List
> allOptions = Skin.flattenOptions(options);
+
+ for (Option> opt : allOptions) {
+ if (!opt.shouldRender()) continue;
+ String name = opt.getName().getString();
+ String desc = opt.getDescription().getString();
+ int nameScore = FUZZY_SCORE.fuzzyScore(name, lowerQuery);
+ int descScore = FUZZY_SCORE.fuzzyScore(desc, lowerQuery);
+ int best = Math.max(nameScore, descScore);
+ scoreMap.put(opt, best);
+ }
+
+
+ if (scoreMap.isEmpty()) return new ArrayList<>();
+
+ //Allow 2 typos for a min score of -1 using the query length
+ int threshold = (minimumScore == -1) ? lowerQuery.length() - 2: minimumScore;
+
+ return filterAndSortOptions(options, threshold, scoreMap);
+ }
+
+ /**
+ * Recursively processes a list of options, returning a filtered and sorted copy.
+ * Groups are re‑created with only matching children, and are expanded.
+ */
+ private static List
> filterAndSortOptions(List
> source, int threshold, Map
, Integer> scoreMap) {
+ List
> result = new ArrayList<>();
+ for (Option> opt : source) {
+ if (opt instanceof OptionGroup group) {
+ // Process children first
+ List
> filteredChildren = filterAndSortOptions(group.getGroupOptions(), threshold, scoreMap);
+ int groupScore = scoreMap.getOrDefault(group, 0);
+ boolean groupMatches = groupScore >= threshold;
+
+ if (groupMatches || !filteredChildren.isEmpty()) {
+ OptionGroup newGroup = new OptionGroup(group.name);
+ newGroup.setExpanded(true);
+ for (Option> child : filteredChildren) {
+ newGroup.addOption(child);
+ }
+ result.add(newGroup);
+ }
+ } else if (scoreMap.getOrDefault(opt, 0) >= threshold) {
+ result.add(opt);
+ }
+ }
+
+ // sort by score descending
+ result.sort((a, b) -> {
+ int sa = getEffectiveScore(a, scoreMap);
+ int sb = getEffectiveScore(b, scoreMap);
+ return Integer.compare(sb, sa);
+ });
+ return result;
+ }
+
+ /**
+ * Returns the highest score among all options inside a group (or the group's own score).
+ */
+ private static int getEffectiveScore(Option> opt, Map
, Integer> scoreMap) {
+ if (opt instanceof OptionGroup group) {
+ int max = scoreMap.getOrDefault(group, 0);
+ for (Option> child : group.getGroupOptions()) {
+ max = Math.max(max, getEffectiveScore(child, scoreMap));
+ }
+ return max;
+ }
+ return scoreMap.getOrDefault(opt, 0);
+ }
+
+
public static boolean isSafeToContinue() {
return DynamicHUD.MC.getWindow() != null && DynamicHUD.MC.font != null;
}
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 2b6c3ea..c84837e 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/ContextMenu.java
@@ -20,10 +20,8 @@
import org.lwjgl.glfw.GLFW;
import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.*;
import java.util.List;
-import java.util.Objects;
@SuppressWarnings({"rawtypes", "unchecked"})
public class ContextMenu implements Input {
@@ -291,11 +289,14 @@ public void mouseScrolled(double mouseX, double mouseY, double horizontalAmount,
@Override
public void charTyped(char c, int modifiers) {
if (!shouldDisplay) return;
+
for (Option> option : options) {
if(option.shouldRender()) {
option.charTyped(c, modifiers);
}
}
+
+ properties.getSkin().charTyped(this, c, modifiers);
}
public void set(int x, int y, int widgetHeight) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
index 2142ccc..a42d598 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/Option.java
@@ -38,7 +38,7 @@ public Option(Component name, Supplier getter, Consumer setter, Supplier getter, Consumer setter, Supplier shouldRender) {
diff --git a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
index b10cd69..d2fea9c 100644
--- a/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
+++ b/src/main/java/com/tanishisherewith/dynamichud/utils/contextmenu/options/OptionGroup.java
@@ -28,6 +28,7 @@ public List