package codechicken.nei.config;
import codechicken.core.CommonUtils;
import codechicken.lib.gui.GuiDraw;
import codechicken.nei.ItemPanel;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.guihook.GuiContainerManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.IntBuffer;
import java.util.Arrays;
public class GuiItemIconDumper extends GuiScreen
{
final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
static {
Arrays.sort(illegalChars);
}
private Option opt;
private int drawIndex;
private int parseIndex;
private File dir = new File(CommonUtils.getMinecraftDir(), "dumps/itempanel_icons");
private int iconSize;
private int borderSize;
private int boxSize;
public GuiItemIconDumper(Option opt, int iconSize) {
this.opt = opt;
this.iconSize = iconSize;
borderSize = iconSize/16;
boxSize = iconSize + borderSize*2;
if (dir.exists()) {
for (File f : dir.listFiles())
if (f.isFile()) f.delete();
} else
dir.mkdirs();
}
private void returnScreen(IChatComponent msg) {
Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui());
NEIClientUtils.printChatMessage(msg);
}
@Override
protected void keyTyped(char c, int keycode) throws IOException {
if (keycode == Keyboard.KEY_ESCAPE || keycode == Keyboard.KEY_BACK) {
returnScreen(new ChatComponentTranslation(opt.fullName()+".icon.cancelled"));
return;
}
super.keyTyped(c, keycode);
}
@Override
public void drawScreen(int mousex, int mousey, float frame) {
try {
drawItems();
exportItems();
} catch (Exception e) {
NEIClientConfig.logger.error("Error dumping item icons", e);
}
}
private void drawItems() {
Dimension d = GuiDraw.displayRes();
GlStateManager.matrixMode(GL11.GL_PROJECTION);
GlStateManager.loadIdentity();
GlStateManager.ortho(0, d.width*16D/iconSize, d.height*16D/iconSize, 0, 1000, 3000);
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
GlStateManager.clearColor(0, 0, 0, 0);
GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
int rows = d.height / boxSize;
int cols = d.width / boxSize;
int fit = rows*cols;
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.enableRescaleNormal();
GlStateManager.color(1, 1, 1, 1);
for(int i = 0; drawIndex < ItemPanel.items.size() && i < fit; drawIndex++, i++) {
int x = i%cols * 18;
int y = i/cols * 18;
GuiContainerManager.drawItem(x+1, y+1, ItemPanel.items.get(drawIndex));
}
GL11.glFlush();
}
private void exportItems() throws IOException {
BufferedImage img = screenshot();
int rows = img.getHeight() / boxSize;
int cols = img.getWidth() / boxSize;
int fit = rows*cols;
for(int i = 0; parseIndex < ItemPanel.items.size() && i < fit; parseIndex++, i++) {
int x = i%cols * boxSize;
int y = i/cols * boxSize;
exportImage(dir, img.getSubimage(x+borderSize, y+borderSize, iconSize, iconSize), ItemPanel.items.get(parseIndex));
}
if(parseIndex >= ItemPanel.items.size())
returnScreen(new ChatComponentTranslation(opt.fullName()+".icon.dumped", "dumps/itempanel_icons"));
}
public static String cleanFileName(String name) {
StringBuilder cleanName = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
int c = (int)name.charAt(i);
if (Arrays.binarySearch(illegalChars, c) < 0)
cleanName.append((char)c);
else
cleanName.append('_');
}
return cleanName.toString();
}
private void exportImage(File dir, BufferedImage img, ItemStack stack) throws IOException {
String name = EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.itemDisplayNameShort(stack));
name = cleanFileName(name);
File file = new File(dir, name+".png");
for(int i = 2; file.exists(); i++)
file = new File(dir, name+'_'+i+".png");
ImageIO.write(img, "png", file);
}
private IntBuffer pixelBuffer;
private int[] pixelValues;
private BufferedImage screenshot() {
Framebuffer fb = Minecraft.getMinecraft().getFramebuffer();
Dimension mcSize = GuiDraw.displayRes();
Dimension texSize = mcSize;
if (OpenGlHelper.isFramebufferEnabled())
texSize = new Dimension(fb.framebufferTextureWidth, fb.framebufferTextureHeight);
int k = texSize.width * texSize.height;
if (pixelBuffer == null || pixelBuffer.capacity() < k) {
pixelBuffer = BufferUtils.createIntBuffer(k);
pixelValues = new int[k];
}
GL11.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 1);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
pixelBuffer.clear();
if (OpenGlHelper.isFramebufferEnabled()) {
GlStateManager.bindTexture(fb.framebufferTexture);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
} else {
GL11.glReadPixels(0, 0, texSize.width, texSize.height, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
}
pixelBuffer.get(pixelValues);
TextureUtil.processPixelValues(pixelValues, texSize.width, texSize.height);
BufferedImage img = new BufferedImage(mcSize.width, mcSize.height, BufferedImage.TYPE_INT_ARGB);
if (OpenGlHelper.isFramebufferEnabled()) {
int yOff = texSize.height - mcSize.height;
for (int y = 0; y < mcSize.height; ++y)
for (int x = 0; x < mcSize.width; ++x)
img.setRGB(x, y, pixelValues[(y + yOff) * texSize.width + x]);
} else {
img.setRGB(0, 0, texSize.width, height, pixelValues, 0, texSize.width);
}
return img;
}
}