package techreborn.cofhLib.gui; import techreborn.cofhLib.audio.SoundBase; import techreborn.cofhLib.gui.element.ElementBase; import techreborn.cofhLib.gui.element.TabBase; import techreborn.cofhLib.gui.slot.SlotFalseCopy; import techreborn.cofhLib.render.RenderHelper; import techreborn.cofhLib.util.helpers.StringHelper; import cpw.mods.fml.client.FMLClientHandler; import net.minecraft.client.audio.SoundHandler; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import net.minecraftforge.fluids.FluidStack; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Base class for a modular GUIs. Works with Elements {@link techreborn.cofhLib.gui.element.ElementBase} and Tabs {@link techreborn.cofhLib.gui.element.TabBase} which are both modular elements. * * @author King Lemming */ public abstract class GuiBase extends GuiContainer { public static final SoundHandler guiSoundManager = FMLClientHandler.instance().getClient().getSoundHandler(); protected boolean drawTitle = true; protected boolean drawInventory = true; protected int mouseX = 0; protected int mouseY = 0; protected int lastIndex = -1; protected String name; protected ResourceLocation texture; public ArrayList tabs = new ArrayList(); protected ArrayList elements = new ArrayList(); protected List tooltip = new LinkedList(); protected boolean tooltips = true; public static void playSound(String name, float volume, float pitch) { guiSoundManager.playSound(new SoundBase(name, volume, pitch)); } public GuiBase(Container container) { super(container); } public GuiBase(Container container, ResourceLocation texture) { super(container); this.texture = texture; } @Override public void initGui() { super.initGui(); tabs.clear(); elements.clear(); } @Override public void drawScreen(int x, int y, float partialTick) { updateElementInformation(); super.drawScreen(x, y, partialTick); if (tooltips && mc.thePlayer.inventory.getItemStack() == null) { addTooltips(tooltip); drawTooltip(tooltip); } mouseX = x - guiLeft; mouseY = y - guiTop; updateElements(); } @Override protected void drawGuiContainerForegroundLayer(int x, int y) { if (drawTitle) { fontRendererObj.drawString(StringHelper.localize(name), getCenteredOffset(StringHelper.localize(name)), 6, 0x404040); } if (drawInventory) { fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 3, 0x404040); } drawElements(0, true); drawTabs(0, true); } @Override protected void drawGuiContainerBackgroundLayer(float partialTick, int x, int y) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); bindTexture(texture); drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); mouseX = x - guiLeft; mouseY = y - guiTop; GL11.glPushMatrix(); GL11.glTranslatef(guiLeft, guiTop, 0.0F); drawElements(partialTick, false); drawTabs(partialTick, false); GL11.glPopMatrix(); } @Override protected void keyTyped(char characterTyped, int keyPressed) { for (int i = elements.size(); i-- > 0;) { ElementBase c = elements.get(i); if (!c.isVisible() || !c.isEnabled()) { continue; } if (c.onKeyTyped(characterTyped, keyPressed)) { return; } } super.keyTyped(characterTyped, keyPressed); } @Override public void handleMouseInput() { int x = Mouse.getEventX() * width / mc.displayWidth; int y = height - Mouse.getEventY() * height / mc.displayHeight - 1; mouseX = x - guiLeft; mouseY = y - guiTop; int wheelMovement = Mouse.getEventDWheel(); if (wheelMovement != 0) { for (int i = elements.size(); i-- > 0;) { ElementBase c = elements.get(i); if (!c.isVisible() || !c.isEnabled() || !c.intersectsWith(mouseX, mouseY)) { continue; } if (c.onMouseWheel(mouseX, mouseY, wheelMovement)) { return; } } TabBase tab = getTabAtPosition(mouseX, mouseY); if (tab != null && tab.onMouseWheel(mouseX, mouseY, wheelMovement)) { return; } } super.handleMouseInput(); } @Override protected void mouseClicked(int mX, int mY, int mouseButton) { mX -= guiLeft; mY -= guiTop; for (int i = elements.size(); i-- > 0;) { ElementBase c = elements.get(i); if (!c.isVisible() || !c.isEnabled() || !c.intersectsWith(mX, mY)) { continue; } if (c.onMousePressed(mX, mY, mouseButton)) { return; } } TabBase tab = getTabAtPosition(mX, mY); if (tab != null) { int tMx = mX; if (!tab.onMousePressed(tMx, mY, mouseButton)) { for (int i = tabs.size(); i-- > 0;) { TabBase other = tabs.get(i); if (other != tab && other.open && other.side == tab.side) { other.toggleOpen(); } } tab.toggleOpen(); return; } } mX += guiLeft; mY += guiTop; if (tab != null) { switch (tab.side) { case TabBase.LEFT: // guiLeft -= tab.currentWidth; break; case TabBase.RIGHT: xSize += tab.currentWidth; break; } } super.mouseClicked(mX, mY, mouseButton); if (tab != null) { switch (tab.side) { case TabBase.LEFT: // guiLeft += tab.currentWidth; break; case TabBase.RIGHT: xSize -= tab.currentWidth; break; } } } @Override protected void mouseMovedOrUp(int mX, int mY, int mouseButton) { mX -= guiLeft; mY -= guiTop; if (mouseButton >= 0 && mouseButton <= 2) { // 0:left, 1:right, 2: middle for (int i = elements.size(); i-- > 0;) { ElementBase c = elements.get(i); if (!c.isVisible() || !c.isEnabled()) { // no bounds checking on mouseUp events continue; } c.onMouseReleased(mX, mY); } } mX += guiLeft; mY += guiTop; super.mouseMovedOrUp(mX, mY, mouseButton); } @Override protected void mouseClickMove(int mX, int mY, int lastClick, long timeSinceClick) { Slot slot = getSlotAtPosition(mX, mY); ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack(); if (this.field_147007_t && slot != null && itemstack != null && slot instanceof SlotFalseCopy) { if (lastIndex != slot.slotNumber) { lastIndex = slot.slotNumber; this.handleMouseClick(slot, slot.slotNumber, 0, 0); } } else { lastIndex = -1; super.mouseClickMove(mX, mY, lastClick, timeSinceClick); } } public Slot getSlotAtPosition(int xCoord, int yCoord) { for (int k = 0; k < this.inventorySlots.inventorySlots.size(); ++k) { Slot slot = (Slot) this.inventorySlots.inventorySlots.get(k); if (this.isMouseOverSlot(slot, xCoord, yCoord)) { return slot; } } return null; } public boolean isMouseOverSlot(Slot theSlot, int xCoord, int yCoord) { return this.func_146978_c(theSlot.xDisplayPosition, theSlot.yDisplayPosition, 16, 16, xCoord, yCoord); } /** * Draws the elements for this GUI. */ protected void drawElements(float partialTick, boolean foreground) { if (foreground) { for (int i = 0; i < elements.size(); i++) { ElementBase element = elements.get(i); if (element.isVisible()) { element.drawForeground(mouseX, mouseY); } } } else { for (int i = 0; i < elements.size(); i++) { ElementBase element = elements.get(i); if (element.isVisible()) { element.drawBackground(mouseX, mouseY, partialTick); } } } } /** * Draws the tabs for this GUI. Handles Tab open/close animation. */ protected void drawTabs(float partialTick, boolean foreground) { int yPosRight = 4; int yPosLeft = 4; if (foreground) { for (int i = 0; i < tabs.size(); i++) { TabBase tab = tabs.get(i); tab.update(); if (!tab.isVisible()) { continue; } if (tab.side == TabBase.LEFT) { tab.drawForeground(mouseX, mouseY); yPosLeft += tab.currentHeight; } else { tab.drawForeground(mouseX, mouseY); yPosRight += tab.currentHeight; } } } else { for (int i = 0; i < tabs.size(); i++) { TabBase tab = tabs.get(i); tab.update(); if (!tab.isVisible()) { continue; } if (tab.side == TabBase.LEFT) { tab.setPosition(0, yPosLeft); tab.drawBackground(mouseX, mouseY, partialTick); yPosLeft += tab.currentHeight; } else { tab.setPosition(xSize, yPosRight); tab.drawBackground(mouseX, mouseY, partialTick); yPosRight += tab.currentHeight; } } } } /** * Called by NEI if installed */ // @Override public List handleTooltip(int mousex, int mousey, List tooltip) { if (mc.thePlayer.inventory.getItemStack() == null) { addTooltips(tooltip); } return tooltip; } public void addTooltips(List tooltip) { TabBase tab = getTabAtPosition(mouseX, mouseY); if (tab != null) { tab.addTooltip(tooltip); } ElementBase element = getElementAtPosition(mouseX, mouseY); if (element != null && element.isVisible()) { element.addTooltip(tooltip); } } /* ELEMENTS */ public ElementBase addElement(ElementBase element) { elements.add(element); return element; } public TabBase addTab(TabBase tab) { int yOffset = 4; for (int i = 0; i < tabs.size(); i++) { if (tabs.get(i).side == tab.side && tabs.get(i).isVisible()) { yOffset += tabs.get(i).currentHeight; } } tab.setPosition(tab.side == TabBase.LEFT ? 0 : xSize, yOffset); tabs.add(tab); if (TabTracker.getOpenedLeftTab() != null && tab.getClass().equals(TabTracker.getOpenedLeftTab())) { tab.setFullyOpen(); } else if (TabTracker.getOpenedRightTab() != null && tab.getClass().equals(TabTracker.getOpenedRightTab())) { tab.setFullyOpen(); } return tab; } protected ElementBase getElementAtPosition(int mX, int mY) { for (int i = elements.size(); i-- > 0;) { ElementBase element = elements.get(i); if (element.intersectsWith(mX, mY)) { return element; } } return null; } protected TabBase getTabAtPosition(int mX, int mY) { int xShift = 0; int yShift = 4; for (int i = 0; i < tabs.size(); i++) { TabBase tab = tabs.get(i); if (!tab.isVisible() || tab.side == TabBase.RIGHT) { continue; } tab.setCurrentShift(xShift, yShift); if (tab.intersectsWith(mX, mY, xShift, yShift)) { return tab; } yShift += tab.currentHeight; } xShift = xSize; yShift = 4; for (int i = 0; i < tabs.size(); i++) { TabBase tab = tabs.get(i); if (!tab.isVisible() || tab.side == TabBase.LEFT) { continue; } tab.setCurrentShift(xShift, yShift); if (tab.intersectsWith(mX, mY, xShift, yShift)) { return tab; } yShift += tab.currentHeight; } return null; } protected final void updateElements() { for (int i = elements.size(); i-- > 0;) { ElementBase c = elements.get(i); if (c.isVisible() && c.isEnabled()) { c.update(mouseX, mouseY); } } } protected void updateElementInformation() { } public void handleElementButtonClick(String buttonName, int mouseButton) { } /* HELPERS */ public void bindTexture(ResourceLocation texture) { mc.renderEngine.bindTexture(texture); } /** * Abstract method to retrieve icons by name from a registry. You must override this if you use any of the String methods below. */ public IIcon getIcon(String name) { return null; } /** * Essentially a placeholder method for tabs to use should they need to draw a button. */ public void drawButton(IIcon icon, int x, int y, int spriteSheet, int mode) { drawIcon(icon, x, y, spriteSheet); } public void drawButton(String iconName, int x, int y, int spriteSheet, int mode) { drawButton(getIcon(iconName), x, y, spriteSheet, mode); } /** * Simple method used to draw a fluid of arbitrary size. */ public void drawFluid(int x, int y, FluidStack fluid, int width, int height) { if (fluid == null || fluid.getFluid() == null) { return; } RenderHelper.setBlockTextureSheet(); RenderHelper.setColor3ub(fluid.getFluid().getColor(fluid)); drawTiledTexture(x, y, fluid.getFluid().getIcon(fluid), width, height); } public void drawTiledTexture(int x, int y, IIcon icon, int width, int height) { int i = 0; int j = 0; int drawHeight = 0; int drawWidth = 0; for (i = 0; i < width; i += 16) { for (j = 0; j < height; j += 16) { drawWidth = Math.min(width - i, 16); drawHeight = Math.min(height - j, 16); drawScaledTexturedModelRectFromIcon(x + i, y + j, icon, drawWidth, drawHeight); } } GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0F); } public void drawIcon(IIcon icon, int x, int y, int spriteSheet) { if (spriteSheet == 0) { RenderHelper.setBlockTextureSheet(); } else { RenderHelper.setItemTextureSheet(); } GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0F); drawTexturedModelRectFromIcon(x, y, icon, 16, 16); } public void drawColorIcon(IIcon icon, int x, int y, int spriteSheet) { if (spriteSheet == 0) { RenderHelper.setBlockTextureSheet(); } else { RenderHelper.setItemTextureSheet(); } drawTexturedModelRectFromIcon(x, y, icon, 16, 16); } public void drawIcon(String iconName, int x, int y, int spriteSheet) { drawIcon(getIcon(iconName), x, y, spriteSheet); } public void drawSizedModalRect(int x1, int y1, int x2, int y2, int color) { int temp; if (x1 < x2) { temp = x1; x1 = x2; x2 = temp; } if (y1 < y2) { temp = y1; y1 = y2; y2 = temp; } float a = (color >> 24 & 255) / 255.0F; float r = (color >> 16 & 255) / 255.0F; float g = (color >> 8 & 255) / 255.0F; float b = (color & 255) / 255.0F; Tessellator tessellator = Tessellator.instance; GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glColor4f(r, g, b, a); tessellator.startDrawingQuads(); tessellator.addVertex(x1, y2, this.zLevel); tessellator.addVertex(x2, y2, this.zLevel); tessellator.addVertex(x2, y1, this.zLevel); tessellator.addVertex(x1, y1, this.zLevel); tessellator.draw(); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_BLEND); } public void drawSizedRect(int x1, int y1, int x2, int y2, int color) { int temp; if (x1 < x2) { temp = x1; x1 = x2; x2 = temp; } if (y1 < y2) { temp = y1; y1 = y2; y2 = temp; } float a = (color >> 24 & 255) / 255.0F; float r = (color >> 16 & 255) / 255.0F; float g = (color >> 8 & 255) / 255.0F; float b = (color & 255) / 255.0F; Tessellator tessellator = Tessellator.instance; GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glColor4f(r, g, b, a); tessellator.startDrawingQuads(); tessellator.addVertex(x1, y2, this.zLevel); tessellator.addVertex(x2, y2, this.zLevel); tessellator.addVertex(x2, y1, this.zLevel); tessellator.addVertex(x1, y1, this.zLevel); tessellator.draw(); GL11.glEnable(GL11.GL_TEXTURE_2D); } public void drawSizedTexturedModalRect(int x, int y, int u, int v, int width, int height, float texW, float texH) { float texU = 1 / texW; float texV = 1 / texH; Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(x + 0, y + height, this.zLevel, (u + 0) * texU, (v + height) * texV); tessellator.addVertexWithUV(x + width, y + height, this.zLevel, (u + width) * texU, (v + height) * texV); tessellator.addVertexWithUV(x + width, y + 0, this.zLevel, (u + width) * texU, (v + 0) * texV); tessellator.addVertexWithUV(x + 0, y + 0, this.zLevel, (u + 0) * texU, (v + 0) * texV); tessellator.draw(); } public void drawScaledTexturedModelRectFromIcon(int x, int y, IIcon icon, int width, int height) { if (icon == null) { return; } double minU = icon.getMinU(); double maxU = icon.getMaxU(); double minV = icon.getMinV(); double maxV = icon.getMaxV(); Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(x + 0, y + height, this.zLevel, minU, minV + (maxV - minV) * height / 16F); tessellator.addVertexWithUV(x + width, y + height, this.zLevel, minU + (maxU - minU) * width / 16F, minV + (maxV - minV) * height / 16F); tessellator.addVertexWithUV(x + width, y + 0, this.zLevel, minU + (maxU - minU) * width / 16F, minV); tessellator.addVertexWithUV(x + 0, y + 0, this.zLevel, minU, minV); tessellator.draw(); } public void drawTooltip(List list) { drawTooltipHoveringText(list, mouseX + guiLeft, mouseY + guiTop, fontRendererObj); tooltip.clear(); } @SuppressWarnings("rawtypes") protected void drawTooltipHoveringText(List list, int x, int y, FontRenderer font) { if (list == null || list.isEmpty()) { return; } GL11.glDisable(GL12.GL_RESCALE_NORMAL); GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); int k = 0; Iterator iterator = list.iterator(); while (iterator.hasNext()) { String s = (String) iterator.next(); int l = font.getStringWidth(s); if (l > k) { k = l; } } int i1 = x + 12; int j1 = y - 12; int k1 = 8; if (list.size() > 1) { k1 += 2 + (list.size() - 1) * 10; } if (i1 + k > this.width) { i1 -= 28 + k; } if (j1 + k1 + 6 > this.height) { j1 = this.height - k1 - 6; } this.zLevel = 300.0F; itemRender.zLevel = 300.0F; int l1 = -267386864; this.drawGradientRect(i1 - 3, j1 - 4, i1 + k + 3, j1 - 3, l1, l1); this.drawGradientRect(i1 - 3, j1 + k1 + 3, i1 + k + 3, j1 + k1 + 4, l1, l1); this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 + k1 + 3, l1, l1); this.drawGradientRect(i1 - 4, j1 - 3, i1 - 3, j1 + k1 + 3, l1, l1); this.drawGradientRect(i1 + k + 3, j1 - 3, i1 + k + 4, j1 + k1 + 3, l1, l1); int i2 = 1347420415; int j2 = (i2 & 16711422) >> 1 | i2 & -16777216; this.drawGradientRect(i1 - 3, j1 - 3 + 1, i1 - 3 + 1, j1 + k1 + 3 - 1, i2, j2); this.drawGradientRect(i1 + k + 2, j1 - 3 + 1, i1 + k + 3, j1 + k1 + 3 - 1, i2, j2); this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 - 3 + 1, i2, i2); this.drawGradientRect(i1 - 3, j1 + k1 + 2, i1 + k + 3, j1 + k1 + 3, j2, j2); for (int k2 = 0; k2 < list.size(); ++k2) { String s1 = (String) list.get(k2); font.drawStringWithShadow(s1, i1, j1, -1); if (k2 == 0) { j1 += 2; } j1 += 10; } this.zLevel = 0.0F; itemRender.zLevel = 0.0F; GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL12.GL_RESCALE_NORMAL); } /** * Passthrough method for tab use. */ public void mouseClicked(int mouseButton) { super.mouseClicked(guiLeft + mouseX, guiTop + mouseY, mouseButton); } public FontRenderer getFontRenderer() { return fontRendererObj; } protected int getCenteredOffset(String string) { return this.getCenteredOffset(string, xSize); } protected int getCenteredOffset(String string, int xWidth) { return (xWidth - fontRendererObj.getStringWidth(string)) / 2; } public int getGuiLeft() { return guiLeft; } public int getGuiTop() { return guiTop; } public int getMouseX() { return mouseX; } public int getMouseY() { return mouseY; } public void overlayRecipe() { } }