From 479c7f8b54d479a32aff56d7e1089b152a3cdde0 Mon Sep 17 00:00:00 2001 From: Lex Manos Date: Wed, 4 Nov 2015 13:57:47 -0800 Subject: [PATCH] Redesign the ModList GUI to use a scrolling list for the main body content. Allowing for larger information to be displayed. URLs are auto-detected and now clickable. Mod Logos are now centered, it looks better. --- .../net/minecraftforge/common/ForgeHooks.java | 41 +- .../fml/client/GuiIngameModOptions.java | 2 +- .../minecraftforge/fml/client/GuiModList.java | 423 ++++++++++++------ .../fml/client/GuiModOptionList.java | 10 +- .../fml/client/GuiScrollingList.java | 363 +++++++-------- .../fml/client/GuiSlotModList.java | 54 ++- src/main/resources/mcplogo.png | Bin 6940 -> 3926 bytes src/main/resources/mcpmod.info | 6 +- 8 files changed, 527 insertions(+), 372 deletions(-) diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index c4c9abbf9..65dd5b154 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -57,6 +57,7 @@ import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.EnumFacing; import net.minecraft.util.IChatComponent; import net.minecraft.util.MathHelper; @@ -442,12 +443,13 @@ public class ForgeHooks "((?:[a-z0-9]{2,}:\\/\\/)?(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3}|(?:[-\\w_\\.]{1,}\\.[a-z]{2,}?))(?::[0-9]{1,5})?.*?(?=[!\"\u00A7 \n]|$))", Pattern.CASE_INSENSITIVE); - public static IChatComponent newChatWithLinks(String string) + public static IChatComponent newChatWithLinks(String string){ return newChatWithLinks(string, true); } + public static IChatComponent newChatWithLinks(String string, boolean allowMissingHeader) { // Includes ipv4 and domain pattern // Matches an ip (xx.xxx.xx.xxx) or a domain (something.com) with or // without a protocol or path. - IChatComponent ichat = new ChatComponentText(""); + IChatComponent ichat = null; Matcher matcher = URL_PATTERN.matcher(string); int lastEnd = 0; String remaining = string; @@ -459,7 +461,14 @@ public class ForgeHooks int end = matcher.end(); // Append the previous left overs. - ichat.appendText(string.substring(lastEnd, start)); + String part = string.substring(lastEnd, start); + if (part.length() > 0) + { + if (ichat == null) + ichat = new ChatComponentText(part); + else + ichat.appendText(part); + } lastEnd = end; String url = string.substring(start, end); IChatComponent link = new ChatComponentText(url); @@ -468,23 +477,43 @@ public class ForgeHooks { // Add schema so client doesn't crash. if ((new URI(url)).getScheme() == null) + { + if (!allowMissingHeader) + { + if (ichat == null) + ichat = new ChatComponentText(url); + else + ichat.appendText(url); + continue; + } url = "http://" + url; + } } catch (URISyntaxException e) { // Bad syntax bail out! - ichat.appendText(url); + if (ichat == null) ichat = new ChatComponentText(url); + else ichat.appendText(url); continue; } // Set the click event and append the link. ClickEvent click = new ClickEvent(ClickEvent.Action.OPEN_URL, url); link.getChatStyle().setChatClickEvent(click); - ichat.appendSibling(link); + link.getChatStyle().setUnderlined(true); + link.getChatStyle().setColor(EnumChatFormatting.BLUE); + if (ichat == null) + ichat = link; + else + ichat.appendSibling(link); } // Append the rest of the message. - ichat.appendText(string.substring(lastEnd)); + String end = string.substring(lastEnd); + if (ichat == null) + ichat = new ChatComponentText(end); + else if (end.length() > 0) + ichat.appendText(string.substring(lastEnd)); return ichat; } diff --git a/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java b/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java index 3424e51d6..fbee967cd 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiIngameModOptions.java @@ -21,7 +21,7 @@ public class GuiIngameModOptions extends GuiScreen public void initGui() { this.optionList=new GuiModOptionList(this); - this.optionList.registerScrollButtons(this.buttonList, 7, 8); + //this.optionList.registerScrollButtons(this.buttonList, 7, 8); this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 168, I18n.format("gui.done", new Object[0]))); } diff --git a/src/main/java/net/minecraftforge/fml/client/GuiModList.java b/src/main/java/net/minecraftforge/fml/client/GuiModList.java index 65cf2c738..ba0085f0a 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiModList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiModList.java @@ -30,6 +30,7 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.gui.GuiUtilRenderComponents; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; @@ -37,15 +38,18 @@ import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.IResourcePack; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StringUtils; +import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.ModContainer.Disableable; +import static net.minecraft.util.EnumChatFormatting.*; import org.apache.logging.log4j.Level; -import org.lwjgl.opengl.GL11; import com.google.common.base.Strings; @@ -93,14 +97,13 @@ public class GuiModList extends GuiScreen private GuiScreen mainMenu; private GuiSlotModList modList; + private GuiScrollingList modInfo; private int selected = -1; private ModContainer selectedMod; private int listWidth; private ArrayList mods; private GuiButton configModButton; private GuiButton disableModButton; - private ResourceLocation cachedLogo; - private Dimension cachedLogoDimensions; private int buttonMargin = 1; private int numButtons = SortType.values().length; @@ -152,7 +155,6 @@ public class GuiModList extends GuiScreen } listWidth = Math.min(listWidth, 150); this.modList = new GuiSlotModList(this, mods, listWidth); - this.modList.registerScrollButtons(this.buttonList, 7, 8); this.buttonList.add(new GuiButton(6, ((modList.right + this.width) / 2) - 100, this.height - 38, I18n.format("gui.done"))); configModButton = new GuiButton(20, 10, this.height - 49, this.listWidth, 20, "Config"); @@ -173,6 +175,8 @@ public class GuiModList extends GuiScreen buttonList.add(new GuiButton(SortType.A_TO_Z.buttonID, x, y, width - buttonMargin, 20, "A-Z")); x += width + buttonMargin; buttonList.add(new GuiButton(SortType.Z_TO_A.buttonID, x, y, width - buttonMargin, 20, "Z-A")); + + updateCache(); } @Override @@ -230,14 +234,15 @@ public class GuiModList extends GuiScreen } @Override - protected void actionPerformed(GuiButton button) throws IOException { + protected void actionPerformed(GuiButton button) throws IOException + { if (button.enabled) { SortType type = SortType.getTypeForButton(button); if (type != null) { - for (GuiButton b : (List) buttonList) + for (GuiButton b : (List)buttonList) { if (SortType.getTypeForButton(b) != null) { @@ -254,9 +259,12 @@ public class GuiModList extends GuiScreen switch (button.id) { case 6: + { this.mc.displayGuiScreen(this.mainMenu); return; + } case 20: + { try { IModGuiFactory guiFactory = FMLClientHandler.instance().getGuiFactoryFor(selectedMod); @@ -269,6 +277,7 @@ public class GuiModList extends GuiScreen } return; } + } } } super.actionPerformed(button); @@ -281,147 +290,15 @@ public class GuiModList extends GuiScreen } @Override - public void drawScreen(int p_571_1_, int p_571_2_, float p_571_3_) + public void drawScreen(int mouseX, int mouseY, float partialTicks) { - this.modList.drawScreen(p_571_1_, p_571_2_, p_571_3_); - this.drawCenteredString(this.fontRendererObj, "Mod List", this.width / 2, 16, 0xFFFFFF); - int offset = this.listWidth + 20; - if (selectedMod != null) - { - GlStateManager.enableBlend(); - if (!selectedMod.getMetadata().autogenerated) - { - configModButton.visible = true; - disableModButton.visible = true; - disableModButton.packedFGColour = 0xFF3377; - configModButton.enabled = false; - int shifty = 35; - String logoFile = selectedMod.getMetadata().logoFile; - if (!logoFile.isEmpty()) - { - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - TextureManager tm = mc.getTextureManager(); - IResourcePack pack = FMLClientHandler.instance().getResourcePackFor(selectedMod.getModId()); - try - { - if (cachedLogo == null) - { - BufferedImage logo = null; - if (pack!=null) - { - logo = pack.getPackImage(); - } - else - { - InputStream logoResource = getClass().getResourceAsStream(logoFile); - if (logoResource != null) - { - logo = ImageIO.read(logoResource); - } - } - if (logo != null) - { - cachedLogo = tm.getDynamicTextureLocation("modlogo", new DynamicTexture(logo)); - cachedLogoDimensions = new Dimension(logo.getWidth(), logo.getHeight()); - } - } - if (cachedLogo != null) - { - this.mc.renderEngine.bindTexture(cachedLogo); - double scaleX = cachedLogoDimensions.width / 200.0; - double scaleY = cachedLogoDimensions.height / 65.0; - double scale = 1.0; - if (scaleX > 1 || scaleY > 1) - { - scale = 1.0 / Math.max(scaleX, scaleY); - } - cachedLogoDimensions.width *= scale; - cachedLogoDimensions.height *= scale; - int top = 32; - Tessellator tess = Tessellator.getInstance(); - WorldRenderer world = tess.getWorldRenderer(); - world.startDrawingQuads(); - world.addVertexWithUV(offset, top + cachedLogoDimensions.height, zLevel, 0, 1); - world.addVertexWithUV(offset + cachedLogoDimensions.width, top + cachedLogoDimensions.height, zLevel, 1, 1); - world.addVertexWithUV(offset + cachedLogoDimensions.width, top, zLevel, 1, 0); - world.addVertexWithUV(offset, top, zLevel, 0, 0); - tess.draw(); + this.modList.drawScreen(mouseX, mouseY, partialTicks); + if (this.modInfo != null) + this.modInfo.drawScreen(mouseX, mouseY, partialTicks); - shifty += 65; - } - } - catch (IOException e) - { - ; - } - } - this.fontRendererObj.drawStringWithShadow(selectedMod.getMetadata().name, offset, shifty, 0xFFFFFF); - shifty += 12; - - shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getDisplayVersion(), selectedMod.getVersion()), offset, shifty); - shifty = drawLine(String.format("Mod ID: '%s' Mod State: %s", selectedMod.getModId(), Loader.instance().getModState(selectedMod)), offset, shifty); - if (!selectedMod.getMetadata().credits.isEmpty()) - { - shifty = drawLine(String.format("Credits: %s", selectedMod.getMetadata().credits), offset, shifty); - } - shifty = drawLine(String.format("Authors: %s", selectedMod.getMetadata().getAuthorList()), offset, shifty); - shifty = drawLine(String.format("URL: %s", selectedMod.getMetadata().url), offset, shifty); - shifty = drawLine(selectedMod.getMetadata().childMods.isEmpty() ? "No child mods for this mod" : String.format("Child mods: %s", selectedMod.getMetadata().getChildModList()), offset, shifty); - int rightSide = this.width - offset - 20; - if (rightSide > 20) - { - this.getFontRenderer().drawSplitString(selectedMod.getMetadata().description, offset, shifty + 10, rightSide, 0xDDDDDD); - } - Disableable disableable = selectedMod.canBeDisabled(); - if (disableable == Disableable.RESTART) - { - disableModButton.enabled = true; - disableModButton.visible = true; - disableModButton.packedFGColour = 0xFF3377; - } - else if (disableable == Disableable.YES) - { - disableModButton.enabled = true; - disableModButton.visible = true; - disableModButton.packedFGColour = 0; - } - else - { - disableModButton.packedFGColour = 0; - disableModButton.visible = true; - disableModButton.enabled = false; - } - IModGuiFactory guiFactory = FMLClientHandler.instance().getGuiFactoryFor(selectedMod); - if (guiFactory == null || guiFactory.mainConfigGuiClass() == null) - { - configModButton.visible = true; - configModButton.enabled = false; - } - else - { - configModButton.visible = true; - configModButton.enabled = true; - } - } - else - { - offset = ( this.listWidth + this.width ) / 2; - this.drawCenteredString(this.fontRendererObj, selectedMod.getName(), offset, 35, 0xFFFFFF); - this.drawCenteredString(this.fontRendererObj, String.format("Version: %s",selectedMod.getVersion()), offset, 45, 0xFFFFFF); - this.drawCenteredString(this.fontRendererObj, String.format("Mod State: %s",Loader.instance().getModState(selectedMod)), offset, 55, 0xFFFFFF); - this.drawCenteredString(this.fontRendererObj, "No mod information found", offset, 65, 0xDDDDDD); - this.drawCenteredString(this.fontRendererObj, "Ask your mod author to provide a mod mcmod.info file", offset, 75, 0xDDDDDD); - configModButton.visible = false; - disableModButton.visible = false; - } - GlStateManager.disableBlend(); - } - else - { - configModButton.visible = false; - disableModButton.visible = false; - } - super.drawScreen(p_571_1_, p_571_2_, p_571_3_); + int left = ((this.width - this.listWidth - 38) / 2) + this.listWidth + 30; + this.drawCenteredString(this.fontRendererObj, "Mod List", left, 16, 0xFFFFFF); + super.drawScreen(mouseX, mouseY, partialTicks); String text = I18n.format("fml.menu.mods.search"); int x = ((10 + modList.right) / 2) - (getFontRenderer().getStringWidth(text) / 2); @@ -441,13 +318,267 @@ public class GuiModList extends GuiScreen public void selectModIndex(int index) { + if (index == this.selected) + return; this.selected = index; this.selectedMod = (index >= 0 && index <= mods.size()) ? mods.get(selected) : null; - cachedLogo = null; + + updateCache(); } public boolean modIndexSelected(int index) { return index == selected; } + + private void updateCache() + { + configModButton.visible = false; + disableModButton.visible = false; + modInfo = null; + + if (selectedMod == null) + return; + + ResourceLocation logoPath = null; + Dimension logoDims = new Dimension(0, 0); + List lines = new ArrayList(); + //CheckResult vercheck = ForgeVersion.getResult(selectedMod); + + String logoFile = selectedMod.getMetadata().logoFile; + if (!logoFile.isEmpty()) + { + TextureManager tm = mc.getTextureManager(); + IResourcePack pack = FMLClientHandler.instance().getResourcePackFor(selectedMod.getModId()); + try + { + BufferedImage logo = null; + if (pack != null) + { + logo = pack.getPackImage(); + } + else + { + InputStream logoResource = getClass().getResourceAsStream(logoFile); + if (logoResource != null) + logo = ImageIO.read(logoResource); + } + if (logo != null) + { + logoPath = tm.getDynamicTextureLocation("modlogo", new DynamicTexture(logo)); + logoDims = new Dimension(logo.getWidth(), logo.getHeight()); + } + } + catch (IOException e) { } + } + + if (!selectedMod.getMetadata().autogenerated) + { + disableModButton.visible = true; + disableModButton.enabled = true; + disableModButton.packedFGColour = 0; + Disableable disableable = selectedMod.canBeDisabled(); + if (disableable == Disableable.RESTART) + { + disableModButton.packedFGColour = 0xFF3377; + } + else if (disableable != Disableable.YES) + { + disableModButton.enabled = false; + } + + IModGuiFactory guiFactory = FMLClientHandler.instance().getGuiFactoryFor(selectedMod); + configModButton.visible = true; + configModButton.enabled = guiFactory != null && guiFactory.mainConfigGuiClass() != null; + + lines.add(selectedMod.getMetadata().name); + lines.add(String.format("Version: %s (%s)", selectedMod.getDisplayVersion(), selectedMod.getVersion())); + lines.add(String.format("Mod ID: '%s' Mod State: %s", selectedMod.getModId(), Loader.instance().getModState(selectedMod))); + + if (!selectedMod.getMetadata().credits.isEmpty()) + { + lines.add("Credits: " + selectedMod.getMetadata().credits); + } + + lines.add("Authors: " + selectedMod.getMetadata().getAuthorList()); + lines.add("URL: " + selectedMod.getMetadata().url); + + if (selectedMod.getMetadata().childMods.isEmpty()) + lines.add("No child mods for this mod"); + else + lines.add("Child mods: " + selectedMod.getMetadata().getChildModList()); + + //if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED) + // lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url)); + + lines.add(null); + lines.add(selectedMod.getMetadata().description); + } + else + { + lines.add(WHITE + selectedMod.getName()); + lines.add(WHITE + "Version: " + selectedMod.getVersion()); + lines.add(WHITE + "Mod State: " + Loader.instance().getModState(selectedMod)); + //if (vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED) + // lines.add("Update Avalible: " + (vercheck.url == null ? "" : vercheck.url)); + + lines.add(null); + lines.add(RED + "No mod information found"); + lines.add(RED + "Ask your mod author to provide a mod mcmod.info file"); + } + + /*if ((vercheck.status == Status.OUTDATED || vercheck.status == Status.BETA_OUTDATED) && vercheck.changes.size() > 0) + { + lines.add(null); + lines.add("Changes:"); + for (Entry entry : vercheck.changes.entrySet()) + { + lines.add(" " + entry.getKey() + ":"); + lines.add(entry.getValue()); + lines.add(null); + } + }*/ + + modInfo = new Info(this.width - this.listWidth - 30, lines, logoPath, logoDims); + } + + private class Info extends GuiScrollingList + { + private ResourceLocation logoPath; + private Dimension logoDims; + private List lines = null; + + public Info(int width, List lines, ResourceLocation logoPath, Dimension logoDims) + { + super(GuiModList.this.getMinecraftInstance(), + width, + GuiModList.this.height, + 32, GuiModList.this.height - 88 + 4, + GuiModList.this.listWidth + 20, 60, + GuiModList.this.width, + GuiModList.this.height); + this.lines = resizeContent(lines); + this.logoPath = logoPath; + this.logoDims = logoDims; + + this.setHeaderInfo(true, getHeaderHeight()); + } + + @Override protected int getSize() { return 0; } + @Override protected void elementClicked(int index, boolean doubleClick) { } + @Override protected boolean isSelected(int index) { return false; } + @Override protected void drawBackground() {} + @Override protected void drawSlot(int slotIdx, int entryRight, int slotTop, int slotBuffer, Tessellator tess) { } + + private List splitLines(String line) + { + return null; + } + + private List resizeContent(List lines) + { + List ret = new ArrayList(); + for (String line : lines) + { + if (line == null) + { + ret.add(null); + continue; + } + + IChatComponent chat = ForgeHooks.newChatWithLinks(line, false); + ret.addAll(GuiUtilRenderComponents.func_178908_a(chat, this.listWidth-8, GuiModList.this.fontRendererObj, false, true)); + } + return ret; + } + + private int getHeaderHeight() + { + int height = 0; + if (logoPath != null) + { + double scaleX = logoDims.width / 200.0; + double scaleY = logoDims.height / 65.0; + double scale = 1.0; + if (scaleX > 1 || scaleY > 1) + { + scale = 1.0 / Math.max(scaleX, scaleY); + } + logoDims.width *= scale; + logoDims.height *= scale; + + height += logoDims.height; + height += 10; + } + height += (lines.size() * 10); + if (height < this.bottom - this.top - 8) height = this.bottom - this.top - 8; + return height; + } + + + protected void drawHeader(int entryRight, int relativeY, Tessellator tess) + { + int top = relativeY; + + if (logoPath != null) + { + GlStateManager.enableBlend(); + GuiModList.this.mc.renderEngine.bindTexture(logoPath); + WorldRenderer world = tess.getWorldRenderer(); + int offset = (this.left + this.listWidth/2) - (logoDims.width / 2); + world.startDrawingQuads(); + world.addVertexWithUV(offset, top + logoDims.height, zLevel, 0, 1); + world.addVertexWithUV(offset + logoDims.width, top + logoDims.height, zLevel, 1, 1); + world.addVertexWithUV(offset + logoDims.width, top, zLevel, 1, 0); + world.addVertexWithUV(offset, top, zLevel, 0, 0); + tess.draw(); + GlStateManager.disableBlend(); + top += logoDims.height + 10; + } + + for (IChatComponent line : lines) + { + if (line != null) + { + GlStateManager.enableBlend(); + GuiModList.this.fontRendererObj.drawStringWithShadow(line.getFormattedText(), this.left + 4, top, 0xFFFFFF); + GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); + } + top += 10; + } + } + + @Override + protected void clickHeader(int x, int y) + { + int offset = y; + if (logoPath != null) { + offset -= logoDims.height + 10; + } + if (offset <= 0) + return; + + int lineIdx = offset / 10; + if (lineIdx >= lines.size()) + return; + + IChatComponent line = lines.get(lineIdx); + if (line != null) + { + int k = -4; + for (IChatComponent part : (Iterable)line) { + if (!(part instanceof ChatComponentText)) + continue; + k += GuiModList.this.fontRendererObj.getStringWidth(((ChatComponentText)part).getChatComponentText_TextValue()); + if (k >= x) + { + System.out.println(part); + GuiModList.this.func_175276_a(part); + break; + } + } + } + } + } } diff --git a/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java b/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java index 645a25169..21e3536f0 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiModOptionList.java @@ -8,7 +8,7 @@ public class GuiModOptionList extends GuiScrollingList { public GuiModOptionList(GuiIngameModOptions parent) { - super(parent.mc, 150, parent.height, 32, parent.height - 65 + 4, 10, 35); + super(parent.mc, 150, parent.height, 32, parent.height - 65 + 4, 10, 35, parent.width, parent.height); this.parent = parent; } @@ -37,11 +37,11 @@ public class GuiModOptionList extends GuiScrollingList { } @Override - protected void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5) + protected void drawSlot(int slotIdx, int entryRight, int slotTop, int slotBuffer, Tessellator tess) { - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("Test 1", listWidth - 10), this.left + 3 , var3 + 2, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("TEST 2", listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("DISABLED", listWidth - 10), this.left + 3 , var3 + 22, 0xFF2222); + this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("Test 1", listWidth - 10), this.left + 3 , slotTop + 2, 0xFF2222); + this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("TEST 2", listWidth - 10), this.left + 3 , slotTop + 12, 0xFF2222); + this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("DISABLED", listWidth - 10), this.left + 3 , slotTop + 22, 0xFF2222); } } diff --git a/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java b/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java index 96c7adf6c..d7f374a1b 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiScrollingList.java @@ -18,7 +18,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; @@ -30,6 +29,8 @@ public abstract class GuiScrollingList private final Minecraft client; protected final int listWidth; protected final int listHeight; + protected final int screenWidth; + protected final int screenHeight; protected final int top; protected final int bottom; protected final int right; @@ -44,11 +45,17 @@ public abstract class GuiScrollingList private float scrollDistance; protected int selectedIndex = -1; private long lastClickTime = 0L; - private boolean field_25123_p = true; - private boolean field_27262_q; - private int field_27261_r; + private boolean highlightSelected = true; + private boolean hasHeader; + private int headerHeight; + protected boolean captureMouse = true; + @Deprecated // We need to know screen size. public GuiScrollingList(Minecraft client, int width, int height, int top, int bottom, int left, int entryHeight) + { + this(client, width, height, top, bottom, left, entryHeight, width, height); + } + public GuiScrollingList(Minecraft client, int width, int height, int top, int bottom, int left, int entryHeight, int screenWidth, int screenHeight) { this.client = client; this.listWidth = width; @@ -58,22 +65,21 @@ public abstract class GuiScrollingList this.slotHeight = entryHeight; this.left = left; this.right = width + this.left; + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; } public void func_27258_a(boolean p_27258_1_) { - this.field_25123_p = p_27258_1_; + this.highlightSelected = p_27258_1_; } - protected void func_27259_a(boolean p_27259_1_, int p_27259_2_) + @Deprecated protected void func_27259_a(boolean hasFooter, int footerHeight){ setHeaderInfo(hasFooter, footerHeight); } + protected void setHeaderInfo(boolean hasHeader, int headerHeight) { - this.field_27262_q = p_27259_1_; - this.field_27261_r = p_27259_2_; - - if (!p_27259_1_) - { - this.field_27261_r = 0; - } + this.hasHeader = hasHeader; + this.headerHeight = headerHeight; + if (!hasHeader) this.headerHeight = 0; } protected abstract int getSize(); @@ -84,42 +90,44 @@ public abstract class GuiScrollingList protected int getContentHeight() { - return this.getSize() * this.slotHeight + this.field_27261_r; + return this.getSize() * this.slotHeight + this.headerHeight; } protected abstract void drawBackground(); - protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5); + protected abstract void drawSlot(int slotIdx, int entryRight, int slotTop, int slotBuffer, Tessellator tess); - protected void func_27260_a(int p_27260_1_, int p_27260_2_, Tessellator p_27260_3_) {} + @Deprecated protected void func_27260_a(int entryRight, int relativeY, Tessellator tess) {} + protected void drawHeader(int entryRight, int relativeY, Tessellator tess) { func_27260_a(entryRight, relativeY, tess); } - protected void func_27255_a(int p_27255_1_, int p_27255_2_) {} + @Deprecated protected void func_27255_a(int x, int y) {} + protected void clickHeader(int x, int y) { func_27255_a(x, y); } - protected void func_27257_b(int p_27257_1_, int p_27257_2_) {} - - public int func_27256_c(int p_27256_1_, int p_27256_2_) + @Deprecated protected void func_27257_b(int mouseX, int mouseY) {} + protected void drawScreen(int mouseX, int mouseY) { func_27257_b(mouseX, mouseY); } + public int func_27256_c(int x, int y) { - int var3 = this.left + 1; - int var4 = this.left + this.listWidth - 7; - int var5 = p_27256_2_ - this.top - this.field_27261_r + (int)this.scrollDistance - 4; - int var6 = var5 / this.slotHeight; - return p_27256_1_ >= var3 && p_27256_1_ <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1; + int left = this.left + 1; + int right = this.left + this.listWidth - 7; + int relativeY = y - this.top - this.headerHeight + (int)this.scrollDistance - 4; + int entryIndex = relativeY / this.slotHeight; + return x >= left && x <= right && entryIndex >= 0 && relativeY >= 0 && entryIndex < this.getSize() ? entryIndex : -1; } - public void registerScrollButtons(@SuppressWarnings("rawtypes") List p_22240_1_, int p_22240_2_, int p_22240_3_) + public void registerScrollButtons(@SuppressWarnings("rawtypes") List buttons, int upActionID, int downActionID) { - this.scrollUpActionId = p_22240_2_; - this.scrollDownActionId = p_22240_3_; + this.scrollUpActionId = upActionID; + this.scrollDownActionId = downActionID; } private void applyScrollLimits() { - int var1 = this.getContentHeight() - (this.bottom - this.top - 4); + int listHeight = this.getContentHeight() - (this.bottom - this.top - 4); - if (var1 < 0) + if (listHeight < 0) { - var1 /= 2; + listHeight /= 2; } if (this.scrollDistance < 0.0F) @@ -127,9 +135,9 @@ public abstract class GuiScrollingList this.scrollDistance = 0.0F; } - if (this.scrollDistance > (float)var1) + if (this.scrollDistance > (float)listHeight) { - this.scrollDistance = (float)var1; + this.scrollDistance = (float)listHeight; } } @@ -152,82 +160,63 @@ public abstract class GuiScrollingList } } - public void drawScreen(int mouseX, int mouseY, float p_22243_3_) + public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.mouseX = mouseX; this.mouseY = mouseY; this.drawBackground(); - int listLength = this.getSize(); - int scrollBarXStart = this.left + this.listWidth - 6; - int scrollBarXEnd = scrollBarXStart + 6; - int boxLeft = this.left; - int boxRight = scrollBarXStart-1; - int var10; - int var11; - int var13; - int var19; + + boolean isHovering = mouseX >= this.left && mouseX <= this.left + this.listWidth && + mouseY >= this.top && mouseY <= this.bottom; + int listLength = this.getSize(); + int scrollBarWidth = 6; + int scrollBarRight = this.left + this.listWidth; + int scrollBarLeft = scrollBarRight - scrollBarWidth; + int entryLeft = this.left; + int entryRight = scrollBarLeft - 1; + int viewHeight = this.bottom - this.top; + int border = 4; if (Mouse.isButtonDown(0)) { if (this.initialMouseClickY == -1.0F) { - boolean var7 = true; - - if (mouseY >= this.top && mouseY <= this.bottom) + if (isHovering) { - var10 = mouseY - this.top - this.field_27261_r + (int)this.scrollDistance - 4; - var11 = var10 / this.slotHeight; + int mouseListY = mouseY - this.top - this.headerHeight + (int)this.scrollDistance - border; + int slotIndex = mouseListY / this.slotHeight; - if (mouseX >= boxLeft && mouseX <= boxRight && var11 >= 0 && var10 >= 0 && var11 < listLength) + if (mouseX >= entryLeft && mouseX <= entryRight && slotIndex >= 0 && mouseListY >= 0 && slotIndex < listLength) { - boolean var12 = var11 == this.selectedIndex && System.currentTimeMillis() - this.lastClickTime < 250L; - this.elementClicked(var11, var12); - this.selectedIndex = var11; + this.elementClicked(slotIndex, slotIndex == this.selectedIndex && System.currentTimeMillis() - this.lastClickTime < 250L); + this.selectedIndex = slotIndex; this.lastClickTime = System.currentTimeMillis(); } - else if (mouseX >= boxLeft && mouseX <= boxRight && var10 < 0) + else if (mouseX >= entryLeft && mouseX <= entryRight && mouseListY < 0) { - this.func_27255_a(mouseX - boxLeft, mouseY - this.top + (int)this.scrollDistance - 4); - var7 = false; + this.clickHeader(mouseX - entryLeft, mouseY - this.top + (int)this.scrollDistance - border); } - if (mouseX >= scrollBarXStart && mouseX <= scrollBarXEnd) + if (mouseX >= scrollBarLeft && mouseX <= scrollBarRight) { this.scrollFactor = -1.0F; - var19 = this.getContentHeight() - (this.bottom - this.top - 4); + int scrollHeight = this.getContentHeight() - viewHeight - border; + if (scrollHeight < 1) scrollHeight = 1; - if (var19 < 1) - { - var19 = 1; - } + int var13 = (int)((float)(viewHeight * viewHeight) / (float)this.getContentHeight()); - var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight()); + if (var13 < 32) var13 = 32; + if (var13 > viewHeight - border*2) + var13 = viewHeight - border*2; - if (var13 < 32) - { - var13 = 32; - } - - if (var13 > this.bottom - this.top - 8) - { - var13 = this.bottom - this.top - 8; - } - - this.scrollFactor /= (float)(this.bottom - this.top - var13) / (float)var19; + this.scrollFactor /= (float)(viewHeight - var13) / (float)scrollHeight; } else { this.scrollFactor = 1.0F; } - if (var7) - { - this.initialMouseClickY = (float)mouseY; - } - else - { - this.initialMouseClickY = -2.0F; - } + this.initialMouseClickY = mouseY; } else { @@ -242,22 +231,15 @@ public abstract class GuiScrollingList } else { - while (Mouse.next()) + while (isHovering && Mouse.next()) { - int var16 = Mouse.getEventDWheel(); - - if (var16 != 0) + int scroll = Mouse.getEventDWheel(); + if (scroll != 0) { - if (var16 > 0) - { - var16 = -1; - } - else if (var16 < 0) - { - var16 = 1; - } + if (scroll > 0) scroll = -1; + else if (scroll < 0) scroll = 1; - this.scrollDistance += (float)(var16 * this.slotHeight / 2); + this.scrollDistance += (float)(scroll * this.slotHeight / 2); } } @@ -265,76 +247,76 @@ public abstract class GuiScrollingList } this.applyScrollLimits(); + Tessellator tess = Tessellator.getInstance(); WorldRenderer worldr = tess.getWorldRenderer(); + if (this.client.theWorld != null) { - this.drawGradientRect(this.left, this.top, this.right, this.bottom, -1072689136, -804253680); + this.drawGradientRect(this.left, this.top, this.right, this.bottom, 0xC0101010, 0xD0101010); } - else + else // Draw dark dirt background { GlStateManager.disableLighting(); GlStateManager.disableFog(); this.client.renderEngine.bindTexture(Gui.optionsBackground); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - float var17 = 32.0F; + float scale = 32.0F; worldr.startDrawingQuads(); worldr.setColorOpaque_I(2105376); - worldr.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, (double)((float)this.left / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17)); - worldr.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, (double)((float)this.right / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17)); - worldr.addVertexWithUV((double)this.right, (double)this.top, 0.0D, (double)((float)this.right / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17)); - worldr.addVertexWithUV((double)this.left, (double)this.top, 0.0D, (double)((float)this.left / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17)); + worldr.addVertexWithUV(this.left, this.bottom, 0.0D, this.left / scale, (this.bottom + (int)this.scrollDistance) / scale); + worldr.addVertexWithUV(this.right, this.bottom, 0.0D, this.right / scale, (this.bottom + (int)this.scrollDistance) / scale); + worldr.addVertexWithUV(this.right, this.top, 0.0D, this.right / scale, (this.top + (int)this.scrollDistance) / scale); + worldr.addVertexWithUV(this.left, this.top, 0.0D, this.left / scale, (this.top + (int)this.scrollDistance) / scale); tess.draw(); } - // boxRight = this.listWidth / 2 - 92 - 16; - var10 = this.top + 4 - (int)this.scrollDistance; - if (this.field_27262_q) - { - this.func_27260_a(boxRight, var10, tess); + int baseY = this.top + border - (int)this.scrollDistance; + + if (this.hasHeader) { + this.drawHeader(entryRight, baseY, tess); } - int var14; - - for (var11 = 0; var11 < listLength; ++var11) + for (int slotIdx = 0; slotIdx < listLength; ++slotIdx) { - var19 = var10 + var11 * this.slotHeight + this.field_27261_r; - var13 = this.slotHeight - 4; + int slotTop = baseY + slotIdx * this.slotHeight + this.headerHeight; + int slotBuffer = this.slotHeight - border; - if (var19 <= this.bottom && var19 + var13 >= this.top) + if (slotTop <= this.bottom && slotTop + slotBuffer >= this.top) { - if (this.field_25123_p && this.isSelected(var11)) + if (this.highlightSelected && this.isSelected(slotIdx)) { - var14 = boxLeft; - int var15 = boxRight; + int min = this.left; + int max = entryRight; GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.disableTexture2D(); worldr.startDrawingQuads(); - worldr.setColorOpaque_I(8421504); - worldr.addVertexWithUV((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D); - worldr.addVertexWithUV((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D); + worldr.setColorOpaque_I(0x808080); + worldr.addVertexWithUV(min, slotTop + slotBuffer + 2, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(max, slotTop + slotBuffer + 2, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(max, slotTop - 2, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(min, slotTop - 2, 0.0D, 0.0D, 0.0D); worldr.setColorOpaque_I(0); - worldr.addVertexWithUV((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D); - worldr.addVertexWithUV((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D); + worldr.addVertexWithUV(min + 1, slotTop + slotBuffer + 1, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(max - 1, slotTop + slotBuffer + 1, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(max - 1, slotTop - 1, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(min + 1, slotTop - 1, 0.0D, 0.0D, 0.0D); tess.draw(); GlStateManager.enableTexture2D(); } - this.drawSlot(var11, boxRight, var19, var13, tess); + this.drawSlot(slotIdx, entryRight, slotTop, slotBuffer, tess); } } GlStateManager.disableDepth(); - byte border = 4; if (this.client.theWorld == null) { - this.overlayBackground(0, this.top, 255, 255); + this.overlayBackground(0, this.top, 255, 255); this.overlayBackground(this.bottom, this.listHeight, 255, 255); } + + // Render the entire background over everything but our view GlStateManager.enableBlend(); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GlStateManager.disableAlpha(); @@ -342,100 +324,95 @@ public abstract class GuiScrollingList GlStateManager.disableTexture2D(); worldr.startDrawingQuads(); worldr.setColorRGBA_I(0, 0); - worldr.addVertexWithUV((double)this.left, (double)(this.top + border), 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)this.right, (double)(this.top + border), 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(this.left, this.top + border, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(this.right, this.top + border, 0.0D, 1.0D, 1.0D); worldr.setColorRGBA_I(0, 255); - worldr.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D); + worldr.addVertexWithUV(this.right, this.top, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(this.left, this.top, 0.0D, 0.0D, 0.0D); tess.draw(); worldr.startDrawingQuads(); worldr.setColorRGBA_I(0, 255); - worldr.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(this.left, this.bottom, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(this.right, this.bottom, 0.0D, 1.0D, 1.0D); worldr.setColorRGBA_I(0, 0); - worldr.addVertexWithUV((double)this.right, (double)(this.bottom - border), 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)this.left, (double)(this.bottom - border), 0.0D, 0.0D, 0.0D); + worldr.addVertexWithUV(this.right, this.bottom - border, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(this.left, this.bottom - border, 0.0D, 0.0D, 0.0D); tess.draw(); - var19 = this.getContentHeight() - (this.bottom - this.top - 4); - if (var19 > 0) + int extraHeight = this.getContentHeight() - viewHeight - border; + if (extraHeight > 0) { - var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight(); + int height = viewHeight * viewHeight / this.getContentHeight(); - if (var13 < 32) + if (height < 32) height = 32; + + if (height > viewHeight - border*2) + height = viewHeight - border*2; + + int barTop = (int)this.scrollDistance * (viewHeight - height) / extraHeight + this.top; + if (barTop < this.top) { - var13 = 32; - } - - if (var13 > this.bottom - this.top - 8) - { - var13 = this.bottom - this.top - 8; - } - - var14 = (int)this.scrollDistance * (this.bottom - this.top - var13) / var19 + this.top; - - if (var14 < this.top) - { - var14 = this.top; + barTop = this.top; } worldr.startDrawingQuads(); worldr.setColorRGBA_I(0, 255); - worldr.addVertexWithUV((double)scrollBarXStart, (double)this.bottom, 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)scrollBarXEnd, (double)this.bottom, 0.0D, 1.0D, 1.0D); - worldr.addVertexWithUV((double)scrollBarXEnd, (double)this.top, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)scrollBarXStart, (double)this.top, 0.0D, 0.0D, 0.0D); + worldr.addVertexWithUV(scrollBarLeft, this.bottom, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight, this.bottom, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight, this.top, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(scrollBarLeft, this.top, 0.0D, 0.0D, 0.0D); tess.draw(); worldr.startDrawingQuads(); - worldr.setColorRGBA_I(8421504, 255); - worldr.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13), 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)scrollBarXEnd, (double)(var14 + var13), 0.0D, 1.0D, 1.0D); - worldr.addVertexWithUV((double)scrollBarXEnd, (double)var14, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D); + worldr.setColorRGBA_I(0x808080, 255); + worldr.addVertexWithUV(scrollBarLeft, barTop + height, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight, barTop + height, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight, barTop, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(scrollBarLeft, barTop, 0.0D, 0.0D, 0.0D); tess.draw(); worldr.startDrawingQuads(); - worldr.setColorRGBA_I(12632256, 255); - worldr.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D); - worldr.addVertexWithUV((double)(scrollBarXEnd - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D); - worldr.addVertexWithUV((double)(scrollBarXEnd - 1), (double)var14, 0.0D, 1.0D, 0.0D); - worldr.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D); + worldr.setColorRGBA_I(0xC0C0C0, 255); + worldr.addVertexWithUV(scrollBarLeft, barTop + height - 1, 0.0D, 0.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight - 1, barTop + height - 1, 0.0D, 1.0D, 1.0D); + worldr.addVertexWithUV(scrollBarRight - 1, barTop, 0.0D, 1.0D, 0.0D); + worldr.addVertexWithUV(scrollBarLeft, barTop, 0.0D, 0.0D, 0.0D); tess.draw(); } - this.func_27257_b(mouseX, mouseY); + this.drawScreen(mouseX, mouseY); GlStateManager.enableTexture2D(); GlStateManager.shadeModel(GL11.GL_FLAT); GlStateManager.enableAlpha(); GlStateManager.disableBlend(); } - private void overlayBackground(int p_22239_1_, int p_22239_2_, int p_22239_3_, int p_22239_4_) + private void overlayBackground(int top, int height, int alpha1, int alpah2) { - Tessellator var5 = Tessellator.getInstance(); - WorldRenderer worldr = var5.getWorldRenderer(); + Tessellator tess = Tessellator.getInstance(); + WorldRenderer worldr = tess.getWorldRenderer(); this.client.renderEngine.bindTexture(Gui.optionsBackground); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - float var6 = 32.0F; + float scale = 32.0F; + double startUV = (screenWidth / scale) / screenWidth * (left-0); worldr.startDrawingQuads(); - worldr.setColorRGBA_I(4210752, p_22239_4_); - worldr.addVertexWithUV(0.0D, (double)p_22239_2_, 0.0D, 0.0D, (double)((float)p_22239_2_ / var6)); - worldr.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_2_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_2_ / var6)); - worldr.setColorRGBA_I(4210752, p_22239_3_); - worldr.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_1_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_1_ / var6)); - worldr.addVertexWithUV(0.0D, (double)p_22239_1_, 0.0D, 0.0D, (double)((float)p_22239_1_ / var6)); - var5.draw(); + worldr.setColorRGBA_I(0x404040, alpah2); + worldr.addVertexWithUV(left, height, 0.0D, startUV, height / scale); + worldr.addVertexWithUV(left+listWidth+8, height, 0.0D, (left+listWidth+8) / scale, height / scale); + worldr.setColorRGBA_I(0x404040, alpha1); + worldr.addVertexWithUV(left+listWidth+8, top, 0.0D, (left+listWidth+8) / scale, top / scale); + worldr.addVertexWithUV(left, top, 0.0D, startUV, top / scale); + tess.draw(); } - protected void drawGradientRect(int par1, int par2, int par3, int par4, int par5, int par6) + protected void drawGradientRect(int left, int top, int right, int bottom, int color1, int color2) { - float f = (float)(par5 >> 24 & 255) / 255.0F; - float f1 = (float)(par5 >> 16 & 255) / 255.0F; - float f2 = (float)(par5 >> 8 & 255) / 255.0F; - float f3 = (float)(par5 & 255) / 255.0F; - float f4 = (float)(par6 >> 24 & 255) / 255.0F; - float f5 = (float)(par6 >> 16 & 255) / 255.0F; - float f6 = (float)(par6 >> 8 & 255) / 255.0F; - float f7 = (float)(par6 & 255) / 255.0F; + float a1 = (float)(color1 >> 24 & 255) / 255.0F; + float r1 = (float)(color1 >> 16 & 255) / 255.0F; + float g1 = (float)(color1 >> 8 & 255) / 255.0F; + float b1 = (float)(color1 & 255) / 255.0F; + float a2 = (float)(color2 >> 24 & 255) / 255.0F; + float r2 = (float)(color2 >> 16 & 255) / 255.0F; + float g2 = (float)(color2 >> 8 & 255) / 255.0F; + float b2 = (float)(color2 & 255) / 255.0F; GlStateManager.disableTexture2D(); GlStateManager.enableBlend(); GlStateManager.disableAlpha(); @@ -444,12 +421,12 @@ public abstract class GuiScrollingList Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); worldrenderer.startDrawingQuads(); - worldrenderer.setColorRGBA_F(f1, f2, f3, f); - worldrenderer.addVertex((double)par3, (double)par2, 0.0D); - worldrenderer.addVertex((double)par1, (double)par2, 0.0D); - worldrenderer.setColorRGBA_F(f5, f6, f7, f4); - worldrenderer.addVertex((double)par1, (double)par4, 0.0D); - worldrenderer.addVertex((double)par3, (double)par4, 0.0D); + worldrenderer.setColorRGBA_F(r1, g1, b1, a1); + worldrenderer.addVertex(right, top, 0.0D); + worldrenderer.addVertex(left, top, 0.0D); + worldrenderer.setColorRGBA_F(r2, g2, b2, a2); + worldrenderer.addVertex(left, bottom, 0.0D); + worldrenderer.addVertex(right, bottom, 0.0D); tessellator.draw(); GlStateManager.shadeModel(GL11.GL_FLAT); GlStateManager.disableBlend(); diff --git a/src/main/java/net/minecraftforge/fml/client/GuiSlotModList.java b/src/main/java/net/minecraftforge/fml/client/GuiSlotModList.java index 2074b9ce6..1d47fea2f 100644 --- a/src/main/java/net/minecraftforge/fml/client/GuiSlotModList.java +++ b/src/main/java/net/minecraftforge/fml/client/GuiSlotModList.java @@ -14,6 +14,7 @@ package net.minecraftforge.fml.client; import java.util.ArrayList; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.util.StringUtils; import net.minecraftforge.fml.common.Loader; @@ -31,9 +32,9 @@ public class GuiSlotModList extends GuiScrollingList public GuiSlotModList(GuiModList parent, ArrayList mods, int listWidth) { - super(parent.getMinecraftInstance(), listWidth, parent.height, 32, parent.height - 88 + 4, 10, 35); - this.parent=parent; - this.mods=mods; + super(parent.getMinecraftInstance(), listWidth, parent.height, 32, parent.height - 88 + 4, 10, 35, parent.width, parent.height); + this.parent = parent; + this.mods = mods; } @Override @@ -43,15 +44,15 @@ public class GuiSlotModList extends GuiScrollingList } @Override - protected void elementClicked(int var1, boolean var2) + protected void elementClicked(int index, boolean doubleClick) { - this.parent.selectModIndex(var1); + this.parent.selectModIndex(index); } @Override - protected boolean isSelected(int var1) + protected boolean isSelected(int index) { - return this.parent.modIndexSelected(var1); + return this.parent.modIndexSelected(index); } @Override @@ -72,22 +73,39 @@ public class GuiSlotModList extends GuiScrollingList } @Override - protected void drawSlot(int listIndex, int var2, int var3, int var4, Tessellator var5) + protected void drawSlot(int idx, int right, int top, int height, Tessellator tess) { - ModContainer mc=mods.get(listIndex); - String name = StringUtils.stripControlCodes(mc.getName()); - String version = StringUtils.stripControlCodes(mc.getDisplayVersion()); - if (Loader.instance().getModState(mc)==ModState.DISABLED) + ModContainer mc = mods.get(idx); + String name = StringUtils.stripControlCodes(mc.getName()); + String version = StringUtils.stripControlCodes(mc.getDisplayVersion()); + FontRenderer font = this.parent.getFontRenderer(); + //CheckResult vercheck = ForgeVersion.getResult(mc); + + if (Loader.instance().getModState(mc) == ModState.DISABLED) { - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth(name, listWidth - 10), this.left + 3 , var3 + 2, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth(version, listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth("DISABLED", listWidth - 10), this.left + 3 , var3 + 22, 0xFF2222); + font.drawString(font.trimStringToWidth(name, listWidth - 10), this.left + 3 , top + 2, 0xFF2222); + font.drawString(font.trimStringToWidth(version, listWidth - 10), this.left + 3 , top + 12, 0xFF2222); + font.drawString(font.trimStringToWidth("DISABLED", listWidth - 10), this.left + 3 , top + 22, 0xFF2222); } else { - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth(name, listWidth - 10), this.left + 3 , var3 + 2, 0xFFFFFF); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth(version, listWidth - 10), this.left + 3 , var3 + 12, 0xCCCCCC); - this.parent.getFontRenderer().drawString(this.parent.getFontRenderer().trimStringToWidth(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , var3 + 22, 0xCCCCCC); + font.drawString(font.trimStringToWidth(name, listWidth - 10), this.left + 3 , top + 2, 0xFFFFFF); + font.drawString(font.trimStringToWidth(version, listWidth - 10), this.left + 3 , top + 12, 0xCCCCCC); + font.drawString(font.trimStringToWidth(mc.getMetadata() != null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , top + 22, 0xCCCCCC); + + /*switch(vercheck.status) //TODO: Change to icons? + { + case BETA_OUTDATED: + case OUTDATED: + font.drawString("U", right - font.getCharWidth('U') - 1, top+height-font.FONT_HEIGHT+2, 0x22FF22); + break; + case AHEAD: + case BETA: + case FAILED: + case PENDING: + case UP_TO_DATE: + break; + }*/ } } diff --git a/src/main/resources/mcplogo.png b/src/main/resources/mcplogo.png index 8ebae880d0244f25a76a984a55729e4c0c9c3cf1..fd5eba5dc90d8484e6833dc7212a21a15170c490 100644 GIT binary patch literal 3926 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

_~`&Fa@&~$bKKN-Eu);~OF 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 i