From 8ff66542c011a8b18ac19b02069893767f5a4071 Mon Sep 17 00:00:00 2001 From: DarkKronicle Date: Thu, 27 Apr 2023 14:48:56 -0600 Subject: [PATCH] Add anchoring points for HUD elements and refactor a ton of HUD code --- .../io/github/solclient/client/SolClient.java | 16 +- .../io/github/solclient/client/mod/Mod.java | 14 ++ .../client/mod/hud/AbstractHudElement.java | 190 ++++++++++++++++++ .../solclient/client/mod/hud/AnchorPoint.java | 94 +++++++++ .../hud/CardinalOrder.java} | 28 ++- .../solclient/client/mod/hud/HudElement.java | 48 +++-- .../client/mod/hud/Justification.java | 51 +++++ .../client/mod/impl/SolClientHudMod.java | 102 ++++++---- .../mod/impl/SolClientSimpleHudMod.java | 8 +- .../impl/discord/DiscordIntegrationMod.java | 3 - .../mod/impl/discord/DiscordVoiceChatHud.java | 39 +--- .../client/mod/impl/hud/BossBarMod.java | 22 +- .../client/mod/impl/hud/ClockMod.java | 4 +- .../client/mod/impl/hud/CoordinatesMod.java | 6 +- .../client/mod/impl/hud/PotionEffectsMod.java | 44 ++-- .../client/mod/impl/hud/SpeedometerMod.java | 12 +- .../client/mod/impl/hud/armour/ArmourMod.java | 2 +- .../client/mod/impl/hud/chat/ChatMod.java | 12 +- .../impl/hud/chat/mixins/ChatHudMixin.java | 2 +- .../mod/impl/hud/crosshair/CrosshairMod.java | 13 +- .../impl/hud/keystrokes/KeystrokesMod.java | 2 +- .../client/mod/impl/hud/timers/TimersMod.java | 38 +--- .../mod/impl/replay/RecordingIndicator.java | 4 +- .../client/ui/screen/mods/MoveHudsScreen.java | 71 ++++++- 24 files changed, 633 insertions(+), 192 deletions(-) create mode 100644 src/main/java/io/github/solclient/client/mod/hud/AbstractHudElement.java create mode 100644 src/main/java/io/github/solclient/client/mod/hud/AnchorPoint.java rename src/main/java/io/github/solclient/client/{util/data/VerticalAlignment.java => mod/hud/CardinalOrder.java} (61%) create mode 100644 src/main/java/io/github/solclient/client/mod/hud/Justification.java diff --git a/src/main/java/io/github/solclient/client/SolClient.java b/src/main/java/io/github/solclient/client/SolClient.java index e8353364..c18f1523 100644 --- a/src/main/java/io/github/solclient/client/SolClient.java +++ b/src/main/java/io/github/solclient/client/SolClient.java @@ -40,7 +40,7 @@ public final class SolClient implements Iterable { public static final SolClient INSTANCE = new SolClient(); - private static final Logger LOGGER = LogManager.getLogger(); + public static final Logger LOGGER = LogManager.getLogger(); private static final Gson DEFAULT_GSON = getGson(null); private final List mods = new ArrayList<>(); @@ -165,11 +165,7 @@ public void configure(Mod mod, JsonObject config) { if (config == null) return; - try { - getGson(mod).fromJson(config, mod.getClass()); - } catch (Throwable error) { - LOGGER.error("Could not configure mod {} on {}", mod.getId(), config, error); - } + mod.loadConfig(config); } /** @@ -251,10 +247,12 @@ private void prepare(ModInfo info) { } } - private static Gson getGson(Mod mod) { + public static Gson getGson(Mod mod) { GsonBuilder builder = new GsonBuilder(); - if (mod != null) - builder.registerTypeAdapter(mod.getClass(), (InstanceCreator) (type) -> mod); + if (mod != null) { + builder.registerTypeAdapter(mod.getClass(), (InstanceCreator) (type) -> mod); + mod.registerTypeAdapters(builder); + } return builder.excludeFieldsWithoutExposeAnnotation().create(); } diff --git a/src/main/java/io/github/solclient/client/mod/Mod.java b/src/main/java/io/github/solclient/client/mod/Mod.java index 78b62d65..bf0e4285 100644 --- a/src/main/java/io/github/solclient/client/mod/Mod.java +++ b/src/main/java/io/github/solclient/client/mod/Mod.java @@ -24,6 +24,7 @@ import java.nio.file.*; import java.util.*; +import io.github.solclient.client.SolClient; import org.apache.logging.log4j.*; import com.google.gson.*; @@ -42,6 +43,8 @@ import lombok.*; import net.minecraft.client.MinecraftClient; +import static io.github.solclient.client.SolClient.getGson; + @AbstractTranslationKey("sol_client.mod.generic") public abstract class Mod extends Object { @@ -337,6 +340,10 @@ public void setPinned(boolean pinned) { } } + public void registerTypeAdapters(GsonBuilder builder) { + + } + void notifyUnpin() { pinned = false; } @@ -361,4 +368,11 @@ public void onRender(PostGameOverlayRenderEvent event) { } } + public void loadConfig(JsonObject config) { + try { + getGson(this).fromJson(config, getClass()); + } catch (Throwable error) { + SolClient.LOGGER.error("Could not configure mod {} on {}", getId(), config, error); + } + } } diff --git a/src/main/java/io/github/solclient/client/mod/hud/AbstractHudElement.java b/src/main/java/io/github/solclient/client/mod/hud/AbstractHudElement.java new file mode 100644 index 00000000..423b7308 --- /dev/null +++ b/src/main/java/io/github/solclient/client/mod/hud/AbstractHudElement.java @@ -0,0 +1,190 @@ +/* + * Sol Client - an open source Minecraft client + * Copyright (C) 2021-2023 TheKodeToad and Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.solclient.client.mod.hud; + +import com.google.gson.annotations.Expose; +import com.mojang.blaze3d.platform.GlStateManager; +import com.replaymod.replay.ReplayModReplay; +import io.github.solclient.client.mod.option.ModOption; +import io.github.solclient.client.mod.option.ModOptionStorage; +import io.github.solclient.client.mod.option.impl.SliderOption; +import io.github.solclient.client.util.data.Position; +import io.github.solclient.client.util.data.Rectangle; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.Window; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public abstract class AbstractHudElement implements HudElement { + + public static final String TRANSLATION_KEY = "sol_client.mod.hud"; + + /** The exact x/y on the screen */ + protected Position truePosition = new Position(0, 0); + + /** Scaled x/y on screen. Matrices should already be scaled if this is used */ + protected Position dividedPosition; + + private Rectangle previousBounds = null; + + @Expose + protected float x = 0; + @Expose + protected float y = 0; + + @Expose + protected float scale = 100; + + @Expose + protected AnchorPoint anchorPoint = AnchorPoint.TOP_LEFT; + + private int lastWidth = 0; + private int lastHeight = 0; + + @Override + public AnchorPoint getAnchor() { + return isDynamic() ? anchorPoint : AnchorPoint.TOP_LEFT; + } + + @Override + public List> createOptions() { + List> options = new ArrayList<>(); + options.add(new SliderOption(TRANSLATION_KEY + ".option.scale", + ModOptionStorage.of(Number.class, () -> scale, (value) -> { + if (scale != value.floatValue()) { + scale = value.floatValue(); + updateBounds(true); + } + }), + Optional.of("sol_client.slider.percent"), 50, 150, 1)); + return options; + } + + @Override + public float getScale() { + return scale / 100; + } + + public static int floatToInt(float percent, int max, int offset) { + return MathHelper.clamp(Math.round((max - offset) * percent), 0, max); + } + + public static float intToFloat(int current, int max, int offset) { + return MathHelper.clamp((float) (current) / (max - offset), 0, 1); + } + + public int offsetTrueWidth(boolean editMode) { + return getAnchor().offsetWidth(getMultipliedBounds(editMode).getWidth()); + } + + public int offsetTrueHeight(boolean editMode) { + return getAnchor().offsetHeight(getMultipliedBounds(editMode).getHeight()); + } + + @Override + public Position getDividedPosition() { + return dividedPosition; + } + + @Override + public Position getConfiguredPosition() { + return truePosition; + } + + @Override + public Position getPosition() { + return truePosition; + } + + @Override + public void setAnchorPoint(AnchorPoint p) { + this.anchorPoint = p; + } + + @Override + public void render(boolean editMode) { + // Don't render HUD in replay or if marked as invisible. + if (!isVisible() || !(editMode || isShownInReplay() || ReplayModReplay.instance.getReplayHandler() == null)) + return; + + Window window = new Window(MinecraftClient.getInstance()); + if ((int) window.getScaledWidth() != lastWidth || (int) window.getScaledHeight() != lastHeight) { + lastWidth = (int) window.getScaledWidth(); + lastHeight = (int) window.getScaledHeight(); + updateBounds(editMode, lastWidth, lastHeight); + previousBounds = getBounds(editMode); + } else { + Rectangle rect = getBounds(editMode); + if (rect != null) { + if (previousBounds == null) { + previousBounds = updateBounds(editMode); + } else if (rect.getWidth() != previousBounds.getWidth() || rect.getHeight() != previousBounds.getHeight()) { + previousBounds = updateBounds(editMode); + } + } + } + + GlStateManager.pushMatrix(); + GlStateManager.scale(getScale(), getScale(), getScale()); + render(getDividedPosition(), editMode); + GlStateManager.popMatrix(); + } + + @Override + public void setPosition(Position position, boolean editMode) { + int x = position.getX() + offsetTrueWidth(editMode); + int y = position.getY() + offsetTrueHeight(editMode); + Window window = new Window(MinecraftClient.getInstance()); + this.x = intToFloat(x, (int) window.getScaledWidth(), 0); + this.y = intToFloat(y, (int) window.getScaledHeight(), 0); + updateBounds(editMode); + } + + @Override + public Rectangle updateBounds(boolean editMode, int scaledWidth, int scaledHeight) { + Rectangle bounds = getBounds(editMode); + if (scaledHeight == 0) { + truePosition = new Position(0, 0); + return truePosition.rectangle(bounds.getWidth(), bounds.getHeight()); + } + int scaledX = floatToInt(x, scaledWidth, 0) - offsetTrueWidth(editMode); + int scaledY = floatToInt(y, scaledHeight, 0) - offsetTrueHeight(editMode); + if (scaledX < 0) { + scaledX = 0; + } + if (scaledY < 0) { + scaledY = 0; + } + int trueWidth = (int) (bounds.getWidth() * getScale()); + if (trueWidth < scaledWidth && scaledX + trueWidth > scaledWidth) { + scaledX = scaledWidth - trueWidth; + } + int trueHeight = (int) (bounds.getHeight() * getScale()); + if (trueHeight < scaledHeight && scaledY + trueHeight > scaledHeight) { + scaledY = scaledHeight - trueHeight; + } + truePosition = new Position(scaledX, scaledY); + dividedPosition = new Position((int) (scaledX / getScale()), (int) (scaledY / getScale())); + return truePosition.rectangle(bounds.getWidth(), bounds.getHeight()); + } + +} diff --git a/src/main/java/io/github/solclient/client/mod/hud/AnchorPoint.java b/src/main/java/io/github/solclient/client/mod/hud/AnchorPoint.java new file mode 100644 index 00000000..5377114c --- /dev/null +++ b/src/main/java/io/github/solclient/client/mod/hud/AnchorPoint.java @@ -0,0 +1,94 @@ +/* + * Sol Client - an open source Minecraft client + * Copyright (C) 2021-2023 TheKodeToad and Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.solclient.client.mod.hud; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Locale; + +/** + * Ported here by DarkKronicle from KronHUD by DarkKronicle + * Github + * + * @license GPL-3.0 + */ +@AllArgsConstructor +public enum AnchorPoint { + + TOP_LEFT(-1, 1), + TOP_MIDDLE(0, 1), + TOP_RIGHT(1, 1), + MIDDLE_LEFT(-1, 0), + MIDDLE_MIDDLE(0, 0), + MIDDLE_RIGHT(1, 0), + BOTTOM_LEFT(-1, -1), + BOTTOM_MIDDLE(0, -1), + BOTTOM_RIGHT(1, -1); + + @Getter + private final int xComponent; + + @Getter + private final int yComponent; + + public int getX(int anchorX, int width) { + switch (xComponent) { + case 0: + return anchorX - (width / 2); + case 1: + return anchorX - width; + default: + return anchorX; + } + } + + public int getY(int anchorY, int height) { + switch (yComponent) { + case 0: + return anchorY - (height / 2); + case 1: + return anchorY - height; + default: + return anchorY; + } + } + + public int offsetWidth(int width) { + switch (xComponent) { + case 0: + return width / 2; + case 1: + return width; + default: + return 0; + } + } + + public int offsetHeight(int height) { + switch (yComponent) { + case 0: + return (height / 2); + case 1: + return 0; + default: + return height; + } + } +} diff --git a/src/main/java/io/github/solclient/client/util/data/VerticalAlignment.java b/src/main/java/io/github/solclient/client/mod/hud/CardinalOrder.java similarity index 61% rename from src/main/java/io/github/solclient/client/util/data/VerticalAlignment.java rename to src/main/java/io/github/solclient/client/mod/hud/CardinalOrder.java index 653d9029..d68cab91 100644 --- a/src/main/java/io/github/solclient/client/util/data/VerticalAlignment.java +++ b/src/main/java/io/github/solclient/client/mod/hud/CardinalOrder.java @@ -16,16 +16,28 @@ * along with this program. If not, see . */ -package io.github.solclient.client.util.data; +package io.github.solclient.client.mod.hud; -import net.minecraft.client.resource.language.I18n; -public enum VerticalAlignment { - TOP, MIDDLE, BOTTOM; +import lombok.AllArgsConstructor; +import lombok.Getter; - @Override - public String toString() { - return I18n.translate("sol_client.vertical_alignment." + name().toLowerCase()); - } +import java.util.Locale; + +@AllArgsConstructor +public enum CardinalOrder { + + TOP_DOWN(false, -1), DOWN_TOP(false, 1), LEFT_RIGHT(true, 1), RIGHT_LEFT(true, -1), + ; + + @Getter + private final boolean xAxis; + + @Getter + private final int direction; + + public String getDisplayKey() { + return "sol_client.cardinal." + name().toLowerCase(Locale.ROOT); + } } diff --git a/src/main/java/io/github/solclient/client/mod/hud/HudElement.java b/src/main/java/io/github/solclient/client/mod/hud/HudElement.java index 16eeb04e..710c141b 100644 --- a/src/main/java/io/github/solclient/client/mod/hud/HudElement.java +++ b/src/main/java/io/github/solclient/client/mod/hud/HudElement.java @@ -22,10 +22,14 @@ import com.replaymod.replay.ReplayModReplay; import io.github.solclient.client.mod.Mod; +import io.github.solclient.client.mod.option.ModOption; import io.github.solclient.client.util.data.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.util.Window; +import java.util.ArrayList; +import java.util.List; + /** * Represents a HUD element. May be contained inside a mod. */ @@ -35,18 +39,31 @@ public interface HudElement { Position getConfiguredPosition(); + default List> createOptions() { + return new ArrayList<>(); + } + default Position getPosition() { Position result = getConfiguredPosition(); if (result == null) { Window window = new Window(MinecraftClient.getInstance()); Position defaultPosition = determineDefaultPosition(window.getWidth(), window.getHeight()); - setPosition(defaultPosition); + setPosition(defaultPosition, true); result = defaultPosition; } return result; } + default Rectangle updateBounds(boolean editMode) { + Window window = new Window(MinecraftClient.getInstance()); + return updateBounds(editMode, (int) window.getScaledWidth(), (int) window.getScaledHeight()); + } + + default Rectangle updateBounds(boolean editMode, int scaledWidth, int scaledHeight) { + return null; + } + default Position getDividedPosition() { return new Position((int) (getPosition().getX() / getScale()), (int) (getPosition().getY() / getScale())); @@ -56,18 +73,22 @@ default Position determineDefaultPosition(int width, int height) { return new Position(0, 0); } - void setPosition(Position position); + void setPosition(Position position, boolean editMode); boolean isVisible(); - default Rectangle getBounds() { - return getBounds(getPosition()); + default Rectangle getBounds(boolean editMode) { + return getBounds(getPosition(), editMode); } - Rectangle getBounds(Position position); + default AnchorPoint getAnchor() { + return AnchorPoint.TOP_LEFT; + } + + Rectangle getBounds(Position position, boolean editMode); - default Rectangle getMultipliedBounds() { - Rectangle rectangle = getBounds(); + default Rectangle getMultipliedBounds(boolean editMode) { + Rectangle rectangle = getBounds(editMode); if (rectangle == null) return null; @@ -89,11 +110,14 @@ default void render(boolean editMode) { Mod getMod(); - default boolean isHovered(int x, int y) { - Rectangle bounds = getMultipliedBounds(); - return bounds != null && bounds.contains(x, y); - } - boolean isShownInReplay(); + default void setAnchorPoint(AnchorPoint p) { + + } + + default boolean isDynamic() { + return false; + } + } diff --git a/src/main/java/io/github/solclient/client/mod/hud/Justification.java b/src/main/java/io/github/solclient/client/mod/hud/Justification.java new file mode 100644 index 00000000..ba523316 --- /dev/null +++ b/src/main/java/io/github/solclient/client/mod/hud/Justification.java @@ -0,0 +1,51 @@ +/* + * Sol Client - an open source Minecraft client + * Copyright (C) 2021-2023 TheKodeToad and Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.solclient.client.mod.hud; + + +import net.minecraft.client.MinecraftClient; + +import java.util.Locale; + +public enum Justification { + + LEFT, CENTER, RIGHT; + + public String getDisplayKey() { + return "sol_client.justification." + name().toLowerCase(Locale.ROOT); + } + + public int getXOffset(String string, int width) { + if (this == LEFT) { + return 0; + } + return getXOffset(MinecraftClient.getInstance().textRenderer.getStringWidth(string), width); + } + + public int getXOffset(int textWidth, int width) { + if (this == LEFT) { + return 0; + } + if (this == RIGHT) { + return width - textWidth; + } + return (width - textWidth) / 2; + } + +} diff --git a/src/main/java/io/github/solclient/client/mod/impl/SolClientHudMod.java b/src/main/java/io/github/solclient/client/mod/impl/SolClientHudMod.java index c8c7a954..5cb66e05 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/SolClientHudMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/SolClientHudMod.java @@ -20,15 +20,21 @@ import java.util.*; +import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.annotations.Expose; import io.github.solclient.client.mod.*; +import io.github.solclient.client.mod.hud.AbstractHudElement; import io.github.solclient.client.mod.hud.HudElement; import io.github.solclient.client.mod.option.*; import io.github.solclient.client.mod.option.annotation.AbstractTranslationKey; -import io.github.solclient.client.mod.option.impl.SliderOption; import io.github.solclient.client.util.data.*; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.util.Window; /** * Represents a mod with only a single HUD. @@ -41,21 +47,20 @@ public abstract class SolClientHudMod extends StandardMod { /** * Represents the single element that this mod contains. */ - protected final HudElement element = new HudModElement(); + @Expose + protected final HudModElement element = new HudModElement(); - @Expose - private Position position; - @Expose - public float scale = 100; protected TextRenderer font; - @Override + @Override + public void registerTypeAdapters(GsonBuilder builder) { + builder.registerTypeAdapter(element.getClass(), (InstanceCreator) (type) -> element); + } + + @Override protected List> createOptions() { List> options = super.createOptions(); - options.add(1, - new SliderOption(TRANSLATION_KEY + ".option.scale", - ModOptionStorage.of(Number.class, () -> scale, (value) -> scale = value.floatValue()), - Optional.of("sol_client.slider.percent"), 50, 150, 1)); + options.addAll(1, element.createOptions()); return options; } @@ -65,26 +70,24 @@ public void lateInit() { this.font = mc.textRenderer; } - protected float getScale() { - return scale / 100; - } + public boolean isDynamic() { + return false; + } @Override public List getHudElements() { return Arrays.asList(element); } - public void setPosition(Position position) { - element.setPosition(position); - } - public boolean isVisible() { return true; } - public Rectangle getBounds(Position position) { - return null; - } + public float getScale() { + return element.getScale(); + } + + public abstract Rectangle getBounds(Position position, boolean editMode); @Override public void render(boolean editMode) { @@ -102,33 +105,44 @@ public Position determineDefaultPosition(int width, int height) { return new Position(0, 0); } - class HudModElement implements HudElement { + @Override + public void loadConfig(JsonObject config) { + // Migrate old format for positions to this new fancy one + JsonObject elementObj = null; + if (!config.has("element")) { + elementObj = new JsonObject(); + config.add("element", elementObj); + } + if (elementObj != null) { + JsonElement jsonScale = config.remove("scale"); + if (jsonScale != null) { + elementObj.add("scale", jsonScale); + } + Window window = new Window(MinecraftClient.getInstance()); + JsonElement jsonX = config.remove("y"); + if (jsonX != null) { + elementObj.addProperty("x", window.getScaledHeight() > 0 ? jsonX.getAsInt() / window.getScaledWidth() : 0); + } + JsonElement jsonY = config.remove("y"); + if (jsonY != null) { + elementObj.addProperty("y", window.getScaledHeight() > 0 ? jsonY.getAsInt() / window.getScaledHeight() : 0); + } + } + super.loadConfig(config); + } + + protected class HudModElement extends AbstractHudElement { @Override public Mod getMod() { return SolClientHudMod.this; } - @Override - public Position getConfiguredPosition() { - return position; - } - - @Override - public void setPosition(Position position) { - SolClientHudMod.this.position = position; - } - @Override public Position determineDefaultPosition(int width, int height) { return SolClientHudMod.this.determineDefaultPosition(width, height); } - @Override - public float getScale() { - return scale / 100F; - } - @Override public boolean isVisible() { return isEnabled() && SolClientHudMod.this.isVisible(); @@ -145,10 +159,18 @@ public boolean isShownInReplay() { } @Override - public Rectangle getBounds(Position position) { - return SolClientHudMod.this.getBounds(position); + public Rectangle getBounds(Position position, boolean editMode) { + return SolClientHudMod.this.getBounds(position, editMode); } - } + public void setScale(float scale) { + this.scale = scale; + } + + @Override + public boolean isDynamic() { + return SolClientHudMod.this.isDynamic(); + } + } } diff --git a/src/main/java/io/github/solclient/client/mod/impl/SolClientSimpleHudMod.java b/src/main/java/io/github/solclient/client/mod/impl/SolClientSimpleHudMod.java index f6e4956c..6328b8ef 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/SolClientSimpleHudMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/SolClientSimpleHudMod.java @@ -67,7 +67,7 @@ public abstract class SolClientSimpleHudMod extends SolClientHudMod { }); @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { return new Rectangle(position.getX(), position.getY(), getWidth(), 16); } @@ -80,7 +80,7 @@ public void render(Position position, boolean editMode) { String text = getText(editMode); if (text != null) { if (background) { - getBounds(position).fill(backgroundColour); + getBounds(position, editMode).fill(backgroundColour); } else { if (!text.isEmpty()) { text = "[" + text + "]"; @@ -88,9 +88,9 @@ public void render(Position position, boolean editMode) { } if (border) { - getBounds(position).stroke(borderColour); + getBounds(position, editMode).stroke(borderColour); } - font.draw(text, position.getX() + (getBounds(position).getWidth() / 2F) - (font.getStringWidth(text) / 2F), + font.draw(text, position.getX() + (getBounds(position, editMode).getWidth() / 2F) - (font.getStringWidth(text) / 2F), position.getY() + 4, textColour.getValue(), shadow); } } diff --git a/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordIntegrationMod.java b/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordIntegrationMod.java index f858d87e..ee7b1ec3 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordIntegrationMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordIntegrationMod.java @@ -65,9 +65,6 @@ public class DiscordIntegrationMod extends StandardMod { @Slider(min = 50, max = 150, step = 1, format = "sol_client.slider.percent") float voiceChatHudScale = 100; @Expose - @Option - VerticalAlignment voiceChatHudAlignment = VerticalAlignment.TOP; - @Expose Position voiceChatHudPosition; @Expose @Option diff --git a/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordVoiceChatHud.java b/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordVoiceChatHud.java index ee51114e..54a29321 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordVoiceChatHud.java +++ b/src/main/java/io/github/solclient/client/mod/impl/discord/DiscordVoiceChatHud.java @@ -29,7 +29,7 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; -public class DiscordVoiceChatHud implements HudElement { +public class DiscordVoiceChatHud extends AbstractHudElement { private static final int USER_HEIGHT = 20; @@ -46,22 +46,16 @@ public boolean isVisible() { return mod.isEnabled() && mod.voiceChatHud; } - @Override - public Rectangle getBounds(Position position) { - int yOffset = 0; - - switch (mod.voiceChatHudAlignment) { - case MIDDLE: - yOffset = (USER_HEIGHT * 4) / 2; - break; - case BOTTOM: - yOffset = USER_HEIGHT * 4; - break; - default: - break; - } + @Override + public boolean isDynamic() { + return true; + } + + @Override + public Rectangle getBounds(Position position, boolean editMode) { + int size = editMode ? 4 : mod.socket.getVoiceCallUsers().size(); - return position.offset(0, -yOffset).rectangle(20 + font.getStringWidth("TheKodeToad") + 4, 76); + return position.rectangle(20 + font.getStringWidth("TheKodeToad") + 4, 20 * size); } @Override @@ -94,17 +88,6 @@ public void render(Position position, boolean editMode) { int y = position.getY(); - switch (mod.voiceChatHudAlignment) { - case MIDDLE: - y -= (USER_HEIGHT * (users.size())) / 2; - break; - case BOTTOM: - y -= USER_HEIGHT * users.size(); - break; - default: - break; - } - for (User user : users) { user.bindTexture(); DrawableHelper.drawTexture(position.getX(), y, 0, 0, 16, 16, 16, 16); @@ -136,7 +119,7 @@ public Position getConfiguredPosition() { } @Override - public void setPosition(Position position) { + public void setPosition(Position position, boolean editMode) { mod.voiceChatHudPosition = position; } diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/BossBarMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/BossBarMod.java index dda1b7ab..e3d4eceb 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/BossBarMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/BossBarMod.java @@ -23,19 +23,25 @@ import io.github.solclient.client.event.EventHandler; import io.github.solclient.client.event.impl.*; +import io.github.solclient.client.mod.Mod; import io.github.solclient.client.mod.ModCategory; import io.github.solclient.client.mod.impl.*; import io.github.solclient.client.mod.option.annotation.*; import io.github.solclient.client.util.MinecraftUtils; import io.github.solclient.client.util.data.Colour; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.util.Window; import net.minecraft.entity.boss.BossBar; -public final class BossBarMod extends SolClientHudMod { +public final class BossBarMod extends StandardMod { @Expose @Option private boolean hide; + @Expose + @Option(translationKey = SolClientHudMod.TRANSLATION_KEY) + @Slider(min = 50, max = 150, step = 1, format = "sol_client.slider.percent") + private float scale = 100; @Expose @Option private boolean text = true; @@ -53,7 +59,19 @@ public final class BossBarMod extends SolClientHudMod { @Slider(min = 0, max = 15, step = 1, format = "sol_client.slider.pixels") private int offset = 2; - @EventHandler + private TextRenderer font; + + @Override + public void lateInit() { + super.lateInit(); + this.font = mc.textRenderer; + } + + public float getScale() { + return scale / 100f; + } + + @EventHandler public void onBossBarRender(PreGameOverlayRenderEvent event) { if (event.type != GameOverlayElement.BOSSHEALTH) return; diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/ClockMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/ClockMod.java index 39554150..c69e8454 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/ClockMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/ClockMod.java @@ -191,11 +191,11 @@ private float getRadiansFromPercent(float percent) { } @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { if (analogue) return position.rectangle(RADIUS * 2, RADIUS * 2); - return super.getBounds(position); + return super.getBounds(position, editMode); } } diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/CoordinatesMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/CoordinatesMod.java index 09c22e40..f487a0c0 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/CoordinatesMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/CoordinatesMod.java @@ -64,7 +64,7 @@ public class CoordinatesMod extends SolClientHudMod { private boolean shadow = true; @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { return new Rectangle(position.getX(), position.getY(), 82, 4 + font.fontHeight + 2 + font.fontHeight + 2 + font.fontHeight + 2); } @@ -77,11 +77,11 @@ public void render(Position position, boolean editMode) { } if (background) { - getBounds(position).fill(backgroundColour); + getBounds(position, editMode).fill(backgroundColour); } if (border) { - getBounds(position).stroke(borderColour); + getBounds(position, editMode).stroke(borderColour); } double x, y, z, yaw; diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/PotionEffectsMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/PotionEffectsMod.java index 8446b777..b375aa3a 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/PotionEffectsMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/PotionEffectsMod.java @@ -34,9 +34,6 @@ public class PotionEffectsMod extends SolClientHudMod { - @Expose - @Option - private VerticalAlignment alignment = VerticalAlignment.MIDDLE; @Expose @Option private boolean icon = true; @@ -64,21 +61,14 @@ public class PotionEffectsMod extends SolClientHudMod { private float spacing = 15; @Override - public Rectangle getBounds(Position position) { - int y = position.getY(); - - switch (alignment) { - case TOP: - break; - case MIDDLE: - y -= getHeight(2) / 2 * getScale(); - break; - case BOTTOM: - y -= getHeight(2) * getScale(); - break; - } - - return new Rectangle(position.getX(), y, getWidth(), getHeight(2) + 12 + (background ? 2 : 0)); + public Rectangle getBounds(Position position, boolean editMode) { + int size; + if (editMode || mc.player == null) + size = 2; + else { + size = mc.player.getStatusEffectInstances().size(); + } + return new Rectangle(position.getX(), position.getY(), getWidth(), getHeight(size) + 12 + (background ? 2 : 0)); } private int getHeight(int size) { @@ -89,7 +79,12 @@ private int getEffectHeight() { return (int) (18 + spacing); } - @Override + @Override + public boolean isDynamic() { + return true; + } + + @Override public void render(Position position, boolean editMode) { int x = position.getX(); int y = position.getY(); @@ -102,16 +97,6 @@ public void render(Position position, boolean editMode) { effects = mc.player.getStatusEffectInstances(); } - switch (alignment) { - case TOP: - break; - case MIDDLE: - y -= (getHeight(effects.size()) / 2); - break; - case BOTTOM: - y -= getHeight(effects.size()); - } - if (!effects.isEmpty()) { GlStateManager.disableLighting(); @@ -166,6 +151,7 @@ public void render(Position position, boolean editMode) { y += getEffectHeight(); } } + GlStateManager.disableBlend(); } private int getWidth() { diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/SpeedometerMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/SpeedometerMod.java index 266279c5..e272bbd0 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/SpeedometerMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/SpeedometerMod.java @@ -49,12 +49,12 @@ public void addSpeed(double speed) { } @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { if (!graphMode) { - return super.getBounds(position); + return super.getBounds(position, editMode); } - return super.getBounds(position).multiply(1.5F, 1.5F); + return super.getBounds(position, editMode).multiply(1.5F, 1.5F); } @Override @@ -68,7 +68,7 @@ public void render(Position position, boolean editMode) { speeds = new double[SPEED_COUNT]; } - Rectangle bounds = element.getMultipliedBounds(); + Rectangle bounds = element.getMultipliedBounds(editMode); MinecraftUtils.scissor(bounds); textColour.bind(); GL11.glLineWidth(1.5F); @@ -89,8 +89,8 @@ public void render(Position position, boolean editMode) { for (int i = 0; i < SPEED_COUNT; i++) { GL11.glVertex2d( - position.getX() + (i * (((getBounds(position).getWidth() + 0.4) / SPEED_COUNT))), - position.getY() - 2 + getBounds(position).getHeight() - (speeds[i] * 16)); + position.getX() + (i * (((getBounds(position, editMode).getWidth() + 0.4) / SPEED_COUNT))), + position.getY() - 2 + getBounds(position, editMode).getHeight() - (speeds[i] * 16)); } GL11.glEnd(); diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/armour/ArmourMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/armour/ArmourMod.java index 88102ddc..6102a5df 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/armour/ArmourMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/armour/ArmourMod.java @@ -57,7 +57,7 @@ public class ArmourMod extends SolClientHudMod { private Colour textColour = Colour.WHITE; @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { if (horizontal) { int width = 1; diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/chat/ChatMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/chat/ChatMod.java index 144ec8a7..6a42d922 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/chat/ChatMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/chat/ChatMod.java @@ -32,6 +32,7 @@ import io.github.solclient.client.mod.option.annotation.*; import io.github.solclient.client.util.data.Colour; import io.github.solclient.util.GlobalConstants; +import lombok.Getter; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.screen.Screen; @@ -39,7 +40,12 @@ import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; -public class ChatMod extends SolClientHudMod { +public class ChatMod extends StandardMod { + + @Expose + @Option(translationKey = SolClientHudMod.TRANSLATION_KEY) + @Slider(min = 50, max = 150, step = 1, format = "sol_client.slider.percent") + private float scale = 100; private static final float ANIMATION_MULTIPLIER = 0.5F; @@ -125,6 +131,10 @@ public void init() { instance = this; } + public float getScale() { + return scale / 100f; + } + @Override public void lateInit() { super.lateInit(); diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/chat/mixins/ChatHudMixin.java b/src/main/java/io/github/solclient/client/mod/impl/hud/chat/mixins/ChatHudMixin.java index 690e6f8a..32aada90 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/chat/mixins/ChatHudMixin.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/chat/mixins/ChatHudMixin.java @@ -62,7 +62,7 @@ public float overrideClosedChatHeight(GameOptions instance) { @Redirect(method = "getChatScale", at = @At(value = "FIELD", target = "Lnet/minecraft/client/option/GameOptions;chatScale:F")) public float overrideChatScale(GameOptions instance) { if (ChatMod.enabled) - return ChatMod.instance.scale / 100F; + return ChatMod.instance.getScale(); return instance.chatScale; } diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/crosshair/CrosshairMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/crosshair/CrosshairMod.java index 0b82d18a..0b0c6b25 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/crosshair/CrosshairMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/crosshair/CrosshairMod.java @@ -26,8 +26,10 @@ import io.github.solclient.client.event.EventHandler; import io.github.solclient.client.event.impl.*; import io.github.solclient.client.mod.impl.SolClientHudMod; +import io.github.solclient.client.mod.impl.StandardMod; import io.github.solclient.client.mod.option.ModOption; import io.github.solclient.client.mod.option.annotation.Option; +import io.github.solclient.client.mod.option.annotation.Slider; import io.github.solclient.client.util.*; import io.github.solclient.client.util.data.*; import net.minecraft.client.gui.DrawableHelper; @@ -35,13 +37,18 @@ import net.minecraft.util.hit.BlockHitResult.Type; import net.minecraft.world.level.LevelInfo.GameMode; -public class CrosshairMod extends SolClientHudMod { +public class CrosshairMod extends StandardMod { public static boolean enabled; public static CrosshairMod instance; private static final String DEFAULT_CROSSHAIR = "LCCH-9-ECBAgPAfAgQIEAA"; + @Expose + @Option(translationKey = SolClientHudMod.TRANSLATION_KEY) + @Slider(min = 50, max = 150, step = 1, format = "sol_client.slider.percent") + private float scale = 100; + @Expose final PixelMatrix pixels = new PixelMatrix(15, 15); @Expose @@ -91,6 +98,10 @@ protected void onDisable() { enabled = false; } + public float getScale() { + return scale / 100f; + } + @Override public List> createOptions() { List> options = super.createOptions(); diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/keystrokes/KeystrokesMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/keystrokes/KeystrokesMod.java index ea76c7f5..27f04b02 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/keystrokes/KeystrokesMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/keystrokes/KeystrokesMod.java @@ -102,7 +102,7 @@ public void lateInit() { } @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { int height = 0; if (movement) diff --git a/src/main/java/io/github/solclient/client/mod/impl/hud/timers/TimersMod.java b/src/main/java/io/github/solclient/client/mod/impl/hud/timers/TimersMod.java index 4f49c35e..3e9b40c5 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/hud/timers/TimersMod.java +++ b/src/main/java/io/github/solclient/client/mod/impl/hud/timers/TimersMod.java @@ -27,7 +27,6 @@ import io.github.solclient.client.event.EventHandler; import io.github.solclient.client.event.impl.*; -import io.github.solclient.client.mod.hud.*; import io.github.solclient.client.mod.impl.*; import io.github.solclient.client.mod.option.annotation.*; import io.github.solclient.client.util.BukkitMaterial; @@ -47,9 +46,6 @@ public class TimersMod extends SolClientHudMod { private final Map timers = new HashMap<>(); - @Expose - @Option - private VerticalAlignment alignment = VerticalAlignment.MIDDLE; @Expose @Option private boolean icon = true; @@ -64,19 +60,11 @@ public class TimersMod extends SolClientHudMod { private Colour timeColour = new Colour(8355711); @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { int y = position.getY(); - switch (alignment) { - case TOP: - break; - case MIDDLE: - y -= ((TIMER_HEIGHT * 3) / 2) * getScale(); - break; - case BOTTOM: - y -= (TIMER_HEIGHT * 3) * getScale(); - } + int size = editMode ? 3 : timers.size(); return new Rectangle(position.getX(), y, - 22 + font.getStringWidth("Dishwasher") + 4 + font.getStringWidth("00:00"), 19 * 3); + 22 + font.getStringWidth("Dishwasher") + 4 + font.getStringWidth("00:00"), TIMER_HEIGHT * size); } @Override @@ -93,29 +81,23 @@ public void render(Position position, boolean editMode) { } DiffuseLighting.enable(); int y = position.getY(); - - switch (alignment) { - case TOP: - break; - case MIDDLE: - y -= (TIMER_HEIGHT * (timers.size())) / 2; - break; - case BOTTOM: - y -= TIMER_HEIGHT * timers.size(); - } - for (Timer timer : timers.values()) { mc.getItemRenderer().renderInGuiWithOverrides(timer.getRenderItem(), position.getX(), y); font.draw(TIME_FORMAT.format(Math.ceil(timer.getTime() / 20F * 1000)), font.draw(timer.getName(), position.getX() + 22, y + 5, nameColour.getValue(), shadow) + (shadow ? 3 : 4), y + 5, timeColour.getValue(), shadow); - y += 19; + y += TIMER_HEIGHT; } DiffuseLighting.disable(); } - @EventHandler + @Override + public boolean isDynamic() { + return true; + } + + @EventHandler public void onWorldLoad(WorldLoadEvent event) { timers.clear(); } diff --git a/src/main/java/io/github/solclient/client/mod/impl/replay/RecordingIndicator.java b/src/main/java/io/github/solclient/client/mod/impl/replay/RecordingIndicator.java index 4aeed0a2..624bc67a 100644 --- a/src/main/java/io/github/solclient/client/mod/impl/replay/RecordingIndicator.java +++ b/src/main/java/io/github/solclient/client/mod/impl/replay/RecordingIndicator.java @@ -87,7 +87,7 @@ public Position getConfiguredPosition() { } @Override - public void setPosition(Position position) { + public void setPosition(Position position, boolean editMode) { mod.recordingIndicatorPosition = position; } @@ -97,7 +97,7 @@ public float getScale() { } @Override - public Rectangle getBounds(Position position) { + public Rectangle getBounds(Position position, boolean editMode) { return new Rectangle(position.getX() - 2, position.getY() - 2, 75, 20); } diff --git a/src/main/java/io/github/solclient/client/ui/screen/mods/MoveHudsScreen.java b/src/main/java/io/github/solclient/client/ui/screen/mods/MoveHudsScreen.java index e623717f..e3b04548 100644 --- a/src/main/java/io/github/solclient/client/ui/screen/mods/MoveHudsScreen.java +++ b/src/main/java/io/github/solclient/client/ui/screen/mods/MoveHudsScreen.java @@ -20,6 +20,7 @@ import java.util.*; +import io.github.solclient.client.mod.hud.AnchorPoint; import org.lwjgl.input.Keyboard; import org.lwjgl.nanovg.NanoVG; @@ -106,7 +107,7 @@ public void render(ComponentRenderInfo info) { if (!hud.isVisible()) continue; - if (selectRect.intersects(hud.getMultipliedBounds())) + if (selectRect.intersects(hud.getMultipliedBounds(true))) selectedHuds.add(hud); } } @@ -115,7 +116,7 @@ public void render(ComponentRenderInfo info) { if (!hud.isVisible()) continue; - Rectangle bounds = hud.getMultipliedBounds(); + Rectangle bounds = hud.getMultipliedBounds(true); if (bounds == null) continue; @@ -125,7 +126,7 @@ public void render(ComponentRenderInfo info) { if (info.relativeMouseX() != dragMouseStart.getX() || info.relativeMouseY() != dragMouseStart.getY()) hud.setPosition(hudStart.offset((int) info.relativeMouseX() - dragMouseStart.getX(), - (int) info.relativeMouseY() - dragMouseStart.getY())); + (int) info.relativeMouseY() - dragMouseStart.getY()), true); } if (selectedHuds.contains(hud)) { @@ -133,6 +134,34 @@ public void render(ComponentRenderInfo info) { NanoVG.nvgFillColor(nvg, Theme.getCurrent().accent.withAlpha(50).nvg()); NanoVG.nvgRect(nvg, bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); NanoVG.nvgFill(nvg); + + + if (hud.isDynamic()) { + int boxHalfWidth = 2; + float wOffset = bounds.getWidth() / 2f; + float hOffset = bounds.getHeight() / 2f; + for (AnchorPoint p : AnchorPoint.values()) { + float x = bounds.getX() + wOffset - (p.getXComponent() * (wOffset - boxHalfWidth)) + (bounds.getWidth() % 2 == 0 && p.getXComponent() > 0 ? 0 : -1); + float y = bounds.getY() + hOffset - (p.getYComponent() * (hOffset - boxHalfWidth)) + (bounds.getHeight() % 2 == 0 && p.getYComponent() > 0 ? 0 : -1); + NanoVG.nvgBeginPath(nvg); + NanoVG.nvgRect(nvg, x - boxHalfWidth + lineWidth / 2, y - boxHalfWidth + lineWidth / 2, boxHalfWidth * 2 + 1 - lineWidth, boxHalfWidth * 2 + 1 - lineWidth); + NanoVG.nvgStrokeWidth(nvg, lineWidth); + NanoVG.nvgStrokeColor(nvg, Theme.getCurrent().accent.withAlpha(255).nvg()); + NanoVG.nvgStroke(nvg); + if (p == hud.getAnchor()) { + NanoVG.nvgFillColor(nvg, Theme.getCurrent().accent.withAlpha(255).nvg()); + NanoVG.nvgFill(nvg); + } else if ( + info.relativeMouseX() > x - boxHalfWidth - 1 + && info.relativeMouseX() < x + boxHalfWidth + 1 + && info.relativeMouseY() > y - boxHalfWidth - 1 + && info.relativeMouseY() < y + boxHalfWidth + 1 + ) { + NanoVG.nvgFillColor(nvg, Theme.getCurrent().accentHover.withAlpha(255).nvg()); + NanoVG.nvgFill(nvg); + } + } + } } NanoVG.nvgBeginPath(nvg); @@ -162,11 +191,11 @@ public void render(ComponentRenderInfo info) { HudElement hud = selectedHuds.get(0); Position targetPosition = hud.getPosition(); - int midX = screen.width / 2 - hud.getMultipliedBounds().getWidth() / 2; - int midY = screen.height / 2 - hud.getMultipliedBounds().getHeight() / 2; + int midX = screen.width / 2 - hud.getMultipliedBounds(true).getWidth() / 2; + int midY = screen.height / 2 - hud.getMultipliedBounds(true).getHeight() / 2; NanoVG.nvgShapeAntiAlias(nvg, false); - if (Math.abs(hud.getMultipliedBounds().getY() + hud.getMultipliedBounds().getHeight() / 2 + if (Math.abs(hud.getMultipliedBounds(true).getY() + hud.getMultipliedBounds(true).getHeight() / 2 - screen.height / 2) <= 6) { // horizontal @@ -178,7 +207,7 @@ public void render(ComponentRenderInfo info) { targetPosition = new Position(targetPosition.getX(), midY); } - if (Math.abs(hud.getMultipliedBounds().getX() + hud.getMultipliedBounds().getWidth() / 2 + if (Math.abs(hud.getMultipliedBounds(true).getX() + hud.getMultipliedBounds(true).getWidth() / 2 - screen.width / 2) <= 6) { // vertical @@ -192,7 +221,7 @@ public void render(ComponentRenderInfo info) { NanoVG.nvgShapeAntiAlias(nvg, true); - hud.setPosition(targetPosition); + hud.setPosition(targetPosition, true); } super.render(info); @@ -203,7 +232,7 @@ private static Optional getHud(int x, int y) { if (!hud.isVisible()) continue; - Rectangle bounds = hud.getMultipliedBounds(); + Rectangle bounds = hud.getMultipliedBounds(true); if (bounds == null) continue; if (!bounds.contains(x, y)) @@ -230,6 +259,26 @@ public boolean mouseClicked(ComponentRenderInfo info, int button) { if (hudOpt.isPresent()) { HudElement hud = hudOpt.get(); + if (hud.isDynamic()) { + Rectangle bounds = hud.getMultipliedBounds(true); + int boxHalfWidth = 2; + float wOffset = bounds.getWidth() / 2f; + float hOffset = bounds.getHeight() / 2f; + for (AnchorPoint p : AnchorPoint.values()) { + float x = bounds.getX() + wOffset - (p.getXComponent() * (wOffset - boxHalfWidth)) + (bounds.getWidth() % 2 == 0 && p.getXComponent() > 0 ? 0 : -1); + float y = bounds.getY() + hOffset - (p.getYComponent() * (hOffset - boxHalfWidth)) + (bounds.getHeight() % 2 == 0 && p.getYComponent() > 0 ? 0 : -1); + if ( + info.relativeMouseX() > x - boxHalfWidth - 1 + && info.relativeMouseX() < x + boxHalfWidth + 1 + && info.relativeMouseY() > y - boxHalfWidth - 1 + && info.relativeMouseY() < y + boxHalfWidth + 1 + ) { + hud.setAnchorPoint(p); + break; + } + } + } + if (selectedHuds.contains(hud)) { if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) selectedHuds.remove(hud); @@ -265,7 +314,7 @@ public boolean mouseReleased(ComponentRenderInfo info, int button) { } private void shift(int x, int y) { - selectedHuds.forEach((hud) -> hud.setPosition(hud.getPosition().offset(x, y))); + selectedHuds.forEach((hud) -> hud.setPosition(hud.getPosition().offset(x, y), true)); } // yayy writing almost the same code that I did nearly two years ago! @@ -287,7 +336,7 @@ public boolean keyPressed(ComponentRenderInfo info, int keyCode, char character) selectedHuds.addAll(SolClient.INSTANCE.getHuds()); return true; } else if (keyCode == Keyboard.KEY_0) { - selectedHuds.forEach((hud) -> hud.setPosition(new Position(0, 0))); + selectedHuds.forEach((hud) -> hud.setPosition(new Position(0, 0), true)); return true; }