diff options
author | Eryk Ruta <70776766+kingstefan26@users.noreply.github.com> | 2022-11-01 15:51:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-01 23:51:30 +0900 |
commit | 292fbd05e13271ca3ad99ebe00ae4302e04848f3 (patch) | |
tree | 2a7aeb12ab95ff688479a4727f76e3e4152c30b5 /src/main/java/kr/syeyoung/dungeonsguide/mod/gui | |
parent | dd7a4209752715db544b2fef804da9762c532cdc (diff) | |
download | Skyblock-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')
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)); + } +} |