aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/thatgravyboat/skyblockhud/core
diff options
context:
space:
mode:
authorThatGravyBoat <thatgravyboat@gmail.com>2021-07-06 15:10:29 -0230
committerThatGravyBoat <thatgravyboat@gmail.com>2021-07-06 15:10:29 -0230
commit6d8e1e5659f64a4f9ba86d6ab5bbc8e688faf22a (patch)
tree7451e53ceeae3c324d83a7faba83ce80005e6f23 /src/main/java/com/thatgravyboat/skyblockhud/core
downloadskyblockhud-6d8e1e5659f64a4f9ba86d6ab5bbc8e688faf22a.tar.gz
skyblockhud-6d8e1e5659f64a4f9ba86d6ab5bbc8e688faf22a.tar.bz2
skyblockhud-6d8e1e5659f64a4f9ba86d6ab5bbc8e688faf22a.zip
Initial Commit
Diffstat (limited to 'src/main/java/com/thatgravyboat/skyblockhud/core')
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/BackgroundBlur.java231
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/ChromaColour.java95
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GlScissorStack.java87
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GuiElement.java8
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementBoolean.java121
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementColour.java368
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementTextField.java534
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/GuiScreenElementWrapper.java35
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/Config.java8
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/Position.java196
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/Category.java15
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigAccordionId.java14
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorAccordion.java14
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorBoolean.java12
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorButton.java15
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorColour.java13
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorDraggableList.java14
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorDropdown.java16
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorSlider.java18
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigEditorText.java13
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/annotations/ConfigOption.java17
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditor.java62
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorAccordion.java82
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorBoolean.java38
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorButton.java64
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorColour.java71
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorDraggableList.java284
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorDropdown.java152
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorSlider.java132
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiOptionEditorText.java84
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/gui/GuiPositionEditor.java179
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/config/struct/ConfigProcessor.java176
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/GuiElementSlider.java123
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/MiscUtils.java104
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/Splitters.java10
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/StringUtils.java39
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/lerp/LerpUtils.java26
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/lerp/LerpingFloat.java68
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/lerp/LerpingInteger.java76
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/render/RenderUtils.java165
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/core/util/render/TextRenderUtils.java215
41 files changed, 3994 insertions, 0 deletions
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/BackgroundBlur.java b/src/main/java/com/thatgravyboat/skyblockhud/core/BackgroundBlur.java
new file mode 100644
index 0000000..6782052
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/BackgroundBlur.java
@@ -0,0 +1,231 @@
+package com.thatgravyboat.skyblockhud.core;
+
+import com.thatgravyboat.skyblockhud.core.util.render.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.util.Matrix4f;
+import net.minecraftforge.client.event.EntityViewRenderEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.opengl.GL11;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class BackgroundBlur {
+
+ private static HashMap<Float, Framebuffer> blurOutput = new HashMap<>();
+ private static HashMap<Float, Long> lastBlurUse = new HashMap<>();
+ private static long lastBlur = 0;
+ private static HashSet<Float> requestedBlurs = new HashSet<>();
+
+ private static int fogColour = 0;
+ private static boolean registered = false;
+ public static void registerListener() {
+ if(!registered) {
+ registered = true;
+ MinecraftForge.EVENT_BUS.register(new BackgroundBlur());
+ }
+ }
+
+ private static boolean shouldBlur = true;
+
+ public static void markDirty() {
+ if(Minecraft.getMinecraft().theWorld != null) {
+ shouldBlur = true;
+ }
+ }
+
+ public static void processBlurs() {
+ if(shouldBlur) {
+ shouldBlur = false;
+
+ long currentTime = System.currentTimeMillis();
+
+ for(float blur : requestedBlurs) {
+ lastBlur = currentTime;
+ lastBlurUse.put(blur, currentTime);
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ Framebuffer output = blurOutput.computeIfAbsent(blur, k -> {
+ Framebuffer fb = new Framebuffer(width, height, false);
+ fb.setFramebufferFilter(GL11.GL_NEAREST);
+ return fb;
+ });
+
+ output.framebufferWidth = output.framebufferTextureWidth = width;
+ output.framebufferHeight = output.framebufferTextureHeight = height;
+
+ blurBackground(output, blur);
+ }
+
+ Set<Float> remove = new HashSet<>();
+ for(Map.Entry<Float, Long> entry : lastBlurUse.entrySet()) {
+ if(currentTime - entry.getValue() > 30*1000) {
+ remove.add(entry.getKey());
+ }
+ }
+ remove.remove(5f);
+
+ lastBlurUse.keySet().removeAll(remove);
+ blurOutput.keySet().removeAll(remove);
+
+ requestedBlurs.clear();
+ }
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onScreenRender(RenderGameOverlayEvent.Pre event) {
+ if(event.type == RenderGameOverlayEvent.ElementType.ALL) {
+ processBlurs();
+ }
+ }
+
+ @SubscribeEvent
+ public void onFogColour(EntityViewRenderEvent.FogColors event) {
+ fogColour = 0xff000000;
+ fogColour |= ((int)(event.red*255) & 0xFF) << 16;
+ fogColour |= ((int)(event.green*255) & 0xFF) << 8;
+ fogColour |= (int)(event.blue*255) & 0xFF;
+ }
+
+ private static Shader blurShaderHorz = null;
+ private static Shader blurShaderVert = null;
+ private static Framebuffer blurOutputHorz = null;
+
+ /**
+ * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
+ * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
+ *
+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to
+ * apply scales and translations manually.
+ */
+ private static Matrix4f createProjectionMatrix(int width, int height) {
+ Matrix4f projMatrix = new Matrix4f();
+ projMatrix.setIdentity();
+ projMatrix.m00 = 2.0F / (float)width;
+ projMatrix.m11 = 2.0F / (float)(-height);
+ projMatrix.m22 = -0.0020001999F;
+ projMatrix.m33 = 1.0F;
+ projMatrix.m03 = -1.0F;
+ projMatrix.m13 = 1.0F;
+ projMatrix.m23 = -1.0001999F;
+ return projMatrix;
+ }
+
+ private static void blurBackground(Framebuffer output, float blurFactor) {
+ if(!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return;
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, width, height, 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ if(blurOutputHorz == null) {
+ blurOutputHorz = new Framebuffer(width, height, false);
+ blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputHorz == null || output == null) {
+ return;
+ }
+ if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
+ blurOutputHorz.createBindFramebuffer(width, height);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+
+ try {
+ blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz);
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch(Exception ignored) { }
+ try {
+ blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ blurOutputHorz, output);
+ blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch(Exception ignored) { }
+ if(blurShaderHorz != null && blurShaderVert != null) {
+ if(blurShaderHorz.getShaderManager().getShaderUniform("Radius") == null) {
+ //Corrupted shader?
+ return;
+ }
+
+ blurShaderHorz.getShaderManager().getShaderUniform("Radius").set(blurFactor);
+ blurShaderVert.getShaderManager().getShaderUniform("Radius").set(blurFactor);
+
+ GL11.glPushMatrix();
+ /*GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject);
+ GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, output.framebufferObject);
+ GL30.glBlitFramebuffer(0, 0, width, height,
+ 0, 0, output.framebufferWidth, output.framebufferHeight,
+ GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST);*/
+
+ blurShaderHorz.loadShader(0);
+ blurShaderVert.loadShader(0);
+ GlStateManager.enableDepth();
+ GL11.glPopMatrix();
+
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ }
+
+ public static void renderBlurredBackground(float blurStrength, int screenWidth, int screenHeight,
+ int x, int y, int blurWidth, int blurHeight) {
+ renderBlurredBackground(blurStrength, screenWidth, screenHeight, x, y, blurWidth, blurHeight, false);
+ }
+
+ /**
+ * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
+ * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
+ */
+ public static void renderBlurredBackground(float blurStrength, int screenWidth, int screenHeight,
+ int x, int y, int blurWidth, int blurHeight, boolean forcedUpdate) {
+ if(!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return;
+ if(blurStrength < 0.5) return;
+ requestedBlurs.add(blurStrength);
+
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastBlur > 300) {
+ shouldBlur = true;
+ if(currentTime - lastBlur > 400 && forcedUpdate) return;
+ }
+
+ if(blurOutput.isEmpty()) return;
+
+ Framebuffer fb = blurOutput.get(blurStrength);
+ if(fb == null) {
+ fb = blurOutput.values().iterator().next();
+ }
+
+ float uMin = x/(float)screenWidth;
+ float uMax = (x+blurWidth)/(float)screenWidth;
+ float vMin = (screenHeight-y)/(float)screenHeight;
+ float vMax = (screenHeight-y-blurHeight)/(float)screenHeight;
+
+ GlStateManager.depthMask(false);
+ Gui.drawRect(x, y, x+blurWidth, y+blurHeight, fogColour);
+ fb.bindFramebufferTexture();
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ RenderUtils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax);
+ fb.unbindFramebufferTexture();
+ GlStateManager.depthMask(true);
+ }
+
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/ChromaColour.java b/src/main/java/com/thatgravyboat/skyblockhud/core/ChromaColour.java
new file mode 100644
index 0000000..b9f4e79
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/ChromaColour.java
@@ -0,0 +1,95 @@
+package com.thatgravyboat.skyblockhud.core;
+
+import java.awt.*;
+
+public class ChromaColour {
+
+ public static String special(int chromaSpeed, int alpha, int rgb) {
+ return special(chromaSpeed, alpha, (rgb & 0xFF0000) >> 16, (rgb & 0x00FF00) >> 8, (rgb & 0x0000FF));
+ }
+
+ private static final int RADIX = 10;
+
+ public static String special(int chromaSpeed, int alpha, int r, int g, int b) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Integer.toString(chromaSpeed, RADIX)).append(":");
+ sb.append(Integer.toString(alpha, RADIX)).append(":");
+ sb.append(Integer.toString(r, RADIX)).append(":");
+ sb.append(Integer.toString(g, RADIX)).append(":");
+ sb.append(Integer.toString(b, RADIX));
+ return sb.toString();
+ }
+
+ private static int[] decompose(String csv) {
+ String[] split = csv.split(":");
+
+ int[] arr = new int[split.length];
+
+
+ for(int i=0; i<split.length; i++) {
+ arr[i] = Integer.parseInt(split[split.length-1-i], RADIX);
+ }
+ return arr;
+ }
+
+ public static int specialToSimpleRGB(String special) {
+ int[] d = decompose(special);
+ int r = d[2];
+ int g = d[1];
+ int b = d[0];
+ int a = d[3];
+ int chr = d[4];
+
+ return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
+ }
+
+ public static int getSpeed(String special) {
+ return decompose(special)[4];
+ }
+
+ public static float getSecondsForSpeed(int speed) {
+ return (255-speed)/254f*(MAX_CHROMA_SECS-MIN_CHROMA_SECS)+MIN_CHROMA_SECS;
+ }
+
+ private static final int MIN_CHROMA_SECS = 1;
+ private static final int MAX_CHROMA_SECS = 60;
+
+ public static long startTime = -1;
+ public static int specialToChromaRGB(String special) {
+ if(startTime < 0) startTime = System.currentTimeMillis();
+
+ int[] d = decompose(special);
+ int chr = d[4];
+ int a = d[3];
+ int r = d[2];
+ int g = d[1];
+ int b = d[0];
+
+ float[] hsv = Color.RGBtoHSB(r, g, b, null);
+
+ if(chr > 0) {
+ float seconds = getSecondsForSpeed(chr);
+ hsv[0] += (System.currentTimeMillis()-startTime)/1000f/seconds;
+ hsv[0] %= 1;
+ if(hsv[0] < 0) hsv[0] += 1;
+ }
+
+ return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
+ }
+
+ public static int rotateHue(int argb, int degrees) {
+ int a = (argb >> 24) & 0xFF;
+ int r = (argb >> 16) & 0xFF;
+ int g = (argb >> 8) & 0xFF;
+ int b = (argb) & 0xFF;
+
+ float[] hsv = Color.RGBtoHSB(r, g, b, null);
+
+ hsv[0] += degrees/360f;
+ hsv[0] %= 1;
+
+ return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
+ }
+
+
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/GlScissorStack.java b/src/main/java/com/thatgravyboat/skyblockhud/core/GlScissorStack.java
new file mode 100644
index 0000000..6f21e9a
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/GlScissorStack.java
@@ -0,0 +1,87 @@
+package com.thatgravyboat.skyblockhud.core;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import org.lwjgl.opengl.GL11;
+
+import java.util.LinkedList;
+
+public class GlScissorStack {
+
+ private static class Bounds {
+ int left;
+ int top;
+ int right;
+ int bottom;
+
+ public Bounds(int left, int top, int right, int bottom) {
+ this.left = left;
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ }
+
+ public Bounds createSubBound(int left, int top, int right, int bottom) {
+ left = Math.max(left, this.left);
+ top = Math.max(top, this.top);
+ right = Math.min(right, this.right);
+ bottom = Math.min(bottom, this.bottom);
+
+ if(top > bottom) {
+ top = bottom;
+ }
+ if(left > right) {
+ left = right;
+ }
+
+ return new Bounds(left, top, right, bottom);
+ }
+
+ public void set(ScaledResolution scaledResolution) {
+ int height = Minecraft.getMinecraft().displayHeight;
+ int scale = scaledResolution.getScaleFactor();
+ GL11.glScissor(left*scale, height-bottom*scale, (right-left)*scale, (bottom-top)*scale);
+ }
+ }
+
+ private static final LinkedList<Bounds> boundsStack = new LinkedList<>();
+
+ public static void push(int left, int top, int right, int bottom, ScaledResolution scaledResolution) {
+ if(right < left) {
+ int temp = right;
+ right = left;
+ left = temp;
+ }
+ if(bottom < top) {
+ int temp = bottom;
+ bottom = top;
+ top = temp;
+ }
+ if(boundsStack.isEmpty()) {
+ boundsStack.push(new Bounds(left, top, right, bottom));
+ } else {
+ boundsStack.push(boundsStack.peek().createSubBound(left, top, right, bottom));
+ }
+ if(!boundsStack.isEmpty()) {
+ boundsStack.peek().set(scaledResolution);
+ }
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ }
+
+ public static void pop(ScaledResolution scaledResolution) {
+ if(!boundsStack.isEmpty()) {
+ boundsStack.pop();
+ }
+ if(boundsStack.isEmpty()) {
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ } else {
+ boundsStack.peek().set(scaledResolution);
+ }
+ }
+
+ public static void clear() {
+ boundsStack.clear();
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }
+
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElement.java b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElement.java
new file mode 100644
index 0000000..94d2375
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElement.java
@@ -0,0 +1,8 @@
+package com.thatgravyboat.skyblockhud.core;
+
+public abstract class GuiElement {
+
+ public abstract void render();
+ public abstract boolean mouseInput(int mouseX, int mouseY);
+ public abstract boolean keyboardInput();
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementBoolean.java b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementBoolean.java
new file mode 100644
index 0000000..d403bef
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementBoolean.java
@@ -0,0 +1,121 @@
+package com.thatgravyboat.skyblockhud.core;
+
+import com.thatgravyboat.skyblockhud.core.util.lerp.LerpUtils;
+import com.thatgravyboat.skyblockhud.core.util.render.RenderUtils;
+import com.thatgravyboat.skyblockhud.GuiTextures;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Mouse;
+
+import java.util.function.Consumer;
+
+public class GuiElementBoolean extends GuiElement {
+
+ public int x;
+ public int y;
+ private boolean value;
+ private int clickRadius;
+ private Consumer<Boolean> toggleCallback;
+
+ private boolean previewValue;
+ private int animation = 0;
+ private long lastMillis = 0;
+
+ private static final int xSize = 48;
+ private static final int ySize = 14;
+
+ public GuiElementBoolean(int x, int y, boolean value, Consumer<Boolean> toggleCallback) {
+ this(x, y, value, 0, toggleCallback);
+ }
+
+ public GuiElementBoolean(int x, int y, boolean value, int clickRadius, Consumer<Boolean> toggleCallback) {
+ this.x = x;
+ this.y = y;
+ this.value = value;
+ this.previewValue = value;
+ this.clickRadius = clickRadius;
+ this.toggleCallback = toggleCallback;
+ this.lastMillis = System.currentTimeMillis();
+
+ if(value) animation = 36;
+ }
+
+ @Override
+ public void render() {
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.BAR);
+ RenderUtils.drawTexturedRect(x, y, xSize, ySize);
+
+ ResourceLocation buttonLoc = GuiTextures.ON;
+ long currentMillis = System.currentTimeMillis();
+ long deltaMillis = currentMillis - lastMillis;
+ lastMillis = currentMillis;
+ boolean passedLimit = false;
+ if(previewValue != value) {
+ if((previewValue && animation > 12) ||
+ (!previewValue && animation < 24)) {
+ passedLimit = true;
+ }
+ }
+ if(previewValue != passedLimit) {
+ animation += deltaMillis/10;
+ } else {
+ animation -= deltaMillis/10;
+ }
+ lastMillis -= deltaMillis%10;
+
+ if(previewValue == value) {
+ animation = Math.max(0, Math.min(36, animation));
+ } else if(!passedLimit) {
+ if(previewValue) {
+ animation = Math.max(0, Math.min(12, animation));
+ } else {
+ animation = Math.max(24, Math.min(36, animation));
+ }
+ } else {
+ if(previewValue) {
+ animation = Math.max(12, animation);
+ } else {
+ animation = Math.min(24, animation);
+ }
+ }
+
+ int animation = (int)(LerpUtils.sigmoidZeroOne(this.animation/36f)*36);
+ if(animation < 3) {
+ buttonLoc = GuiTextures.OFF;
+ } else if(animation < 13) {
+ buttonLoc = GuiTextures.ONE;
+ } else if(animation < 23) {
+ buttonLoc = GuiTextures.TWO;
+ } else if(animation < 33) {
+ buttonLoc = GuiTextures.THREE;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(buttonLoc);
+ RenderUtils.drawTexturedRect(x+animation, y, 12, 14);
+ }
+
+ @Override
+ public boolean mouseInput(int mouseX, int mouseY) {
+ if(mouseX > x-clickRadius && mouseX < x+xSize+clickRadius &&
+ mouseY > y-clickRadius && mouseY < y+ySize+clickRadius) {
+ if(Mouse.getEventButton() == 0) {
+ if(Mouse.getEventButtonState()) {
+ previewValue = !value;
+ } else if(previewValue == !value) {
+ value = !value;
+ toggleCallback.accept(value);
+ }
+ }
+ } else {
+ previewValue = value;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean keyboardInput() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementColour.java b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementColour.java
new file mode 100644
index 0000000..8774595
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/core/GuiElementColour.java
@@ -0,0 +1,368 @@
+package com.thatgravyboat.skyblockhud.core;
+
+import com.thatgravyboat.skyblockhud.core.util.render.RenderUtils;
+import com.thatgravyboat.skyblockhud.core.util.render.TextRenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.util.function.Consumer;
+
+public class GuiElementColour extends GuiElement {
+
+ public static final ResourceLocation colour_selector_dot = new ResourceLocation("skyblockhud:core/colour_selector_dot.png");
+ public static final ResourceLocation colour_selector_bar = new ResourceLocation("skyblockhud:core/colour_selector_bar.png");
+ public static final ResourceLocation colour_selector_bar_alpha = new ResourceLocation("skyblockhud:core/colour_selector_bar_alpha.png");
+ public static final Re