From a0ff501947a84b268e099524a06b56a6b900dad2 Mon Sep 17 00:00:00 2001 From: DeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com> Date: Tue, 3 May 2022 18:25:32 +0200 Subject: move to cc.polyfrost --- .../java/cc/polyfrost/oneconfig/gui/HudGui.java | 326 ++++++++++++++++ .../cc/polyfrost/oneconfig/gui/OneConfigGui.java | 231 ++++++++++++ .../java/cc/polyfrost/oneconfig/gui/SideBar.java | 67 ++++ .../oneconfig/gui/elements/BasicButton.java | 157 ++++++++ .../oneconfig/gui/elements/BasicElement.java | 107 ++++++ .../oneconfig/gui/elements/ColorSelector.java | 250 ++++++++++++ .../polyfrost/oneconfig/gui/elements/ModCard.java | 146 +++++++ .../oneconfig/gui/elements/SearchField.java | 14 + .../oneconfig/gui/elements/TextInputField.java | 418 +++++++++++++++++++++ .../gui/elements/config/ConfigCheckbox.java | 61 +++ .../gui/elements/config/ConfigColorElement.java | 115 ++++++ .../gui/elements/config/ConfigDropdown.java | 167 ++++++++ .../gui/elements/config/ConfigDualOption.java | 53 +++ .../gui/elements/config/ConfigPageButton.java | 57 +++ .../gui/elements/config/ConfigSlider.java | 184 +++++++++ .../gui/elements/config/ConfigSwitch.java | 54 +++ .../gui/elements/config/ConfigTextBox.java | 61 +++ .../gui/elements/config/ConfigUniSelector.java | 78 ++++ .../cc/polyfrost/oneconfig/gui/pages/HomePage.java | 28 ++ .../oneconfig/gui/pages/ModConfigPage.java | 152 ++++++++ .../cc/polyfrost/oneconfig/gui/pages/ModsPage.java | 76 ++++ .../cc/polyfrost/oneconfig/gui/pages/Page.java | 31 ++ 22 files changed, 2833 insertions(+) create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/HudGui.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/SideBar.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicButton.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicElement.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/ColorSelector.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/ModCard.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/SearchField.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/TextInputField.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigCheckbox.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigColorElement.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDropdown.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigDualOption.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigPageButton.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigSlider.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigSwitch.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigTextBox.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/elements/config/ConfigUniSelector.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/pages/HomePage.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/pages/ModConfigPage.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/pages/ModsPage.java create mode 100644 src/main/java/cc/polyfrost/oneconfig/gui/pages/Page.java (limited to 'src/main/java/cc/polyfrost/oneconfig/gui') diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/HudGui.java b/src/main/java/cc/polyfrost/oneconfig/gui/HudGui.java new file mode 100644 index 0000000..c3437fa --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/HudGui.java @@ -0,0 +1,326 @@ +package cc.polyfrost.oneconfig.gui; + +import cc.polyfrost.oneconfig.hud.HudCore; +import cc.polyfrost.oneconfig.hud.interfaces.BasicHud; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import org.lwjgl.input.Keyboard; + +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; + +public class HudGui extends GuiScreen { + private BasicHud editingHud; + private boolean isDragging; + private boolean isScaling; + private int xOffset; + private int yOffset; + + @Override + public void initGui() { + HudCore.editing = true; + Keyboard.enableRepeatEvents(true); + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + Gui.drawRect(0, 0, this.width, this.height, new Color(80, 80, 80, 50).getRGB()); + + if (isDragging) { + setPosition(mouseX - xOffset, mouseY - yOffset, true); + } + + for (BasicHud hud : HudCore.huds) { + processHud(hud, mouseX); + } + } + + private void processHud(BasicHud hud, int mouseX) { + if (hud == editingHud && isScaling) { + float xFloat = hud.getXScaled(this.width); + float yFloat = hud.getYScaled(this.height); + float pos = getXSnapping(mouseX, true); + float newWidth = pos - xFloat; + float newScale = newWidth / ((hud.getWidth(hud.scale) + hud.paddingX * hud.scale) / hud.scale); + if (newScale > 20) + newScale = 20; + else if (newScale < 0.3) + newScale = 0.3f; + hud.scale = newScale; + + if (xFloat / this.width > 0.5) + editingHud.xUnscaled = (xFloat + (hud.getWidth(hud.scale) + hud.paddingX * hud.scale)) / (double) this.width; + if (yFloat / this.height > 0.5) + editingHud.yUnscaled = (yFloat + (hud.getHeight(hud.scale) + hud.paddingY * hud.scale)) / (double) this.height; + } + + int width = (int) (hud.getWidth(hud.scale) + hud.paddingX * hud.scale); + int height = (int) (hud.getHeight(hud.scale) + hud.paddingY * hud.scale); + int x = (int) hud.getXScaled(this.width); + int y = (int) hud.getYScaled(this.height); + + if (hud.parent == null) + hud.drawExampleAll(x, y, hud.scale, true); + int color = new Color(215, 224, 235).getRGB(); + if (editingHud == hud) { + color = new Color(43, 159, 235).getRGB(); + if (isDragging) + Gui.drawRect(x, y, x + width, y + height, new Color(108, 176, 255, 60).getRGB()); + } + int finalColor = color; + RenderManager.setupAndDraw(true, (vg) -> { + RenderManager.drawLine(vg, x - 2 / 4f, y, x + width + 2 / 4f, y, 1, finalColor); + RenderManager.drawLine(vg, x, y, x, y + height, 1, finalColor); + RenderManager.drawLine(vg, x + width, y, x + width, y + height, 1, finalColor); + RenderManager.drawLine(vg, x - 2 / 4f, y + height, x + width + 2 / 4f, y + height, 1, finalColor); + }); + + if (hud == editingHud && !isDragging) { + RenderManager.setupAndDraw(true, (vg) -> { + RenderManager.drawCircle(vg, x + width, y + height, 3, new Color(43, 159, 235).getRGB()); + }); + } + + if (hud.childBottom != null) processHud(hud.childBottom, mouseX); + if (hud.childRight != null) processHud(hud.childRight, mouseX); + } + + private void setPosition(float newX, float newY, boolean snap) { + float width = editingHud.getWidth(editingHud.scale) + editingHud.paddingX * editingHud.scale; + float height = editingHud.getHeight(editingHud.scale) + editingHud.paddingY * editingHud.scale; + + if (editingHud.childRight != null) { + HudCore.huds.add(editingHud.childRight); + editingHud.childRight.parent = null; + editingHud.childRight = null; + } + if (editingHud.childBottom != null) { + HudCore.huds.add(editingHud.childBottom); + editingHud.childBottom.parent = null; + editingHud.childBottom = null; + } + if (editingHud.parent != null) { + HudCore.huds.add(editingHud); + if (editingHud.parent.childBottom == editingHud) + editingHud.parent.childBottom = null; + else if (editingHud.parent.childRight == editingHud) + editingHud.parent.childRight = null; + editingHud.parent = null; + } + + if (newX < 0) + newX = 0; + else if (newX + width > this.width) + newX = this.width - width; + if (newY < 0) + newY = 0; + else if (newY + height > this.height) + newY = this.height - height; + + if (snap) { + float snapX = getXSnapping(newX, false); + float snapY = getYSnapping(newY); + if (snapX != newX || snapY != newY) { + newX = snapX; + newY = snapY; + for (BasicHud hud : HudCore.huds) { + if (findParent(hud, snapX, snapY)) + break; + } + } + } + + if (newX / this.width <= 0.5) + editingHud.xUnscaled = newX / (double) this.width; + else + editingHud.xUnscaled = (newX + width) / (double) this.width; + if (newY / this.height <= 0.5) + editingHud.yUnscaled = newY / (double) this.height; + else + editingHud.yUnscaled = (newY + height) / (double) this.height; + } + + private boolean findParent(BasicHud hud, float snapX, float snapY) { + int hudWidth = (int) (hud.getWidth(hud.scale) + hud.paddingX * hud.scale); + int hudX = (int) hud.getXScaled(this.width); + int hudHeight = (int) (hud.getHeight(hud.scale) + hud.paddingY * hud.scale); + int hudY = (int) hud.getYScaled(this.height); + if (hudX + hudWidth == snapX && hudY == snapY && hud.childRight == null) { + editingHud.parent = hud; + hud.childRight = editingHud; + HudCore.huds.remove(editingHud); + return true; + } else if (hudX == snapX && hudY + hudHeight == snapY && hud.childBottom == null) { + editingHud.parent = hud; + hud.childBottom = editingHud; + HudCore.huds.remove(editingHud); + return true; + } + return hud.childRight != null && findParent(hud.childRight, snapX, snapY) || hud.childBottom != null && findParent(hud.childBottom, snapX, snapY); + } + + private float getXSnapping(float pos, boolean rightOnly) { + float width = editingHud.getWidth(editingHud.scale) + editingHud.paddingX * editingHud.scale; + ArrayList verticalLines = new ArrayList<>(); + for (BasicHud hud : HudCore.huds) { + verticalLines.addAll(getXSnappingHud(hud)); + } + getSpaceSnapping(verticalLines); + verticalLines.add(this.width / 2f); + float smallestDiff = -1; + float smallestLine = 0; + float smallestOffset = 0; + for (float lineX : verticalLines) { + for (float offset = 0; offset <= (rightOnly ? 0 : width); offset += width / 2f) { + if (Math.abs(lineX - pos - offset) < 5 && (Math.abs(lineX - pos - offset) < smallestDiff || smallestDiff == -1)) { + smallestDiff = Math.abs(lineX - pos); + smallestLine = lineX; + smallestOffset = offset; + } + } + } + if (smallestDiff != -1) { + RenderManager.drawDottedLine(smallestLine, 0, smallestLine, this.height, 2, 12, new Color(255, 255, 255).getRGB()); + return smallestLine - smallestOffset; + } + return pos; + } + + private ArrayList getXSnappingHud(BasicHud hud) { + ArrayList verticalLines = new ArrayList<>(); + if (hud == editingHud) return verticalLines; + if (hud.childRight != null) verticalLines.addAll(getXSnappingHud(hud.childRight)); + int hudWidth = (int) (hud.getWidth(hud.scale) + hud.paddingX * hud.scale); + int hudX = (int) hud.getXScaled(this.width); + verticalLines.add((float) hudX); + verticalLines.add((float) (hudX + hudWidth)); + return verticalLines; + } + + private float getYSnapping(float pos) { + float height = editingHud.getHeight(editingHud.scale) + editingHud.paddingY * editingHud.scale; + ArrayList horizontalLines = new ArrayList<>(); + for (BasicHud hud : HudCore.huds) { + horizontalLines.addAll(getYSnappingHud(hud)); + } + getSpaceSnapping(horizontalLines); + horizontalLines.add(this.height / 2f); + float smallestDiff = -1; + float smallestLine = 0; + float smallestOffset = 0; + for (float lineY : horizontalLines) { + for (float offset = 0; offset <= height; offset += height / 2f) { + if (Math.abs(lineY - pos - offset) < 5 && (Math.abs(lineY - pos - offset) < smallestDiff || smallestDiff == -1)) { + smallestDiff = Math.abs(lineY - pos); + smallestLine = lineY; + smallestOffset = offset; + } + } + } + if (smallestDiff != -1) { + RenderManager.drawDottedLine(0, smallestLine, this.width, smallestLine, 2, 12, new Color(255, 255, 255).getRGB()); + return smallestLine - smallestOffset; + } + return pos; + } + + private ArrayList getYSnappingHud(BasicHud hud) { + ArrayList horizontalLines = new ArrayList<>(); + if (hud == editingHud) return horizontalLines; + if (hud.childBottom != null) horizontalLines.addAll(getYSnappingHud(hud.childBottom)); + int hudHeight = (int) (hud.getHeight(hud.scale) + hud.paddingY * hud.scale); + int hudY = (int) hud.getYScaled(this.height); + horizontalLines.add((float) hudY); + horizontalLines.add((float) (hudY + hudHeight)); + return horizontalLines; + } + + private void getSpaceSnapping(ArrayList lines) { + ArrayList newLines = new ArrayList<>(); + for (int i = 0; i < lines.size(); i++) { + for (int l = i + 1; l < lines.size(); l++) { + newLines.add(Math.max(lines.get(i), lines.get(l)) + Math.abs(lines.get(i) - lines.get(l))); + newLines.add(Math.min(lines.get(i), lines.get(l)) - Math.abs(lines.get(i) - lines.get(l))); + } + } + lines.addAll(newLines); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { + if (mouseButton == 0) { + if (editingHud != null) { + int width = (int) (editingHud.getWidth(editingHud.scale) + editingHud.paddingX * editingHud.scale); + int height = (int) (editingHud.getHeight(editingHud.scale) + editingHud.paddingY * editingHud.scale); + float x = editingHud.getXScaled(this.width); + float y = editingHud.getYScaled(this.height); + if (mouseX >= x + width - 3 && mouseX <= x + width + 3 && mouseY >= y + height - 3 && mouseY <= y + height + 3) { + isScaling = true; + return; + } + } + editingHud = null; + for (BasicHud hud : HudCore.huds) { + if (mouseClickedHud(hud, mouseX, mouseY)) + break; + } + } + } + + private boolean mouseClickedHud(BasicHud hud, int mouseX, int mouseY) { + int width = (int) (hud.getWidth(hud.scale) + hud.paddingX * hud.scale); + int height = (int) (hud.getHeight(hud.scale) + hud.paddingY * hud.scale); + float x = hud.getXScaled(this.width); + float y = hud.getYScaled(this.height); + if (mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { + editingHud = hud; + xOffset = (int) (mouseX - x); + yOffset = (int) (mouseY - y); + isDragging = true; + return true; + } + return hud.childBottom != null && mouseClickedHud(hud.childBottom, mouseX, mouseY) || hud.childRight != null && mouseClickedHud(hud.childRight, mouseX, mouseY); + } + + @Override + protected void mouseReleased(int mouseX, int mouseY, int state) { + isDragging = false; + isScaling = false; + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + if (editingHud != null) { + float x = editingHud.getXScaled(this.width); + float y = editingHud.getYScaled(this.height); + switch (keyCode) { + case Keyboard.KEY_UP: + setPosition(x, y - 1, false); + break; + case Keyboard.KEY_DOWN: + setPosition(x, y + 1, false); + break; + case Keyboard.KEY_LEFT: + setPosition(x - 1, y, false); + break; + case Keyboard.KEY_RIGHT: + setPosition(x + 1, y, false); + break; + } + } + super.keyTyped(typedChar, keyCode); + } + + @Override + public void onGuiClosed() { + HudCore.editing = false; + Keyboard.enableRepeatEvents(false); + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java b/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java new file mode 100644 index 0000000..72cd8c0 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/OneConfigGui.java @@ -0,0 +1,231 @@ +package cc.polyfrost.oneconfig.gui; + +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.gui.elements.BasicElement; +import cc.polyfrost.oneconfig.gui.elements.ColorSelector; +import cc.polyfrost.oneconfig.gui.elements.TextInputField; +import cc.polyfrost.oneconfig.gui.pages.HomePage; +import cc.polyfrost.oneconfig.gui.pages.Page; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.lwjgl.Scissor; +import cc.polyfrost.oneconfig.lwjgl.ScissorManager; +import cc.polyfrost.oneconfig.lwjgl.font.Fonts; +import cc.polyfrost.oneconfig.lwjgl.image.Images; +import cc.polyfrost.oneconfig.utils.InputUtils; +import cc.polyfrost.oneconfig.utils.MathUtils; +import net.minecraft.client.gui.GuiScreen; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.nanovg.NanoVG; + +import java.awt.*; +import java.util.ArrayList; + +public class OneConfigGui extends GuiScreen { + public static OneConfigGui INSTANCE; + public final int x = 320; + public final int y = 140; + private final SideBar sideBar = new SideBar(); + protected Page currentPage; + protected Page prevPage; + private float pageProgress = -224f; + private final TextInputField textInputField = new TextInputField(248, 40, "Search all of OneConfig...", false, false); + private final ArrayList previousPages = new ArrayList<>(); + private final ArrayList nextPages = new ArrayList<>(); + private final BasicElement backArrow = new BasicElement(40, 40, -1, false); + private final BasicElement forwardArrow = new BasicElement(40, 40, -1, false); + private final ArrayList parents = new ArrayList<>(); + private ColorSelector currentColorSelector; + public boolean mouseDown; + + public OneConfigGui() { + INSTANCE = this; + } + + public OneConfigGui(Page page) { + INSTANCE = this; + currentPage = page; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + long start = System.nanoTime(); + RenderManager.setupAndDraw((vg) -> { + if (currentPage == null) { + currentPage = new HomePage(); + parents.add(currentPage); + } + //nvgScale(vg, 0.5f, 0.5f); + if (OneConfigConfig.ROUNDED_CORNERS) { + RenderManager.drawRoundedRect(vg, 544, 140, 1056, 800, OneConfigConfig.GRAY_800, OneConfigConfig.CORNER_RADIUS_WIN); + RenderManager.drawRoundedRect(vg, 320, 140, 244, 800, OneConfigConfig.GRAY_900_80, OneConfigConfig.CORNER_RADIUS_WIN); + RenderManager.drawRect(vg, 544, 140, 20, 800, OneConfigConfig.GRAY_800); + //RenderManager.drawDropShadow(vg, 544, 140, 1056, 800, 20f, 32f, OneConfigConfig.GRAY_800); + } + + RenderManager.drawLine(vg, 544, 212, 1600, 212, 1, OneConfigConfig.GRAY_700); + RenderManager.drawLine(vg, 544, 140, 544, 940, 1, OneConfigConfig.GRAY_700); + + RenderManager.drawImage(vg, Images.LOGO, x + 19, y + 19, 42, 42); + RenderManager.drawString(vg, "OneConfig", x + 69, y + 32, OneConfigConfig.WHITE, 18f, Fonts.INTER_BOLD); // added half line height to center text + RenderManager.drawString(vg, "By Polyfrost", x + 69, y + 51, OneConfigConfig.WHITE, 12f, Fonts.INTER_REGULAR); + textInputField.draw(vg, x + 1020, y + 16); + sideBar.draw(vg, x, y); + backArrow.draw(vg, x + 240, y + 16); + forwardArrow.draw(vg, x + 280, y + 16); + + if (previousPages.size() == 0) { + backArrow.disable(true); + NanoVG.nvgGlobalAlpha(vg, 0.5f); + } else { + backArrow.disable(false); + if (!backArrow.isHovered() || Mouse.isButtonDown(0)) NanoVG.nvgGlobalAlpha(vg, 0.8f); + } + NanoVG.nvgTranslate(vg, x + 271, y + 47); + NanoVG.nvgRotate(vg, (float) Math.toRadians(180)); + RenderManager.drawImage(vg, Images.CIRCLE_ARROW, 0, 0, 22, 22); + NanoVG.nvgResetTransform(vg); + NanoVG.nvgGlobalAlpha(vg, 1f); + if (nextPages.size() == 0) { + forwardArrow.disable(true); + NanoVG.nvgGlobalAlpha(vg, 0.5f); + } else { + forwardArrow.disable(false); + if (!forwardArrow.isHovered() || Mouse.isButtonDown(0)) NanoVG.nvgGlobalAlpha(vg, 0.8f); + } + RenderManager.drawImage(vg, Images.CIRCLE_ARROW, x + 289, y + 25, 22, 22); + NanoVG.nvgGlobalAlpha(vg, 1f); + + if (backArrow.isClicked() && previousPages.size() > 0) { + try { + nextPages.add(0, currentPage); + openPage(previousPages.get(0), false); + previousPages.remove(0); + } catch (Exception ignored) { + } + } else if (forwardArrow.isClicked() && nextPages.size() > 0) { + try { + previousPages.add(0, currentPage); + openPage(nextPages.get(0), false); + nextPages.remove(0); + } catch (Exception ignored) { + } + } + + Scissor scissor = ScissorManager.scissor(vg, x + 224, y + 72, 1056, 728); + if (prevPage != null) { + pageProgress = MathUtils.easeInOutCirc(50, pageProgress, 832 - pageProgress, 220); + prevPage.draw(vg, (int) (x - pageProgress), y + 72); + RenderManager.drawLine(vg, (int) (x - pageProgress + 1055), y + 72, (int) (x - pageProgress + 1057), y + 800, 2, OneConfigConfig.GRAY_700); // TODO might remove this + currentPage.draw(vg, (int) (x - pageProgress + 1056), y + 72); + if (pageProgress > 830f) { // this number is the 'snap' point of the page + prevPage = null; + pageProgress = -224f; + } + } else { + currentPage.draw(vg, (int) (x - pageProgress), y + 72); + } + ScissorManager.resetScissor(vg, scissor); + if (currentColorSelector != null) { + currentColorSelector.draw(vg); + } + + float breadcrumbX = x + 336; + for (int i = 0; i < parents.size(); i++) { + String title = parents.get(i).getTitle(); + float width = RenderManager.getTextWidth(vg, title, 24f, Fonts.INTER_SEMIBOLD); + boolean hovered = InputUtils.isAreaHovered((int) breadcrumbX, y + 24, (int) width, 36); + int color = OneConfigConfig.WHITE_60; + if (i == parents.size() - 1) color = OneConfigConfig.WHITE_95; + else if (hovered && !Mouse.isButtonDown(0)) color = OneConfigConfig.WHITE_80; + RenderManager.drawString(vg, title, breadcrumbX, y + 38, color, 24f, Fonts.INTER_SEMIBOLD); + if (i != 0) + RenderManager.drawImage(vg, Images.CHEVRON_ARROW, breadcrumbX - 22, y + 26, 13, 22, color); + if (hovered && i != parents.size() - 1) + RenderManager.drawLine(vg, breadcrumbX, y + 48, breadcrumbX + width, y + 48, 2, color); + if (hovered && InputUtils.isClicked()) openPage(parents.get(i)); + breadcrumbX += width + 32; + } + + long end = System.nanoTime() - start; + String s = (" draw: " + end / 1000000f + "ms"); + RenderManager.drawString(vg, s, x + 1170, y + 790, OneConfigConfig.GRAY_300, 10f, Fonts.INTER_MEDIUM); + }); + mouseDown = Mouse.isButtonDown(0); + } + + protected void keyTyped(char key, int keyCode) { + Keyboard.enableRepeatEvents(true); + try { + super.keyTyped(key, keyCode); + textInputField.keyTyped(key, keyCode); + currentPage.keyTyped(key, keyCode); + } catch (Exception e) { + System.out.println("this should literally never happen"); + } + } + + public void openPage(@NotNull Page page) { + openPage(page, true); + } + + public void openPage(@NotNull Page page, boolean addToPrevious) { + if (page == currentPage) return; + currentPage.finishUpAndClose(); + if (!page.isBase()) { + boolean alreadyInParents = false; + for (int i = 0; i < parents.size(); i++) { + Page parent = parents.get(i); + if (parent == page) { + alreadyInParents = true; + parents.subList(i + 1, parents.size()).clear(); + break; + } + } + if (!alreadyInParents) parents.add(page); + } else { + parents.clear(); + parents.add(page); + } + if (addToPrevious) { + previousPages.add(0, currentPage); + nextPages.clear(); + } + if (prevPage == null) { + prevPage = currentPage; + } + currentPage = page; + } + + /** + * initialize a new ColorSelector and add it to the draw script. This method is used to make sure it is always rendered on top. + * + * @implNote Correct usage: OneConfigGui.INSTANCE.initColorSelector(new ColorSelector(color, InputUtils.mouseX(), InputUtils.mouseY())); + */ + public void initColorSelector(ColorSelector colorSelector) { + currentColorSelector = colorSelector; + } + + /** + * Close the current color selector and return the color it had when it closed. + */ + public Color closeColorSelector() { + Color color = currentColorSelector.getColor(); + currentColorSelector = null; + return color; + } + + + @Override + public boolean doesGuiPauseGame() { + return false; + } + + @Override + public void onGuiClosed() { + currentPage.finishUpAndClose(); + INSTANCE = null; + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/SideBar.java b/src/main/java/cc/polyfrost/oneconfig/gui/SideBar.java new file mode 100644 index 0000000..73f46f7 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/SideBar.java @@ -0,0 +1,67 @@ +package cc.polyfrost.oneconfig.gui; + +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.gui.elements.BasicButton; +import cc.polyfrost.oneconfig.gui.pages.HomePage; +import cc.polyfrost.oneconfig.gui.pages.ModsPage; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.lwjgl.font.Fonts; +import cc.polyfrost.oneconfig.lwjgl.image.Images; +import cc.polyfrost.oneconfig.utils.MathUtils; +import net.minecraft.client.Minecraft; + +import java.util.ArrayList; +import java.util.List; + +public class SideBar { + private final List btnList = new ArrayList<>(); + + private float targetY = 0, currentY = 0; + + public SideBar() { + btnList.add(new BasicButton(192, 36, "Dashboard", Images.DASHBOARD, null, -3, BasicButton.ALIGNMENT_LEFT, new HomePage())); + btnList.add(new BasicButton(192, 36, "Global Search", Images.SEARCH, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Mods", Images.MODS, null, -3, BasicButton.ALIGNMENT_LEFT, new ModsPage())); + btnList.add(new BasicButton(192, 36, "Performance", Images.PERFORMANCE, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Profiles", Images.PROFILES, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Updates", Images.UPDATES, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Theme", Images.THEMES, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Screenshots", Images.SCREENSHOT, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "HUD Settings", Images.HUD_SETTINGS, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Preferences", Images.PREFERENCES, null, -3, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Close", Images.CLOSE, null, -1, BasicButton.ALIGNMENT_LEFT, () -> Minecraft.getMinecraft().displayGuiScreen(null))); + btnList.add(new BasicButton(192, 36, "Minimize", Images.MINIMIZE, null, -1, BasicButton.ALIGNMENT_LEFT)); + btnList.add(new BasicButton(192, 36, "Edit HUD", Images.HUD, null, 0, BasicButton.ALIGNMENT_LEFT, () -> Minecraft.getMinecraft().displayGuiScreen(new HudGui()))); + } + + public void draw(long vg, int x, int y) { + //percentMove = 36f; + + currentY = MathUtils.easeInOutCirc(50, currentY, targetY - currentY, 120); + RenderManager.drawRoundedRect(vg, x + 16, currentY, 192, 36, OneConfigConfig.BLUE_600, OneConfigConfig.CORNER_RADIUS); + int i = 0; + if (targetY == 0) { + targetY = y + 96; + currentY = targetY; + } + for (BasicButton btn : btnList) { + btn.draw(vg, x + 16, y + 96 + i); + i += 44; + if (i == 88) { // +88 + RenderManager.drawString(vg, "MOD CONFIG", x + 16, y + 200, OneConfigConfig.WHITE_90, 12f, Fonts.INTER_SEMIBOLD); + i = 122; + } + if (i == 298) { + RenderManager.drawString(vg, "PERSONALIZATION", x + 16, y + 420, OneConfigConfig.WHITE_90, 12f, Fonts.INTER_SEMIBOLD); + i = 342; + } + if (i == 518) { + i = 562; + } + + if (btn.isClicked() && btn.getPage() != null) { + if (i < 520) targetY = btn.y; + } + } + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicButton.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicButton.java new file mode 100644 index 0000000..faf0b07 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicButton.java @@ -0,0 +1,157 @@ +package cc.polyfrost.oneconfig.gui.elements; + +import cc.polyfrost.oneconfig.gui.OneConfigGui; +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.gui.pages.Page; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.lwjgl.font.Fonts; +import cc.polyfrost.oneconfig.lwjgl.image.Images; +import cc.polyfrost.oneconfig.utils.ColorUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class BasicButton extends BasicElement { + + protected String text; + protected Images fileNameLeftIco, fileNameRightIco; + private final int thisAlignment; + private final float fontSize; + private final int colorPalette; + public int x, y; + public static final int ALIGNMENT_LEFT = 0; + public static final int ALIGNMENT_CENTER = 1; + private boolean toggleable; + private Page page; + private Runnable runnable; + + /** + * Create a new basic button. Used mostly on the homepage and the sidebar. Note: The button will not be drawn until you call {@link #draw(long, int, int)}. + * The button's content is centered on its total length, so the text is not always in the middle. + * + * @param text Text to display on the button. Has to be there. + * @param fileNameLeftIco file path of the icon to display on the left. Can be null if you don't want to display an icon on the left. + * @param fileNameRightIco file path of the icon to display on the right. Can be null if you don't want to display an icon on the right. + * @param colorPalette color palette to use. see {@link ColorUtils} for more info. Can support color palette of -2, which is larger font and icons. Also supports -3, which is just the text changing color. + * @param alignment alignment of the button. ALIGNMENT_LEFT or ALIGNMENT_CENTER. + */ + public BasicButton(int width, int height, @NotNull String text, @Nullable Images fileNameLeftIco, @Nullable Images fileNameRightIco, int colorPalette, int alignment) { + super(width, height, colorPalette, true); + this.text = text; + if (fileNameLeftIco != null) this.fileNameLeftIco = fileNameLeftIco; + if (fileNameRightIco != null) this.fileNameRightIco = fileNameRightIco; + this.thisAlignment = alignment; + if (colorPalette == -2) { + fontSize = 24f; + this.colorPalette = -1; + } else { + fontSize = 14f; + this.colorPalette = colorPalette; + } + } + + public BasicButton(int width, int height, @NotNull String text, @Nullable Images fileNameLeftIco, @Nullable Images fileNameRightIco, int colorPalette, int alignment, Page page) { + this(width, height, text, fileNameLeftIco, fileNameRightIco, colorPalette, alignment); + this.page = page; + } + + public BasicButton(int width, int height, @NotNull String text, @Nullable Images fileNameLeftIco, @Nullable Images fileNameRightIco, int colorPalette, int alignment, boolean toggleable) { + this(width, height, text, fileNameLeftIco, fileNameRightIco, colorPalette, alignment); + this.toggleable = toggleable; + } + + public BasicButton(int width, int height, @NotNull String text, @Nullable Images fileNameLeftIco, @Nullable Images fileNameRightIco, int colorPalette, int alignment, Runnable runnable) { + this(width, height, text, fileNameLeftIco, fileNameRightIco, colorPalette, alignment); + this.runnable = runnable; + } + + public BasicButton(int width, int height, @NotNull String text, @Nullable Images fileNameLeftIco, @Nullable Images fileNameRightIco, int colorPalette, int alignment, boolean toggleable, Runnable runnable) { + this(width, height, text, fileNameLeftIco, fileNameRightIco, colorPalette, alignment, runnable); + this.toggleable = toggleable; + } + + @Override + public void draw(long vg, int x, int y) { + this.x = x; + this.y = y; + int textColor = -1; + RenderManager.drawRectangle(vg, x, y, this.width, this.height, this.currentColor); + float contentWidth = RenderManager.getTextWidth(vg, text, fontSize, Fonts.INTER_MEDIUM); + if (fileNameLeftIco != null) { + contentWidth += 28; + } + if (fileNameRightIco != null) { + contentWidth += 28; + } + + if (this.colorPalette == -3) { + textColor = OneConfigConfig.WHITE_80; + if (hovered) textColor = OneConfigConfig.WHITE; + if (clicked) textColor = OneConfigConfig.WHITE_80; + if (page == null) textColor = OneConfigConfig.WHITE_50; + } + + if (thisAlignment == ALIGNMENT_CENTER) { + int middle = x + this.width / 2; + RenderManager.drawString(vg, text, middle - contentWidth / 2 + (fileNameLeftIco != null ? 28 : 0), y + ((float) height / 2) + 1, textColor, fontSize, Fonts.INTER_MEDIUM); + if (fileNameLeftIco != null) { + RenderManager.drawImage(vg, fileNameLeftIco, middle - contentWidth / 2, y + 8, 20, 20); + } + if (fileNameRightIco != null) { + RenderManager.drawImage(vg, fileNameRightIco, middle + contentWidth / 2 - (fileNameLeftIco != null ? 20 : 24), y + 8, 20, 20); + } + } + if (thisAlignment == ALIGNMENT_LEFT) { + if (fileNameLeftIco != null) { + RenderManager.drawImage(vg, fileNameLeftIco, x + 12, y + 8, 20, 20, textColor); + RenderManager.drawString(vg, text, x + 40, y + ((float) height / 2) + 1, textColor, fontSize, Fonts.INTER_MEDIUM); + } else { + RenderManager.drawString(vg, text, x + 12, y + ((float) height / 2) + 1, textColor, fontSize, Fonts.INTER_MEDIUM); + } + if (fileNameRightIco != null) { + RenderManager.drawImage(vg, fileNameRightIco, x + width - 28, y + 8, 20, 20); + } + } + this.update(x, y); + if (hoverFx) { + if (colorPalette == -3) { + currentColor = OneConfigConfig.TRANSPARENT; + return; + } + if (!toggleable) { + currentColor = ColorUtils.getColor(currentColor, colorPalette, hovered, clicked); + } else { + if (toggled) { + currentColor = ColorUtils.smoothColor(currentColor, OneConfigConfig.GRAY_500, OneConfigConfig.BLUE_600, true, 30f); + } else currentColor = ColorUtils.getColor(currentColor, colorPalette, hovered, clicked); + } + } + } + + + @Override + public void onClick() { + if (this.page != null) { + OneConfigGui.INSTANCE.openPage(page); + } else if (this.runnable != null) { + runnable.run(); + } + } + + @Override + public void update(int x, int y) { + if (toggleable && toggled) return; + super.update(x, y); + } + + public void setToggled(boolean state) { + this.toggled = state; + } + + public Page getPage() { + return page; + } + + public String getText() { + return text; + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicElement.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicElement.java new file mode 100644 index 0000000..80eec9b --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/BasicElement.java @@ -0,0 +1,107 @@ +package cc.polyfrost.oneconfig.gui.elements; + +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.utils.ColorUtils; +import cc.polyfrost.oneconfig.utils.InputUtils; + +public class BasicElement { + protected int width, height; + protected int colorPalette; + protected int hitBoxX, hitBoxY; + protected final boolean hoverFx; + protected boolean hovered = false; + protected boolean clicked = false; + protected boolean toggled = false; + protected boolean disabled = false; + protected int currentColor; + + public BasicElement(int width, int height, int colorPalette, boolean hoverFx) { + this.height = height; + this.width = width; + this.colorPalette = colorPalette; + this.hoverFx = hoverFx; + } + + public BasicElement(int width, int height, boolean hoverFx) { + this.height = height; + this.width = width; + this.colorPalette = -1; + this.hoverFx = hoverFx; + } + + + public void draw(long vg, int x, int y) { + RenderManager.drawRectangle(vg, x, y, width, height, currentColor); + + update(x, y); + if (hoverFx) { + currentColor = ColorUtils.getColor(currentColor, colorPalette, hovered, clicked); + } + } + + public void update(int x, int y) { + if(disabled) { + hovered = false; + clicked = false; + return; + } + hovered = InputUtils.isAreaHovered(x - hitBoxX, y - hitBoxY, width + hitBoxX, height + hitBoxY); + clicked = InputUtils.isClicked() && hovered; + + if (hovered) { + if (clicked) { + toggled = !toggled; + onClick(); + } + } + } + + + public void onClick() { + + } + + public void setCustomHitbox(int x, int y) { + hitBoxX = x; + hitBoxY = y; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setColorPalette(int colorPalette) { + this.colorPalette = colorPalette; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public boolean isHovered() { + return hovered; + } + + public boolean isClicked() { + return clicked; + } + + public boolean isToggled() { + return toggled; + } + + public boolean isDisabled() { + return disabled; + } + public void disable(boolean state) { + disabled = state; + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/ColorSelector.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/ColorSelector.java new file mode 100644 index 0000000..83d0f7c --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/ColorSelector.java @@ -0,0 +1,250 @@ +package cc.polyfrost.oneconfig.gui.elements; + +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.utils.InputUtils; +import org.lwjgl.input.Mouse; + +import java.awt.*; +import java.util.ArrayList; + +public class ColorSelector { + private Color color; + private final int x, y; + private final int width = 416; + private final int height = 768; + + private final BasicElement HSBButton = new BasicElement(128, 32, -1, true); + private final BasicElement RGBButton = new BasicElement(128, 32, -1, true); + private final BasicElement ChromaButton = new BasicElement(128, 32, -1, true); + + private final ArrayList faves = new ArrayList<>(); + private final ArrayList history = new ArrayList<>(); + private final BasicElement closeButton = new BasicElement(32, 32, -1, true); + + + public ColorSelector(Color color, int mouseX, int mouseY) { + this.color = color; + this.y = mouseY - 768; + this.x = mouseX - 208; + + } + + public void draw(long vg) { + RenderManager.drawRoundedRect(vg, x, y, width, height, OneConfigConfig.GRAY_800, 20f); + + } + + public Color getColor() { + return color; + } + + + + private class HSBSelector extends ColorSelectorBase { + + + public HSBSelector(Color color) { + super(color); + } + + @Override + public void drawBox(long vg, int x, int y) { + + } + + @Override + public void setColor(Color color) { + + } + + @Override + public int[] drawTopSlider() { + return new int[0]; + } + + @Override + public int[] drawBottomSlider() { + return new int[0]; + } + + @Override + public float[] getColorAtPos(int clickX, int clickY) { + return new float[0]; + } + } + + + private class RGBSelector extends ColorSelectorBase { + + public RGBSelector(Color color) { + super(color); + } + + @Override + public void drawBox(long vg, int x, int y) { + + } + + @Override + public void setColor(Color color) { + + } + + @Override + public int[] drawTopSlider() { + return new int[0]; + } + + @Override + public int[] drawBottomSlider() { + return new int[0]; + } + + + @Override + public float[] getColorAtPos(int clickX, int clickY) { + return new float[0]; + } + } + + + + private abstract class ColorSelectorBase { + + private int selectedX; + private int selectedY; + private float[] hsb = new float[3]; + private float[] rgba; + private final TextInputFieldNumber hueField = new TextInputFieldNumber(72, 32, "", 0, 100); + private final TextInputFieldNumber saturationField = new TextInputFieldNumber(72, 32, "", 0, 100); + private final TextInputFieldNumber brightnessField = new TextInputFieldNumber(72, 32, "", 0, 100); + private final TextInputFieldNumber alphaField = new TextInputFieldNumber(72, 32, "", 0, 100); + + private final TextInputField hexField = new TextInputField(107, 32, true, false, ""); + private final TextInputFieldNumber redField = new TextInputFieldNumber(44, 32, "", 0, 255); + private final TextInputFieldNumber greenField = new TextInputFieldNumber(44, 32, "", 0, 255); + private final TextInputFieldNumber blueField = new TextInputFieldNumber(44, 32, "", 0, 255); + + private final Slider sliderTop = new Slider(0); + private final Slider sliderBottom = new Slider(0); + + public ColorSelectorBase(Color color) { + rgba = new float[]{color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f}; + } + + public void updateElements(float[] rgba) { + this.rgba = rgba; + hsb = Color.RGBtoHSB((int) (rgba[0] * 255), (int) (rgba[1] * 255), (int) (rgba[2] * 255), hsb); + hueField.setInput(String.valueOf(hsb[0])); + saturationField.setInput(String.valueOf(hsb[1])); + brightnessField.setInput(String.valueOf(hsb[2])); + alphaField.setInput(String.valueOf(rgba[3])); + redField.setInput(String.valueOf(rgba[0])); + greenField.setInput(String.valueOf(rgba[1])); + blueField.setInput(String.valueOf(rgba[2])); + } + public abstract void drawBox(long vg, int x, int y); + + /** draw the color selector contents, including the box, and the input fields. If it is clicked, getColorAtPos is called. updateElements is also called to update all the input fields. */ + public void draw(long vg, int x, int y) { + drawBox(vg, x + 16, y + 120); + if(InputUtils.isAreaHovered(x + 16, y + 120, 384, 288) && Mouse.isButtonDown(0)) { + selectedX = InputUtils.mouseX() - x - 16; + selectedY = InputUtils.mouseY() - y - 120; + rgba = getColorAtPos(selectedX, selectedY); + } // TODO all of this + hueField.draw(vg, x + 104, y + 544); + saturationField.draw(vg, x + 312, y + 544); + brightnessField.draw(vg, x + 103, y + 584); + alphaField.draw(vg, x + 103, y + 584); + hexField.draw(vg, x + 96, y + 624); + redField.draw(vg, x + 228, y + 624); + greenField.draw(vg, x + 292, y + 664); + blueField.draw(vg, x + 356, y + 664); + sliderTop.draw(vg, x + 16, y + 424, drawTopSlider()[0], drawTopSlider()[1]); + sliderBottom.draw(vg, x + 16, y + 576, drawBottomSlider()[0], drawBottomSlider()[1]); + updateElements(rgba); + Color color1 = new Color(rgba[0], rgba[1], rgba[2], rgba[3]); + setColor(color1); + RenderManager.drawRoundedRect(vg, x + 16, y + 488, 384, 40, color1.getRGB(), 12f); + } + + /** called to set the color of the color selector box based on the values of the input fields. */ + public abstract void setColor(Color color); + + /** return an array of two ints of the start color of the gradient and the end color of the gradient. */ + public abstract int[] drawTopSlider(); + /** return an array of two ints of the start color of the gradient and the end color of the gradient. */ + public abstract int[] drawBottomSlider(); + + /** + * This method is called when the color selector is clicked. It needs to return color at the clicked position. + * @return color at the clicked position as a float[] rgba. + */ + public abstract float[] getColorAtPos(int clickX, int clickY); + + public float getRed() { + return rgba[0]; + } + public float getGreen(){ + return rgba[1]; + } + public float getBlue(){ + return rgba[2]; + } + public float getAlpha(){ + return rgba[3]; + } + + public float getHue(){ + return hsb[0]; + } + + public float getSaturation(){ + return hsb[1]; + } + + public float getBrightness(){ + return hsb[2]; + } + + public String getHex() { + return null; + }; + + public Color getColor() { + return new Color(rgba[0], rgba[1], rgba[2], rgba[3]); + } + + } + + private class TextInputFieldNumber extends TextInputField { + private final float min, max; + public TextInputFieldNumber(int width, int height, String defaultValue, float min, float max) { + super(width, height, true, true, defaultValue); + this.min = min; + this.max = max; + } + + @Override + public void draw(long vg, int x, int y) { + super.draw(vg, x, y); + + } + } + + private class Slider { + private final int style; + + public Slider(int style) { + this.style = style; + } + + public void draw(long vg, int x, int y, int color1, int color2) { + + } + } +} + + diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/ModCard.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/ModCard.java new file mode 100644 index 0000000..4fe1524 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/ModCard.java @@ -0,0 +1,146 @@ +package cc.polyfrost.oneconfig.gui.elements; + +import cc.polyfrost.oneconfig.OneConfig; +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.config.data.Mod; +import cc.polyfrost.oneconfig.config.data.ModType; +import cc.polyfrost.oneconfig.gui.OneConfigGui; +import cc.polyfrost.oneconfig.gui.pages.ModConfigPage; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.lwjgl.font.Fonts; +import cc.polyfrost.oneconfig.lwjgl.image.Images; +import cc.polyfrost.oneconfig.utils.ColorUtils; +import cc.polyfrost.oneconfig.utils.InputUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.command.CommandException; +import net.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.fml.common.ModMetadata; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.nanovg.NanoVG; + +import java.util.ArrayList; + +public class ModCard extends BasicElement { + private final String iconPath; + private final Mod modData; + private final BasicElement favoriteHitbox = new BasicElement(32, 32, -2, true); + private boolean active, disabled, favorite; + private int colorGray = OneConfigConfig.GRAY_600; + private int colorPrimary = OneConfigConfig.BLUE_600; + private boolean isHoveredMain = false; + + public ModCard(@NotNull Mod mod, @Nullable String iconPath, boolean active, boolean disabled, boolean favorite) { + super(244, 119, false); + this.modData = mod; + this.iconPath = iconPath; + this.active = active; + toggled = active; + this.disabled = disabled; + this.favorite = favorite; + } + + @Override + public void draw(long vg, int x, int y) { + if (disabled) NanoVG.nvgGlobalAlpha(vg, 0.5f); + RenderManager.drawRoundedRectVaried(vg, x, y, width, 87, colorGray, 12f, 12f, 0f, 0f); + RenderManager.drawRoundedRectVaried(vg, x, y + 87, width, 32, colorPrimary, 0f, 0f, 12f, 12f); + RenderManager.drawLine(vg, x, y + 86, x + width, y + 86, 2, OneConfigConfig.GRAY_300); + if (iconPath != null) { + RenderManager.drawImage(vg, iconPath, x, y, width, 87); + } else { + RenderManager.drawImage(vg, Images.MOD_BOX, x + 98, y + 19, 48, 48); + } + favoriteHitbox.update(x + 212, y + 87); + favoriteHitbox.currentColor = ColorUtils.getColor(favoriteHitbox.currentColor, favoriteHitbox.colorPalette, favoriteHitbox.hovered, favoriteHitbox.clicked); + RenderManager.drawRoundedRectVaried(vg, x + 212, y + 87, 32, 32, favoriteHitbox.currentColor, 0f, 0f, 12f, 0f); + favorite = favoriteHitbox.isToggled(); + RenderManager.drawString(vg, modData.name, x + 12, y + 103, OneConfigConfig.WHITE, 14f, Fonts.INTER_MEDIUM); + if (favorite) { + RenderManager.drawImage(vg, Images.FAVORITE, x + 220, y + 95, 16, 16); + } else { + RenderManager.drawImage(vg, Images.FAVORITE_OFF, x + 220, y + 95, 16, 16); + } + super.update(x, y); + isHoveredMain = InputUtils.isAreaHovered(x, y, width, 87); + boolean isHoveredSecondary = InputUtils.isAreaHovered(x, y + 87, width - 32, 32) && !disabled; + colorGray = ColorUtils.getColor(colorGray, 0, isHoveredMain, clicked && isHoveredMain); + if (active && !disabled) { + colorPrimary = ColorUtils.getColor(colorPrimary, 1, isHoveredSecondary, clicked && isHoveredSecondary); + } else + colorPrimary = ColorUtils.smoothColor(colorPrimary, OneConfigConfig.GRAY_500, OneConfigConfig.GRAY_400, isHoveredSecondary, 20f); + + if (clicked && isHoveredMain) { + if (!active) toggled = false; + } + if (clicked && favoriteHitbox.hovered) toggled = false; + if (clicked && !isHoveredSecondary && active) toggled = true; + if (!active & disabled) toggled = false; + //RenderManager.drawString(vg, "active=" + active, x + 150, y + 92, OneConfigConfig.WHITE, 10f, Fonts.INTER_MEDIUM); // debug stuff + //RenderManager.drawString(vg, "disabled=" + disabled, x + 150, y + 103, OneConfigConfig.WHITE, 10f, Fonts.INTER_MEDIUM); + //RenderManager.drawString(vg, "favorite=" + favorite, x + 150, y + 114, OneConfigConfig.WHITE, 10f, Fonts.INTER_MEDIUM); + + + active = toggled; + NanoVG.nvgGlobalAlpha(vg, 1f); + } + + public void onClick() { + if (isHoveredMain) { + for (Mod data : OneConfig.loadedMods) { + if (data.modType != ModType.OTHER) { + if (data.name.equalsIgnoreCase(modData.name)) { + OneConfigGui.INSTANCE.openPage(new ModConfigPage(data.defaultPage)); + } + } + } + for (ModMetadata mod : OneConfig.loadedOtherMods) { + if (mod.name.equalsIgnoreCase(modData.name)) { + ArrayList possibleCommands = new ArrayList<>(); + possibleCommands.add(mod.name.toLowerCase().replace(" ", "")); + possibleCommands.add(mod.modId.toLowerCase().replaceAll("[ -_]", "")); + if (mod.name.split(" ").length > 1) { + StringBuilder result = new StringBuilder(); + for (String word : mod.name.split(" ")) { + if (word.length() == 0) continue; + result.append(word.charAt(0)); + } + possibleCommands.add(result.toString().toLowerCase()); + } + for (String command : ClientCommandHandler.instance.getCommands().keySet()) { + if (possibleCommands.contains(command)) { + try { + ClientCommandHandler.instance.getCommands().get(command).processCommand(Minecraft.getMinecraft().thePlayer, new String[]{}); + } catch (CommandException e) { + throw new RuntimeException(e); + } + break; + } + } + return; + } + + } + } + } + + public Mod getModData() { + return modData; + } + + public boolean isDisabled() { + return disabled; + } + + public boolean isActive() { + return active; + } + + public void setDisabled(boolean disabled) { + this.disabled = disabled; + } + + public boolean isFavorite() { + return favorite; + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/SearchField.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/SearchField.java new file mode 100644 index 0000000..6f460d6 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/SearchField.java @@ -0,0 +1,14 @@ +package cc.polyfrost.oneconfig.gui.elements; + +public class SearchField extends TextInputField { + + public SearchField(int width, int height, String defaultText, boolean multiLine, boolean password) { + super(width, height, defaultText, multiLine, password); + } + + @Override + public void draw(long vg, int x, int y) { + super.draw(vg, x, y); + // TODO + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/gui/elements/TextInputField.java b/src/main/java/cc/polyfrost/oneconfig/gui/elements/TextInputField.java new file mode 100644 index 0000000..3058643 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/gui/elements/TextInputField.java @@ -0,0 +1,418 @@ +package cc.polyfrost.oneconfig.gui.elements; + +import cc.polyfrost.oneconfig.config.OneConfigConfig; +import cc.polyfrost.oneconfig.lwjgl.RenderManager; +import cc.polyfrost.oneconfig.lwjgl.Scissor; +import cc.polyfrost.oneconfig.lwjgl.ScissorManager; +import cc.polyfrost.oneconfig.lwjgl.font.Fonts; +import cc.polyfrost.oneconfig.utils.InputUtils; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.ChatAllowedCharacters; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; + +public class TextInputField extends BasicElement { + + protected final String defaultText; + protected String input, selectedText; + protected final boolean multiLine; + protected boolean password; + + protected int caretPos; + protected int x, y; + protected float start, end; + private long clickTimeD1; + protected long vg; + protected int prevCaret = 0; + protected boolean isDoubleClick = false; + protected boolean onlyNums = false; + protected boolean errored = false; + protected boolean centered = false; + + public TextInputField(int width, int height, String defaultText, boolean multiLine, boolean password) { + super(width, height, false); + this.multiLine = multiLine; + this.defaultText = defaultText; + this.password = password; + this.input = ""; + } + + public TextInputField(int width, int height, boolean centered, boolean onlyNums, String defaultText) { + this(width, height, defaultText, false, false); + this.centered = centered; + this.onlyNums = onlyNums; + } + + public void onlyAcceptNumbers(boolean state) { + onlyNums = state; + } + + public void setInput(String input) { + this.input = input; + } + + public String getInput() { + return input; + } + + public void setPassword(boolean password) { + this.password = password; + } + + public boolean getPassword() { + return password; + } + + public void setErrored(boolean errored) { + this.errored = errored; + } + + public void setCentered(boolean centered) { + this.centered = centered; + } + + public boolean isErrored() { + return errored; + } + + @Override + public void draw(long vg, int x, int y) { + this.x = x; + this.y = y; + this.vg = vg; + try { + Scissor scissor = ScissorManager.scissor(vg, x, y, width, height); + int colorOutline = errored ? OneConfigConfig.ERROR_700 : OneConfigConfig.GRAY_700; + RenderManager.drawHollowRoundRect(vg, x, y, width, height, colorOutline, 12f, 2f); + super.update(x, y); + if (Mouse.isButtonDown(0) && !InputUtils.isAreaHovered(x - 40, y - 20, width + 90, height + 20)) { + toggled = false; + } + int color = toggled ? OneConfigConfig.WHITE : OneConfigConfig.WHITE_60; + if (!toggled) caretPos = input.length(); + float width; + StringBuilder s = new StringBuilder(); + if (!password) { + width = RenderManager.getTextWidth(vg, input.substring(0, caretPos), 14f, Fonts.INTER_REGULAR); + } else { + for (int i = 0; i < input.length(); i++) { + s.append("*"); + } + width = RenderManager.getTextWidth(vg, s.substring(0, caretPos), 14f, Fonts.INTER_REGULAR); + } + if (hovered) { + while (Mouse.next()) { + if (Mouse.getEventButtonState()) { + if (Mouse.getEventButton() == 0) { + prevCaret = calculatePos(Mouse.getX()); + if (System.currentTimeMillis() - clickTimeD1 < 300) { + onDoubleClick(); + isDoubleClick = true; + } + clickTimeD1 = System.currentTimeMillis(); + } + } else { + if (Mouse.getEventButton() == 0) { + long clickTimeU = System.currentTimeMillis(); + if (clickTimeU - clickTimeD1 < 200) { + if (!isDoubleClick) { + start = 0; + end = 0; + } + prevCaret = caretPos; + isDoubleClick = false; + } + + } + } + } + } + float halfTextWidth = this.getTextWidth(vg, input) / 2f; + if (start != 0f && end != 0f && toggled) { + RenderManager.drawRect(vg, start, y + height / 2f - 10, end, 20, OneConfigConfig.GRAY_300); + } + if (hovered) { + if (Mouse.isButtonDown(0) && !isDoubleClick) { + caretPos = calculatePos(Mouse.getX()); + if (caretPos > prevCaret) { + if (!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + else + start = x + this.width / 2f - halfTextWidth + this.getTextWidth(vg, input.substring(0, prevCaret)); + end = this.getTextWidth(vg, input.substring(prevCaret, caretPos)); + selectedText = input.substring(prevCaret, caretPos); + } else { + if (!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + else + start