/** * Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team * http://www.mod-buildcraft.com * <p/> * BuildCraft is distributed under the terms of the Minecraft Mod Public * License 1.0, or MMPL. Please check the contents of the license located in * http://www.mod-buildcraft.com/MMPL-1.0.txt */ package buildcraft.core.lib.gui; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; import buildcraft.core.lib.gui.slots.IPhantomSlot; import buildcraft.core.lib.gui.tooltips.IToolTipProvider; import buildcraft.core.lib.gui.tooltips.ToolTip; import buildcraft.core.lib.gui.tooltips.ToolTipLine; import buildcraft.core.lib.gui.widgets.Widget; import buildcraft.core.lib.render.RenderUtils; import buildcraft.core.lib.utils.SessionVars; public abstract class GuiBuildCraft extends GuiContainer { public static final ResourceLocation LEDGER_TEXTURE = new ResourceLocation("buildcraftcore:textures/gui/ledger.png"); public final LedgerManager ledgerManager = new LedgerManager(this); public final TileEntity tile; public final BuildCraftContainer container; public ResourceLocation texture; public GuiBuildCraft(BuildCraftContainer container, IInventory inventory, ResourceLocation texture) { super(container); this.container = container; this.texture = texture; if (inventory instanceof TileEntity) { tile = (TileEntity) inventory; } else { tile = null; } initLedgers(inventory); } public FontRenderer getFontRenderer() { return fontRendererObj; } protected void initLedgers(IInventory inventory) { } /** * Draws the screen and all the components in it. */ @Override public void drawScreen(int mouseX, int mouseY, float par3) { super.drawScreen(mouseX, mouseY, par3); int left = this.guiLeft; int top = this.guiTop; GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glPushMatrix(); GL11.glTranslatef(left, top, 0.0F); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); RenderHelper.disableStandardItemLighting(); InventoryPlayer playerInv = this.mc.thePlayer.inventory; if (playerInv.getItemStack() == null) { drawToolTips(container.getWidgets(), mouseX - left, mouseY - top, left, top); drawToolTips(buttonList, mouseX, mouseY, 0, 0); drawToolTips(inventorySlots.inventorySlots, mouseX, mouseY, 0, 0); } GL11.glPopMatrix(); GL11.glEnable(GL11.GL_LIGHTING); GL11.glEnable(GL11.GL_DEPTH_TEST); } private void drawToolTips(Collection<?> objects, int mouseX, int mouseY, int offsetX, int offsetY) { for (Object obj : objects) { if (!(obj instanceof IToolTipProvider)) { continue; } IToolTipProvider provider = (IToolTipProvider) obj; if (!provider.isToolTipVisible()) { continue; } ToolTip tips = provider.getToolTip(); if (tips == null) { continue; } boolean mouseOver = provider.isMouseOver(mouseX, mouseY); tips.onTick(mouseOver); if (mouseOver && tips.isReady()) { tips.refresh(); drawToolTips(tips, mouseX + offsetX, mouseY + offsetY); } } } public void drawFluid(FluidStack fluid, int x, int y, int width, int height, int maxCapacity) { if (fluid == null || fluid.getFluid() == null) { return; } IIcon icon = fluid.getFluid().getIcon(fluid); if (icon == null) { icon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); } mc.renderEngine.bindTexture(TextureMap.locationBlocksTexture); RenderUtils.setGLColorFromInt(fluid.getFluid().getColor(fluid)); int fullX = width / 16; int fullY = height / 16; int lastX = width - fullX * 16; int lastY = height - fullY * 16; int level = fluid.amount * height / maxCapacity; int fullLvl = (height - level) / 16; int lastLvl = (height - level) - fullLvl * 16; for (int i = 0; i < fullX; i++) { for (int j = 0; j < fullY; j++) { if (j >= fullLvl) { drawCutIcon(icon, x + i * 16, y + j * 16, 16, 16, j == fullLvl ? lastLvl : 0); } } } for (int i = 0; i < fullX; i++) { drawCutIcon(icon, x + i * 16, y + fullY * 16, 16, lastY, fullLvl == fullY ? lastLvl : 0); } for (int i = 0; i < fullY; i++) { if (i >= fullLvl) { drawCutIcon(icon, x + fullX * 16, y + i * 16, lastX, 16, i == fullLvl ? lastLvl : 0); } } drawCutIcon(icon, x + fullX * 16, y + fullY * 16, lastX, lastY, fullLvl == fullY ? lastLvl : 0); } //The magic is here private void drawCutIcon(IIcon icon, int x, int y, int width, int height, int cut) { Tessellator tess = Tessellator.instance; tess.startDrawingQuads(); tess.addVertexWithUV(x, y + height, zLevel, icon.getMinU(), icon.getInterpolatedV(height)); tess.addVertexWithUV(x + width, y + height, zLevel, icon.getInterpolatedU(width), icon.getInterpolatedV(height)); tess.addVertexWithUV(x + width, y + cut, zLevel, icon.getInterpolatedU(width), icon.getInterpolatedV(cut)); tess.addVertexWithUV(x, y + cut, zLevel, icon.getMinU(), icon.getInterpolatedV(cut)); tess.draw(); } @Override protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); bindTexture(texture); drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); int mX = mouseX - guiLeft; int mY = mouseY - guiTop; drawWidgets(mX, mY); } protected void drawWidgets(int mX, int mY) { for (Widget widget : container.getWidgets()) { if (widget.hidden) { continue; } bindTexture(texture); widget.draw(this, guiLeft, guiTop, mX, mY); } } @Override protected void drawGuiContainerForegroundLayer(int par1, int par2) { drawLedgers(par1, par2); } protected void drawLedgers(int x, int y) { ledgerManager.drawLedgers(x, y); } public void drawCenteredString(String string, int xCenter, int yCenter, int textColor) { fontRendererObj.drawString(string, xCenter - fontRendererObj.getStringWidth(string) / 2, yCenter - fontRendererObj.FONT_HEIGHT / 2, textColor); } protected int getCenteredOffset(String string) { return getCenteredOffset(string, xSize); } protected int getCenteredOffset(String string, int xWidth) { return (xWidth - fontRendererObj.getStringWidth(string)) / 2; } /** * Returns if the passed mouse position is over the specified slot. */ private boolean isMouseOverSlot(Slot slot, int mouseX, int mouseY) { int left = this.guiLeft; int top = this.guiTop; int realMouseX = mouseX - left; int realMouseY = mouseY - top; return realMouseX >= slot.xDisplayPosition - 1 && realMouseX < slot.xDisplayPosition + 16 + 1 && realMouseY >= slot.yDisplayPosition - 1 && realMouseY < slot.yDisplayPosition + 16 + 1; } // / MOUSE CLICKS @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { int mX = mouseX - guiLeft; int mY = mouseY - guiTop; for (Widget widget : container.getWidgets()) { if (widget.hidden) { continue; } else if (!widget.isMouseOver(mX, mY)) { continue; } else if (widget.handleMouseClick(mX, mY, mouseButton)) { return; } } super.mouseClicked(mouseX, mouseY, mouseButton); // / Handle ledger clicks ledgerManager.handleMouseClicked(mouseX, mouseY, mouseButton); } @Override protected void mouseClickMove(int mouseX, int mouseY, int mouseButton, long time) { int mX = mouseX - guiLeft; int mY = mouseY - guiTop; for (Widget widget : container.getWidgets()) { if (widget.hidden) { continue; } widget.handleMouseMove(mX, mY, mouseButton, time); } Slot slot = getSlotAtPosition(mouseX, mouseY); if (mouseButton == 1 && slot instanceof IPhantomSlot) { return; } super.mouseClickMove(mouseX, mouseY, mouseButton, time); } @Override protected void mouseMovedOrUp(int mouseX, int mouseY, int eventType) { super.mouseMovedOrUp(mouseX, mouseY, eventType); int mX = mouseX - guiLeft; int mY = mouseY - guiTop; for (Widget widget : container.getWidgets()) { if (widget.hidden) { continue; } widget.handleMouseRelease(mX, mY, eventType); } } public Slot getSlotAtPosition(int x, int y) { for (int slotIndex = 0; slotIndex < this.inventorySlots.inventorySlots.size(); ++slotIndex) { Slot slot = (Slot) this.inventorySlots.inventorySlots.get(slotIndex); if (isMouseOverSlot(slot, x, y)) { return slot; } } return null; } public void bindTexture(ResourceLocation texture) { Minecraft.getMinecraft().renderEngine.bindTexture(texture); } private void drawToolTips(ToolTip toolTips, int mouseX, int mouseY) { if (toolTips.size() > 0) { int left = this.guiLeft; int top = this.guiTop; int length = 0; int x; int y; for (ToolTipLine tip : toolTips) { y = this.fontRendererObj.getStringWidth(tip.text); if (y > length) { length = y; } } x = mouseX - left + 12; y = mouseY - top - 12; int var14 = 8; if (toolTips.size() > 1) { var14 += 2 + (toolTips.size() - 1) * 10; } this.zLevel = 300.0F; itemRender.zLevel = 300.0F; int var15 = -267386864; this.drawGradientRect(x - 3, y - 4, x + length + 3, y - 3, var15, var15); this.drawGradientRect(x - 3, y + var14 + 3, x + length + 3, y + var14 + 4, var15, var15); this.drawGradientRect(x - 3, y - 3, x + length + 3, y + var14 + 3, var15, var15); this.drawGradientRect(x - 4, y - 3, x - 3, y + var14 + 3, var15, var15); this.drawGradientRect(x + length + 3, y - 3, x + length + 4, y + var14 + 3, var15, var15); int var16 = 1347420415; int var17 = (var16 & 16711422) >> 1 | var16 & -16777216; this.drawGradientRect(x - 3, y - 3 + 1, x - 3 + 1, y + var14 + 3 - 1, var16, var17); this.drawGradientRect(x + length + 2, y - 3 + 1, x + length + 3, y + var14 + 3 - 1, var16, var17); this.drawGradientRect(x - 3, y - 3, x + length + 3, y - 3 + 1, var16, var16); this.drawGradientRect(x - 3, y + var14 + 2, x + length + 3, y + var14 + 3, var17, var17); for (ToolTipLine tip : toolTips) { String line = tip.text; if (tip.color == -1) { line = "\u00a77" + line; } else { line = "\u00a7" + Integer.toHexString(tip.color) + line; } this.fontRendererObj.drawStringWithShadow(line, x, y, -1); y += 10 + tip.getSpacing(); } this.zLevel = 0.0F; itemRender.zLevel = 0.0F; } } protected class LedgerManager { protected ArrayList<Ledger> ledgers = new ArrayList<Ledger>(); private GuiBuildCraft gui; public LedgerManager(GuiBuildCraft gui) { this.gui = gui; } public void add(Ledger ledger) { this.ledgers.add(ledger); if (SessionVars.getOpenedLedger() != null && ledger.getClass().equals(SessionVars.getOpenedLedger())) { ledger.setFullyOpen(); } } /** * Inserts a ledger into the next-to-last position. * * @param ledger */ public void insert(Ledger ledger) { this.ledgers.add(ledgers.size() - 1, ledger); } protected Ledger getAtPosition(int mX, int mY) { int xShift = ((gui.width - gui.xSize) / 2) + gui.xSize; int yShift = ((gui.height - gui.ySize) / 2) + 8; for (Ledger ledger : ledgers) { if (!ledger.isVisible()) { continue; } ledger.currentShiftX = xShift; ledger.currentShiftY = yShift; if (ledger.intersectsWith(mX, mY, xShift, yShift)) { return ledger; } yShift += ledger.getHeight(); } return null; } protected void drawLedgers(int mouseX, int mouseY) { int yPos = 8; for (Ledger ledger : ledgers) { ledger.update(); if (!ledger.isVisible()) { continue; } ledger.draw(xSize, yPos); yPos += ledger.getHeight(); } Ledger ledger = getAtPosition(mouseX, mouseY); if (ledger != null) { int startX = mouseX - ((gui.width - gui.xSize) / 2) + 12; int startY = mouseY - ((gui.height - gui.ySize) / 2) - 12; String tooltip = ledger.getTooltip(); int textWidth = fontRendererObj.getStringWidth(tooltip); drawGradientRect(startX - 3, startY - 3, startX + textWidth + 3, startY + 8 + 3, 0xc0000000, 0xc0000000); fontRendererObj.drawStringWithShadow(tooltip, startX, startY, -1); } } public void handleMouseClicked(int x, int y, int mouseButton) { if (mouseButton == 0) { Ledger ledger = this.getAtPosition(x, y); // Default action only if the mouse click was not handled by the // ledger itself. if (ledger != null && !ledger.handleMouseClicked(x, y, mouseButton)) { for (Ledger other : ledgers) { if (other != ledger && other.isOpen()) { other.toggleOpen(); } } ledger.toggleOpen(); } } } } /** * Side ledger for guis */ protected abstract class Ledger { public int currentShiftX = 0; public int currentShiftY = 0; protected int overlayColor = 0xffffff; protected int maxWidth = 124; protected int minWidth = 24; protected int currentWidth = minWidth; protected int maxHeight = 24; protected int minHeight = 24; protected int currentHeight = minHeight; private boolean open; private long lastUpdateTime = -1; public void update() { if (lastUpdateTime < 0) { lastUpdateTime = (new Date()).getTime(); } long updateTime = (new Date()).getTime(); int updateVal = (int) Math.round((updateTime - lastUpdateTime) / 8.0); // Width if (open && currentWidth < maxWidth) { currentWidth += updateVal; currentWidth = Math.min(maxWidth, currentWidth); } else if (!open && currentWidth > minWidth) { currentWidth -= updateVal; currentWidth = Math.max(minWidth, currentWidth); } // Height if (open && currentHeight < maxHeight) { currentHeight += updateVal; currentHeight = Math.min(maxWidth, currentHeight); } else if (!open && currentHeight > minHeight) { currentHeight -= updateVal; currentHeight = Math.max(minHeight, currentHeight); } lastUpdateTime = updateTime; } public int getHeight() { return currentHeight; } public abstract void draw(int x, int y); public abstract String getTooltip(); public boolean handleMouseClicked(int x, int y, int mouseButton) { return false; } public boolean intersectsWith(int mouseX, int mouseY, int shiftX, int shiftY) { if (mouseX >= shiftX && mouseX <= shiftX + currentWidth && mouseY >= shiftY && mouseY <= shiftY + getHeight()) { return true; } return false; } public void setFullyOpen() { open = true; currentWidth = maxWidth; currentHeight = maxHeight; } public void toggleOpen() { if (open) { open = false; SessionVars.setOpenedLedger(null); } else { open = true; SessionVars.setOpenedLedger(this.getClass()); } } public boolean isVisible() { return true; } public boolean isOpen() { return this.open; } protected boolean isFullyOpened() { return currentWidth >= maxWidth; } protected void drawBackground(int x, int y) { RenderUtils.setGLColorFromInt(overlayColor); mc.renderEngine.bindTexture(LEDGER_TEXTURE); drawTexturedModalRect(x, y, 0, 256 - currentHeight, 4, currentHeight); drawTexturedModalRect(x + 4, y, 256 - currentWidth + 4, 0, currentWidth - 4, 4); // Add in top left corner again drawTexturedModalRect(x, y, 0, 0, 4, 4); drawTexturedModalRect(x + 4, y + 4, 256 - currentWidth + 4, 256 - currentHeight + 4, currentWidth - 4, currentHeight - 4); GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0F); } protected void drawIcon(IIcon icon, int x, int y) { GL11.glDisable(GL11.GL_BLEND); GL11.glEnable(GL11.GL_ALPHA_TEST); GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0F); drawTexturedModelRectFromIcon(x, y, icon, 16, 16); } } public BuildCraftContainer getContainer() { return container; } }