From 8462c4fd0be929c6cf594cda613fa4b9ded19e9e Mon Sep 17 00:00:00 2001 From: boomboompower Date: Sat, 7 Mar 2020 18:42:30 +1100 Subject: [PATCH] Work on UI #4 --- .../skinchanger/commands/SkinCommand.java | 5 + .../mods/skinchanger/gui/SkinChangerMenu.java | 82 ++++- .../utils/general/Prerequisites.java | 13 + .../skinchanger/utils/general/XYPosition.java | 39 +++ .../skinchanger/utils/gui/ModernDrawable.java | 57 ++++ .../utils/gui/impl/ModernBlurBox.java | 114 +++++++ .../utils/gui/impl/ModernButton.java | 120 ++++++- .../skinchanger/utils/gui/impl/ModernGui.java | 64 +++- .../utils/gui/impl/ModernHeader.java | 315 ++++++++++++++++++ .../utils/gui/impl/ModernSlider.java | 137 ++++++++ .../skinchanger/utils/mod/CacheRetriever.java | 4 + 11 files changed, 932 insertions(+), 18 deletions(-) create mode 100644 src/main/java/me/do_you_like/mods/skinchanger/utils/general/XYPosition.java create mode 100644 src/main/java/me/do_you_like/mods/skinchanger/utils/gui/ModernDrawable.java create mode 100644 src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernBlurBox.java create mode 100644 src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernHeader.java create mode 100644 src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernSlider.java diff --git a/src/main/java/me/do_you_like/mods/skinchanger/commands/SkinCommand.java b/src/main/java/me/do_you_like/mods/skinchanger/commands/SkinCommand.java index 735d848..6fbbc19 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/commands/SkinCommand.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/commands/SkinCommand.java @@ -24,6 +24,7 @@ import java.util.List; import me.do_you_like.mods.skinchanger.SkinChangerMod; +import me.do_you_like.mods.skinchanger.gui.SkinChangerMenu; import me.do_you_like.mods.skinchanger.utils.backend.InternetConnection; import me.do_you_like.mods.skinchanger.utils.resources.LocalFileData; import me.do_you_like.mods.skinchanger.utils.game.ChatColor; @@ -97,6 +98,10 @@ public void onCommand(ICommandSender sender, String[] args) { sendMessage(ChatColor.AQUA + "Your skin is now " + (IS_SLIM_SKIN ? "slim" : "normal")); + return; + } else if (args[0].equalsIgnoreCase("ui") || args[0].equalsIgnoreCase("gui")) { + new SkinChangerMenu().display(); + return; } } diff --git a/src/main/java/me/do_you_like/mods/skinchanger/gui/SkinChangerMenu.java b/src/main/java/me/do_you_like/mods/skinchanger/gui/SkinChangerMenu.java index 1a2f80f..67f59b7 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/gui/SkinChangerMenu.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/gui/SkinChangerMenu.java @@ -17,24 +17,104 @@ package me.do_you_like.mods.skinchanger.gui; +import java.awt.Color; + import me.do_you_like.mods.skinchanger.utils.gui.impl.ModernButton; import me.do_you_like.mods.skinchanger.utils.gui.impl.ModernGui; +import me.do_you_like.mods.skinchanger.utils.gui.impl.ModernHeader; +import me.do_you_like.mods.skinchanger.utils.gui.impl.ModernSlider; public class SkinChangerMenu extends ModernGui { + // ModernHeader hack + // + // For the middle of the left half of the screen do: + // xPosition = (this.width / 2) / scale + // + // For the middle of the right half of the screen do: + // xPosition = (this.width / 2) * scale + @Override public void onGuiOpen() { + ModernHeader title = new ModernHeader((int) ((this.width / 2) / 1.5F), 12, "SkinChanger", 1.5F, false); + + title.setDrawCentered(true); + + // ---------------------------------- + + ModernHeader skinSettings = new ModernHeader(95, 165, "Skin Settings", 1.20F, true, Color.RED); + + skinSettings.setOffsetBetweenDrawables(32F); + + skinSettings.getSubDrawables().add(new ModernButton(12, 5, 20, "Load from Player").setAsPartOfHeader(skinSettings)); + skinSettings.getSubDrawables().add(new ModernButton(13, 5, 20, "Load from URL").setAsPartOfHeader(skinSettings)); + skinSettings.getSubDrawables().add(new ModernButton(14, 5, 20, "Load from File").setAsPartOfHeader(skinSettings)); + skinSettings.getSubDrawables().add(new ModernButton(15, 5, 20, "Reset Skin").setAsPartOfHeader(skinSettings)); + + // ---------------------------------- + + ModernHeader capeSettings = new ModernHeader(95, 585, "Cape Settings", 1.25F, true, Color.GREEN); + + capeSettings.getSubDrawables().add(new ModernButton(12, 5, 20, "Load from Player").setAsPartOfHeader(capeSettings)); + capeSettings.getSubDrawables().add(new ModernButton(13, 5, 20, "Load from URL").setAsPartOfHeader(capeSettings)); + capeSettings.getSubDrawables().add(new ModernButton(14, 5, 20, "Load from File").setAsPartOfHeader(capeSettings)); + capeSettings.getSubDrawables().add(new ModernButton(15, 5, 20, "Reset Skin").setAsPartOfHeader(capeSettings)); + + // ---------------------------------- + + ModernHeader recentSkins = new ModernHeader(525, 165, "Recent Skins", 1.3F, true, Color.YELLOW); + // ---------------------------------- + + ModernHeader recentCapes = new ModernHeader(525, 585, "Recent Capes", 1.33F, true, Color.LIGHT_GRAY); + + // ---------------------------------- + + this.headerList.add(title); + this.headerList.add(skinSettings); + this.headerList.add(capeSettings); + this.headerList.add(recentSkins); + this.headerList.add(recentCapes); + + this.sliderList.add(new ModernSlider(5, this.width / 2 - 100, this.height / 2 + 74, 200, 20, "Scale: ", 1.0F, 200.0F, 100.0F) { + @Override + public void onSliderUpdate() { + System.out.println(getValue() / 100); + + for (ModernHeader header : SkinChangerMenu.this.headerList) { + if (header == title) { + continue; + } + + header.setScaleSize((float) (getValue() / 100.0D)); + } + } + }); + + this.sliderList.add(new ModernSlider(6, this.width / 2 - 100, this.height / 2 + 98, 200, 20, "Offset: ", 1.0F, 100.0F, 50.0F) { + @Override + public void onSliderUpdate() { + skinSettings.getWidth(); + + //skinSettings.setOffsetBetweenDrawables((float) (getValue() / 1.0D)); + } + }); } @Override - public void preRender() { + public void onGuiClose() { + this.headerList.clear(); + } + @Override + public void preRender() { } @Override public void onRender(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + drawCenteredString(this.fontRendererObj, "by boomboompower", this.width / 2, 16, Color.CYAN.getRGB()); } @Override diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/general/Prerequisites.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/general/Prerequisites.java index 8973cb9..91ed376 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/utils/general/Prerequisites.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/general/Prerequisites.java @@ -100,4 +100,17 @@ public static void notEmpty(String value, String errorMessage) { // Hit em with the fat exception throw new IllegalArgumentException(errorMessage); } + + public static void conditionMet(boolean condition) { + conditionMet(condition, "Condition was not met."); + } + + public static void conditionMet(boolean condition, String errorMessage) { + if (condition) { + return; + } + + // Hit em with the fat exception + throw new IllegalArgumentException(errorMessage); + } } diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/general/XYPosition.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/general/XYPosition.java new file mode 100644 index 0000000..26816e9 --- /dev/null +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/general/XYPosition.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 boomboompower + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.do_you_like.mods.skinchanger.utils.general; + +import lombok.Getter; + +public class XYPosition { + + @Getter + private final float x; + + @Getter + private final float y; + + public XYPosition(XYPosition position) { + this.x = position.x; + this.y = position.y; + } + + public XYPosition(float x, float y) { + this.x = x; + this.y = y; + } +} diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/ModernDrawable.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/ModernDrawable.java new file mode 100644 index 0000000..b413059 --- /dev/null +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/ModernDrawable.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 boomboompower + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.do_you_like.mods.skinchanger.utils.gui; + +import me.do_you_like.mods.skinchanger.utils.gui.impl.ModernHeader; + +public interface ModernDrawable { + + public int getX(); + + public int getY(); + + /** + * Calls the render function for the drawable. + * + * @param mouseX the current x position of the mouse. + * @param mouseY the current y position of the mouse. + */ + public void render(int mouseX, int mouseY); + + public default void renderFromHeader(int xPos, int yPos, int mouseX, int mouseY, int recommendedYOffset) { + render(mouseX, mouseY); + } + + /** + * Should this drawable be drawn? If this is false the header will not call the {@link #render(int, int)} method. + * + * @return true if {@link #render(int, int)} should be called for the drawable. + */ + public boolean isEnabled(); + + public ModernDrawable setAsPartOfHeader(ModernHeader parent); + + /** + * Should this drawable be rendered relative to its header (if its part of one)? + * + * @return true if the drawable should be moved based on header position. + */ + public default boolean renderRelativeToHeader() { + return true; + } +} diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernBlurBox.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernBlurBox.java new file mode 100644 index 0000000..30fbf97 --- /dev/null +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernBlurBox.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2020 boomboompower + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.do_you_like.mods.skinchanger.utils.gui.impl; + +import java.io.File; +import lombok.Getter; +import lombok.Setter; + +import me.do_you_like.mods.skinchanger.utils.gui.ModernDrawable; +import me.do_you_like.mods.skinchanger.utils.resources.LocalFileData; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; + +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +import org.lwjgl.opengl.GL11; + +public class ModernBlurBox implements ModernDrawable { + + @Getter + private int x; + + @Getter + private int y; + + @Getter + @Setter + private int width; + + @Getter + @Setter + private int height; + + @Getter + @Setter + private boolean enabled; + + public ModernBlurBox(int xPos, int yPos, int width, int height) { + + } + + @Override + public void render(int mouseX, int mouseY) { + ResourceLocation location = new ResourceLocation("textures/misc/vignette.png"); + + LocalFileData data = new LocalFileData(location, new File("icon.png")); + + GlStateManager.disableDepth(); + GlStateManager.disableAlpha(); + GlStateManager.enableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.alphaFunc(770, 771); + + GlStateManager.bindTexture(data.getGlTextureId()); + + GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, this.x, this.y, this.x + this.width, this.y + this.height, 1); + + ScaledResolution scaler = new ScaledResolution(Minecraft.getMinecraft()); + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer renderer = tessellator.getWorldRenderer(); + + renderer.color(1.0F, 1.0F, 1.0F, 1.0F); + renderer.begin(7, DefaultVertexFormats.POSITION_TEX); // 7 = OpenGl.GL_QUADS + + // tessellator.addVertexWithUV(x,y,z,u,v); + // to + // renderer.pos(x,y,z).tex(u,v).endVertex(); + + renderer.pos(this.x / (scaler.getScaleFactor() * 2.0f), this.y + this.height / (scaler.getScaleFactor() * 2.0f), 0).tex(0.0f, 0.0f).endVertex(); + renderer.pos(this.x + this.width / (scaler.getScaleFactor() * 2.0f), this.y + this.height / (scaler.getScaleFactor() * 2.0f), 1.0F).tex(1.0f, 0.0f).endVertex(); + renderer.pos(this.x + this.width / (scaler.getScaleFactor() * 2.0f), this.y / (scaler.getScaleFactor() * 2.0f), 0).tex(1.0f, 1.0f).endVertex(); + renderer.pos( this.x / (scaler.getScaleFactor() * 2.0f), this.y / (scaler.getScaleFactor() * 2.0f), 0).tex(0.0f, 1.0f).endVertex(); + + GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, this.x, this.y, this.x + this.width, this.y + this.height, 1); + + tessellator.draw(); + } + + @Override + public void renderFromHeader(int xPos, int yPos, int mouseX, int mouseY, int recommendedYOffset) { + + } + + @Override + public boolean renderRelativeToHeader() { + return true; + } + + @Override + public ModernDrawable setAsPartOfHeader(ModernHeader parent) { + return this; + } +} diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernButton.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernButton.java index 0fe2e2e..c2d2f41 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernButton.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernButton.java @@ -20,11 +20,14 @@ import lombok.Getter; import lombok.Setter; +import me.do_you_like.mods.skinchanger.utils.general.XYPosition; +import me.do_you_like.mods.skinchanger.utils.gui.ModernDrawable; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; @@ -36,7 +39,7 @@ * @author boomboompower * @version 2.0 */ -public class ModernButton extends Gui { +public class ModernButton extends Gui implements ModernDrawable { protected static final ResourceLocation buttonTextures = new ResourceLocation("textures/gui/widgets.png"); @@ -75,6 +78,11 @@ public class ModernButton extends Gui { @Getter private Object buttonData; + @Getter + private boolean partOfHeader; + + private ModernHeader parentHeader; + public ModernButton(int buttonId, int x, int y, String buttonText) { this(buttonId, "", x, y, 200, 20, buttonText); } @@ -116,34 +124,47 @@ protected int getHoverState(boolean mouseOver) { return i; } - /** - * Draws this button to the screen. - */ - public void drawButton(Minecraft mc, int mouseX, int mouseY) { + @Override + public int getX() { + return this.xPosition; + } + + @Override + public int getY() { + return this.yPosition; + } + + @Override + public void render(int mouseX, int mouseY) { if (this.visible) { - FontRenderer fontrenderer = mc.fontRendererObj; + FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - this.hovered = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height; + + int xPosition = this.xPosition; + int yPosition = this.yPosition; + + this.hovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + this.width && mouseY < yPosition + this.height; int i = this.getHoverState(this.hovered); int j = 14737632; - boolean modern = true; //SkinChangerMod.getInstance().getConfigurationHandler().isModernButton(); + boolean modern = false; //SkinChangerMod.getInstance().getConfigurationHandler().isModernButton(); if (modern) { - mc.getTextureManager().bindTexture(buttonTextures); + Minecraft.getMinecraft().getTextureManager().bindTexture(buttonTextures); GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); GlStateManager.blendFunc(770, 771); - this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, 46 + i * 20, this.width / 2, this.height); - this.drawTexturedModalRect(this.xPosition + this.width / 2, this.yPosition, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height); + this.drawTexturedModalRect(xPosition, yPosition, 0, 46 + i * 20, this.width / 2, this.height); + this.drawTexturedModalRect(xPosition + this.width / 2, yPosition, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height); } else { if (this.enabled) { - drawRect(this.xPosition, this.yPosition, this.xPosition + this.width, this.yPosition + height, getEnabledColor().getRGB()); + drawRect(xPosition, yPosition, xPosition + this.width, yPosition + height, getEnabledColor().getRGB()); } else { - drawRect(this.xPosition, this.yPosition, this.xPosition + this.width, this.yPosition + height, getDisabledColor().getRGB()); + drawRect(xPosition, yPosition, xPosition + this.width, yPosition + height, getDisabledColor().getRGB()); } } @@ -154,15 +175,82 @@ public void drawButton(Minecraft mc, int mouseX, int mouseY) { } if (this.enabled && this.favourite) { - fontrenderer.drawString("\u2726", this.xPosition + this.width - fontrenderer.getStringWidth("\u2726") - 4, this.yPosition + ((fontrenderer.FONT_HEIGHT / 2) + 2), Color.ORANGE.getRGB()); + fontrenderer.drawString("\u2726", xPosition + this.width - fontrenderer.getStringWidth("\u2726") - 4, yPosition + ((fontrenderer.FONT_HEIGHT / 2) + 2), Color.ORANGE.getRGB()); } - fontrenderer.drawString(this.displayString, (this.xPosition + this.width / 2 - fontrenderer.getStringWidth(this.displayString) / 2), this.yPosition + (this.height - 8) / 2, j, modern); + fontrenderer.drawString(this.displayString, (xPosition + this.width / 2 - fontrenderer.getStringWidth(this.displayString) / 2), yPosition + (this.height - 8) / 2, j, modern); } } + @Override + public void renderFromHeader(int xPos, int yPos, int mouseX, int mouseY, int recommendedYOffset) { + if (this.visible) { + FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj; + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + int xPosition = xPos + 5; + int yPosition = yPos + recommendedYOffset; + + this.hovered = mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + this.width && mouseY < yPosition + this.height; + int i = this.getHoverState(this.hovered); + + int j = 14737632; + + boolean modern = false; //SkinChangerMod.getInstance().getConfigurationHandler().isModernButton(); + + if (modern) { + Minecraft.getMinecraft().getTextureManager().bindTexture(buttonTextures); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.blendFunc(770, 771); + + this.drawTexturedModalRect(xPosition, yPosition, 0, 46 + i * 20, this.width / 2, this.height); + this.drawTexturedModalRect(xPosition + this.width / 2, yPosition, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height); + } else { + if (this.enabled) { + drawRect(xPosition, yPosition, xPosition + this.width, yPosition + height, getEnabledColor().getRGB()); + } else { + drawRect(xPosition, yPosition, xPosition + this.width, yPosition + height, getDisabledColor().getRGB()); + } + } + + if (!this.enabled) { + j = 10526880; + } else if (this.hovered) { + j = 16777120; + } + + if (this.enabled && this.favourite) { + fontrenderer.drawString("\u2726", xPosition + this.width - fontrenderer.getStringWidth("\u2726") - 4, yPosition + ((fontrenderer.FONT_HEIGHT / 2) + 2), Color.ORANGE.getRGB()); + } + + fontrenderer.drawString(this.displayString, (xPosition + this.width / 2 - fontrenderer.getStringWidth(this.displayString) / 2), yPosition + (this.height - 8) / 2, j, modern); + } + } + + @Override + public ModernDrawable setAsPartOfHeader(ModernHeader parent) { + this.partOfHeader = true; + + this.parentHeader = parent; + + return this; + } + public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) { - return this.enabled && this.visible && mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height; + int xPosition = this.xPosition; + int yPosition = this.yPosition; + + if (this.partOfHeader) { + XYPosition realPosition = this.parentHeader.getScreenPositionFromLocal(this); + + xPosition = (int) realPosition.getX(); + yPosition = (int) realPosition.getY(); + } + + return this.enabled && this.visible && mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + this.width && mouseY < yPosition + this.height; } public void mouseReleased(int mouseX, int mouseY) { diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernGui.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernGui.java index d04072e..e630c9f 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernGui.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernGui.java @@ -24,6 +24,7 @@ import me.do_you_like.mods.skinchanger.SkinChangerMod; import me.do_you_like.mods.skinchanger.utils.game.ChatColor; +import me.do_you_like.mods.skinchanger.utils.gui.ModernDrawable; import me.do_you_like.mods.skinchanger.utils.gui.UISkeleton; import me.do_you_like.mods.skinchanger.utils.gui.lock.UILock; @@ -53,13 +54,18 @@ public abstract class ModernGui extends UILock implements UISkeleton { protected List textList = Lists.newArrayList(); protected List buttonList = Lists.newArrayList(); + protected List headerList = Lists.newArrayList(); + protected List sliderList = Lists.newArrayList(); private ModernButton selectedButton; + private ModernSlider selectedSlider; @Override public final void initGui() { this.textList.clear(); this.buttonList.clear(); + this.sliderList.clear(); + this.headerList.clear(); onGuiOpen(); } @@ -100,7 +106,7 @@ public final void drawScreen(int mouseX, int mouseY, float partialTicks) { } for (ModernButton button : this.buttonList) { - button.drawButton(this.mc, mouseX, mouseY); + button.render(mouseX, mouseY); } for (GuiLabel label : this.labelList) { @@ -111,6 +117,18 @@ public final void drawScreen(int mouseX, int mouseY, float partialTicks) { text.drawTextBox(); } + for (ModernSlider slider : this.sliderList) { + slider.drawButton(this.mc, mouseX, mouseY); + } + + for (ModernHeader header : this.headerList) { + GlStateManager.pushMatrix(); + + header.render(mouseX, mouseY); + + GlStateManager.popMatrix(); + } + try { postRender(); } catch (Exception ex) { @@ -144,6 +162,24 @@ protected final void keyTyped(char typedChar, int keyCode) { @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { if (mouseButton == 0) { + for (ModernHeader header : this.headerList) { + if (header.getSubDrawables().size() > 0) { + for (ModernDrawable drawable : header.getSubDrawables()) { + if (drawable instanceof ModernButton) { + ModernButton button = (ModernButton) drawable; + + if (button.mousePressed(this.mc, mouseX, mouseY)) { + this.selectedButton = button; + + button.playPressSound(this.mc.getSoundHandler()); + + buttonPressed(button); + } + } + } + } + } + for (ModernButton button : this.buttonList) { if (button.mousePressed(this.mc, mouseX, mouseY)) { this.selectedButton = button; @@ -156,6 +192,20 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { } if (mouseButton == 1) { + for (ModernHeader header : this.headerList) { + if (header.getSubDrawables().size() > 0) { + for (ModernDrawable drawable : header.getSubDrawables()) { + if (drawable instanceof ModernButton) { + ModernButton button = (ModernButton) drawable; + + if (button.mousePressed(this.mc, mouseX, mouseY)) { + rightClicked(button); + } + } + } + } + } + for (ModernButton button : this.buttonList) { if (button != null) { if (button.mousePressed(this.mc, mouseX, mouseY)) { @@ -168,6 +218,12 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { for (ModernTextBox text : this.textList) { text.mouseClicked(mouseX, mouseY, mouseButton); } + + for (ModernSlider slider : this.sliderList) { + if (slider.mousePressed(this.mc, mouseX, mouseY)) { + this.selectedSlider = slider; + } + } } @Override @@ -181,6 +237,7 @@ public void setWorldAndResolution(Minecraft mc, int width, int height) { this.textList.clear(); this.buttonList.clear(); + this.headerList.clear(); initGui(); } @@ -198,6 +255,11 @@ protected final void mouseReleased(int mouseX, int mouseY, int state) { this.selectedButton.mouseReleased(mouseX, mouseY); this.selectedButton = null; } + + if (this.selectedSlider != null && state == 0) { + this.selectedSlider.mouseReleased(mouseX, mouseY); + this.selectedSlider = null; + } } /** diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernHeader.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernHeader.java new file mode 100644 index 0000000..092ad43 --- /dev/null +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernHeader.java @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2020 boomboompower + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.do_you_like.mods.skinchanger.utils.gui.impl; + +import com.google.common.collect.Lists; + +import java.awt.Color; +import java.util.List; + +import lombok.Getter; +import lombok.Setter; + +import me.do_you_like.mods.skinchanger.utils.general.Prerequisites; +import me.do_you_like.mods.skinchanger.utils.general.XYPosition; +import me.do_you_like.mods.skinchanger.utils.gui.ModernDrawable; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; + +/** + * A simple class for drawing headers. Useful for UI categories. + * + * @version 1.1 + * @author boomboompower + */ +public class ModernHeader extends Gui implements ModernDrawable { + + @Getter + private int x; + + @Getter + private int y; + + @Getter + private String headerText; + + @Getter + @Setter + private float scaleSize; + + @Getter + private boolean drawUnderline; + + @Getter + @Setter + private boolean visible = true; + + @Getter + @Setter + private boolean drawCentered = false; + + @Getter + @Setter + private Color headerColor; + + @Getter + private List subDrawables; + + @Getter + @Setter + private float offsetBetweenDrawables = 12; + + private ScaledResolution scaledResolution; + + /** + * Basic constructor for UI headers. Scale size is 1.5 of normal text. Draws an underline. + * + * @param x the x location of the header + * @param y the y location of the header + * @param header the text which will be rendered + */ + public ModernHeader(int x, int y, String header) { + this(x, y, header, 1.5F, true); + } + + /** + * Basic constructor for UI headers. Draws an underline. + * + * @param x the x location of the header + * @param y the y location of the header + * @param header the text which will be rendered + * @param scaleSize the scale of the text. (scale > 1 means bigger) + */ + public ModernHeader(int x, int y, String header, float scaleSize) { + this(x, y, header, scaleSize, true); + } + + /** + * Basic constructor for UI headers. Draws an underline. + * + * @param x the x location of the header + * @param y the y location of the header + * @param header the text which will be rendered + * @param scaleSize the scale of the text. (scale > 1 means bigger) + */ + public ModernHeader(int x, int y, String header, int scaleSize) { + this(x, y, header, scaleSize, true); + } + + /** + * Basic constructor for UI headers. + * + * @param x the x location of the header + * @param y the y location of the header + * @param header the text which will be rendered + * @param scaleSize the scale of the text. (scale > 1 means bigger) + * @param drawUnderline true if an underline should be drawn. + */ + public ModernHeader(int x, int y, String header, float scaleSize, boolean drawUnderline) { + this(x, y, header, scaleSize, drawUnderline, Color.WHITE); + } + + /** + * Basic constructor for UI headers. + * + * @param x the x location of the header + * @param y the y location of the header + * @param header the text which will be rendered + * @param scaleSize the scale of the text. (scale > 1 means bigger) + * @param drawUnderline true if an underline should be drawn. + * @param color the color of which the elements will be drawn. + */ + public ModernHeader(int x, int y, String header, float scaleSize, boolean drawUnderline, Color color) { + Prerequisites.notNull(header); + Prerequisites.conditionMet(scaleSize > 0, "Scale cannot be less than 0"); + + this.x = x; + this.y = y; + + this.headerText = header; + this.scaleSize = scaleSize; + this.drawUnderline = drawUnderline; + this.headerColor = color; + + this.scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + this.subDrawables = Lists.newArrayList(); + } + + @Override + public void render(int mouseX, int mouseY) { + if (!this.visible) { + return; + } + + ScaledResolution resolution = getScaledResolution(); + + if (resolution == null) { + return; + } + + // Retrieve the renderer. + FontRenderer fontRenderer = getFontRenderer(); + + // Ensure minecraft actually has a font renderer we can use. + if (fontRenderer == null) { + return; + } + + // Push the stack, making our own GL sandbox. + GlStateManager.pushMatrix(); + + // Reset the colors. + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + //GlStateManager.scale(-Minecraft.getMinecraft().gameSettings.guiScale, -Minecraft.getMinecraft().gameSettings.guiScale, 0F); + + // Scales it up + GlStateManager.scale(this.scaleSize, this.scaleSize, 0F); + + float xPos = this.x ;/// Minecraft.getMinecraft().gameSettings.guiScale; + float yPos = this.y ;/// Minecraft.getMinecraft().gameSettings.guiScale; + + if (this.drawCentered) { + // Draws the text + fontRenderer.drawString(this.headerText, (xPos / this.scaleSize) - (getWidth() / this.scaleSize), yPos / this.scaleSize, this.headerColor.getRGB(), false); + } else { + // Draws the text + fontRenderer.drawString(this.headerText, xPos / this.scaleSize, yPos / this.scaleSize, this.headerColor.getRGB(), false); + } + + // Check if the header should have an underline or not. + if (this.drawUnderline) { + drawHorizontalLine((int) (xPos / this.scaleSize), (int) ((xPos + (getWidth() * this.scaleSize)) / this.scaleSize), (int) ((yPos + (12 * this.scaleSize)) / this.scaleSize), this.headerColor.getRGB()); + } + + // Pop the changes to the gl stack. + GlStateManager.popMatrix(); + + if (this.subDrawables.size() > 0) { + float yOffset = (12 * this.scaleSize) + this.offsetBetweenDrawables / 2; + + for (ModernDrawable drawable : this.subDrawables) { + if (drawable.isEnabled()) { + + // Renders relative to this headers position. + if (drawable.renderRelativeToHeader()) { + GlStateManager.pushMatrix(); + + //GlStateManager.translate(xPos / this.scaleSize, yPos / this.scaleSize, 0.0F); + + drawable.renderFromHeader((int) xPos, (int) yPos, mouseX, mouseY, (int) yOffset); + + GlStateManager.popMatrix(); + } else { + drawable.renderFromHeader((int) xPos, (int) yPos, mouseX, mouseY, (int) yOffset); + } + } + + yOffset += this.offsetBetweenDrawables; + } + } + } + + @Override + public boolean isEnabled() { + return this.visible; + } + + @Override + public ModernDrawable setAsPartOfHeader(ModernHeader parent) { + return this; + } + + /** + * The width of this string based off the FontRenderer's width calculations. + * + * @return the width of the string. + */ + public int getWidth() { + if (getFontRenderer() == null) { + return 0; + } + + return getFontRenderer().getStringWidth(this.headerText); + } + + /** + * Retrieves the minecraft font renderer if one exists, or null if not applicable + * + * @return the minecraft font renderer. + */ + private FontRenderer getFontRenderer() { + if (Minecraft.getMinecraft() == null) { + return null; + } + + return Minecraft.getMinecraft().fontRendererObj; + } + + /** + * Retrieves Minecraft's scaled resolution. + * + * @return scaled resolution. + */ + private ScaledResolution getScaledResolution() { + if (this.scaledResolution != null) { + return this.scaledResolution; + } + + if (Minecraft.getMinecraft() == null) { + return null; + } + + this.scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + + return this.scaledResolution; + } + + /** + * Force updates the resolution. + */ + public void updateResolution() { + this.scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + } + + public XYPosition getScreenPositionFromLocal(ModernDrawable drawable) { + return getScreenPositionFromLocal(drawable.getX(), drawable.getY()); + } + + public XYPosition getScreenPositionFromLocal(int x, int y) { + return new XYPosition(this.x + x, this.y + y); + } + + + /* Some good scales. + * + * Largest 2.0 + * Larger 1.58 + * Large 1.27 (a bit weird) + * Skinny 1.24 (larger skinny text) + * Skinny 1.05 (normal skinny text) + * Normal 1.0 + * Fat 0.94 (only k's are slightly distored, seems fat). + * Skinny 0.75 (a bit distorted, but skinny) + * Half 0.5 (lowest scale where text is not distorted) + */ +} diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernSlider.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernSlider.java new file mode 100644 index 0000000..9f34b9e --- /dev/null +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/gui/impl/ModernSlider.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2020 boomboompower + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package me.do_you_like.mods.skinchanger.utils.gui.impl; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; + +import java.awt.*; + +public class ModernSlider extends GuiButton { + + private boolean dragging = false; + + private double sliderValue = 1F; + private double minValue = 0D; + private double maxValue = 5D; + + private String prefix = ""; + + public ModernSlider(int id, int xPos, int yPos, int width, int height, String prefix, double minVal, double maxVal, double currentVal) { + super(id, xPos, yPos, width, height, prefix); + this.minValue = minVal; + this.maxValue = maxVal; + this.sliderValue = (currentVal - minValue) / (maxValue - minValue); + this.prefix = prefix; + + this.displayString = prefix + (int) Math.round(sliderValue * (maxValue - minValue) + minValue); + } + + @Override + public void drawButton(Minecraft mc, int mouseX, int mouseY) { + if (this.visible) { + this.hovered = mouseX >= this.xPosition && mouseY >= this.yPosition && mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height; + + if (this.enabled) { + drawRect(this.xPosition, this.yPosition, this.xPosition + width, this.yPosition + height, new Color(95, 255, 95, 75).getRGB()); + } else { + drawRect(this.xPosition, this.yPosition, this.xPosition + width, this.yPosition + height, new Color(67, 175, 67, 75).getRGB()); + } + this.mouseDragged(mc, mouseX, mouseY); + + int color = 14737632; + if (!this.enabled) { + color = Color.WHITE.getRGB(); + } else if (this.hovered) { + color = 16777120; + } + + String buttonText = this.displayString; + + int strWidth = mc.fontRendererObj.getStringWidth(buttonText); + int ellipsisWidth = mc.fontRendererObj.getStringWidth("..."); + + if (strWidth > width - 6 && strWidth > ellipsisWidth) + buttonText = mc.fontRendererObj.trimStringToWidth(buttonText, width - 6 - ellipsisWidth).trim() + "..."; + + mc.fontRendererObj.drawString(buttonText, (this.xPosition + this.width / 2 - mc.fontRendererObj.getStringWidth(buttonText) / 2), this.yPosition + (this.height - 8) / 2, color, false); + } + } + + @Override + public int getHoverState(boolean mouseOver) { + return 0; + } + + @Override + protected void mouseDragged(Minecraft par1Minecraft, int mouseX, int mouseY) { + if (this.visible) { + if (this.dragging) { + this.sliderValue = (mouseX - (this.xPosition + 4)) / (float) (this.width - 8); + updateSlider(); + } + + drawRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 4)), this.yPosition, this.xPosition + (int) (this.sliderValue * (float) (this.width - 4)) + 4, this.yPosition + this.height, Color.WHITE.getRGB()); + } + } + + @Override + public boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) { + if (super.mousePressed(minecraft, mouseX, mouseY)) { + this.sliderValue = (float) (mouseX - (this.xPosition + 4)) / (float) (this.width - 8); + updateSlider(); + this.dragging = true; + return true; + } else { + return false; + } + } + + protected final void updateSlider() { + if (this.sliderValue < 0.0F) { + this.sliderValue = 0.0F; + } + + if (this.sliderValue > 1.0F) { + this.sliderValue = 1.0F; + } + + displayString = prefix + (int) Math.round(sliderValue * (maxValue - minValue) + minValue); + + onSliderUpdate(); + } + + /** + * Override as the trigger. + */ + public void onSliderUpdate() { + } + + @Override + public void mouseReleased(int mouseX, int mouseY) { + this.dragging = false; + } + + public double getValue() { + return sliderValue * (maxValue - minValue) + minValue; + } + + public void setValue(double value) { + this.sliderValue = (value - minValue) / (maxValue - minValue); + } +} \ No newline at end of file diff --git a/src/main/java/me/do_you_like/mods/skinchanger/utils/mod/CacheRetriever.java b/src/main/java/me/do_you_like/mods/skinchanger/utils/mod/CacheRetriever.java index 094d43a..987bbf9 100644 --- a/src/main/java/me/do_you_like/mods/skinchanger/utils/mod/CacheRetriever.java +++ b/src/main/java/me/do_you_like/mods/skinchanger/utils/mod/CacheRetriever.java @@ -52,6 +52,10 @@ public CacheRetriever(SkinChangerMod mod) { this.mod = mod; this.cacheDirectory = new File(mod.getModConfigDirectory(), "cache"); + for (int i = 0; i < 50; i++) { + System.out.println(this.cacheDirectory); + } + genCacheDirectory(); }