From 07451771aa692d20eeae8963e66c5f94a5c3dd02 Mon Sep 17 00:00:00 2001 From: Chicken-Bomes Date: Fri, 25 Jul 2014 14:41:37 +1000 Subject: [PATCH] Added scrollable description override to content in GuiModList --- build/build.properties | 2 +- resources/cccmod.info | 4 +- src/codechicken/core/GuiModListScroll.java | 130 ++++++++++++++++++ .../core/asm/CodeChickenCoreModContainer.java | 34 +---- src/codechicken/core/gui/GuiCCButton.java | 62 +++++---- src/codechicken/core/gui/GuiScreenWidget.java | 43 +++--- .../core/internal/CCCEventHandler.java | 12 ++ 7 files changed, 205 insertions(+), 82 deletions(-) create mode 100644 src/codechicken/core/GuiModListScroll.java diff --git a/build/build.properties b/build/build.properties index 556524d..9442bda 100644 --- a/build/build.properties +++ b/build/build.properties @@ -1,4 +1,4 @@ mc_version=1.7.10 forge_version=10.13.0.1151 ccl_version=1.1.1.96 -mod_version=1.0.2 +mod_version=1.0.3 diff --git a/resources/cccmod.info b/resources/cccmod.info index f03bd25..abaebd3 100644 --- a/resources/cccmod.info +++ b/resources/cccmod.info @@ -1,4 +1,4 @@ -[ +[ { "modid": "CodeChickenCore", "name": "CodeChicken Core", @@ -6,6 +6,6 @@ "version": "${version}", "mcversion": "${mc_version}", "url": "http://www.minecraftforum.net/topic/909223", - "authors": [ "ChickenBones" ] + "authorList": [ "ChickenBones" ] } ] \ No newline at end of file diff --git a/src/codechicken/core/GuiModListScroll.java b/src/codechicken/core/GuiModListScroll.java new file mode 100644 index 0000000..063c3f5 --- /dev/null +++ b/src/codechicken/core/GuiModListScroll.java @@ -0,0 +1,130 @@ +package codechicken.core; + +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.lib.gui.GuiDraw; +import codechicken.lib.vec.Rectangle4i; +import cpw.mods.fml.client.GuiModList; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.ModContainer; +import cpw.mods.fml.common.ModMetadata; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.MinecraftForgeClient; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import static org.lwjgl.opengl.GL11.*; + +import java.util.LinkedList; +import java.util.List; + +public class GuiModListScroll +{ + private static List scrollMods = new LinkedList(); + + public static void register(Object mod) { + register(FMLCommonHandler.instance().findContainerFor(mod)); + } + + private static void register(ModContainer mod) { + if (MinecraftForgeClient.getStencilBits() == 0) + CodeChickenCorePlugin.logger.error("Unable to do mod description scrolling due to lack of stencil buffer"); + else + scrollMods.add(mod); + } + + private static ModContainer lastMod; + private static double scroll; + private static double lastFrameTime; + private static double timeStart; + public static void draw(GuiModList gui, int mouseX, int mouseY) { + ModContainer selectedMod = ReflectionManager.getField(GuiModList.class, ModContainer.class, gui, "selectedMod"); + if(selectedMod != lastMod) { + lastMod = selectedMod; + scroll = 0; + timeStart = ClientUtils.getRenderTime(); + } + if(!scrollMods.contains(selectedMod) || selectedMod.getMetadata().autogenerated) + return; + + int y1 = calcDescY(gui, selectedMod); + int y1draw = y1 + 10; + int y2 = gui.height-38; + int x1 = ReflectionManager.getField(GuiModList.class, Integer.class, gui, "listWidth") + 20; + int x2 = gui.width - 20; + if(x2 - x1 <= 20) + return; + + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 1); + glColorMask(false, false, false, false); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + GuiDraw.drawRect(0, 0, gui.width, gui.height, -1);//clear stencil buffer + + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + GuiDraw.drawRect(x1, y1, gui.width-x1, gui.height-y1, -1);//add description area (even below button) + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + GuiDraw.drawRect(gui.width / 2 - 75, y2, 200, 20, -1);//subtract done button + + glColorMask(true, true, true, true); + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gui.drawDefaultBackground();//fill stencil with background + + glColorMask(false, false, false, false); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + GuiDraw.drawRect(0, 0, gui.width, gui.height, -1); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + GuiDraw.drawRect(x1, y1draw, x2-x1, y2-y1draw, -1); + + glColorMask(true, true, true, true); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + String description = selectedMod.getMetadata().description; + int height = GuiDraw.fontRenderer.listFormattedStringToWidth(description, x2-x1).size()*GuiDraw.fontRenderer.FONT_HEIGHT; + + boolean needsScroll = height > y2-y1draw; + if((ClientUtils.getRenderTime() - timeStart) > 40 && needsScroll) { + double dt = ClientUtils.getRenderTime() - lastFrameTime; + if (new Rectangle4i(x1, y1draw, x2 - x1, y2 - y1draw).contains(mouseX, mouseY)) { + double d = Keyboard.isKeyDown(Keyboard.KEY_UP) ? -1 : Keyboard.isKeyDown(Keyboard.KEY_DOWN) ? 1 : 0; + scroll += d * dt * 1.5; + } else { + scroll += dt * 0.2; + } + } + lastFrameTime = ClientUtils.getRenderTime(); + + //draw description + + double dy = scroll % (height + 20); + GL11.glPushMatrix(); + GL11.glTranslated(0, -dy, 0); + GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2-x1, 0xDDDDDD); + if(needsScroll) { + GL11.glTranslated(0, height + 20, 0); + GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD); + } + GL11.glPopMatrix(); + + glDisable(GL_STENCIL_TEST); + } + + /** + * Does not add the last 10 px space before the description normally starts + * Ignores empty child mods expecting a background draw overwrite + */ + private static int calcDescY(GuiModList gui, ModContainer mod) { + ModMetadata meta = mod.getMetadata(); + int y = 35; + if(!!meta.logoFile.isEmpty() && ReflectionManager.getField(GuiModList.class, ResourceLocation.class, gui, "cachedLogo") != null) + y += 65; + y += 12; // title + y += 40; // necessary lines + if(!meta.credits.isEmpty()) + y += 10; + if(!meta.childMods.isEmpty()) + y += 10; + return y; + } +} diff --git a/src/codechicken/core/asm/CodeChickenCoreModContainer.java b/src/codechicken/core/asm/CodeChickenCoreModContainer.java index 75d934f..2d8caf2 100644 --- a/src/codechicken/core/asm/CodeChickenCoreModContainer.java +++ b/src/codechicken/core/asm/CodeChickenCoreModContainer.java @@ -3,8 +3,6 @@ package codechicken.core.asm; import java.io.File; import java.util.LinkedList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import codechicken.core.CCUpdateChecker; import codechicken.core.featurehack.LiquidTextures; @@ -12,8 +10,6 @@ import codechicken.core.internal.CCCEventHandler; import codechicken.core.launch.CodeChickenCorePlugin; import codechicken.lib.config.ConfigFile; -import codechicken.lib.config.ConfigTag; -import com.google.common.base.Function; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -23,6 +19,7 @@ import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.versioning.ArtifactVersion; import cpw.mods.fml.common.versioning.VersionParser; import cpw.mods.fml.common.versioning.VersionRange; +import net.minecraftforge.common.MinecraftForge; public class CodeChickenCoreModContainer extends DummyModContainer { @@ -64,38 +61,11 @@ public class CodeChickenCoreModContainer extends DummyModContainer if (event.getSide().isClient()) { if (config.getTag("checkUpdates").getBooleanValue(true)) CCUpdateChecker.updateCheck(getModId()); - notificationCheck(); FMLCommonHandler.instance().bus().register(new CCCEventHandler()); + MinecraftForge.EVENT_BUS.register(new CCCEventHandler()); } } - private void notificationCheck() { - final ConfigTag tag = config.getTag("checkNotifications").setComment("The most recent notification number recieved. -1 to disable"); - final int notify = tag.getIntValue(0); - if(notify < 0) - return; - - CCUpdateChecker.updateCheck( - "http://www.chickenbones.net/Files/notification/general.php", - new Function() - { - @Override - public Void apply(String ret) { - Matcher m = Pattern.compile("Ret \\((\\d+)\\): (.+)").matcher(ret); - if (!m.matches()) { - CodeChickenCorePlugin.logger.error("Failed to check notifications: " + ret); - return null; - } - int index = Integer.parseInt(m.group(1)); - if(index > notify) { - tag.setIntValue(index); - CCUpdateChecker.addUpdateMessage(m.group(2)); - } - return null; - } - }); - } - @Override public VersionRange acceptableMinecraftVersionRange() { return VersionParser.parseRange(CodeChickenCorePlugin.mcVersion); diff --git a/src/codechicken/core/gui/GuiCCButton.java b/src/codechicken/core/gui/GuiCCButton.java index 5f6e7b4..c1571ef 100644 --- a/src/codechicken/core/gui/GuiCCButton.java +++ b/src/codechicken/core/gui/GuiCCButton.java @@ -12,63 +12,65 @@ public class GuiCCButton extends GuiWidget public String actionCommand; private boolean isEnabled = true; public boolean visible = true; - - public GuiCCButton(int x, int y, int width, int height, String text) - { + + public GuiCCButton(int x, int y, int width, int height, String text) { super(x, y, width, height); this.text = text; } - - public void setText(String s) - { + + public void setText(String s) { text = s; } - - public boolean isEnabled() - { + + public boolean isEnabled() { return isEnabled; } - public void setEnabled(boolean b) - { + public void setEnabled(boolean b) { isEnabled = b; } - + @Override - public void mouseClicked(int x, int y, int button) - { - if(isEnabled && pointInside(x, y) && actionCommand != null) - { + public void mouseClicked(int x, int y, int button) { + if (isEnabled && pointInside(x, y) && actionCommand != null) { sendAction(actionCommand, button); Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); } } - + @Override - public void draw(int mousex, int mousey, float frame) - { - if(!visible) + public void draw(int mousex, int mousey, float frame) { + if (!visible) return; - - renderEngine.bindTexture(guiTex); + + drawButtonTex(mousex, mousey); + if(text != null) + drawText(mousex, mousey); + } + + public void drawButtonTex(int mousex, int mousey) { GL11.glColor4f(1, 1, 1, 1); - boolean mouseover = pointInside(mousex, mousey); - int state = !isEnabled ? 0 : mouseover ? 2 : 1; + renderEngine.bindTexture(guiTex); + int state = getButtonTex(mousex, mousey); drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2);//top left drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2);//top right drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom left drawTexturedModalRect(x + width / 2, y + height / 2, 200 - width / 2, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom right - + } + + public int getButtonTex(int mousex, int mousey) { + return !isEnabled ? 0 : pointInside(mousex, mousey) ? 2 : 1; + } + + public void drawText(int mousex, int mousey) { drawCenteredString(fontRenderer, text, x + width / 2, y + (height - 8) / 2, getTextColour(mousex, mousey)); } - - public int getTextColour(int mousex, int mousey) - { + + public int getTextColour(int mousex, int mousey) { return !isEnabled ? 0xFFA0A0A0 : pointInside(mousex, mousey) ? 0xFFFFFFA0 : 0xFFE0E0E0; } - public GuiCCButton setActionCommand(String string) - { + public GuiCCButton setActionCommand(String string) { actionCommand = string; return this; } diff --git a/src/codechicken/core/gui/GuiScreenWidget.java b/src/codechicken/core/gui/GuiScreenWidget.java index 1bc7b88..1138a9b 100644 --- a/src/codechicken/core/gui/GuiScreenWidget.java +++ b/src/codechicken/core/gui/GuiScreenWidget.java @@ -11,51 +11,56 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; public class GuiScreenWidget extends GuiScreen implements IGuiActionListener -{ +{ public ArrayList widgets = new ArrayList(); public int xSize, ySize, guiTop, guiLeft; - + public GuiScreenWidget() { this(176, 166); } - + public GuiScreenWidget(int xSize, int ySize) { super(); this.xSize = xSize; this.ySize = ySize; } - + @Override public void initGui() { guiTop = (height - ySize) / 2; guiLeft = (width - xSize) / 2; + if(!widgets.isEmpty()) + resize(); } - + public void reset() { - initGui(); widgets.clear(); + initGui(); addWidgets(); + resize(); } - + @Override public void setWorldAndResolution(Minecraft mc, int i, int j) { boolean init = this.mc == null; super.setWorldAndResolution(mc, i, j); - if(init) + if(init) { addWidgets(); + resize(); + } } - + public void add(GuiWidget widget) { widgets.add(widget); widget.onAdded(this); } - + @Override public void drawScreen(int mousex, int mousey, float f) { @@ -66,11 +71,11 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener drawForeground(); GL11.glTranslated(-guiLeft, -guiTop, 0); } - + public void drawBackground() { } - + public void drawForeground() { } @@ -82,7 +87,7 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener for(GuiWidget widget : widgets) widget.mouseClicked(x-guiLeft, y-guiTop, button); } - + @Override protected void mouseMovedOrUp(int x, int y, int button) { @@ -90,7 +95,7 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener for(GuiWidget widget : widgets) widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button); } - + @Override protected void mouseClickMove(int x, int y, int button, long time) { @@ -98,7 +103,7 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener for(GuiWidget widget : widgets) widget.mouseDragged(x-guiLeft, y-guiTop, button, time); } - + @Override public void updateScreen() { @@ -107,13 +112,13 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener for(GuiWidget widget : widgets) widget.update(); } - + @Override public void keyTyped(char c, int keycode) { super.keyTyped(c, keycode); for(GuiWidget widget : widgets) - widget.keyTyped(c, keycode); + widget.keyTyped(c, keycode); } @Override @@ -135,6 +140,10 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener { } + public void resize() + { + } + public void addWidgets() { } diff --git a/src/codechicken/core/internal/CCCEventHandler.java b/src/codechicken/core/internal/CCCEventHandler.java index c547515..3775fe2 100644 --- a/src/codechicken/core/internal/CCCEventHandler.java +++ b/src/codechicken/core/internal/CCCEventHandler.java @@ -2,9 +2,14 @@ package codechicken.core.internal; import codechicken.core.CCUpdateChecker; +import codechicken.core.GuiModListScroll; +import cpw.mods.fml.client.GuiModList; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.gameevent.TickEvent.Phase; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraftforge.client.event.GuiScreenEvent; public class CCCEventHandler { @@ -24,4 +29,11 @@ public class CCCEventHandler if(event.phase == Phase.START) renderFrame = event.renderTickTime; } + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void posGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + if(event.gui instanceof GuiModList) + GuiModListScroll.draw((GuiModList)event.gui, event.mouseX, event.mouseY); + } }