aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/kr/syeyoung/dungeonsguide/mod/gui
diff options
context:
space:
mode:
authorEryk Ruta <70776766+kingstefan26@users.noreply.github.com>2022-11-01 15:51:30 +0100
committerGitHub <noreply@github.com>2022-11-01 23:51:30 +0900
commit292fbd05e13271ca3ad99ebe00ae4302e04848f3 (patch)
tree2a7aeb12ab95ff688479a4727f76e3e4152c30b5 /src/main/java/kr/syeyoung/dungeonsguide/mod/gui
parentdd7a4209752715db544b2fef804da9762c532cdc (diff)
downloadSkyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.gz
Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.tar.bz2
Skyblock-Dungeons-Guide-292fbd05e13271ca3ad99ebe00ae4302e04848f3.zip
3rd time is the charm (#70)
* Updated some dependencies, used my crusty skytils forgegradle fork + removed the IRRELEVANT hytils fixes. generally made the thing build * made the logs less annoying * temp fix so it doesn't throw an exception * FAT REFACTOR General refactor on Authenticator.java DungeonsGuide.java Main.java removed unnecessary imports where not needed to be removed DGInterface.java (no real reason to exist) in DungeonsGuide.java made the retry stomp a singe-thread executor, so it doesn't leak when offline added an "offline mode" so it doesn't just error when server down TODO: move auth to DungeonsGuide.java and make it retry when network down on launch * New auth implementation that should replace the old one: does all the things the old one did removed progressBar cuz it would make the impl 3x more complicated in the name of a splash screen added a token changed event (so now it supports re-logging with a different account) code is (should) be more readable / extensible TODO: surgically replace Authenticator.java with new impl AND support re-logging * Made the chat processor logger name less obnoxious * implemented my implementation of an implementation of auth can and is very buggy, essentially the loading of the remote classes but the mod works so idk TODO: MAKE STOMP NOT DO STUFF TILL STOMPCONNECTED IS EMITTED * fix for stomp client null bc forge events not going tru on pre-init TODO: make work and test the web loadable classes, then make all the stuff that relies on stomp not throw exceptions when stomp is not connected * move the create auth method into AuthProvider interface, so we don't clutter AuthManager with implementation details * Decouple AuthProviderUtil and DgAuth, move some stuff around and make it more readable * moved AuthUtil to make more sense * de-clutter the tree a little bit * Inline StompClientStatus.java / refactor * inline the useless interface * refactoringgg * fix ahUtils exeption spam * small StompClient refactor * fix GLCursors exeption spam + logger * make sure we are authenticated when downloading resources * new .destination("value") instead of .header("destination", "value") * StompMessageHandler -> StompMessageSubscription * Introduced StompManager * fix dungeon map not showing ppl heads * ehhh * wip (commit cuz im chekig out) * fix player profile not never loading in chat * remove this specific line * fix player profile not never loading in chat * cut out hychat like a cancer * ApiFetchur now caches whole players not single profiles, added a switch profile button in gui * ugh git * Revert "cut out hychat like a cancer" This reverts commit 2ee11afa * ugh git x2 * I tried, good luck maintaining this * forgot to uncomment hychat fix * make my new party ready work and look ok * change the look and add some "somewhere" locations * make stomp connection "null safe" * i hate git * introduce callbacks on parameter change for cleaner code add one example * impl new system, half way done * now shows which profile is now selected put button on top a lil refactor * fix player profile sometimes not loading * add players knowing who is using dg (try to) * announcing that we are a dg user will get reworked in the future * update deps * make it not spam logs * sanity check for premium features so it doesn't 403 * add YoMamaOutdated that checks if you are using outdated dg * hychat?? anyone * try catch in FeatureRegistry * added Ether transmission ability * chat shredder borken, disabled for now * party deserves its own folder * dungeon stuff in dungeon folder * events folders moved * fix score data collection hanging forever if stomp is not connected * fix stomp never connecting * re-add the removed * fix wonky rendering * server side implementation is not ready, canning this for a future release * attempt to fix heads loading on main thread * discord * me when sonar lint * new consumer based stomp subscriptions * replace old with new subscriptions * remove the remains of StompSubscription and replace CloseListener with a forge event * StompSubscription is now a functional interface * remove unnecessary event message chains, feature logic should be in the feature * fix events being set up wrongly * Revert "fix events being set up wrongly" This reverts commit e6ea7efa557a5f5c8a3ea33be998717bc024b8cb. * Revert "remove unnecessary event message chains," This reverts commit 96f508bae85b33cdcef6be19226c00fc52a1439b. * fix stomp client sending payload object instead of the actual payload * fix null pointer on empty party * fix players with cosmetics name being white in tab * added message when not connected to dg changed YoMamaOutdated to use CloudFlare workers added client sided message queue * the mod doesn't init when outdated * mcmod.info * dont busy wait in authmenager * test pepole crusty tests * chill out the authmanager * name the thread pool in auth manager * clear most compiler warnings * make outdated check allow to play without the mod initialized * make first startup VERY noticeable, move config creation to main * major dungeon package refactor * refactor checkpoint * refactor checkpoint #1 * final refactor checkpoint #2 * remove the player if from version check, made the version check not nesssery for playing Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove trap room fix that didnt fix anything Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make secret beacons optional Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make the checkmarks on map align with the rest of everyone Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * removed debug function Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move the menus to make more sense + make destination text on secrets optional Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * improve dungeonMap performance by ~90% temporarly disabled 9 slot map player location due to bugs fix DungeonContext not getting player from ScoreBoard Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * add epic countdown on dungeon start (still wip) Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added a option to cache blockstaes Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added TabListUtil Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fixed epic countdown Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * (i want to sleep) made all the dungeon room detection async TODO: fix ol the bugs i created by doing that Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * stuff still broken but almost playable, unlike last commit Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * upload build jar to discord Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * cache the deps for the love of god Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * who needs linux and 32bit windows anyway Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * only upload to discord on beta branch Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added "kick" when a member joins party Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move stuff that sends chat to player into a separate class Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * use our chat queue instead of calling `thePlayer.addChatMessage` to proxy ourselves from 1.8 code Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Added and implemented MortDetector2000.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * extract duplicate + make more readable Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * added dummy support in FeatureDebugTrap Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * gradle now puts version in mcmod.info Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove side effects from DgAuth.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move debug commands into debug CommandDgDebug.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix key being wrong Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move epic countdown to dungeon huds, clean up Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Revert "who needs linux and 32bit windows anyway" This reverts commit 0f3c2d544a70fc799cd3215dad5e997c0c8b6c06. * make FeatureRegistry not static initialise to get rid of "ClassNotDefined" errors Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * null check on Exception since it threw NullPointers Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * finish up progress bar in DungeonsGuide.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * warn about null features Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move stuff around in SkyblockStatus, move the stuff that updates status into SkyblockStatus from DungeonListener Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * rename DungeonGodObject.java to DungeonFacade.java Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * add cleanChat clause in FeatureEpicCountdown Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * implement getPreRequisites and isComplete in ActionBreakWithSuperBoom Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * clean up FeatureParameter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * eliminate possible state inconsistency in DungeonListener Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move percentage from DungeonFacade to DungeonContext Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `purge` and `partymax` back into CommandDungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * stop repeating ReceiveChatQueue in ChatTransmitter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Clean up DungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `sendDebugChat` to `ChatTransmitter.java` Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * duplicate code since it currently doesn't make sense, to be reworked Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix typo Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove the trycatch so we fail fast Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * fix null pointer when trying to get fontRenderer before minecraft is initialised Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * broken checkpoint 0 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * broken checkpoint 1 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * Revert "broken checkpoint 1" This reverts commit 64985e6287c7b5650b509668e42b9803e25c419c. * Revert "broken checkpoint 0" This reverts commit 5f62e1345d9c8e7f66f1e5792004a05027913d92. * Revert "fix null pointer when trying to get fontRenderer before minecraft is initialised" This reverts commit 57d92a78d31c410f699b58c8995c94055d57e2a4. * Revert "remove the trycatch so we fail fast" This reverts commit 12772255ed575e411fb99edf37ec16d0e5f42924. * Revert "fix typo" This reverts commit aa96cc2436d3ead42d53ead78f3334fac5100713. * Revert "duplicate code since it currently doesn't make sense, to be reworked" This reverts commit 6d71b88e3102d23bcfd90d85e8996327776fd52f. * Revert "change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better" This reverts commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a. * Revert "move `sendDebugChat` to `ChatTransmitter.java`" This reverts commit 5b8b2e22fff33768134a01c15c7650100ebb9257. * Revert "Clean up DungeonsGuide" This reverts commit 2069ad3ebc4344eb1e778954dc1d8f6c9303de69. * fix typo Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit aa96cc2436d3ead42d53ead78f3334fac5100713) * duplicate code since it currently doesn't make sense, to be reworked Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit 6d71b88e3102d23bcfd90d85e8996327776fd52f) * change CommandDgDebug into a `else if` from an `switch` because some bigot decided its better Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> (cherry picked from commit ffea84d9b5fd4adbe034a88249bc920eafa7c53a) * move debug chat into ChatTransmitter Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * null pointer in SkyblockStatus bc context was not initialised yet Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move dungeon starting door detection up the tree since it was a duplicate in both children, inline MortDetector2000 Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move dungeon name to DungeonContext Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * clean up Main Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * separate the "loader" and "mod" Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * separate DungeonsGuide and Main even more Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * change singleton implementation of DungeonsGuide Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move classes since their paths are hardcoded into roomdatas Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * create CatacombsDataProvider.java and implement it Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove unnecessary `DungeonsGuide.getDungeonsGuide();` (IntelliJ refactor bug) Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * move `help` text in commands Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * a certain someone hates switch statements Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * remove my version check, since we have to wait for out lord and savior to make his own Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make `Main` and `DungeonsGuide` compatible with supported jar classloading Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * make the beta upload action run on push since it didnt get the secret on pull request and failed anyway, TODO: make the jar name not hardcoded Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> * upload all jar Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> Signed-off-by: kingstefan26 <70776766+kingstefan26@users.noreply.github.com> Co-authored-by: syeyoung <42869671+cyoung06@users.noreply.github.com>
Diffstat (limited to 'src/main/java/kr/syeyoung/dungeonsguide/mod/gui')
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MGui.java247
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java296
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MButton.java117
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MCollapsable.java137
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MColor.java48
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MEditableAColor.java106
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MFloatSelectionButton.java97
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MIntegerSelectionButton.java95
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MKeyEditButton.java147
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabel.java72
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabelAndElement.java75
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MList.java93
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModal.java92
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalConfirmation.java87
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalMessage.java77
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MNavigatingPane.java213
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPanelScaledGUI.java213
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MParameter.java90
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPassiveLabelAndElement.java71
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPopupMenu.java97
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPortableColorEdit.java292
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MRootPanel.java60
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollBar.java209
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollablePanel.java185
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MSpacer.java36
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MStringSelectionButton.java94
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTabbedPane.java160
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTextField.java418
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MToggleButton.java96
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltip.java107
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltipText.java44
-rwxr-xr-xsrc/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MValue.java79
32 files changed, 4250 insertions, 0 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MGui.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MGui.java
new file mode 100644
index 00000000..1db826a4
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MGui.java
@@ -0,0 +1,247 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui;
+
+import kr.syeyoung.dungeonsguide.mod.gui.elements.MRootPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.GLCursors;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.IOException;
+
+public class MGui extends GuiScreen {
+
+ @Getter
+ private final MRootPanel mainPanel = new MRootPanel();
+ private boolean isOpen = false;
+
+ public MGui() {
+ try {
+ Mouse.setNativeCursor(GLCursors.getCursor(EnumCursor.DEFAULT));
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void initGui() {
+ super.initGui();
+ Keyboard.enableRepeatEvents(true);
+ isOpen = true;
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ mainPanel.setBounds(new Rectangle(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight));
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ int i = Mouse.getEventX();
+ int j = this.mc.displayHeight - Mouse.getEventY();
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ GlStateManager.pushMatrix();
+ GlStateManager.disableDepth();
+ GlStateManager.enableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.scale(1.0 / scaledResolution.getScaleFactor(), 1.0 / scaledResolution.getScaleFactor(), 1.0d);
+ mainPanel.render0(1, new Point(0, 0), new Rectangle(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight), i, j, i, j, partialTicks);
+ GlStateManager.popMatrix();
+ GlStateManager.enableBlend();
+ GlStateManager.enableDepth();
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }
+
+ @Override
+ public void keyTyped(char typedChar, int keyCode) throws IOException {
+ try {
+ mainPanel.keyPressed0(typedChar, keyCode);
+ super.keyTyped(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ public void keyHeld(int keyCode, char typedChar) throws IOException {
+ try {
+ mainPanel.keyHeld0(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ public void keyReleased(int keyCode, char typedChar) throws IOException {
+ try {
+ mainPanel.keyReleased0(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ try {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+ mainPanel.mouseClicked0(mouseX, mouseY
+ , mouseX, mouseY, mouseButton);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onGuiClosed() {
+ super.onGuiClosed();
+ Keyboard.enableRepeatEvents(false);
+ isOpen = false;
+
+ try {
+ Mouse.setNativeCursor(null);
+ mainPanel.setCursor(EnumCursor.DEFAULT);
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY, int state) {
+ try {
+ mainPanel.mouseReleased0(mouseX, mouseY
+ , mouseX, mouseY, state);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ try {
+ mainPanel.mouseClickMove0(mouseX, mouseY
+ , mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+ public void mouseMove(int mouseX, int mouseY) {
+ try {
+ mainPanel.mouseMoved0(mouseX, mouseY
+ , mouseX, mouseY);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+
+ private int touchValue;
+ private int eventButton;
+ private long lastMouseEvent;
+
+
+ private int lastX, lastY;
+
+
+ @Override
+ public void handleMouseInput() throws IOException {
+ if (!isOpen) return;
+ try {
+ int i = Mouse.getEventX();
+ int j = this.mc.displayHeight - Mouse.getEventY();
+ int k = Mouse.getEventButton();
+
+ if (Mouse.getEventButtonState()) {
+ if (this.mc.gameSettings.touchscreen && this.touchValue++ > 0) {
+ return;
+ }
+
+ this.eventButton = k;
+ this.lastMouseEvent = Minecraft.getSystemTime();
+ this.mouseClicked(i, j, this.eventButton);
+ } else if (k != -1) {
+ if (this.mc.gameSettings.touchscreen && --this.touchValue > 0) {
+ return;
+ }
+
+ this.eventButton = -1;
+ this.mouseReleased(i, j, k);
+ } else if (this.eventButton != -1 && this.lastMouseEvent > 0L) {
+ long l = Minecraft.getSystemTime() - this.lastMouseEvent;
+ this.mouseClickMove(i, j, this.eventButton, l);
+ }
+ if (lastX != i || lastY != j) {
+ try {
+ EnumCursor prevCursor = mainPanel.getCurrentCursor();
+ mainPanel.setCursor(EnumCursor.DEFAULT);
+ this.mouseMove(i, j);
+ EnumCursor newCursor = mainPanel.getCurrentCursor();
+ if (prevCursor != newCursor) Mouse.setNativeCursor(GLCursors.getCursor(newCursor));
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+
+ int wheel = Mouse.getEventDWheel();
+ if (wheel != 0) {
+ mainPanel.mouseScrolled0(i, j, i, j, wheel);
+ }
+ lastX = i;
+ lastY = j;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void handleKeyboardInput() throws IOException {
+ if (!isOpen) return;
+
+ if (Keyboard.getEventKeyState()) {
+ if (Keyboard.isRepeatEvent())
+ this.keyHeld(Keyboard.getEventKey(), Keyboard.getEventCharacter());
+ else
+ this.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ } else {
+ this.keyReleased(Keyboard.getEventKey(), Keyboard.getEventCharacter());
+ }
+
+ this.mc.dispatchKeypresses();
+ }
+
+ @Override
+ public void handleInput() throws IOException {
+// Keyboard.enableRepeatEvents(true); // i hope it's temproary solution
+ super.handleInput();
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java
new file mode 100644
index 00000000..6a329110
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java
@@ -0,0 +1,296 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui;
+
+import kr.syeyoung.dungeonsguide.mod.gui.elements.MTooltip;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@Getter
+public class MPanel {
+ protected Rectangle bounds = new Rectangle(0,0,0,0); // relative to parent
+
+ protected List<MPanel> childComponents = new CopyOnWriteArrayList<MPanel>();
+
+ protected Color backgroundColor = new Color(0,0,0,0);
+
+ protected Rectangle lastAbsClip = new Rectangle(0,0,0,0);
+
+ @Getter(AccessLevel.PUBLIC)
+ @Setter
+ protected boolean isFocused;
+
+ @Getter
+ @Setter
+ protected MPanel parent;
+
+ private boolean debug;
+
+ public void setBackgroundColor(Color c) {
+ if (c == null) return;
+ this.backgroundColor = c;
+ }
+
+ public void setPosition(Point pt) {
+ this.setBounds(new Rectangle(pt.x, pt.y, getBounds().width, getBounds().height));
+ }
+
+ public void setSize(Dimension dim) {
+ this.setBounds(new Rectangle(getBounds().x, getBounds().y, dim.width, dim.height));
+ }
+
+ public Dimension getSize() {
+ return getBounds().getSize();
+ }
+
+ public Dimension getPreferredSize() { return getSize(); }
+
+ public void setBounds(Rectangle bounds) {
+ if (bounds == null) return;
+ this.bounds.x = bounds.x;
+ this.bounds.y = bounds.y;
+ this.bounds.width = bounds.width;
+ this.bounds.height = bounds.height;
+
+ for (MPanel childComponent : childComponents) {
+ childComponent.resize0(getBounds().width, getBounds().height);
+ }
+ onBoundsUpdate();
+ }
+
+ public void onBoundsUpdate() {
+
+ }
+
+ public void add(MPanel child) {
+ if (child.parent != null) throw new IllegalArgumentException("What have you done");
+ this.childComponents.add(child);
+ child.setParent(this);
+ }
+
+ public void openTooltip(MTooltip mPanel) {
+ parent.openTooltip(mPanel);
+ }
+ public int getTooltipsOpen() {
+ return parent.getTooltipsOpen();
+ }
+
+ public void remove(MPanel panel) {
+ if (panel != null)
+ panel.setParent(null);
+ this.childComponents.remove(panel);
+ }
+
+ protected Point lastParentPoint;
+
+ @Getter
+ @Setter
+ private boolean ignoreBoundOnClip;
+
+ public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { // 0,0 - a a
+
+ lastParentPoint = parentPoint;
+ int relMousex = relMousex0 - getBounds().x;
+ int relMousey = relMousey0 - getBounds().y;
+
+ GlStateManager.translate(getBounds().x, getBounds().y, 5);
+ GlStateManager.color(1,1,1,1);
+
+
+ Rectangle absBound = getBounds().getBounds();
+ absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y);
+ Rectangle clip;
+ if (ignoreBoundOnClip) clip = parentClip;
+ else clip = determineClip(parentClip, absBound);
+ lastAbsClip = clip;
+ if (clip.getSize().height * clip.getSize().width == 0) return;
+
+ this.scale = scale;
+ clip(clip.x, clip.y, clip.width, clip.height);
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+
+ GuiScreen.drawRect(0,0, getBounds().width, getBounds().height, backgroundColor.getRGB());
+ GlStateManager.enableBlend();
+
+ GlStateManager.pushMatrix();
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.enableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
+
+ render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip);
+ GlStateManager.popMatrix();
+ if (debug && lastAbsClip.contains(absMousex, absMousey)) {
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ Gui.drawRect(0, 0, getBounds().width, getBounds().height, 0x2200FF00);
+ Gui.drawRect(0, 0, getPreferredSize().width, getPreferredSize().height, 0x220000FF);
+ }
+
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+ Point newPt = new Point(parentPoint.x + getBounds().x, parentPoint.y + getBounds().y);
+
+ for (MPanel mPanel : getChildComponents()){
+ GlStateManager.pushMatrix();
+ mPanel.render0(scale, newPt, clip, absMousex, absMousey, relMousex, relMousey, partialTicks);
+ GlStateManager.popMatrix();
+ }
+ }
+ protected double scale;
+ public void clip(int x, int y, int width, int height) {
+ if (width < 0 || height < 0) return;
+
+ GL11.glScissor((int) (x * scale), Minecraft.getMinecraft().displayHeight - (int) ((y + height) * scale), (int)(width* scale + scale) - 1, (int) (height * scale + scale) - 1);
+ }
+
+ protected Rectangle determineClip(Rectangle rect1, Rectangle rect2) {
+ int minX = Math.max(rect1.x, rect2.x);
+ int minY = Math.max(rect1.y, rect2.y);
+ int maxX = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
+ int maxY = Math.min(rect1.y + rect1.height, rect2.y +rect2.height);
+ if (minX > maxX) return new Rectangle(0,0,0,0);
+ if (minY > maxY) return new Rectangle(0,0,0,0);
+ return new Rectangle(minX, minY, maxX - minX, maxY - minY);
+ }
+
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {}
+
+ public void resize0(int parentWidth, int parentHeight) {
+ resize(parentWidth, parentHeight);
+ }
+
+ public void resize(int parentWidth, int parentHeight) {}
+
+
+ public void keyPressed0(char typedChar, int keyCode) {
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.keyPressed0(typedChar, keyCode);
+ }
+
+ if (isFocused)
+ keyPressed(typedChar, keyCode);
+ }
+ public void keyPressed(char typedChar, int keyCode) {}
+ public void keyHeld0(char typedChar, int keyCode) {
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.keyHeld0(typedChar, keyCode);
+ }
+
+ if (isFocused)
+ keyHeld(typedChar, keyCode);
+ }
+ public void keyHeld(char typedChar, int keyCode) {}
+ public void keyReleased0(char typedChar, int keyCode) {
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.keyReleased0(typedChar, keyCode);
+ }
+
+ if (isFocused)
+ keyReleased(typedChar, keyCode);
+ }
+ public void keyReleased(char typedChar, int keyCode) {}
+
+
+ public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) {
+ int relMousex = relMouseX0 - getBounds().x;
+ int relMousey = relMouseY0 - getBounds().y;
+
+ boolean noClip = true;
+ boolean focusedOverall = false;
+ for (MPanel childComponent : getChildComponents()) {
+ if (childComponent.mouseClicked0(absMouseX, absMouseY, relMousex, relMousey, mouseButton)) {
+ noClip = false;
+ focusedOverall = true;
+ }
+ }
+
+ if (getBounds().contains(relMouseX0, relMouseY0) && noClip) {
+ isFocused = true;
+ focusedOverall = true;
+ } else {
+ isFocused = false;
+ }
+
+ mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton);
+ return focusedOverall;
+ }
+
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {}
+
+ public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) {
+ int relMousex = relMouseX0 - getBounds().x;
+ int relMousey = relMouseY0 - getBounds().y;
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseReleased0(absMouseX, absMouseY, relMousex, relMousey, state);
+ }
+ mouseReleased(absMouseX, absMouseY, relMousex, relMousey, state);
+ }
+ public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) {}
+
+ public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) {
+ int relMousex = relMouseX0 - getBounds().x;
+ int relMousey = relMouseY0 - getBounds().y;
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseClickMove0(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick);
+ }
+ mouseClickMove(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick);
+ }
+ public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) {}
+
+ public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {
+ int relMousex = relMouseX0 - getBounds().x;
+ int relMousey = relMouseY0 - getBounds().y;
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseScrolled0(absMouseX, absMouseY, relMousex, relMousey, scrollAmount);
+ }
+ mouseScrolled(absMouseX, absMouseY, relMousex, relMousey, scrollAmount);
+ }
+ public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {}
+
+ public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ int relMousex = relMouseX0 - getBounds().x;
+ int relMousey = relMouseY0 - getBounds().y;
+
+ mouseMoved(absMouseX, absMouseY, relMousex, relMousey);
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseMoved0(absMouseX, absMouseY, relMousex, relMousey);
+ }
+ }
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {}
+
+ public void setCursor(EnumCursor enumCursor) {
+ parent.setCursor(enumCursor);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MButton.java
new file mode 100755
index 00000000..4d8ee52f
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MButton.java
@@ -0,0 +1,117 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+
+@Getter
+@Setter
+public class MButton extends MPanel {
+ private String text;
+
+ private Color foreground = Color.white;
+ private int background = RenderUtils.blendAlpha(0xFF141414, 0.08f);
+ private int hover = RenderUtils.blendAlpha(0xFF141414, 0.14f);
+ private int clicked = RenderUtils.blendAlpha(0xFF141414, 0.16f);
+ private int border = 0x0;
+ private int disabled =0xFF141414;
+ private int roundness = 0;
+
+ private boolean enabled = true;
+
+ private Runnable onActionPerformed;
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ int bg = background;
+ if (!enabled) {
+ bg = disabled;
+ } else if (getTooltipsOpen() > 0) {
+ } else if (isclicked) {
+ bg = clicked;
+ } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) {
+ bg = hover;
+ }
+ if (roundness == 0) {
+ if (((border >> 24) & 0xFF) == 0)
+ Gui.drawRect(0, 0, getBounds().width, getBounds().height, bg);
+ else {
+ Gui.drawRect(0, 0, getBounds().width, getBounds().height, border);
+ Gui.drawRect(1, 1, getBounds().width - 1, getBounds().height - 1, bg);
+ }
+ } else {
+ if (((border >> 24) & 0xFF) == 0)
+ RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, bg);
+ else {
+ RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, border);
+ RenderUtils.drawRoundedRectangle(1, 1, getBounds().width-2, getBounds().height-2, roundness, Math.PI/8, bg);
+ }
+ GlStateManager.enableTexture2D();
+ }
+ FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj;
+ int width = renderer.getStringWidth(getText());
+ int x = (getBounds().width - width) / 2;
+ int y = (getBounds().height - renderer.FONT_HEIGHT) / 2 + 1;
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ renderer.drawString(getText(), x,y, foreground.getRGB());
+ }
+
+ boolean isclicked = false;
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) {
+ isclicked = true;
+ if (onActionPerformed != null)
+ onActionPerformed.run();
+ Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+ }
+ }
+
+ @Override
+ public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) {
+ isclicked = false;
+ }
+
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ if (lastAbsClip.contains(absMouseX, absMouseY) && enabled)
+ setCursor(EnumCursor.POINTING_HAND);
+ }
+
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MCollapsable.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MCollapsable.java
new file mode 100644
index 00000000..f665ee15
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MCollapsable.java
@@ -0,0 +1,137 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+/**
+ * Note it is passive.
+ */
+public class MCollapsable extends MPanel {
+ @Getter
+ @Setter
+ private boolean collapsed = true;
+
+ private MPanel representing;
+ @Getter
+ private MList lowerElements;
+
+ @Getter @Setter
+ private int leftPad = 0, leftPadElements = 13;
+
+ private Runnable onPreferedSizeChange;
+
+ public MCollapsable(MPanel representing, Runnable onPreferedSizeChange) {
+ this.representing = representing;
+ super.add(representing);
+ lowerElements = new MList();
+ lowerElements.setGap(0);
+ super.add(lowerElements);
+
+ this.onPreferedSizeChange = onPreferedSizeChange;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension rep = representing.getPreferredSize();
+ if (collapsed) {
+ return new Dimension(rep.width+leftPad+10, rep.height);
+ } else {
+ Dimension lowerElem = lowerElements.getPreferredSize();
+ return new Dimension(Math.max(rep.width+leftPad+10, leftPadElements + lowerElem.width), rep.height+lowerElem.height+lowerElements.getGap());
+ }
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ super.setBounds(bounds);
+ Dimension representingSize =this.representing.getPreferredSize();
+ Dimension lowerSize = lowerElements.getPreferredSize();
+
+ representing.setBounds(new Rectangle(new Point(leftPad+10, 0), new Dimension(bounds.width - (leftPad+10), representingSize.height)));
+ lowerElements.setBounds(new Rectangle(new Point(leftPadElements, representingSize.height+lowerElements.getGap()), new Dimension(bounds.width - (leftPadElements), lowerSize.height)));
+ lowerElements.realignChildren();
+ }
+
+ @Override
+ public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) {
+ super.render0(scale, parentPoint, parentClip, absMousex, absMousey, relMousex0, relMousey0, partialTicks);
+
+ clip(lastAbsClip.x, lastAbsClip.y, lastAbsClip.width, lastAbsClip.height);
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+
+
+ GlStateManager.pushMatrix();
+
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.enableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ if (collapsed) {
+ GlStateManager.translate(leftPad + 10 - fr.getStringWidth(">"),(bounds.height - fr.FONT_HEIGHT)/2,0);
+ } else {
+ GlStateManager.translate(leftPad + fr.FONT_HEIGHT,(representing.getPreferredSize().height - fr.getStringWidth(">"))/2,0);
+ GlStateManager.rotate(90, 0,0,1);
+ }
+
+ fr.drawString(">", 0,0, -1);
+
+
+ GlStateManager.popMatrix();
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }
+
+ @Override
+ public void add(MPanel child) {
+ lowerElements.add(child);
+ if (onPreferedSizeChange != null) onPreferedSizeChange.run();
+ }
+
+ @Override
+ public void remove(MPanel panel) {
+ lowerElements.remove(panel);
+ if (onPreferedSizeChange != null) onPreferedSizeChange.run();
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (relMouseX >= leftPad && relMouseY >= 0 && relMouseX <= leftPad + 10 && relMouseY <= representing.getPreferredSize().height) {
+ collapsed = !collapsed;
+ if (onPreferedSizeChange != null) onPreferedSizeChange.run();
+ }
+ }
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX, int relMouseY) {
+ if (relMouseX >= leftPad && relMouseY >= 0 && relMouseX <= leftPad + 10 && relMouseY <= representing.getPreferredSize().height)
+ setCursor(EnumCursor.POINTING_HAND);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MColor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MColor.java
new file mode 100644
index 00000000..d7cccdc6
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MColor.java
@@ -0,0 +1,48 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+
+@AllArgsConstructor
+@NoArgsConstructor
+public class MColor extends MPanel {
+ @Getter
+ @Setter
+ private Color color = Color.white;
+ @Getter
+ @Setter
+ private Dimension size = new Dimension(20,15);
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ Rectangle rectangle = getBounds();
+
+ int x = (rectangle.width - getSize().width) / 2;
+ int y = (rectangle.height - getSize().height) / 2;
+
+ Gui.drawRect(x,y,x+getSize().width,y+getSize().height, getColor().getRGB());
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MEditableAColor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MEditableAColor.java
new file mode 100644
index 00000000..b33a2b48
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MEditableAColor.java
@@ -0,0 +1,106 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+
+@AllArgsConstructor
+@NoArgsConstructor
+public class MEditableAColor extends MPanel {
+ @Getter
+ @Setter
+ private AColor color = new AColor(0xffffffff, true);
+ @Getter
+ @Setter
+ private Dimension size = new Dimension(20,15);
+
+ @Getter
+ private boolean enableEdit = false;
+
+ @Getter
+ @Setter
+ private Runnable onUpdate;
+
+ public void setEnableEdit(boolean enableEdit) {
+ this.enableEdit = enableEdit;
+ if (portable != null && !enableEdit) {
+ remove(portable);
+ portable = null;
+ }
+ }
+
+ private MPortableColorEdit portable = null;
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ Rectangle rectangle = getBounds();
+
+ int x = (rectangle.width - getSize().width) / 2;
+ int y = (rectangle.height - getSize().height) / 2;
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ Gui.drawRect(x,y,x+getSize().width,y+getSize().height, RenderUtils.getColorAt(absMousex - relMousex0, absMousey - relMousey0, color));
+
+ Gui.drawRect(x,y,x+getSize().width,y+1, 0xff333333);
+ Gui.drawRect(x,y,x+1,y+getSize().height, 0xff333333);
+ Gui.drawRect(x+getSize().width-1,y,x+getSize().width,y+getSize().height, 0xff333333);
+ Gui.drawRect(x,y+getSize().height-1,x+getSize().width,y+getSize().height, 0xff333333);
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (!enableEdit) return;
+ if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) {
+ portable = new MPortableColorEdit() {
+ @Override
+ public void update2() {
+ super.update2();
+ MEditableAColor.this.color = portable.getColor();
+ if (onUpdate != null)
+ onUpdate.run();
+ }
+ };
+ portable.setColor(color);
+ Rectangle startWith = new Rectangle((int)(absMouseX * getScale()), (int) (absMouseY* getScale()), (int) (100 * getScale()), (int) (90 * getScale()));
+ if (startWith.x < 10) startWith.x = 10;
+ if (startWith.y < 10) startWith.y = 10;
+ if (startWith.x + startWith.width > Minecraft.getMinecraft().displayWidth - 10) startWith.x = Minecraft.getMinecraft().displayWidth - 10 - startWith.width;
+ if (startWith.y + startWith.height > Minecraft.getMinecraft().displayHeight - 10) startWith.y = Minecraft.getMinecraft().displayHeight - 10 - startWith.height;
+ portable.setBounds(startWith);
+
+
+ portable.setScale(2.0f);
+ portable.open(this);
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MFloatSelectionButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MFloatSelectionButton.java
new file mode 100755
index 00000000..1bda009c
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MFloatSelectionButton.java
@@ -0,0 +1,97 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.awt.*;
+
+@Getter
+@Setter
+public class MFloatSelectionButton extends MPanel {
+
+ private float data;
+
+ private MButton dec;
+ private MButton inc;
+ private MTextField selected;
+
+ @Getter
+ @Setter
+ private Runnable onUpdate;
+
+ public MFloatSelectionButton(float data2) {
+ this.data = data2;
+
+ dec = new MButton(); dec.setText("<"); add(dec);
+ inc = new MButton(); inc.setText(">"); add(inc);
+ selected = new MTextField() {
+ @Override
+ public String getText() {
+ return data +"";
+ }
+ @Override
+ public void edit(String str) {
+ try {
+ data = Float.parseFloat(str);
+ onUpdate.run();
+ } catch (Exception e) {}
+ }
+ }; updateSelected(); add(selected);
+
+ dec.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ data--;
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ inc.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ data ++;
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(-1,15);
+ }
+
+ public float getSelected() {
+ return data;
+ }
+
+ public void updateSelected() {
+ selected.setText(data+"");
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height));
+ inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height));
+ selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MIntegerSelectionButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MIntegerSelectionButton.java
new file mode 100755
index 00000000..6d17aebf
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MIntegerSelectionButton.java
@@ -0,0 +1,95 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import org.lwjgl.input.Keyboard;
+
+import java.awt.*;
+
+@Getter
+@Setter
+public class MIntegerSelectionButton extends MPanel {
+
+ private int data;
+
+ private MButton dec;
+ private MButton inc;
+ private MTextField selected;
+
+ @Getter
+ @Setter
+ private Runnable onUpdate;
+
+ public MIntegerSelectionButton(int data2) {
+ this.data = data2;
+
+ dec = new MButton(); dec.setText("<"); add(dec);
+ inc = new MButton(); inc.setText(">"); add(inc);
+ selected = new MTextField() {
+ @Override
+ public void edit(String str) {
+ try {
+ data = Integer.parseInt(str);
+ onUpdate.run();
+ } catch (Exception e) {}
+ }
+ }; updateSelected(); add(selected);
+
+ dec.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ data -= (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1);
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ inc.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ data += (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1);
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ }
+
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(-1,15);
+ }
+
+ public int getSelected() {
+ return data;
+ }
+
+ private void updateSelected() {
+ selected.setText(data+"");
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height));
+ inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height));
+ selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MKeyEditButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MKeyEditButton.java
new file mode 100755
index 00000000..70330f03
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MKeyEditButton.java
@@ -0,0 +1,147 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.settings.GameSettings;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+
+@Getter
+@Setter
+public class MKeyEditButton extends MPanel {
+ private int key;
+ private Runnable onKeyEdit;
+
+ private Color foreground = Color.white;
+ private int background = RenderUtils.blendAlpha(0xFF141414, 0.08f);
+ private int hover = RenderUtils.blendAlpha(0xFF141414, 0.14f);
+ private int clicked = RenderUtils.blendAlpha(0xFF141414, 0.16f);
+ private int border = 0x0;
+ private int disabled =0xFF141414;
+ private int roundness = 0;
+
+ private boolean enabled = true;
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ int bg = background;
+ if (!enabled) {
+ bg = disabled;
+ } else if (getTooltipsOpen() > 0) {
+ } else if (selected) {
+ bg = clicked;
+ } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) {
+ bg = hover;
+ }
+ if (roundness == 0) {
+ if (((border >> 24) & 0xFF) == 0)
+ Gui.drawRect(0, 0, getBounds().width, getBounds().height, bg);
+ else {
+ Gui.drawRect(0, 0, getBounds().width, getBounds().height, border);
+ Gui.drawRect(1, 1, getBounds().width - 1, getBounds().height - 1, bg);
+ }
+ } else {
+ if (((border >> 24) & 0xFF) == 0)
+ RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, bg);
+ else {
+ RenderUtils.drawRoundedRectangle(0, 0, getBounds().width, getBounds().height, roundness, Math.PI/8, border);
+ RenderUtils.drawRoundedRectangle(1, 1, getBounds().width-2, getBounds().height-2, roundness, Math.PI/8, bg);
+ }
+ GlStateManager.enableTexture2D();
+ }
+
+ String str = GameSettings.getKeyDisplayString(key);
+ if (selected) str = "> "+str+" <";
+ FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj;
+ int width = renderer.getStringWidth(str);
+ int x = (getBounds().width - width) / 2;
+ int y = (getBounds().height - renderer.FONT_HEIGHT) / 2 + 1;
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ renderer.drawString(str, x,y, foreground.getRGB());
+ }
+
+ private boolean selected;
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) {
+ if (selected) {
+ key = -100 + mouseButton;
+ selected = false;
+ if (onKeyEdit != null)
+ onKeyEdit.run();
+ } else {
+ selected = true;
+ }
+ Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+ } else {
+ selected = false;
+ }
+ }
+
+ @Override
+ public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) {
+
+ }
+
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ if (lastAbsClip.contains(absMouseX, absMouseY) && enabled)
+ setCursor(EnumCursor.POINTING_HAND);
+ }
+
+ @Override
+ public void keyPressed(char typedChar, int keyCode) {
+ if (!selected) return;
+ if (keyCode == 1) {
+ key = 0;
+ } else if (keyCode != 0) {
+ key = keyCode;
+ } else if (typedChar > 0) {
+ key = typedChar + 256;
+ }
+ selected = false;
+ if (onKeyEdit != null)
+ onKeyEdit.run();
+ throw new RuntimeException("hack to stop event propagation");
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(80, 15);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabel.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabel.java
new file mode 100755
index 00000000..a7fc06c1
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabel.java
@@ -0,0 +1,72 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+
+public class MLabel extends MPanel {
+ @Getter
+ @Setter
+ private String text;
+
+ @Getter
+ @Setter
+ private Color foreground = Color.white;
+
+ public enum Alignment {
+ LEFT, CENTER, RIGHT
+ }
+ @Getter
+ @Setter
+ private Alignment alignment= Alignment.LEFT;
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj;
+ int width = renderer.getStringWidth(getText());
+ int x,y;
+ if (alignment == Alignment.CENTER) {
+ x = (getBounds().width - width) / 2;
+ y = (getBounds().height - renderer.FONT_HEIGHT) / 2;
+ } else if (alignment == Alignment.LEFT) {
+ x = 0;
+ y = (getBounds().height - renderer.FONT_HEIGHT) / 2;
+ } else if (alignment == Alignment.RIGHT) {
+ x = getBounds().width - width;
+ y = (getBounds().height - renderer.FONT_HEIGHT) / 2;
+ } else{
+ return;
+ }
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ renderer.drawString(getText(), x,y, 0xffffffff);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabelAndElement.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabelAndElement.java
new file mode 100755
index 00000000..20f2aa93
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MLabelAndElement.java
@@ -0,0 +1,75 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+
+public class MLabelAndElement extends MPanel {
+ private final MLabel label;
+ private final MPanel element;
+
+ @Getter @Setter
+ private Color hover;
+ @Getter @Setter
+ private Runnable onClick;
+
+ public MLabelAndElement(String label, MPanel element) {
+ this.add(this.label = new MLabel());
+ this.label.setText(label);
+ this.add(element);
+ this.element = element;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(200, 30);
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) {
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB());
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (onClick!= null && lastAbsClip.contains(absMouseX, absMouseY)) {
+ onClick.run();
+ }
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ this.setSize(new Dimension(parentWidth, getBounds().height));
+ label.setBounds(new Rectangle(0,0,parentHeight / 3, getBounds().height));
+ element.setBounds(new Rectangle(parentWidth / 3,0,parentWidth / 3 * 2, getBounds().height));
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ label.setBounds(new Rectangle(0,0,getBounds().width / 3, getBounds().height));
+ element.setBounds(new Rectangle(getBounds().width / 3,0,getBounds().width / 3 * 2, getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MList.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MList.java
new file mode 100644
index 00000000..bfdcae26
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MList.java
@@ -0,0 +1,93 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+
+public class MList extends MPanel {
+ @Getter
+ private int gap = 5;
+
+ @Getter @Setter
+ private boolean drawLine = true;
+
+ public void setGap(int gap) {
+ this.gap = gap;
+ realignChildren();
+ }
+
+ @Getter @Setter
+ private int gapLineColor = 0xFFFFFFFF;
+
+ public void realignChildren() {
+ int y = 0;
+ for (MPanel childComponent : getChildComponents()) {
+ Dimension preferedSize = childComponent.getPreferredSize();
+ int height = Math.max(10, preferedSize.height);
+ childComponent.setBounds(new Rectangle(0, y, bounds.width, height));
+ y += height;
+ if (gap > 0)
+ y += gap;
+ }
+ setSize(new Dimension(getSize().width, Math.max(0, y-gap)));
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ int maxW = 0;
+ int h = 0;
+ for (MPanel childComponent : getChildComponents()) {
+ Dimension preferedSize = childComponent.getPreferredSize();
+ int height = Math.max(10, preferedSize.height);
+ if (preferedSize.width > maxW) maxW = preferedSize.width;
+ h += height;
+ if (gap > 0) h += gap;
+ }
+ return new Dimension(maxW, Math.max(0, h-gap));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ if (gap <= 0) return;
+ if (!drawLine) return;
+ for (int i = 1; i < getChildComponents().size(); i++) {
+ MPanel panel = getChildComponents().get(i);
+ Rectangle bound = panel.getBounds();
+ int top = bound.y - (int)Math.ceil(gap/2.0);
+ Gui.drawRect(0, top, getBounds().width, top + 1, gapLineColor);
+ }
+ }
+
+ @Override
+ public void add(MPanel child) {
+ super.add(child);
+ realignChildren();
+ }
+
+ @Override
+ public void remove(MPanel panel) {
+ super.remove(panel);
+ realignChildren();
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModal.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModal.java
new file mode 100644
index 00000000..1a2abc6e
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModal.java
@@ -0,0 +1,92 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+
+import java.awt.*;
+
+public class MModal extends MTooltip {
+ @Getter
+ private MPanel modalContent = new MPanel();
+
+ @Getter @Setter
+ private String title = "Default Title";
+
+ public MModal() {
+ super.add(modalContent);
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ super.resize(parentWidth, parentHeight);
+ setBounds(new Rectangle(0,0, parentWidth, parentHeight));
+ }
+
+ @Getter @Setter
+ private Dimension modalSize = new Dimension(300,200);
+
+
+ @Override
+ public void onBoundsUpdate() {
+ super.onBoundsUpdate();
+ Dimension effDim = getEffectiveDimension();
+
+ modalContent.setBounds(new Rectangle((effDim.width - modalSize.width)/2, (effDim.height - modalSize.height)/2 + 16, modalSize.width, modalSize.height-16));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ RenderUtils.drawGradientRect(0, 0, bounds.width, bounds.height, -1072689136, -804253680);
+ Dimension effDim = getEffectiveDimension();
+ int x = (effDim.width-modalSize.width)/2;
+ int y = (effDim.height - modalSize.height)/2;
+ GlStateManager.translate(x,y, 0);
+ RenderUtils.drawRoundedRectangle(0,0,modalSize.width, modalSize.height, 3, Math.PI/8, RenderUtils.blendAlpha(0x141414, 0.20f));
+ Gui.drawRect(0,15, modalSize.width, 16, 0xFF02EE67);
+ Gui.drawRect(0,16,modalSize.width, 26, RenderUtils.blendAlpha(0x141414, 0.1f));
+ RenderUtils.drawRoundedRectangle(0,16,modalSize.width, modalSize.height-16, 3, Math.PI/8, RenderUtils.blendAlpha(0x141414, 0.1f));
+
+ GlStateManager.enableTexture2D();
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ fr.drawString(title, 5,(16-fr.FONT_HEIGHT)/2, -1);
+ }
+
+ @Override
+ public void add(MPanel child) {
+ modalContent.add(child);
+ }
+
+ protected void addSuper(MPanel child) {
+ super.add(child);
+ }
+
+ @Override
+ public void remove(MPanel panel) {
+ modalContent.remove(panel);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalConfirmation.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalConfirmation.java
new file mode 100644
index 00000000..746d1afa
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalConfirmation.java
@@ -0,0 +1,87 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public class MModalConfirmation extends MModal {
+ private String content;
+ private Runnable callBackYes;
+ private Runnable callBackNo;
+ @Getter
+ private MButton yes, no;
+ public MModalConfirmation(String title, String content, Runnable callBackYes, Runnable callBackNo) {
+ super();
+ setTitle(title);
+ this.content = content;
+ this.callBackYes = callBackYes;
+ this.callBackNo = callBackNo;
+ this.yes = new MButton();
+ this.no = new MButton();
+ yes.setText("Yes"); no.setText("No");
+ no.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f));
+ no.setHover(RenderUtils.blendAlpha(0x141414, 0.17f));
+ yes.setOnActionPerformed(() -> {
+ close();
+ if (callBackYes != null) callBackYes.run();
+ });
+ no.setOnActionPerformed(() -> {
+ close();
+ if (callBackNo != null) callBackNo.run();
+ });
+ yes.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f));
+ yes.setHover(RenderUtils.blendAlpha(0x141414, 0.17f));
+
+ add(new ConfirmationContent());
+ }
+
+ public class ConfirmationContent extends MPanel {
+ public ConfirmationContent() {
+ add(yes); add(no);
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ setBounds(new Rectangle(0,0,parentWidth, parentHeight));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ GlStateManager.translate(5,5,0);
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ fr.drawSplitString(content, 0,0, ConfirmationContent.this.bounds.width-10, -1);
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ super.setBounds(bounds);
+ yes.setBounds(new Rectangle(10,bounds.height-25,(bounds.width-30)/2, 15));
+ no.setBounds(new Rectangle(yes.getBounds().x + yes.getBounds().width + 10,bounds.height-25,(bounds.width-30)/2, 15));
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalMessage.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalMessage.java
new file mode 100644
index 00000000..1973e239
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MModalMessage.java
@@ -0,0 +1,77 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public class MModalMessage extends MModal {
+ private String content;
+ private Runnable callBackOk;
+ @Getter
+ private MButton yes;
+ public MModalMessage(String title, String content, Runnable callBackOk) {
+ super();
+ setTitle(title);
+ this.content = content;
+ this.callBackOk = callBackOk;
+ this.yes = new MButton();
+ yes.setText("Ok");
+ yes.setOnActionPerformed(() -> {
+ close();
+ if (callBackOk != null) callBackOk.run();
+ });
+ yes.setBackground(RenderUtils.blendAlpha(0x141414, 0.15f));
+ yes.setHover(RenderUtils.blendAlpha(0x141414, 0.17f));
+
+ add(new MessageContent());
+ }
+
+ public class MessageContent extends MPanel {
+ public MessageContent() {
+ add(yes);
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ setBounds(new Rectangle(0,0,parentWidth, parentHeight));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ GlStateManager.translate(5,5,0);
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ fr.drawSplitString(content, 0,0, MModalMessage.MessageContent.this.bounds.width-10, -1);
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ super.setBounds(bounds);
+ yes.setBounds(new Rectangle(10,bounds.height-25,(bounds.width-20), 15));
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MNavigatingPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MNavigatingPane.java
new file mode 100755
index 00000000..76de53d5
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MNavigatingPane.java
@@ -0,0 +1,213 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import com.google.common.base.Function;
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class MNavigatingPane extends MPanel {
+
+ private final Map<String, MPanel> pages = new HashMap<String, MPanel>();
+ private final List<MTabButton> bookMarks = new ArrayList<MTabButton>();
+
+ @Getter
+ @Setter
+ private Function<String, MPanel> pageGenerator;
+
+ @Getter
+ private String currentPage = "";
+
+ public void setCurrentPage(String currentPage) {
+ this.history.push(this.currentPage);
+ this.currentPage = currentPage;
+ }
+
+ @Getter
+ private Color background2;
+
+ private final Stack<String> history = new Stack<String>();
+
+ private final MButton back = new MButton();
+
+ public MNavigatingPane() {
+ back.setText("<");
+ back.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ if (history.size() > 0)
+ currentPage = history.pop();
+ }
+ });
+ back.setBackgroundColor(Color.darkGray);
+ back.setBounds(new Rectangle(3,18,12,12));
+ add(back);
+ }
+
+ public void setBackground2(Color background2) {
+ this.background2 = background2;
+ for (MPanel value : pages.values()) {
+ value.setBackgroundColor(background2);
+ }
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+
+ Gui.drawRect(0, 15, getBounds().width, getBounds().height, 0xFF444444);
+ Gui.drawRect(1, 16, getBounds().width-1, getBounds().height-1, background2 != null ? background2.getRGB() : 0);
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ fr.drawString(currentPage.replace(".", " > "), 20, 20, 0xFFFFFFFF);
+
+ }
+
+ public void addBookmark(String name, String addr) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ MTabButton button = new MTabButton(this, name, addr);
+ int totalX = 0;
+ for (MTabButton button1:bookMarks)
+ totalX += button1.getBounds().width;
+ button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(name) + 6), 15));
+ bookMarks.add(button);
+ if (currentPage.isEmpty())
+ currentPage = addr;
+ }
+ public void addBookmarkRunnable(String name, final Runnable toRun) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ MTabButton button = new MTabButton(this, name, null) {
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (lastAbsClip.contains(absMouseX, absMouseY)) {
+ toRun.run();
+ }
+ }
+ };
+ int totalX = 0;
+ for (MTabButton button1:bookMarks)
+ totalX += button1.getBounds().width;
+ button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(name) + 6), 15));
+ bookMarks.add(button);
+ }
+
+ @Override
+ public List<MPanel> getChildComponents() {
+ ArrayList<MPanel> dynamic = new ArrayList<MPanel>(bookMarks);
+ if (!pages.containsKey(currentPage)) {
+ MPanel panel = pageGenerator.apply(currentPage);
+ MPanel panel2 = new MPanel() ;
+ if (panel != null)
+ panel2.add(panel);
+ panel2.setBackgroundColor(background2);
+ pages.put(currentPage, panel2);
+ panel2.setBounds(new Rectangle(1,30,getBounds().width-2, getBounds().height-31));
+ panel2.setParent(this);
+ }
+ dynamic.add(pages.get(currentPage));
+ dynamic.add(back);
+ return dynamic;
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ this.setBounds(new Rectangle(0,0,parentWidth, parentHeight));
+ for (MPanel ma:pages.values())
+ ma.setBounds(new Rectangle(1,30,getBounds().width-2, getBounds().height-31));
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ if (bounds == null) return;
+ this.bounds.x = bounds.x;
+ this.bounds.y = bounds.y;
+ this.bounds.width = bounds.width;
+ this.bounds.height = bounds.height;
+ }
+
+ @Getter
+ @Setter
+ public static class MTabButton extends MPanel {
+ private String text;
+ private String address;
+
+ private Color foreground = Color.white;
+ private Color hover = new Color(154, 154, 154, 255);
+ private Color clicked = new Color(88, 88, 88,255);
+ private Color selected = new Color(111, 111, 111,255);
+ private Color disabled = new Color(0,0,0);
+
+ private boolean enabled = true;
+
+ private MNavigatingPane tabbedPane;
+
+ public MTabButton(MNavigatingPane tabbedPane, String key, String address) {
+ this.tabbedPane = tabbedPane;
+ this.text = key;
+ this.address = address;
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ Color bg = null;
+ if (!enabled) {
+ bg = disabled;
+ } else if (tabbedPane.getCurrentPage().equals(address)) {
+ bg = selected;
+ } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) {
+ bg = hover;
+ }
+ Gui.drawRect(0, tabbedPane.getCurrentPage().equals(address) ? 0 : 2, getBounds().width, getBounds().height, 0xFF444444);
+ if (bg != null)
+ Gui.drawRect(1,tabbedPane.getCurrentPage().equals(address) ? 1 : 3,getBounds().width - 1, getBounds().height, bg.getRGB());
+
+ FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj;
+ int width = renderer.getStringWidth(text);
+ int x = (getBounds().width - width) / 2;
+ int y = (getBounds().height - 3 - renderer.FONT_HEIGHT) / 2 + 3;
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ renderer.drawString(text, x,y, foreground.getRGB());
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (lastAbsClip.contains(absMouseX, absMouseY)) {
+ tabbedPane.setCurrentPage(address);
+ }
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPanelScaledGUI.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPanelScaledGUI.java
new file mode 100644
index 00000000..0941116a
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPanelScaledGUI.java
@@ -0,0 +1,213 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public class MPanelScaledGUI extends MPanel {
+ @Getter
+ protected double scale = 1.0;
+ @Getter
+ protected double relativeScale;
+
+ public void setScale(double scale) {
+ this.scale = scale;
+ for (MPanel childComponent : childComponents) {
+ childComponent.resize0((int) (getBounds().width/scale), (int) (getBounds().height/scale));
+ }
+ onBoundsUpdate();
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ if (bounds == null) return;
+ this.bounds.x = bounds.x;
+ this.bounds.y = bounds.y;
+ this.bounds.width = bounds.width;
+ this.bounds.height = bounds.height;
+
+ for (MPanel childComponent : childComponents) {
+ childComponent.resize0((int) (getBounds().width/scale), (int) (getBounds().height/scale));
+ }
+ onBoundsUpdate();
+ }
+
+ public Dimension getEffectiveDimension() {
+ return new Dimension((int)(getBounds().width / scale), (int)(getBounds().height / scale));
+ }
+
+ @Override
+ public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) {
+ lastParentPoint = parentPoint;
+
+ GlStateManager.translate(getBounds().x, getBounds().y, 5);
+ GlStateManager.color(1,1,1,1);
+
+ Rectangle absBound = getBounds().getBounds();
+ absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y);
+
+ Rectangle clip;
+ if (isIgnoreBoundOnClip()) clip = parentClip;
+ else clip = determineClip(parentClip, absBound);
+ lastAbsClip = clip;
+
+ if (clip.getSize().height * clip.getSize().width == 0) return;
+
+ int absMousex = (int) (absMousex0 / scale), absMousey = (int) (absMousey0 / scale);
+ int relMousex = (int) ((relMousex0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMousey0 - getBounds().y) /scale);
+
+ // FROM HERE, IT IS SCALED
+
+ GlStateManager.scale(this.scale, this.scale, 1);
+ clip = new Rectangle((int) (clip.x / scale), (int) (clip.y / scale), (int) (clip.width / scale), (int) (clip.height / scale));
+ lastAbsClip = clip;
+
+
+ this.relativeScale = parentScale * this.scale;
+ clip(clip.x, clip.y, clip.width, clip.height);
+
+
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+
+
+ GuiScreen.drawRect(0,0, (int) (getBounds().width / scale), (int) (getBounds().height / scale), backgroundColor.getRGB());
+ GlStateManager.enableBlend();
+
+
+ GlStateManager.pushMatrix();
+
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.enableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
+
+ render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip);
+
+ GlStateManager.popMatrix();
+
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+
+
+ Point newPt = new Point((int) ((parentPoint.x + getBounds().x) / scale), (int) ((parentPoint.y + getBounds().y) / scale));
+
+ for (MPanel mPanel : getChildComponents()){
+ GlStateManager.pushMatrix();
+
+ mPanel.render0(relativeScale, newPt,clip,absMousex, absMousey, relMousex, relMousey, partialTicks);
+
+ GlStateManager.popMatrix();
+ }
+ }
+
+ @Override
+ public void clip(int x, int y, int width, int height) {
+ if (width < 0 || height < 0) return;
+
+ GL11.glScissor((int) (x * relativeScale), Minecraft.getMinecraft().displayHeight - (int) ((y + height+1) * relativeScale), (int)((width+1)* relativeScale), (int) ((height+1) * relativeScale));
+ }
+
+ @Override
+ public void resize0(int parentWidth, int parentHeight) {
+ super.resize0(parentWidth, parentHeight);
+ }
+
+
+ public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) {
+ int relMousex = (int) ((relMouseX0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMouseY0 - getBounds().y) / scale);
+ absMouseX = (int) (absMouseX / scale);
+ absMouseY = (int) (absMouseY / scale);
+
+ boolean noClip = true;
+ boolean focusedOverall = false;
+ for (MPanel childComponent : getChildComponents()) {
+ if (childComponent.mouseClicked0(absMouseX, absMouseY,relMousex, relMousey, mouseButton)) {
+ noClip = false;
+ focusedOverall = true;
+ }
+ }
+
+ if (getBounds().contains(relMouseX0, relMouseY0) && noClip) {
+ isFocused = true;
+ focusedOverall = true;
+ } else {
+ isFocused = false;
+ }
+ mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton);
+
+ return focusedOverall;
+ }
+ public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) {
+ int relMousex = (int) ((relMouseX0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMouseY0 - getBounds().y) / scale);
+ absMouseX = (int) (absMouseX / scale);
+ absMouseY = (int) (absMouseY / scale);
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseReleased0(absMouseX, absMouseY, relMousex, relMousey, state);
+ }
+ mouseReleased(absMouseX, absMouseY, relMousex, relMousey, state);
+ }
+ public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) {
+ int relMousex = (int) ((relMouseX0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMouseY0 - getBounds().y) / scale);
+ absMouseX = (int) (absMouseX / scale);
+ absMouseY = (int) (absMouseY / scale);
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseClickMove0(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick);
+ }
+ mouseClickMove(absMouseX, absMouseY, relMousex, relMousey, clickedMouseButton, timeSinceLastClick);
+ }
+ public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {
+ int relMousex = (int) ((relMouseX0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMouseY0 - getBounds().y) / scale);
+ absMouseX = (int) (absMouseX / scale);
+ absMouseY = (int) (absMouseY / scale);
+
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseScrolled0(absMouseX, absMouseY, relMousex, relMousey, scrollAmount);
+ }
+ mouseScrolled(absMouseX, absMouseY, relMousex, relMousey, scrollAmount);
+ }
+
+ @Override
+ public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ int relMousex = (int) ((relMouseX0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMouseY0 - getBounds().y) / scale);
+ absMouseX = (int) (absMouseX / scale);
+ absMouseY = (int) (absMouseY / scale);
+
+ mouseMoved(absMouseX, absMouseY, relMousex, relMousey);
+ for (MPanel childComponent : getChildComponents()) {
+ childComponent.mouseMoved0(absMouseX, absMouseY, relMousex, relMousey);
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MParameter.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MParameter.java
new file mode 100755
index 00000000..72f64de1
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MParameter.java
@@ -0,0 +1,90 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext;
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter;
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonParameterEdit;
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.panes.DynamicEditor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+
+public class MParameter extends MPanel {
+ private final MLabel label;
+ private final MLabel data;
+
+ @Getter @Setter
+ private Color hover = Color.gray;
+
+ @Getter @Setter
+ private Parameter parameter;
+ private final DynamicEditor processorParameterEditPane;
+
+ public MParameter(final Parameter parameter, DynamicEditor processorParameterEditPane) {
+ this.processorParameterEditPane = processorParameterEditPane;
+ this.add(this.label = new MLabel() {
+ @Override
+ public String getText() {
+ return parameter.getName();
+ }
+ });
+ this.add(this.data = new MLabel() {
+ @Override
+ public String getText() {
+ return parameter.getNewData() != null ?parameter.getNewData().toString() :"-empty-";
+ }
+ });
+ this.label.setAlignment(MLabel.Alignment.LEFT);
+ this.data.setAlignment(MLabel.Alignment.RIGHT);
+
+ this.parameter = parameter;
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) {
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB());
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (this.getBounds().x > -20 && lastAbsClip.contains(absMouseX, absMouseY)) {
+ // open new gui;
+ EditingContext.getEditingContext().openGui(new GuiDungeonParameterEdit(this, processorParameterEditPane));
+ }
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ this.setSize(new Dimension(parentWidth, getBounds().height));
+ label.setBounds(new Rectangle(0,0,parentHeight / 3, getBounds().height));
+ data.setBounds(new Rectangle(parentWidth / 3,0,parentWidth / 3 * 2, getBounds().height));
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ label.setBounds(new Rectangle(0,0,getBounds().width / 3, getBounds().height));
+ data.setBounds(new Rectangle(getBounds().width / 3,0,getBounds().width / 3 * 2, getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPassiveLabelAndElement.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPassiveLabelAndElement.java
new file mode 100755
index 00000000..9a4cd791
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPassiveLabelAndElement.java
@@ -0,0 +1,71 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+
+public class MPassiveLabelAndElement extends MPanel {
+ private final MLabel label;
+ private final MPanel element;
+
+ @Getter @Setter
+ private Color hover;
+ @Getter @Setter
+ private Runnable onClick;
+
+ @Getter @Setter
+ private double divideRatio = 1/3.0;
+
+ public MPassiveLabelAndElement(String label, MPanel element) {
+ this.add(this.label = new MLabel());
+ this.label.setText(label);
+ this.add(element);
+ this.element = element;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(100, 20);
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) {
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB());
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (onClick!= null && lastAbsClip.contains(absMouseX, absMouseY)) {
+ onClick.run();
+ }
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ label.setBounds(new Rectangle(0,0, (int) (getBounds().width * divideRatio), getBounds().height));
+ element.setBounds(new Rectangle((int) (getBounds().width * divideRatio),0, (int) (getBounds().width * (1-divideRatio)), getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPopupMenu.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPopupMenu.java
new file mode 100644
index 00000000..bc2a656b
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPopupMenu.java
@@ -0,0 +1,97 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+import java.util.List;
+
+public class MPopupMenu extends MTooltip {
+ private int x, y;
+ public MPopupMenu(int x, int y, List<MPanel> popupMenuElementList) {
+ this.x = x; this.y = y;
+ int maxWidth = 150;
+ for (MPanel mPanel : popupMenuElementList) {
+ Dimension dimension = mPanel.getPreferredSize();
+ if (dimension.width > maxWidth) maxWidth = dimension.width;
+ }
+ int h1 = 7;
+ for (MPanel mPanel : popupMenuElementList) {
+ Dimension dimension = mPanel.getPreferredSize();
+ mPanel.setBounds(new Rectangle(7,h1, maxWidth-13, dimension.height));
+ h1 += dimension.height + 7;
+ add(mPanel);
+ }
+
+ if (y + h1 > Minecraft.getMinecraft().displayHeight)
+ y = Minecraft.getMinecraft().displayHeight - h1;
+ if (x + maxWidth+ 2 > Minecraft.getMinecraft().displayWidth)
+ x = Minecraft.getMinecraft().displayWidth - maxWidth-2;
+ setBounds(new Rectangle(x,y,maxWidth+2, h1));
+ }
+
+ @Override
+ public void setScale(double scale) {
+ super.setScale(scale);
+
+ int maxWidth = 150;
+ for (MPanel mPanel : getChildComponents()) {
+ Dimension dimension = mPanel.getPreferredSize();
+ if (dimension.width > maxWidth) maxWidth = dimension.width;
+ }
+ int h1 = 7;
+ for (MPanel mPanel : getChildComponents()) {
+ Dimension dimension = mPanel.getPreferredSize();
+ mPanel.setBounds(new Rectangle(7,h1, maxWidth-13, dimension.height));
+ h1 += dimension.height + 7;
+ }
+ maxWidth += 2;
+ maxWidth *= scale; h1 *= scale;
+
+ if (y + h1 > Minecraft.getMinecraft().displayHeight)
+ y = Minecraft.getMinecraft().displayHeight - h1;
+ if (x + maxWidth > Minecraft.getMinecraft().displayWidth)
+ x = Minecraft.getMinecraft().displayWidth - maxWidth;
+ setBounds(new Rectangle(x,y,maxWidth, h1));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor);
+ int radius = 7;
+ double deltaDegree = Math.PI/6;
+ Dimension effectiveDim = getEffectiveDimension();
+ RenderUtils.drawRoundedRectangle(0,0,effectiveDim.width,effectiveDim.height,radius,deltaDegree, RenderUtils.blendAlpha(0x121212, 0.0f));
+ for (int i = 1; i < getChildComponents().size(); i++) {
+ MPanel childComponent = getChildComponents().get(i);
+ Gui.drawRect(7,childComponent.getBounds().y - 4, effectiveDim.width-7, childComponent.getBounds().y - 3, RenderUtils.blendAlpha(0x121212, 0.10f));
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (!lastAbsClip.contains(absMouseX, absMouseY)) {
+ close();
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPortableColorEdit.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPortableColorEdit.java
new file mode 100644
index 00000000..d86a07ee
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MPortableColorEdit.java
@@ -0,0 +1,292 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.Getter;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.MathHelper;
+import org.apache.commons.lang3.StringUtils;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public class MPortableColorEdit extends MTooltip {
+
+ private final float[] hsv = new float[3];
+ private float alpha = 0;
+ private float chromaSpeed = 0;
+
+ @Getter
+ private AColor color;
+
+ private final MTextField textField;
+
+ public MPortableColorEdit() {
+ textField = new MTextField() {
+ @Override
+ public void edit(String str) {
+ if (str.length() >= 7 && str.startsWith("#")) {
+ String color = str.substring(1);
+ try {
+ long colorInt = Long.parseLong(color, 16);
+
+ Color.RGBtoHSB((int) (colorInt >> 16) & 0xFF, (int) (colorInt >> 8) & 0xFF, (int) colorInt & 0xFF, hsv);
+ if (color.length() >= 8)
+ alpha = ((int) ((colorInt >> 24) & 0xFF)) / 255.0f;
+ update2();
+ } catch (Exception e) {}
+ }
+ }
+ };
+ add(textField);
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ super.onBoundsUpdate();
+
+ textField.setBounds(new Rectangle(5, getEffectiveDimension().height - 25, getEffectiveDimension().width - 10, 20));
+ }
+
+ public void setColor(AColor color) {
+ this.color = color;
+
+ alpha = color.getAlpha() / 255.0f;
+ chromaSpeed = color.isChroma() ? color.getChromaSpeed() : 0;
+ Color.RGBtoHSB(color.getRed(), color.getBlue(), color.getGreen(), hsv);
+
+ int rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]);
+ rgb = (rgb & 0xFFFFFF) | ((int)(alpha * 255) << 24);
+ textField.setText("#" + StringUtils.leftPad(Integer.toHexString(rgb).toUpperCase(), 8, '0'));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ Dimension size = getEffectiveDimension();
+
+ Gui.drawRect(0,0,size.width,size.height, 0xff333333);
+ Gui.drawRect(1,1,size.width-1,size.height-1, 0xffa1a1a1);
+
+ int width = size.height- 35;
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL);
+ GlStateManager.shadeModel(GL11.GL_SMOOTH);
+ GlStateManager.enableBlend();
+ GlStateManager.disableDepth();
+ GlStateManager.disableTexture2D();
+ GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ // worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR);
+
+ int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1);
+ float r = (rgb >> 16 & 255) / 255.0f;
+ float g = (rgb >> 8 & 255) / 255.0f;
+ float b = (rgb & 255) / 255.0f;
+ GL11.glBegin(GL11.GL_TRIANGLES);
+ GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(15+width ,5, 0);
+ GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(10+width , 5, 0);
+ GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(15+width , 5+width, 0);
+
+ GlStateManager.color(0,0,0,alpha); GL11.glVertex3i(10+width , 5, 0);
+ GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(10+width , 5 + width, 0);
+ GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(15+width , 5+width, 0);
+ GL11.glEnd();
+ rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]);
+ r = (rgb >> 16 & 255) / 255.0f;
+ g = (rgb >> 8 & 255) / 255.0f;
+ b = (rgb & 255) / 255.0f;
+ GL11.glBegin(GL11.GL_TRIANGLES);
+ GlStateManager.color(r,g,b,0);GL11.glVertex3i(25+width ,5, 0);
+ GlStateManager.color(r,g,b,0);GL11.glVertex3i(20+width , 5, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 5+width, 0);
+
+ GlStateManager.color(r,g,b,0); GL11.glVertex3i(20+width , 5, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(20+width , 5+ width, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 5+width, 0);
+ GL11.glEnd();
+
+
+ GL11.glBegin(GL11.GL_TRIANGLES);
+ rgb = RenderUtils.getChromaColorAt(0,0, chromaSpeed, hsv[1], hsv[2], alpha);
+ r = (rgb >> 16 & 255) / 255.0f;
+ g = (rgb >> 8 & 255) / 255.0f;
+ b = (rgb & 255) / 255.0f;
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width ,5, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(30+width , 5, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 5+width, 0);
+
+ GlStateManager.color(r,g,b,1); GL11.glVertex3i(30+width , 5, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(30+width , 5+ width, 0);
+ GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 5+width, 0);
+ GL11.glEnd();
+
+
+
+ float radius = width/2f;
+ float cx = 5 + radius;
+ float cy = 5 + radius;
+
+ GL11.glBegin(GL11.GL_TRIANGLE_FAN);
+ GlStateManager.color(1,1,1,alpha);
+ GL11.glVertex3f(cx,cy,0);
+ for (int i = 0; i <= 360; i++) {
+ float rad = 3.141592653f * i / 180;
+ int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]);
+ float r2 = (rgb2 >> 16 & 255) / 255.0f;
+ float g2 = (rgb2 >> 8 & 255) / 255.0f;
+ float b2 = (rgb2 & 255) / 255.0f;
+ GlStateManager.color(r2,g2,b2, alpha);
+ GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0);
+ }
+ GL11.glEnd();
+ GlStateManager.shadeModel(shademodel);
+
+ GlStateManager.color(1,1,1,1);
+ worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION);
+ float rad2 = 2 * 3.141592653f * hsv[0] ;
+ float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius;
+ float y = 5 + radius + (MathHelper.cos(rad2))* hsv[1] * radius;
+ for (int i = 0; i < 100; i++) {
+ float rad = 2 * 3.141592653f * (i / 100f);
+ worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex();
+ }
+ tessellator.draw();
+
+ worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(8+width, 5 + (hsv[2]) * width, 0.5).endVertex();
+ worldrenderer.pos(17+width, 5 + (hsv[2]) * width, 0.5).endVertex();
+ tessellator.draw();
+
+ worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(18+width, 5 + (alpha) * width, 0.5).endVertex();
+ worldrenderer.pos(27+width, 5 + (alpha) * width, 0.5).endVertex();
+ tessellator.draw();
+
+ worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(28+width, 5 + (chromaSpeed) * width, 0.5).endVertex();
+ worldrenderer.pos(37+width, 5 + (chromaSpeed) * width, 0.5).endVertex();
+ tessellator.draw();
+
+ GlStateManager.enableTexture2D();
+ GlStateManager.disableBlend();
+ GlStateManager.color(1,1,1,1);
+ GlStateManager.color(1,1,1,1);
+ }
+
+ private int selected = 0;
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ int width = getEffectiveDimension().height- 35;
+ float radius = width / 2f;
+ float circleX = 5 + radius;
+ float circleY = 5 + radius;
+
+ selected = 0;
+ if (!lastAbsClip.contains(absMouseX, absMouseY)) {
+ close();
+ return;
+ }
+
+ {
+ // check circle
+ float dx = relMouseX - circleX;
+ float dy = circleY - relMouseY;
+ if (dx * dx + dy * dy <= radius * radius) {
+ double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180+90) % 360;
+ hsv[0] = (float) theta / 360f;
+ hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius;
+ selected = 1;
+ }
+ }
+ {
+ if (10+width <= relMouseX && relMouseX <= 15 + width &&
+ 5 <= relMouseY && relMouseY <= 5 + width) {
+ hsv[2] = (relMouseY - 5) / (float)width;
+ selected = 2;
+ }
+ }
+ {
+ if (20+width <= relMouseX && relMouseX <= 25 + width &&
+ 5 <= relMouseY && relMouseY <= 5 + width) {
+ alpha = (relMouseY - 5) / (float)width;
+ selected = 3;
+ }
+ }
+ {
+ if (30+width <= relMouseX && relMouseX <= 35 + width &&
+ 5 <= relMouseY && relMouseY <= 5 + width) {
+ chromaSpeed = (relMouseY - 5) / (float)width;
+ selected = 4;
+ }
+ }
+ update();
+ }
+
+ @Override
+ public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+ int width = getEffectiveDimension().height- 35;
+ float radius = width / 2f;
+ float circleX = 5 + radius;
+ float circleY = 5 + radius;
+ {
+ // check circle
+ float dx = relMouseX - circleX; // sin theta
+ float dy = circleY - relMouseY; // cos theta
+ if (selected == 1) {
+ double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180+90) % 360;
+ hsv[0] = (float) theta / 360f;
+ hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1);
+ }
+ }
+ {
+ if (selected == 2) {
+ hsv[2] = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1);
+ }
+ if (selected == 3) {
+ alpha = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1);
+ }
+ if (selected == 4) {
+ chromaSpeed = MathHelper.clamp_float((relMouseY - 5) / (float)width, 0, 1);
+ }
+ }
+ update();
+ }
+
+
+ public void update() {
+ int rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]);
+ rgb = (rgb & 0xFFFFFF) | ((int)(alpha * 255) << 24);
+ textField.setText("#" + StringUtils.leftPad(Integer.toHexString(rgb).toUpperCase(), 8, '0'));
+ update2();
+ }
+
+ public void update2() {
+ color = new AColor(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0xffffff | (MathHelper.clamp_int((int)(alpha * 255), 0, 255) << 24), true);
+ color.setChromaSpeed(chromaSpeed);
+ color.setChroma(chromaSpeed != 0);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MRootPanel.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MRootPanel.java
new file mode 100644
index 00000000..949dd0d3
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MRootPanel.java
@@ -0,0 +1,60 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@Getter
+public class MRootPanel extends MPanel {
+ @Getter
+ private List<MTooltip> tooltips = new CopyOnWriteArrayList<>();
+
+
+ @Override
+ public void openTooltip(MTooltip mPanel) {
+ mPanel.setRoot(this);
+ tooltips.add(mPanel);
+ mPanel.resize(getBounds().width, getBounds().height);
+ add(mPanel);
+ }
+
+ @Override
+ public int getTooltipsOpen() {
+ return tooltips.size();
+ }
+
+ public void removeTooltip(MTooltip mTooltip) {
+ mTooltip.setRoot(null);
+ tooltips.remove(mTooltip);
+ remove(mTooltip);
+ }
+
+ @Getter @Setter
+ private EnumCursor currentCursor = EnumCursor.DEFAULT;
+ @Override
+ public void setCursor(EnumCursor enumCursor) {
+ currentCursor = enumCursor;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollBar.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollBar.java
new file mode 100644
index 00000000..e8ea25bd
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollBar.java
@@ -0,0 +1,209 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.util.MathHelper;
+
+import java.awt.*;
+
+public class MScrollBar extends MPanel {
+ private final Axis axis;
+
+ @Getter
+ private int thumbSize, max, min;
+ @Setter
+ @Getter
+ private int current;
+
+ @Getter
+ @Setter
+ private int width = 10;
+
+ public void setMax(int max) {
+ if (max < min) max = min;
+ this.max = max;
+
+ current = MathHelper.clamp_int(current, min, max);
+ if (onUpdate != null) onUpdate.run();
+ }
+
+ public void setMin(int min) {
+ if (max < min) max = min;
+ this.min = min;
+
+ current = MathHelper.clamp_int(current, min, max);
+ if (onUpdate != null) onUpdate.run();
+ }
+
+ public void setThumbSize(int thumbSize) {
+ this.thumbSize = thumbSize;
+
+ current = MathHelper.clamp_int(current, min, max);
+ if (onUpdate != null) onUpdate.run();
+ }
+
+ public void addToCurrent(int dv) {
+ int current2 = current + dv;
+
+ current = MathHelper.clamp_int(current2, min, max);
+
+ if (onUpdate != null) onUpdate.run();
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(axis == Axis.X ? -1 : width, axis == Axis.Y ? -1 : width);
+ }
+
+ @Getter
+ @Setter
+ private int background = RenderUtils.blendAlpha(0xFF141414, 0.04f),
+ thumb = RenderUtils.blendAlpha(0xFF141414, 0.14f),
+ thumbHover = RenderUtils.blendAlpha(0xFF141414, 0.15f),
+ thumbClick = RenderUtils.blendAlpha(0xFF141414, 0.20f);
+
+ private Runnable onUpdate;
+
+ public MScrollBar(int min, int max, int thumbSize, int current, Axis axis, Runnable onUpdate) {
+ if (max < min) max = min;
+ this.min = min; this.min = max; this.thumbSize = thumbSize; this.current = current; this.axis = axis;
+ this.current = MathHelper.clamp_int(current, min, max);
+ this.onUpdate = onUpdate;
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ super.setBounds(bounds);
+ lastThumbRect.width = 0; lastThumbRect.height = 0;
+ }
+
+ private Rectangle lastThumbRect = new Rectangle();
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ // RENDER SUPER NICE SCROLL BAR
+ int minimalThumbLen = 20;
+
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, background);
+ int length = axis == Axis.X ? bounds.width :bounds.height;
+ int totalUnscaledLength = max-min + thumbSize;
+ double subPoint = ((double)max-min) * length / totalUnscaledLength;
+ if (length - subPoint < minimalThumbLen) {
+ subPoint = length - minimalThumbLen;
+ }
+ double thumbSize = length - subPoint;
+
+ double startPt;
+ if (max - min == 0) {
+ startPt =0;
+ } else {
+ startPt = subPoint * (current - min)/((double)max - min);
+ }
+
+ int color = thumbHover;
+ if (getBounds().contains(relMousex0, relMousey0)) color = thumbHover;
+ if (grabbed) color = thumbClick;
+
+ if (axis == Axis.X) {
+ int startX = (int) startPt;
+ int endX = (int) (startPt + thumbSize);
+
+ Gui.drawRect(startX,0,endX,getBounds().height, color);
+ lastThumbRect.x = startX; lastThumbRect.y = 0; lastThumbRect.width = endX - startX; lastThumbRect.height = getBounds().height;
+ } else if (axis == Axis.Y) {
+ int startY = (int) startPt;
+ int endY = (int) (startPt + thumbSize);
+
+ Gui.drawRect(0,startY,getBounds().width,endY, color);
+ lastThumbRect.x = 0; lastThumbRect.y = startY; lastThumbRect.width = getBounds().width; lastThumbRect.height = endY - startY;
+ }
+ }
+
+ private int lastX;
+ private int lastY;
+ private int actualValue;
+ private boolean grabbed;
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (!lastAbsClip.contains(absMouseX, absMouseY)) return;
+ if (getTooltipsOpen() > 0) return;
+ grabbed = true;
+ actualValue = current;
+ lastX = absMouseX;
+ lastY = absMouseY;
+ }
+
+ @Override
+ public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+ if (!grabbed) return;
+
+ int minimalThumbLen = 20;
+
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, background);
+ int length = axis == Axis.X ? bounds.width :bounds.height;
+ int totalUnscaledLength = max-min + thumbSize;
+ double subPoint = ((double)max-min) * length / totalUnscaledLength;
+ if (length - subPoint < minimalThumbLen) {
+ subPoint = length - minimalThumbLen;
+ }
+ double thumbSize = length - subPoint;
+
+
+
+ int dx = absMouseX - lastX, dy = absMouseY - lastY;
+
+ lastX = absMouseX;
+ lastY = absMouseY;
+
+ int prevVal = current;
+ if (axis == Axis.Y) {
+ actualValue += dy * (max - min) / subPoint;
+ } else if (axis == Axis.X) {
+ actualValue += dx * (max - min) / subPoint;
+ }
+
+ current = MathHelper.clamp_int(actualValue, min, max);
+
+ if (onUpdate != null && prevVal != current) onUpdate.run();
+ }
+
+ @Override
+ public void mouseReleased(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int state) {
+ grabbed= false;
+ }
+
+ public static enum Axis {
+ X, Y
+ }
+
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ if (grabbed)
+ setCursor(EnumCursor.CLOSED_HAND);
+ else if (lastThumbRect.contains(relMouseX0, relMouseY0)) {
+ setCursor(EnumCursor.OPEN_HAND);
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollablePanel.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollablePanel.java
new file mode 100644
index 00000000..c791d7a2
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MScrollablePanel.java
@@ -0,0 +1,185 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import lombok.Getter;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.util.MathHelper;
+
+import java.awt.*;
+
+public class MScrollablePanel extends MPanel {
+ @Getter
+ private boolean hideScrollBarWhenNotNecessary = false;
+
+ public void setHideScrollBarWhenNotNecessary(boolean hideScrollBarWhenNotNecessary) {
+ this.hideScrollBarWhenNotNecessary = hideScrollBarWhenNotNecessary;
+ setBounds(getBounds());
+ }
+
+ private final int axis; // 1: Y 2: X 3: both.
+
+
+ private MPanel viewPort;
+ @Getter
+ private MPanel contentArea;
+ @Getter
+ private MScrollBar scrollBarX, scrollBarY;
+
+ private Rectangle contentAreaDim;
+
+ public MScrollablePanel(int axis) {
+ this.axis = axis;
+ viewPort = new MPanel();
+ scrollBarX = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.X, this::onScrollBarUpdate);
+ scrollBarY = new MScrollBar(0, 1, 1, 0, MScrollBar.Axis.Y, this::onScrollBarUpdate);
+
+ if ((axis & 1) > 0)
+ super.add(scrollBarY);
+ if ((axis & 2) > 0)
+ super.add(scrollBarX);
+ super.add(viewPort);
+
+
+ contentArea = new MPanel() {
+ @Override
+ public void add(MPanel child) {
+ super.add(child);
+ evalulateContentArea();
+ }
+
+ @Override
+ public void remove(MPanel panel) {
+ super.remove(panel);
+ evalulateContentArea();
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ if (bounds == null) return;
+ this.bounds.x = bounds.x;
+ this.bounds.y = bounds.y;
+ this.bounds.width = bounds.width;
+ this.bounds.height = bounds.height;
+
+ onBoundsUpdate();
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ for (MPanel childComponent : childComponents) {
+ childComponent.resize0(parentWidth, parentHeight);
+ }
+ evalulateContentArea();
+ }
+ };
+ viewPort.add(contentArea);
+ contentArea.setIgnoreBoundOnClip(true);
+ evalulateContentArea();
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ super.render(absMousex, absMousey, relMousex0, relMousey0, partialTicks, scissor);
+
+ boolean hideX = (axis & 2) == 0, hideY = (axis & 1) == 0;
+ if (bounds.width >= contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true;
+ if (bounds.height >= contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true;
+ if (axis == 3 && !(hideX && hideY)) {
+ Gui.drawRect(scrollBarX.getBounds().width, scrollBarY.getBounds().height, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.03f));
+ }
+ }
+
+ public void evalulateContentArea() {
+ if (contentArea.getChildComponents().size() == 0) {
+ contentAreaDim= new Rectangle(0,0,0,0);
+ return;
+ }
+ int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
+ for (MPanel childComponent : contentArea.getChildComponents()) {
+ Rectangle bounds = childComponent.getBounds();
+ if (bounds.x < minX) minX = bounds.x;
+ if (bounds.x + bounds.width > maxX) maxX = bounds.x + bounds.width;
+ if (bounds.y < minY) minY = bounds.y;
+ if (bounds.y + bounds.height > maxY) maxY = bounds.y + bounds.height;
+ }
+ contentAreaDim = new Rectangle(minX, minY, maxX - minX, maxY - minY);
+ scrollBarX.setMin(contentAreaDim.x);
+ scrollBarX.setMax(contentAreaDim.x + contentAreaDim.width-scrollBarX.getThumbSize());
+ scrollBarY.setMin(contentAreaDim.y);
+ scrollBarY.setMax(contentAreaDim.y + contentAreaDim.height-scrollBarY.getThumbSize());
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ super.setBounds(bounds);
+ boolean hideX = (axis & 2) == 0, hideY = (axis & 1) == 0;
+ viewPort.setBounds(new Rectangle(0,0,bounds.width, bounds.height));
+ evalulateContentArea();
+ if (bounds.width >= contentAreaDim.width && hideScrollBarWhenNotNecessary) hideX = true;
+ if (bounds.height >= contentAreaDim.height && hideScrollBarWhenNotNecessary) hideY = true;
+
+ if (!(hideX || hideY)) {
+ Dimension preferedX = scrollBarX.getPreferredSize();
+ Dimension preferedY = scrollBarY.getPreferredSize();
+ scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height - preferedX.height));
+ scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width - preferedY.width, preferedX.height));
+ } else if ((hideY && !hideX)) {
+ Dimension preferedX = scrollBarX.getPreferredSize();
+ scrollBarY.setBounds(new Rectangle(0,0,0,0));
+ scrollBarX.setBounds(new Rectangle(0, bounds.height - preferedX.height, bounds.width, preferedX.height));
+ } else if ((hideX && !hideY)) {
+ Dimension preferedY = scrollBarY.getPreferredSize();
+ scrollBarX.setBounds(new Rectangle(0,0,0,0));
+ scrollBarY.setBounds(new Rectangle(bounds.width - preferedY.width, 0, preferedY.width, bounds.height));
+ } else if (hideX && hideY){
+ scrollBarY.setBounds(new Rectangle(0,0,0,0));
+ scrollBarX.setBounds(new Rectangle(0,0,0,0));
+ }
+
+ viewPort.setBounds(new Rectangle(0,0,bounds.width-scrollBarY.getBounds().width, bounds.height - scrollBarX.getBounds().height));
+
+ scrollBarX.setThumbSize(viewPort.getBounds().width);
+ scrollBarY.setThumbSize(viewPort.getBounds().height);
+ scrollBarX.setMax(contentAreaDim.x + contentAreaDim.width-scrollBarX.getThumbSize());
+ scrollBarY.setMax(contentAreaDim.y + contentAreaDim.height-scrollBarY.getThumbSize());
+ evalulateContentArea();
+ }
+
+
+ private void onScrollBarUpdate() {
+ contentArea.setPosition(new Point(-scrollBarX.getCurrent(), -scrollBarY.getCurrent()));
+ }
+
+
+ @Override
+ public void add(MPanel child) { contentArea.add(child); }
+
+ @Override
+ public void remove(MPanel panel) { contentArea.remove(panel); }
+
+ @Override
+ public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {
+ if (lastAbsClip.contains(absMouseX, absMouseY) && (axis == 1 || axis == 3)) {
+ scrollBarY.addToCurrent(MathHelper.clamp_int(scrollAmount, -1, 1) * -30);
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MSpacer.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MSpacer.java
new file mode 100644
index 00000000..f891946e
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MSpacer.java
@@ -0,0 +1,36 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+
+import java.awt.*;
+
+public class MSpacer extends MPanel {
+
+ int width, height;
+ public MSpacer(int x, int y, int width, int height) {
+ setBounds(new Rectangle(x,y,width,height));
+ this.width = width; this.height = height;
+ }
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(width, height);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MStringSelectionButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MStringSelectionButton.java
new file mode 100755
index 00000000..92472180
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MStringSelectionButton.java
@@ -0,0 +1,94 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.awt.*;
+import java.util.List;
+
+@Getter
+@Setter
+public class MStringSelectionButton extends MPanel {
+
+ private List<String> possible;
+ private int selectedIndex;
+
+ private MButton dec;
+ private MButton inc;
+ private MLabel selected;
+
+ @Getter
+ @Setter
+ private Runnable onUpdate;
+
+ public MStringSelectionButton(final List<String> possible, String defaultValue) {
+ this.possible = possible;
+ selectedIndex = possible.indexOf(defaultValue);
+ if (selectedIndex == -1) selectedIndex = 0;
+
+ dec = new MButton(); dec.setText("<"); add(dec);
+ inc = new MButton(); inc.setText(">"); add(inc);
+ selected = new MLabel(); updateSelected(); add(selected);
+ selected.setBackgroundColor(Color.black);
+ selected.setAlignment(MLabel.Alignment.CENTER);
+
+ dec.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ selectedIndex --;
+ if (selectedIndex < 0) selectedIndex = possible.size() - 1;
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ inc.setOnActionPerformed(new Runnable() {
+ @Override
+ public void run() {
+ selectedIndex++;
+ if (selectedIndex >= possible.size()) selectedIndex = 0;
+ updateSelected();
+ onUpdate.run();
+ }
+ });
+ }
+
+ public String selectionToDisplay(String selection) {
+ return selection;
+ }
+
+ public String getSelected() {
+ if (possible.size() == 0) return null;
+ return possible.get(selectedIndex);
+ }
+
+ private void updateSelected() {
+ if (possible.size() == 0) selected.setText("-Empty-");
+ else selected.setText(selectionToDisplay(possible.get(selectedIndex)));
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ dec.setBounds(new Rectangle(0,0,getBounds().height, getBounds().height));
+ inc.setBounds(new Rectangle(getBounds().width - getBounds().height, 0, getBounds().height, getBounds().height));
+ selected.setBounds(new Rectangle(getBounds().height, 0, getBounds().width - getBounds().height - getBounds().height, getBounds().height));
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTabbedPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTabbedPane.java
new file mode 100755
index 00000000..ae06fb37
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTabbedPane.java
@@ -0,0 +1,160 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MTabbedPane extends MPanel {
+
+ private final Map<String, MPanel> tabs = new HashMap<String, MPanel>();
+ private final Map<String, MTabButton> buttons = new HashMap<String, MTabButton>();
+
+ @Getter
+ @Setter
+ private String selectedKey = "";
+
+ @Getter
+ private Color background2;
+
+ public void setBackground2(Color background2) {
+ this.background2 = background2;
+ for (MPanel value : tabs.values()) {
+ value.setBackgroundColor(background2);
+ }
+ for (MTabButton value : buttons.values()) {
+ value.setBackgroundColor(background2.brighter());
+ }
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ Gui.drawRect(0, 15, getBounds().width, getBounds().height, 0xFF444444);
+ }
+
+ public void addTab(String tab, MPanel panel) {
+ MPanel panel2 = new MPanel() ;
+ panel2.add(panel);
+ panel2.setBackgroundColor(background2);
+ tabs.put(tab, panel2);
+ panel2.setParent(this);
+ panel2.setBounds(new Rectangle(1,16,getBounds().width-2, getBounds().height-17));
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ MTabButton button = new MTabButton(this, tab);
+ int totalX = 0;
+ for (MTabButton button1:buttons.values())
+ totalX += button1.getBounds().width;
+ button.setBounds(new Rectangle(totalX, 0, Math.max(25, fr.getStringWidth(tab) + 6), 15));
+ buttons.put(tab, button);
+ if (tabs.size() == 1)
+ selectedKey = tab;
+ }
+
+ @Override
+ public List<MPanel> getChildComponents() {
+ ArrayList<MPanel> dynamic = new ArrayList<MPanel>(buttons.values());
+ dynamic.add(tabs.get(selectedKey));
+ return dynamic;
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ this.setBounds(new Rectangle(0,0,parentWidth, parentHeight));
+ for (MPanel ma:tabs.values())
+ ma.setBounds(new Rectangle(1,16,getBounds().width-2, getBounds().height-17));
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ if (bounds == null) return;
+ this.bounds.x = bounds.x;
+ this.bounds.y = bounds.y;
+ this.bounds.width = bounds.width;
+ this.bounds.height = bounds.height;
+ }
+
+ @Getter
+ @Setter
+ public static class MTabButton extends MPanel {
+ private String text;
+
+ private Color foreground = Color.white;
+ private Color hover = new Color(154, 154, 154, 255);
+ private Color clicked = new Color(88, 88, 88,255);
+ private Color selected = new Color(111, 111, 111,255);
+ private Color disabled = new Color(0,0,0);
+
+ private boolean enabled = true;
+
+ private MTabbedPane tabbedPane;
+
+ public MTabButton(MTabbedPane tabbedPane, String key) {
+ this.tabbedPane = tabbedPane;
+ this.text = key;
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ Color bg = null;
+ if (!enabled) {
+ bg = disabled;
+ } else if (tabbedPane.getSelectedKey().equals(text)) {
+ bg = selected;
+ } else if (new Rectangle(new Point(0,0),bounds).contains(relMousex0, relMousey0)) {
+ bg = hover;
+ }
+ Gui.drawRect(0, tabbedPane.getSelectedKey().equals(text) ? 0 : 2, getBounds().width, getBounds().height, 0xFF444444);
+ if (bg != null)
+ Gui.drawRect(1,tabbedPane.getSelectedKey().equals(text) ? 1 : 3,getBounds().width - 1, getBounds().height, bg.getRGB());
+
+ FontRenderer renderer = Minecraft.getMinecraft().fontRendererObj;
+ int width = renderer.getStringWidth(text);
+ int x = (getBounds().width - width) / 2;
+ int y = (getBounds().height - 3 - renderer.FONT_HEIGHT) / 2 + 3;
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ renderer.drawString(text, x,y, foreground.getRGB());
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (lastAbsClip.contains(absMouseX, absMouseY)) {
+ tabbedPane.setSelectedKey(text);
+ }
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTextField.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTextField.java
new file mode 100755
index 00000000..20378c20
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTextField.java
@@ -0,0 +1,418 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.MathHelper;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+
+@Getter
+public class MTextField extends MPanel {
+ private final Color foreground = Color.white;
+ private final Color placeHolderColor = Color.lightGray;
+
+ private String text = "";
+ @Setter
+ private String placeHolder = "";
+ private int cursorBlickTicker = 0;
+
+ private int selectionStart = 0;
+ private int selectionEnd = 0;
+
+ private int cursor = 0;
+
+ private int xOffset = 0;
+
+ public void edit(String str) {
+
+ }
+
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(-1,15);
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+ private void setText0(String text) {
+ this.text = text;
+ edit(text);
+ }
+
+ private void setCursor0(int cursor) {
+ if (cursor > text.length()) cursor = text.length();
+ if (cursor < 0) cursor = 0;
+ this.cursor = cursor;
+
+
+ int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text.substring(0, cursor));
+ int cursorX = width + 3- xOffset;
+ cursorX = MathHelper.clamp_int(cursorX,10, getBounds().width - 10);
+ xOffset = width+ 3 - cursorX;
+ xOffset = MathHelper.clamp_int(xOffset, 0,Math.max(0, Minecraft.getMinecraft().fontRendererObj.getStringWidth(text) - getBounds().width+10));
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ clip(clip.x - 1, clip.y - 1, clip.width +2, clip.height + 2);
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, isFocused ? Color.white.getRGB() : Color.gray.getRGB());
+ Gui.drawRect(1,1,getBounds().width - 1, getBounds().height - 1, Color.black.getRGB());
+
+ Minecraft mc = Minecraft.getMinecraft();
+ clip(clip.x + 1, clip.y + 1, clip.width - 2, clip.height - 2);
+ FontRenderer fr = mc.fontRendererObj;
+ int y = (getBounds().height - fr.FONT_HEIGHT) / 2;
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ fr.drawString(text, 3 - xOffset, y, foreground.getRGB());
+ if (text.isEmpty())
+ fr.drawString(placeHolder, 3, y, placeHolderColor.getRGB());
+ // draw selection
+ if (isFocused) {
+ if (selectionStart != -1) {
+ int startX = fr.getStringWidth(text.substring(0, selectionStart)) - xOffset;
+ int endX = fr.getStringWidth(text.substring(0, selectionEnd)) - xOffset;
+ Gui.drawRect(3 + startX, y, 3 + endX, y + fr.FONT_HEIGHT, 0xFF00FF00);
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ fr.drawString(text.substring(selectionStart, selectionEnd), 3 + startX, y, foreground.getRGB());
+ }
+
+ // draw cursor
+ if (cursor != -1) {
+ if (cursor > text.length()) setCursor0(text.length());
+ int x = fr.getStringWidth(text.substring(0, cursor)) - xOffset;
+ cursorBlickTicker++;
+ if (cursorBlickTicker < 10)
+ Gui.drawRect(3 + x, y, 4 + x, y + fr.FONT_HEIGHT, 0xFFFFFFFF);
+ if (cursorBlickTicker == 20) cursorBlickTicker = 0;
+ }
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ Rectangle actualField = new Rectangle(1, 3,getBounds().width - 2, getBounds().height - 6);
+ if (!actualField.contains(relMouseX, relMouseY)) return;
+ if (!lastAbsClip.contains(absMouseX, absMouseY)) return;
+ if (getTooltipsOpen() > 0) return;
+
+
+
+ int relStartT = relMouseX-3;
+ int offseted = relStartT + xOffset;
+
+ selectionStart = -1;
+
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+
+ for (int i = 0; i < text.length(); i++) {
+ int totalWidth = fr.getStringWidth(text.substring(0, i));
+ if (offseted < totalWidth) {
+ setCursor0(i);
+ return;
+ }
+ }
+ setCursor0(text.length());
+ }
+
+ @Override
+ public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+ if (!isFocused) return;
+ selectionStart = cursor;
+ selectionEnd = cursor;
+
+ int relStartT = relMouseX-3;
+ int offseted = relStartT + xOffset;
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+
+ for (int i = 0; i < text.length(); i++) {
+ int totalWidth = fr.getStringWidth(text.substring(0, i));
+ if (offseted < totalWidth) {
+ if (i < cursor) {
+ selectionStart = i;
+ selectionEnd = cursor;
+ } else {
+ selectionStart = cursor;
+ selectionEnd = i;
+ }
+ return;
+ }
+ }
+ selectionEnd = text.length();
+ if (selectionStart == selectionEnd) {
+ selectionStart = -1;
+ }
+ }
+
+ @Override
+ public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {
+ if (!isFocused) return;
+ if (scrollAmount > 0) {
+ xOffset += 5;
+ } else if (scrollAmount < 0){
+ xOffset -= 5;
+ }
+ if (xOffset < 0) {
+ xOffset = 0;
+ }
+ int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text);
+ int overflow = getBounds().width - 3 - width;
+ if (overflow >= 0) {
+ xOffset = 0;
+ } else if (width - xOffset + 10 < getBounds().width) {
+ xOffset = width - getBounds().width+10;
+ }
+ }
+
+ @Override
+ public void keyHeld(char typedChar, int keyCode) {
+ if (!isFocused) return;
+ this.keyPressed(typedChar, keyCode);
+ }
+
+ @Override
+ public void keyPressed(char typedChar, int keycode) {
+ if (!isFocused) return;
+
+ if (selectionStart == -1) {
+ if (keycode == 199) { // home
+ setCursor0(0);
+ xOffset = 0;
+ return;
+ }
+
+ if (keycode == 207) { // end
+ setCursor0(text.length());
+
+ int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text);
+ xOffset = Integer.max(0, width - getBounds().width+10);
+ return;
+ }
+
+ if (keycode == 203) { // left
+ setCursor0(this.cursor-1);;
+ if (cursor < 0) setCursor0(0);
+ return;
+ }
+
+ if (keycode == 205) { // right
+ setCursor0(this.cursor+1);
+ if (cursor > text.length()) setCursor0(text.length());
+ return;
+ }
+
+ // backspace
+ if (keycode == 14 && cursor > 0) {
+ setText0(this.text.substring(0, cursor-1) + this.text.substring(cursor));
+ setCursor0(this.cursor-1);
+ return;
+ }
+
+ //del
+ if (keycode == 211 && cursor < text.length()) {
+ setText0(this.text.substring(0, cursor) + this.text.substring(cursor+1));
+ return;
+ }
+
+ // paste
+ boolean shouldPaste = false;
+ if (keycode == 47) {
+ if (Minecraft.isRunningOnMac) { // mac
+ if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) {
+ shouldPaste = true;
+ }
+ } else { // literally everything else
+ if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) {
+ shouldPaste = true;
+ }
+ }
+ }
+ if (shouldPaste) {
+ Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+ if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+ try {
+ Object theText = transferable.getTransferData(DataFlavor.stringFlavor);
+ setText0(
+ this.text.substring(0, this.cursor)
+ + theText
+ + this.text.substring(this.cursor));
+
+ cursor += theText.toString().length();
+ } catch (UnsupportedFlavorException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return;
+ }
+
+ // text
+ if (isPrintableChar(typedChar)) {
+ setText0(
+ this.text.substring(0, this.cursor)
+ + typedChar
+ + this.text.substring(this.cursor));
+ this.setCursor0(this.cursor+1);;
+ return;
+ }
+ } else {
+ if (keycode == 199) { // home
+ setCursor0(0);
+ selectionStart = -1;
+ xOffset =0;
+ return;
+ }
+
+ if (keycode == 207) { // end
+ selectionStart = -1;
+ setCursor0(text.length());
+ int width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(text);
+ xOffset = Integer.max(0, width - getBounds().width+10);
+ return;
+ }
+
+ if (keycode == 203) { // left
+ setCursor0(selectionStart);
+ selectionStart = -1;
+ return;
+ }
+
+ if (keycode == 205) { // right
+ setCursor0(selectionEnd);
+ selectionStart = -1;
+ return;
+ }
+
+ // backspace
+ if (keycode == 14 && cursor > 0) {
+ setText0(this.text.substring(0, selectionStart) + this.text.substring(selectionEnd));
+ setCursor0(selectionStart);
+ selectionStart = -1;
+ return;
+ }
+
+ //del
+ if (keycode == 211 && cursor < text.length()) {
+ setText0(this.text.substring(0, selectionStart) + this.text.substring(selectionEnd));
+ setCursor0(selectionStart);
+ selectionStart = -1;
+ return;
+ }
+
+ // paste
+ boolean shouldPaste = false;
+ if (keycode == 47) {
+ if (Minecraft.isRunningOnMac) { // mac
+ if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) {
+ shouldPaste = true;
+ }
+ } else { // literally everything else
+ if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) {
+ shouldPaste = true;
+ }
+ }
+ }
+ if (shouldPaste) {
+ Transferable transferable = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+ if (transferable != null && transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+ try {
+ Object theText = transferable.getTransferData(DataFlavor.stringFlavor);
+ setText0(
+ this.text.substring(0, this.selectionStart)
+ + theText
+ + this.text.substring(this.selectionEnd));
+ setCursor0(this.selectionStart + theText.toString().length());
+ } catch (UnsupportedFlavorException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ selectionStart = -1;
+ }
+ return;
+ }
+ boolean shouldCopy = false;
+ if (keycode == 46) {
+ if (Minecraft.isRunningOnMac) { // mac
+ if (Keyboard.isKeyDown(219) || Keyboard.isKeyDown(220)) {
+ shouldCopy = true;
+ }
+ } else { // literally everything else
+ if (Keyboard.isKeyDown(29) || Keyboard.isKeyDown(157)) {
+ shouldCopy = true;
+ }
+ }
+ }
+ if (shouldCopy) {
+ StringSelection selection = new StringSelection(text.substring(selectionStart, selectionEnd));
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(selection, selection);
+ return;
+ }
+
+ // text
+ if (isPrintableChar(typedChar)) {
+ setText0(
+ this.text.substring(0, this.selectionStart)
+ + typedChar
+ + this.text.substring(this.selectionEnd));
+ this.setCursor0(this.selectionStart + 1);
+ selectionStart = -1;
+ return;
+ }
+ }
+ }
+ public boolean isPrintableChar( char c ) {
+ Character.UnicodeBlock block = Character.UnicodeBlock.of( c );
+ return (!Character.isISOControl(c)) &&
+ c != KeyEvent.CHAR_UNDEFINED &&
+ block != null &&
+ block != Character.UnicodeBlock.SPECIALS;
+ }
+
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ if (lastAbsClip.contains(absMouseX, absMouseY))
+ setCursor(EnumCursor.BEAM_CURSOR);
+ }
+
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MToggleButton.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MToggleButton.java
new file mode 100755
index 00000000..ee336d77
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MToggleButton.java
@@ -0,0 +1,96 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+
+@Getter
+@Setter
+public class MToggleButton extends MPanel {
+ private boolean enabled = true;
+ private Runnable onToggle;
+
+ private int border = 0xFF333333, background = 0xFF171717;
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) {
+ Dimension bounds = getSize();
+
+ int gap = 1;
+
+ Gui.drawRect(0, 0, bounds.width, bounds.height, border);
+ Gui.drawRect(gap, gap, bounds.width-gap, bounds.height-gap, background);
+
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ double scale = 1;
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ if (enabled) {
+ int x = (int) ((scale * bounds.height - fr.FONT_HEIGHT)/2 + gap);
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(1.0/scale,1.0/scale,0);
+ fr.drawString("ON", x, x, 0xFF9B9B9B);
+ GlStateManager.popMatrix();
+ Gui.drawRect(bounds.width - bounds.height+gap,gap, bounds.width - gap, bounds.height - gap, 0xFF00B200);
+ } else {
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(1.0/scale,1.0/scale,0);
+ int x = (int) ((scale * bounds.height - fr.FONT_HEIGHT)/2 + gap);
+ fr.drawString("OFF", (int) (scale * bounds.width - x - fr.getStringWidth("OFF")), x, 0xFF9B9B9B);
+ GlStateManager.popMatrix();
+ Gui.drawRect(gap,gap, bounds.height - gap, bounds.height - gap, 0xFFCD4000);
+ }
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(40,15);
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (onToggle != null && lastAbsClip.contains(absMouseX, absMouseY) && getTooltipsOpen() == 0) {
+ enabled = !enabled;
+ Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+ onToggle.run();
+ }
+ }
+
+
+ @Override
+ public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
+ if (lastAbsClip.contains(absMouseX, absMouseY))
+ setCursor(EnumCursor.POINTING_HAND);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltip.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltip.java
new file mode 100644
index 00000000..b11afb04
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltip.java
@@ -0,0 +1,107 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+
+public class MTooltip extends MPanelScaledGUI {
+ @Getter @Setter
+ private MRootPanel root;
+
+ public void open(MPanel component) {
+ if (root == null)
+ component.openTooltip(this);
+ }
+ public void close() {
+ if (root != null)
+ root.removeTooltip(this);
+ }
+
+
+ public boolean isOpen() {
+ return root != null;
+ }
+
+ @Override
+ public int getTooltipsOpen() {
+ return super.getTooltipsOpen() - 1;
+ }
+
+ @Override
+ public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) {
+ lastParentPoint = parentPoint;
+
+ GlStateManager.translate(getBounds().x, getBounds().y, 300);
+ GlStateManager.color(1,1,1,1);
+
+ Rectangle absBound = getBounds().getBounds();
+ absBound.setLocation(absBound.x + parentPoint.x, absBound.y + parentPoint.y);
+
+ Rectangle clip = absBound;
+ lastAbsClip = clip;
+
+ if (clip.getSize().height * clip.getSize().width == 0) return;
+
+ int absMousex = (int) (absMousex0 / scale), absMousey = (int) (absMousey0 / scale);
+ int relMousex = (int) ((relMousex0 - getBounds().x) / scale);
+ int relMousey = (int) ((relMousey0 - getBounds().y) /scale);
+
+ // FROM HERE, IT IS SCALED
+
+ GlStateManager.scale(this.scale, this.scale, 1);
+ clip = new Rectangle((int) (clip.x / scale), (int) (clip.y / scale), (int) (clip.width / scale), (int) (clip.height / scale));
+ lastAbsClip = clip;
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ this.relativeScale = parentScale * this.scale;
+ clip(clip.x, clip.y, clip.width, clip.height);
+
+
+ GuiScreen.drawRect(0,0, (int) (getBounds().width / scale), (int) (getBounds().height / scale), backgroundColor.getRGB());
+ GlStateManager.enableBlend();
+
+
+ GlStateManager.pushMatrix();
+
+ render(absMousex, absMousey, relMousex, relMousey, partialTicks, clip);
+
+ GlStateManager.popMatrix();
+
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+
+
+ Point newPt = new Point((int) ((parentPoint.x + getBounds().x) / scale), (int) ((parentPoint.y + getBounds().y) / scale));
+
+ for (MPanel mPanel : getChildComponents()){
+ GlStateManager.pushMatrix();
+
+ mPanel.render0(relativeScale, newPt,clip,absMousex, absMousey, relMousex, relMousey, partialTicks);
+
+ GlStateManager.popMatrix();
+ }
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltipText.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltipText.java
new file mode 100644
index 00000000..8ea9068f
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MTooltipText.java
@@ -0,0 +1,44 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraftforge.fml.client.config.GuiUtils;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@AllArgsConstructor
+public class MTooltipText extends MTooltip {
+ @Getter @Setter
+ private List<String> tooltipText = new ArrayList<>();
+ @Override
+ public Rectangle getBounds() {
+ return new Rectangle(0,0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ GuiUtils.drawHoveringText(tooltipText, relMousex0, relMousey0, (int) (Minecraft.getMinecraft().displayWidth/getRelativeScale()), (int) (Minecraft.getMinecraft().displayHeight/getRelativeScale()), -1, Minecraft.getMinecraft().fontRendererObj);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MValue.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MValue.java
new file mode 100755
index 00000000..1a251dc0
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/elements/MValue.java
@@ -0,0 +1,79 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.mod.gui.elements;
+
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext;
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonValueEdit;
+import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditOffsetPointSet;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.gui.Gui;
+
+import java.awt.*;
+import java.util.List;
+public class MValue<T> extends MPanel {
+ @Getter
+ private final T data;
+ private ValueEditOffsetPointSet valueEditOffsetPointSet;
+ private final MLabel dataLab;
+
+ @Getter @Setter
+ private Color hover = Color.gray;
+
+ private final List<MPanel> addons;
+
+ public MValue(final T parameter, List<MPanel> addons) {
+ this.addons = addons;
+ this.add(this.dataLab = new MLabel() {
+ @Override
+ public String getText() {
+ return data != null ?data.toString() :"-empty-";
+ }
+ });
+ this.dataLab.setAlignment(MLabel.Alignment.RIGHT);
+
+ this.data = parameter;
+ }
+
+ @Override
+ public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
+ if (hover != null && new Rectangle(new Point(0,0),getBounds().getSize()).contains(relMousex0, relMousey0)) {
+ Gui.drawRect(0,0,getBounds().width, getBounds().height, hover.getRGB());
+ }
+ }
+
+ @Override
+ public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
+ if (this.getBounds().x > -20 && lastAbsClip.contains(absMouseX, absMouseY)) {
+ EditingContext.getEditingContext().openGui(new GuiDungeonValueEdit(data, addons));
+ }
+ }
+
+ @Override
+ public void resize(int parentWidth, int parentHeight) {
+ this.setSize(new Dimension(parentWidth, getBounds().height));
+ dataLab.setBounds(new Rectangle(0,0,parentWidth, getBounds().height));
+ }
+
+ @Override
+ public void onBoundsUpdate() {
+ dataLab.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height));
+ }
+}