Files
JustEnoughCalculation/src/main/java/me/towdium/jecalculation/gui/JecaGui.java
T
2021-05-02 04:17:58 +08:00

535 lines
20 KiB
Java

package me.towdium.jecalculation.gui;
import codechicken.nei.guihook.GuiContainerManager;
import cpw.mods.fml.client.config.GuiUtils;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import me.towdium.jecalculation.JustEnoughCalculation;
import me.towdium.jecalculation.data.label.ILabel;
import me.towdium.jecalculation.gui.guis.IGui;
import me.towdium.jecalculation.nei.NEIPlugin;
import me.towdium.jecalculation.polyfill.mc.client.renderer.GlStateManager;
import me.towdium.jecalculation.utils.Utilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
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.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraftforge.fluids.Fluid;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static codechicken.lib.gui.GuiDraw.renderEngine;
/**
* Author: towdium
* Date: 8/12/17.
*/
@ParametersAreNonnullByDefault
@SideOnly(Side.CLIENT)
public class JecaGui extends GuiContainer {
public static final int COLOR_GUI_GREY = 0xFFA1A1A1;
public static final int COLOR_TEXT_RED = 0xFF0000;
public static final int COLOR_TEXT_GREY = 0x404040;
public static final int COLOR_TEXT_WHITE = 0xFFFFFF;
public static final boolean ALWAYS_TOOLTIP = false;
public ILabel hand = ILabel.EMPTY;
protected static JecaGui last;
protected static Runnable scheduled;
protected static int timeout;
protected JecaGui parent;
public IGui root;
public JecaGui(@Nullable JecaGui parent, IGui root) {
this(parent, false, root);
}
public JecaGui(@Nullable JecaGui parent, boolean acceptsTransfer, IGui root) {
super(acceptsTransfer ? new ContainerTransfer() : new ContainerNonTransfer());
this.parent = parent;
this.root = root;
if (inventorySlots instanceof JecContainer)
((JecContainer) inventorySlots).setGui(this);
}
public static int getMouseX() {
JecaGui gui = getCurrent();
return Mouse.getEventX() * gui.width / gui.mc.displayWidth - gui.guiLeft;
}
public static int getMouseY() {
JecaGui gui = getCurrent();
return gui.height - Mouse.getEventY() * gui.height / gui.mc.displayHeight - 1 - gui.guiTop;
}
@Override
public void initGui() {
this.guiLeft = (this.width - this.xSize) / 2;
this.guiTop = (this.height - this.ySize) / 2;
}
public static boolean mouseIn(int xPos, int yPos, int xSize, int ySize, int xMouse, int yMouse) {
return xMouse > xPos && yMouse > yPos && xMouse <= xPos + xSize && yMouse <= yPos + ySize;
}
public static void displayGui(IGui root) {
displayGui(true, false, root);
}
public static void displayGui(boolean updateParent, boolean acceptsTransfer, IGui root) {
displayGui(updateParent, acceptsTransfer, false, root);
}
public static void displayGui(boolean updateParent, boolean acceptsTransfer, boolean scheduled, IGui root) {
Runnable r = () -> {
// isCallingFromMinecraftThread
if (Minecraft.getMinecraft().func_152345_ab())
displayGuiUnsafe(updateParent, acceptsTransfer, root);
};
if (scheduled) {
JecaGui.scheduled = r;
JecaGui.timeout = 2;
} else
r.run();
}
/**
* @return The currently displayed {@link JecaGui}
* Make sure the method is called when a {@link JecaGui} is displayed!
* Otherwise it will throw a {@link NullPointerException}
*/
public static JecaGui getCurrent() {
GuiScreen gui = Minecraft.getMinecraft().currentScreen;
JecaGui ret = gui instanceof JecaGui ? (JecaGui) gui : null;
Objects.requireNonNull(ret);
return ret;
}
private static void displayGuiUnsafe(boolean updateParent, boolean acceptsTransfer, IGui root) {
Minecraft mc = Minecraft.getMinecraft();
JecaGui parent;
if (mc.currentScreen == null)
parent = null;
else if (!(mc.currentScreen instanceof JecaGui))
parent = last;
else if (updateParent)
parent = (JecaGui) mc.currentScreen;
else
parent = ((JecaGui) mc.currentScreen).parent;
JecaGui toShow = new JecaGui(parent, acceptsTransfer, root);
root.onVisible(toShow);
last = toShow;
mc.displayGuiScreen(toShow);
}
public static void displayParent() {
// isCallingFromMinecraftThread
if (Minecraft.getMinecraft().func_152345_ab()) {
JecaGui gui = getCurrent().parent;
gui.root.onVisible(gui);
last = gui;
Minecraft.getMinecraft().displayGuiScreen(gui);
}
}
public static void onGameTick() {
if (scheduled != null) {
if (timeout <= 0) {
Runnable r = scheduled;
scheduled = null;
r.run();
} else
timeout--;
}
}
public static boolean isShiftDown() {
return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
}
@Override
public boolean doesGuiPauseGame() {
return false;
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
drawDefaultBackground();
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
super.drawScreen(mouseX, mouseY, partialTicks);
GlStateManager.pushMatrix();
GlStateManager.translate(guiLeft, guiTop, 0);
GlStateManager.disableLighting();
GlStateManager.disableDepth();
root.onDraw(this, mouseX - guiLeft, mouseY - guiTop);
GlStateManager.popMatrix();
GlStateManager.pushMatrix();
GlStateManager.translate(0, 0, 80);
hand.drawLabel(this, mouseX, mouseY, true);
GlStateManager.popMatrix();
List<String> tooltip = new ArrayList<>();
root.onTooltip(this, mouseX - guiLeft, mouseY - guiTop, tooltip);
drawHoveringText(tooltip, mouseX, mouseY);
GlStateManager.enableLighting();
GlStateManager.enableDepth();
}
@Override
// modified from vanilla
public void drawHoveringText(List lines, int x, int y, FontRenderer font) {
List<String> textLines = (List<String>) lines;
if (!textLines.isEmpty()) {
GlStateManager.disableRescaleNormal();
RenderHelper.disableStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.disableDepth();
int i = 0;
for (String s : textLines) {
int j = this.fontRendererObj.getStringWidth(s);
if (j > i)
i = j;
}
int l1 = x + 12;
int i2 = y - 12;
int k = 8 + (textLines.size() - 1) * 10;
if (l1 + i > this.width)
l1 -= 28 + i;
if (i2 + k + 6 > this.height)
i2 = this.height - k - 6;
zLevel = 300.0F;
itemRender.zLevel = 300.0F;
drawGradientRect(l1 - 3, i2 - 4, l1 + i + 3, i2 - 3, -267386864, -267386864);
drawGradientRect(l1 - 3, i2 + k + 3, l1 + i + 3, i2 + k + 4, -267386864, -267386864);
drawGradientRect(l1 - 3, i2 - 3, l1 + i + 3, i2 + k + 3, -267386864, -267386864);
drawGradientRect(l1 - 4, i2 - 3, l1 - 3, i2 + k + 3, -267386864, -267386864);
drawGradientRect(l1 + i + 3, i2 - 3, l1 + i + 4, i2 + k + 3, -267386864, -267386864);
drawGradientRect(l1 - 3, i2 - 3 + 1, l1 - 3 + 1, i2 + k + 3 - 1, 1347420415, 1344798847);
drawGradientRect(l1 + i + 2, i2 - 3 + 1, l1 + i + 3, i2 + k + 3 - 1, 1347420415, 1344798847);
drawGradientRect(l1 - 3, i2 - 3, l1 + i + 3, i2 - 3 + 1, 1347420415, 1347420415);
drawGradientRect(l1 - 3, i2 + k + 2, l1 + i + 3, i2 + k + 3, 1344798847, 1344798847);
for (String s1 : textLines) {
fontRendererObj.drawStringWithShadow(s1, l1, i2, -1);
i2 += 10;
}
zLevel = 0.0F;
itemRender.zLevel = 0.0F;
GlStateManager.enableLighting();
GlStateManager.enableDepth();
RenderHelper.enableStandardItemLighting();
GlStateManager.enableRescaleNormal();
}
}
/**
* This function handles events within the interface.
* Specifically, handles mouse wheel within interface.
* Different from {@link #handleMouseEvent()}, which is
* used to handle mouse event outside.
*/
@Override
public void handleMouseInput() {
super.handleMouseInput();
int diff = Mouse.getEventDWheel() / 120;
if (diff != 0)
root.onScroll(this, Mouse.getEventX() * width / mc.displayWidth - guiLeft,
height - Mouse.getEventY() * height / mc.displayHeight - 1 - guiTop, diff);
}
/**
* @return if the event is canceled
* This function handles click outside the rNormal region,
* especially the overlap with JEI overlay. It handles
* mouse event before JEI.
*/
public boolean handleMouseEvent() {
JustEnoughCalculation.logger.info("handle mouse clicked");
int xMouse = Mouse.getEventX() * this.width / this.mc.displayWidth;
int yMouse = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
int button = Mouse.getEventButton();
if (Mouse.getEventButtonState()) {
if (hand != ILabel.EMPTY) {
hand = ILabel.EMPTY;
return true;
} else {
ILabel e = NEIPlugin.getLabelUnderMouse();
if (e != ILabel.EMPTY) {
hand = e;
return true;
}
}
}
return false;
}
public void drawResource(Resource r, int xPos, int yPos) {
drawResource(r, xPos, yPos, 0xFFFFFF);
}
public void drawResource(Resource r, int xPos, int yPos, int color) {
float red = (color >> 16 & 0xFF) / 255.0F;
float green = (color >> 8 & 0xFF) / 255.0F;
float blue = (color & 0xFF) / 255.0F;
float alpha = (~(color >> 24) & 0xFF) / 255.0F;
GlStateManager.color(red, green, blue, alpha);
mc.getTextureManager().bindTexture(r.getResourceLocation());
drawTexturedModalRect(xPos, yPos, r.getXPos(), r.getYPos(), r.getXSize(), r.getYSize());
}
public void drawResourceContinuous(Resource r, int xPos, int yPos, int xSize, int ySize, int border) {
drawResourceContinuous(r, xPos, yPos, xSize, ySize, border, border, border, border);
}
public void drawResourceContinuous(Resource r,
int xPos,
int yPos,
int xSize,
int ySize,
int borderTop,
int borderBottom,
int borderLeft,
int borderRight) {
GuiUtils.drawContinuousTexturedBox(r.getResourceLocation(), xPos, yPos, r.getXPos(), r.getYPos(), xSize, ySize,
r.getXSize(), r.getYSize(), borderTop, borderBottom, borderLeft, borderRight,
zLevel);
}
private void setColor(int color) {
float red = (color >> 16 & 0xFF) / 255.0F;
float green = (color >> 8 & 0xFF) / 255.0F;
float blue = (color & 0xFF) / 255.0F;
float alpha = (~(color >> 24) & 0xFF) / 255.0F;
GlStateManager.color(red, green, blue, alpha);
}
public void drawFluid(Fluid f, int xPos, int yPos, int xSize, int ySize) {
IIcon fluidStillIcon = f.getStillIcon();
mc.renderEngine.bindTexture(TextureMap.locationBlocksTexture);
setColor(f.getColor() & 0x00FFFFFF);
if (fluidStillIcon != null)
drawTexturedModelRectFromIcon(xPos, yPos, fluidStillIcon, xSize, ySize);
}
public void drawRectangle(int xPos, int yPos, int xSize, int ySize, int color) {
float f3 = (float) (color >> 24 & 255) / 255.0F;
float f = (float) (color >> 16 & 255) / 255.0F;
float f1 = (float) (color >> 8 & 255) / 255.0F;
float f2 = (float) (color & 255) / 255.0F;
int right = xPos + xSize;
int bottom = yPos + ySize;
Tessellator tessellator = Tessellator.instance;
GlStateManager.disableTexture2D();
GlStateManager.color(f, f1, f2, f3);
GlStateManager.disableAlpha();
tessellator.startDrawingQuads();
tessellator.addVertex((double) xPos, (double) bottom, 0.0D);
tessellator.addVertex((double) right, (double) bottom, 0.0D);
tessellator.addVertex((double) right, (double) yPos, 0.0D);
tessellator.addVertex((double) xPos, (double) yPos, 0.0D);
tessellator.draw();
GlStateManager.enableAlpha();
GlStateManager.enableTexture2D();
}
public void drawOverRectangle(int xPos, int yPos, int xSize, int ySize, int color) {
GlStateManager.disableLighting();
GlStateManager.disableDepth();
GlStateManager.colorMask(true, true, true, false);
this.drawGradientRect(xPos, yPos, xPos + xSize, yPos + ySize, color, color);
GlStateManager.colorMask(true, true, true, true);
GlStateManager.enableLighting();
GlStateManager.enableDepth();
}
public int getStringWidth(String s) {
return fontRendererObj.getStringWidth(s);
}
public void drawSplitText(float xPos, float yPos, Font f, String s) {
drawSplitText(xPos, yPos, Integer.MAX_VALUE, f, s);
}
public void drawSplitText(float xPos, float yPos, int width, Font f, String s) {
drawSplitText(xPos, yPos, f, Utilities.I18n.wrap(s, width));
}
public void drawSplitText(float xPos, float yPos, Font f, List<String> ss) {
drawText(xPos, yPos, f, () -> {
int y = 0;
for (String i : ss) {
fontRendererObj.drawString(i, 0, y, f.color, f.shadow);
y += fontRendererObj.FONT_HEIGHT + 1;
}
});
}
public void drawText(float xPos, float yPos, Font f, String s) {
drawText(xPos, yPos, Integer.MAX_VALUE, f, s);
}
public void drawText(float xPos, float yPos, int width, Font f, String s) {
drawText(xPos, yPos, f, () -> {
String str = s;
int strWidth = f.getTextWidth(str);
int ellipsisWidth = f.getTextWidth("...");
if (strWidth > width && strWidth > ellipsisWidth)
str = f.trimToWidth(str, width - ellipsisWidth).trim() + "...";
fontRendererObj.drawString(str, 0, 0, f.color, f.shadow);
});
}
private void drawText(float xPos, float yPos, Font f, Runnable r) {
boolean unicode = fontRendererObj.getUnicodeFlag();
if (f.raw)
fontRendererObj.setUnicodeFlag(false);
GlStateManager.pushMatrix();
GlStateManager.translate(xPos, yPos, 0);
if (f.half)
GlStateManager.scale(0.5, 0.5, 1);
r.run();
GlStateManager.popMatrix();
fontRendererObj.setUnicodeFlag(unicode);
}
public void drawItemStack(int xPos, int yPos, ItemStack is, boolean centred) {
if (is.getItem() == null) {
return;
}
if (centred) {
xPos -= 8;
yPos -= 8;
}
float zLevel = itemRender.zLevel += 100F;
GlStateManager.enableDepth();
RenderHelper.enableGUIStandardItemLighting();
itemRender.renderItemAndEffectIntoGUI(fontRendererObj, renderEngine, is, xPos, yPos);
itemRender.renderItemOverlayIntoGUI(fontRendererObj, renderEngine, is, xPos, yPos);
RenderHelper.disableStandardItemLighting();
GlStateManager.disableDepth();
itemRender.zLevel = zLevel - 100F;
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
JustEnoughCalculation.logger.info("mouse clicked");
super.mouseClicked(mouseX, mouseY, mouseButton);
boolean inGui = root.onClicked(this, mouseX - guiLeft, mouseY - guiTop, mouseButton);
if (!inGui) {
this.handleMouseEvent();
}
}
@Override
protected void keyTyped(char typedChar, int keyCode) {
if (keyCode == Keyboard.KEY_ESCAPE && hand != ILabel.EMPTY)
hand = ILabel.EMPTY;
else if (!root.onKey(this, typedChar, keyCode)) {
if (keyCode == Keyboard.KEY_ESCAPE && parent != null)
displayParent();
else
super.keyTyped(typedChar, keyCode);
}
}
public static class Font {
public static final Font SHADOW = new Font(JecaGui.COLOR_TEXT_WHITE, true, false, false);
public static final Font PLAIN = new Font(JecaGui.COLOR_TEXT_GREY, false, false, false);
public static final Font RAW = new Font(JecaGui.COLOR_TEXT_GREY, false, false, true);
public static final Font HALF = new Font(JecaGui.COLOR_TEXT_WHITE, true, true, true);
public int color;
public boolean shadow, half, raw;
public Font(int color, boolean shadow, boolean half, boolean raw) {
this.color = color;
this.shadow = shadow;
this.half = half;
this.raw = raw;
}
public int getTextWidth(String s) {
FontRenderer fr = getCurrent().fontRendererObj;
boolean flag = fr.getUnicodeFlag();
if (raw)
fr.setUnicodeFlag(false);
int ret = (int) Math.ceil(fr.getStringWidth(s) * (half ? 0.5f : 1));
fr.setUnicodeFlag(flag);
return ret;
}
public int getTextHeight() {
return (int) Math.ceil(getCurrent().fontRendererObj.FONT_HEIGHT * (half ? 0.5f : 1));
}
public String trimToWidth(String s, int i) {
return getCurrent().fontRendererObj.trimStringToWidth(s, i * (half ? 2 : 1));
}
}
public static class JecContainer extends Container {
JecaGui gui;
public JecaGui getGui() {
return gui;
}
public void setGui(JecaGui gui) {
this.gui = gui;
}
@Override
public boolean canInteractWith(EntityPlayer playerIn) {
return true;
}
}
public static class ContainerTransfer extends JecContainer {
}
public static class ContainerNonTransfer extends JecContainer {
}
public int getGuiLeft() {
return guiLeft;
}
public int getGuiTop() {
return guiTop;
}
public void drawHoveringText(String text, int x, int y) {
super.drawHoveringText(Collections.singletonList(text), x, y, fontRendererObj);
}
public void drawHoveringText(List<String> textLines, int x, int y) {
super.drawHoveringText(textLines, x, y, fontRendererObj);
}
public int getXSize() {
return xSize;
}
public int getYSize() {
return ySize;
}
}