From cd0326365df1128d370687cd5771c178922d1f74 Mon Sep 17 00:00:00 2001 From: AterAnimAvis Date: Thu, 7 May 2020 17:53:58 +0100 Subject: [PATCH] Refactor + Error Handling --- This refactor abstracts most of the bulk/single render logic in preparation for Entity/Structure renders. Signed-off-by: AterAnimAvis --- .../blockrenderer/BlockRenderer.java | 12 +- .../blockrenderer/render/BulkRenderer.java | 132 ++++++++ .../blockrenderer/render/IRenderer.java | 69 ++++ .../render/ItemStackRenderer.java | 299 ------------------ .../blockrenderer/render/SingleRenderer.java | 19 ++ .../render/impl/ItemStackRenderer.java | 160 ++++++++++ .../render/impl/package-info.java | 7 + .../render/request/item/BulkItemRequest.java | 17 +- .../render/request/item/ItemRequest.java | 5 +- .../blockrenderer/utils/ImageUtils.java | 34 +- .../blockrenderer/utils/StringUtils.java | 5 + .../assets/blockrenderer/lang/en_us.json | 9 +- 12 files changed, 419 insertions(+), 349 deletions(-) create mode 100644 src/main/java/com/unascribed/blockrenderer/render/BulkRenderer.java create mode 100644 src/main/java/com/unascribed/blockrenderer/render/IRenderer.java delete mode 100644 src/main/java/com/unascribed/blockrenderer/render/ItemStackRenderer.java create mode 100644 src/main/java/com/unascribed/blockrenderer/render/SingleRenderer.java create mode 100644 src/main/java/com/unascribed/blockrenderer/render/impl/ItemStackRenderer.java create mode 100644 src/main/java/com/unascribed/blockrenderer/render/impl/package-info.java diff --git a/src/main/java/com/unascribed/blockrenderer/BlockRenderer.java b/src/main/java/com/unascribed/blockrenderer/BlockRenderer.java index 856eed8..ab1509e 100644 --- a/src/main/java/com/unascribed/blockrenderer/BlockRenderer.java +++ b/src/main/java/com/unascribed/blockrenderer/BlockRenderer.java @@ -1,7 +1,8 @@ package com.unascribed.blockrenderer; import com.unascribed.blockrenderer.init.Keybindings; -import com.unascribed.blockrenderer.render.ItemStackRenderer; +import com.unascribed.blockrenderer.render.SingleRenderer; +import com.unascribed.blockrenderer.render.impl.ItemStackRenderer; import com.unascribed.blockrenderer.render.request.IRequest; import com.unascribed.blockrenderer.screens.EnterNamespaceScreen; import com.unascribed.blockrenderer.screens.EnterSizeScreen; @@ -46,14 +47,7 @@ public BlockRenderer() { public void onFrameStart(TickEvent.RenderTickEvent e) { if (e.phase != TickEvent.Phase.START) return; - /* - * Quick primer: OpenGL is double-buffered. This means, where we draw to is - * /not/ on the screen. As such, we are free to do whatever we like before - * Minecraft renders, as long as we put everything back the way it was. - */ - if (pendingRequest != null) { - // We *must* call render code in pre-render. If we don't, it won't work right. pendingRequest.render(); pendingRequest = null; } @@ -124,7 +118,7 @@ private static void renderStack(ItemStack stack) { return; } - ItemStackRenderer.renderItem(512, stack, false, false); + SingleRenderer.render(new ItemStackRenderer(), stack, 512, false, false); } private static boolean isKeyDown() { diff --git a/src/main/java/com/unascribed/blockrenderer/render/BulkRenderer.java b/src/main/java/com/unascribed/blockrenderer/render/BulkRenderer.java new file mode 100644 index 0000000..406cbca --- /dev/null +++ b/src/main/java/com/unascribed/blockrenderer/render/BulkRenderer.java @@ -0,0 +1,132 @@ +package com.unascribed.blockrenderer.render; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.unascribed.blockrenderer.utils.Rendering; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.IngameMenuScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.Util; +import net.minecraft.util.text.TranslationTextComponent; + +import javax.annotation.Nullable; +import java.io.File; +import java.util.List; + +import static com.unascribed.blockrenderer.render.IRenderer.DEFAULT_FOLDER; +import static com.unascribed.blockrenderer.utils.MiscUtils.isEscapePressed; +import static com.unascribed.blockrenderer.utils.StringUtils.*; + +public class BulkRenderer { + + private static final int WAIT = 1500; + + private static final Minecraft client = Minecraft.getInstance(); + private static final MainWindow window = client.mainWindow; + + public static void bulkRender(IRenderer renderer, String spec, List renders, int size, boolean useId, boolean addSize) { + if (renders.size() < 1) { + addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.noItems", spec)); + return; + } + + client.displayGuiScreen(new IngameMenuScreen(false)); + + int errored = 0; + int rendered = 0; + long lastUpdate = 0; + int total = renders.size(); + + String sizeString = addSize ? size + "x" + size + "_" : ""; + File folder = new File(DEFAULT_FOLDER, dateTime() + "_" + sizeString + sanitize(spec) + "/"); + String title = I18n.format("blockrenderer.gui.rendering", total, spec); + + long start = Util.milliTime(); + + renderer.setup(size); + for (T value : renders) { + if (isEscapePressed()) break; + + String fileName = renderer.getFilename(value, useId); + + try { + renderer.render(value); + renderer.saveRaw(folder, fileName); + } catch (Exception e) { + System.err.println("Rendering: " + renderer.getId(value)); + e.printStackTrace(); + errored++; + } + + rendered++; + + if (Util.milliTime() - lastUpdate > 33) { + renderer.teardown(); + + renderLoading(renderer, title, I18n.format("blockrenderer.gui.progress", rendered, total, (total - rendered)), value, (float)rendered/ total); + + lastUpdate = Util.milliTime(); + renderer.setup(size); + } + } + + long elapsed = Util.milliTime() - start; + + if (rendered >= total) { + renderLoading(renderer, I18n.format("blockrenderer.gui.rendered", total, spec), "", null, 1f); + addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.finished", total, spec, asClickable(folder))); + } else { + renderLoading(renderer, I18n.format("blockrenderer.gui.renderCancelled"), I18n.format("blockrenderer.gui.progress", rendered, total, (total - rendered)), null, (float)rendered/ total); + addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.cancelled", rendered, spec, asClickable(folder), total)); + } + + if (errored > 0) addMessage(I18n.format("msg.blockrenderer.bulk.errored", errored)); + + addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.time", elapsed / 1000f)); + + renderer.teardown(); + + try { Thread.sleep(WAIT); } catch (InterruptedException ignored) {} + + client.displayGuiScreen(null); + } + + private static void renderLoading(IRenderer renderer, String title, String subtitle, @Nullable T value, float progress) { + client.getFramebuffer().unbindFramebuffer(); + + GlStateManager.pushMatrix(); + + int displayWidth = window.getScaledWidth(); + int displayHeight = window.getScaledHeight(); + Rendering.setupOverlayRendering(); + + // Draw the dirt background + Rendering.drawBackground(displayWidth, displayHeight); + + // ...and the title + Rendering.drawCenteredString(client.fontRenderer, title, displayWidth / 2, displayHeight / 2 - 24, -1); + + // ...and the progress bar + Rendering.drawRect(displayWidth / 2 - 50, displayHeight / 2 - 1, displayWidth / 2 + 50, displayHeight / 2 + 1, 0xFF001100); + Rendering.drawRect(displayWidth / 2 - 50, displayHeight / 2 - 1, (displayWidth / 2 - 50) + (int) (progress * 100), displayHeight / 2 + 1, 0xFF55FF55); + + GlStateManager.pushMatrix(); + + GlStateManager.scalef(0.5f, 0.5f, 1); + + // ...and the subtitle + Rendering.drawCenteredString(client.fontRenderer, subtitle, displayWidth, displayHeight - 20, -1); + + // ...and the tooltip. + if (value != null) renderer.renderTooltip(value, displayWidth, displayHeight); + + GlStateManager.popMatrix(); + + GlStateManager.popMatrix(); + + client.updateDisplay(false); + + client.getFramebuffer().bindFramebuffer(false); + } + +} diff --git a/src/main/java/com/unascribed/blockrenderer/render/IRenderer.java b/src/main/java/com/unascribed/blockrenderer/render/IRenderer.java new file mode 100644 index 0000000..d5ab7b6 --- /dev/null +++ b/src/main/java/com/unascribed/blockrenderer/render/IRenderer.java @@ -0,0 +1,69 @@ +package com.unascribed.blockrenderer.render; + +import com.google.common.io.Files; +import com.unascribed.blockrenderer.lib.TileRenderer; +import com.unascribed.blockrenderer.utils.ImageUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; + +import javax.annotation.Nullable; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; + +import static com.unascribed.blockrenderer.utils.FileUtils.getFile; +import static com.unascribed.blockrenderer.utils.StringUtils.getRenderSuccess; +import static com.unascribed.blockrenderer.utils.StringUtils.sanitize; + +public interface IRenderer { + + File DEFAULT_FOLDER = new File("renders"); + + void setup(int size); + + void render(T value); + + void teardown(); + + void renderTooltip(T value, int displayWidth, int displayHeight); + + ResourceLocation getId(T value); + + ITextComponent getName(T value); + + default String getFilename(T value, boolean useId) { + return useId ? sanitize(getId(value)) : sanitize(getName(value)); + } + + @Nullable + TileRenderer getRenderer(); + + @SuppressWarnings("UnstableApiUsage") + default File saveRaw(File folder, String filename) throws Exception { + TileRenderer renderer = getRenderer(); + + if (renderer == null) throw new IllegalStateException("TileRenderer is null"); + + BufferedImage img = ImageUtils.readPixels(renderer); + + File file = getFile(folder, filename); + Files.createParentDirs(file); + + ImageIO.write(img, "PNG", file); + + return file; + } + + default ITextComponent save(T value, File folder, String filename) { + try { + File file = saveRaw(folder, filename); + return getRenderSuccess(folder, file); + } catch (Exception e) { + System.err.println("Rendering: " + getId(value)); + e.printStackTrace(); + return new TranslationTextComponent("msg.blockrenderer.render.fail"); + } + } + +} diff --git a/src/main/java/com/unascribed/blockrenderer/render/ItemStackRenderer.java b/src/main/java/com/unascribed/blockrenderer/render/ItemStackRenderer.java deleted file mode 100644 index 5eef566..0000000 --- a/src/main/java/com/unascribed/blockrenderer/render/ItemStackRenderer.java +++ /dev/null @@ -1,299 +0,0 @@ -package com.unascribed.blockrenderer.render; - -import com.google.common.base.Joiner; -import com.google.common.io.Files; -import com.mojang.blaze3d.platform.GlStateManager; -import com.unascribed.blockrenderer.lib.TileRenderer; -import com.unascribed.blockrenderer.utils.ImageUtils; -import com.unascribed.blockrenderer.utils.Rendering; -import net.minecraft.client.MainWindow; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.screen.IngameMenuScreen; -import net.minecraft.client.renderer.ItemRenderer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Util; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraftforge.registries.ForgeRegistries; -import org.lwjgl.opengl.GL11; - -import javax.annotation.Nullable; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; -import java.util.List; -import java.util.Set; -import java.util.function.LongSupplier; - -import static com.unascribed.blockrenderer.utils.FileUtils.getFile; -import static com.unascribed.blockrenderer.utils.MathUtils.minimum; -import static com.unascribed.blockrenderer.utils.MiscUtils.collectStacks; -import static com.unascribed.blockrenderer.utils.MiscUtils.isEscapePressed; -import static com.unascribed.blockrenderer.utils.StringUtils.*; - -public class ItemStackRenderer { - - public static final File DEFAULT_FOLDER = new File("renders"); - - private static final Minecraft client = Minecraft.getInstance(); - private static final MainWindow window = client.mainWindow; - private static final ItemRenderer itemRenderer = client.getItemRenderer(); - - private float oldZLevel; - - private TileRenderer renderer; - - public void setup(int desiredSize) { - int displayWidth = window.getFramebufferWidth(); - int displayHeight = window.getFramebufferHeight(); - - - int size = minimum(displayHeight, displayWidth, desiredSize); - renderer = TileRenderer.forSize(desiredSize, size); - - /* Push Stack */ - GlStateManager.pushMatrix(); - - /* Setup Projection */ - Rendering.setupOverlayRendering(renderer); - - /* Setup Lighting */ - RenderHelper.enableGUIStandardItemLighting(); - - /* Scale based on desired size */ - float scale = desiredSize / 16f; - GlStateManager.translatef(0, 0, -scale * 100); - GlStateManager.scalef(scale, scale, scale); - - /* Flip culling due to the flipped projection */ - GL11.glCullFace(GL11.GL_FRONT); - - /* 1.14.4 - DepthTest needs to be enabled for Enchanted Books */ - GlStateManager.enableDepthTest(); - - /* 1.14.4 - Blend needs to be enabled for Glass */ - GlStateManager.enableBlend(); - GlStateManager.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA, GL11.GL_ONE); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - - /* Modify zLevel */ - oldZLevel = itemRenderer.zLevel; - itemRenderer.zLevel = -50; - } - - public void render(ItemStack stack) { - /* Clear Pixel Buffer */ - renderer.buffer.clear(); - - /* Force Glint to be the same between renders by changing nano supplier */ - LongSupplier oldSupplier = Util.nanoTimeSupplier; - Util.nanoTimeSupplier = () -> 0L; - - do { - renderer.beginTile(); - - GlStateManager.pushMatrix(); - - /* Clear Framebuffer */ - GlStateManager.clearColor(0, 0, 0, 0); - GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); - - /* Render */ - itemRenderer.renderItemAndEffectIntoGUI(stack, 0, 0); - - GlStateManager.popMatrix(); - } while (renderer.endTile()); - - /* Reset nano supplier */ - Util.nanoTimeSupplier = oldSupplier; - - } - - @SuppressWarnings("UnstableApiUsage") - public ITextComponent save(File folder, String filename) { - try { - BufferedImage img = ImageUtils.readPixels(renderer); - - File file = getFile(folder, filename); - Files.createParentDirs(file); - - ImageIO.write(img, "PNG", file); - return getRenderSuccess(folder, file); - } catch (Exception ex) { - ex.printStackTrace(); - return new TranslationTextComponent("msg.blockrenderer.render.fail"); - } - } - - public void teardown() { - /* Reset zLevel */ - itemRenderer.zLevel = oldZLevel; - - /* Reset Blend */ - GlStateManager.disableBlend(); - - /* Reset Depth Test */ - GlStateManager.disableDepthTest(); - - /* Reset Culling */ - GL11.glCullFace(GL11.GL_BACK); - - /* Pop Stack */ - GlStateManager.popMatrix(); - } - - public static void renderItem(int size, ItemStack stack, boolean useId, boolean addSize) { - ItemStackRenderer renderer = new ItemStackRenderer(); - - ResourceLocation identifier = ForgeRegistries.ITEMS.getKey(stack.getItem()); - if (identifier == null) identifier = new ResourceLocation("air"); - - String sizeString = addSize ? size + "x" + size + "_" : ""; - String fileName = useId ? sanitize(identifier.toString()) : sanitize(stack.getDisplayName()); - - renderer.setup(size); - renderer.render(stack); - addMessage(renderer.save(DEFAULT_FOLDER, dateTime() + "_" + sizeString + fileName)); - renderer.teardown(); - } - - public static void bulkRender(int size, String namespaceSpec, boolean useId, boolean addSize) { - Set namespaces = getNamespaces(namespaceSpec); - List renders = collectStacks(namespaces); - String joined = Joiner.on(", ").join(namespaces); - - if (renders.size() < 1) { - addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.noItems", joined)); - return; - } - - client.displayGuiScreen(new IngameMenuScreen(false)); - - int rendered = 0; - long lastUpdate = 0; - int total = renders.size(); - - String sizeString = addSize ? size + "x" + size + "_" : ""; - File folder = new File(DEFAULT_FOLDER, dateTime() + "_" + sizeString + sanitize(namespaceSpec) + "/"); - String title = I18n.format("blockrenderer.gui.rendering", total, joined); - - long start = Util.milliTime(); - - ItemStackRenderer renderer = new ItemStackRenderer(); - - renderer.setup(size); - for (ItemStack stack : renders) { - if (isEscapePressed()) break; - - ResourceLocation identifier = ForgeRegistries.ITEMS.getKey(stack.getItem()); - if (identifier == null) identifier = new ResourceLocation("air"); - - String fileName = useId ? sanitize(identifier.toString()) : sanitize(stack.getDisplayName()); - - renderer.render(stack); - renderer.save(folder, fileName); - rendered++; - - if (Util.milliTime() - lastUpdate > 33) { - renderer.teardown(); - - renderLoading(title, I18n.format("blockrenderer.gui.progress", rendered, total, (total - rendered)), stack, (float)rendered/ total); - - lastUpdate = Util.milliTime(); - renderer.setup(size); - } - } - - long elapsed = Util.milliTime() - start; - - if (rendered >= total) { - renderLoading(I18n.format("blockrenderer.gui.rendered", total, joined), "", 1f); - addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.finished", total, joined, asClickable(folder))); - } else { - renderLoading(I18n.format("blockrenderer.gui.renderCancelled"), I18n.format("blockrenderer.gui.progress", rendered, total, (total - rendered)), (float)rendered/ total); - addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.cancelled", rendered, joined, asClickable(folder), total)); - } - - addMessage(new TranslationTextComponent("msg.blockrenderer.bulk.time", elapsed / 1000f)); - - renderer.teardown(); - - try { Thread.sleep(1500); } catch (InterruptedException ignored) {} - - client.displayGuiScreen(null); - } - - private static void renderLoading(String title, String subtitle, float progress) { - renderLoading(title, subtitle, null, progress); - } - - private static void renderLoading(String title, String subtitle, @Nullable ItemStack is, float progress) { - client.getFramebuffer().unbindFramebuffer(); - GlStateManager.pushMatrix(); - - { - int displayWidth = window.getScaledWidth(); - int displayHeight = window.getScaledHeight(); - Rendering.setupOverlayRendering(); - - // Draw the dirt background - Rendering.drawBackground(displayWidth, displayHeight); - - // ...and the title - Rendering.drawCenteredString(client.fontRenderer, title, displayWidth / 2, displayHeight / 2 - 24, -1); - - // ...and the progress bar - Rendering.drawRect(displayWidth / 2 - 50, displayHeight / 2 - 1, displayWidth / 2 + 50, displayHeight / 2 + 1, 0xFF001100); - Rendering.drawRect(displayWidth / 2 - 50, displayHeight / 2 - 1, (displayWidth / 2 - 50) + (int) (progress * 100), displayHeight / 2 + 1, 0xFF55FF55); - - GlStateManager.pushMatrix(); - - { - GlStateManager.scalef(0.5f, 0.5f, 1); - - // ...and the subtitle - Rendering.drawCenteredString(client.fontRenderer, subtitle, displayWidth, displayHeight - 20, -1); - - // ...and the tooltip. - if (is != null) { - try { - List list = getTooltipFromItem(is); - - // This code is copied from the tooltip renderer, so we can properly center it. - FontRenderer font = is.getItem().getFontRenderer(is); - if (font == null) font = client.fontRenderer; - - int width = 0; - for (String s : list) { - int j = font.getStringWidth(s); - if (j > width) width = j; - } - // End copied code. - - GlStateManager.translatef((displayWidth - width / 2f) - 12, displayHeight + 30, 0); - Rendering.drawHoveringText(list, 0, 0, font); - } catch (Throwable ignored) {} - } - } - - GlStateManager.popMatrix(); - } - - GlStateManager.popMatrix(); - - client.updateDisplay(false); - - /* - * While OpenGL itself is double-buffered, Minecraft is actually *triple*-buffered. - * This is to allow shaders to work, as shaders are only available in "modern" GL. - * Minecraft uses "legacy" GL, so it renders using a separate GL context to this - * third buffer, which is then flipped to the back buffer with this call. - */ - client.getFramebuffer().bindFramebuffer(false); - } - -} diff --git a/src/main/java/com/unascribed/blockrenderer/render/SingleRenderer.java b/src/main/java/com/unascribed/blockrenderer/render/SingleRenderer.java new file mode 100644 index 0000000..b3decca --- /dev/null +++ b/src/main/java/com/unascribed/blockrenderer/render/SingleRenderer.java @@ -0,0 +1,19 @@ +package com.unascribed.blockrenderer.render; + +import static com.unascribed.blockrenderer.render.IRenderer.DEFAULT_FOLDER; +import static com.unascribed.blockrenderer.utils.StringUtils.addMessage; +import static com.unascribed.blockrenderer.utils.StringUtils.dateTime; + +public class SingleRenderer { + + public static void render(IRenderer renderer, T value, int size, boolean useId, boolean addSize) { + String sizeString = addSize ? size + "x" + size + "_" : ""; + String fileName = renderer.getFilename(value, useId); + + renderer.setup(size); + renderer.render(value); + addMessage(renderer.save(value, DEFAULT_FOLDER, dateTime() + "_" + sizeString + fileName)); + renderer.teardown(); + } + +} diff --git a/src/main/java/com/unascribed/blockrenderer/render/impl/ItemStackRenderer.java b/src/main/java/com/unascribed/blockrenderer/render/impl/ItemStackRenderer.java new file mode 100644 index 0000000..a9ac6e3 --- /dev/null +++ b/src/main/java/com/unascribed/blockrenderer/render/impl/ItemStackRenderer.java @@ -0,0 +1,160 @@ +package com.unascribed.blockrenderer.render.impl; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.unascribed.blockrenderer.lib.TileRenderer; +import com.unascribed.blockrenderer.render.IRenderer; +import com.unascribed.blockrenderer.utils.Rendering; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Util; +import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.registries.ForgeRegistries; +import org.lwjgl.opengl.GL11; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.function.LongSupplier; + +import static com.unascribed.blockrenderer.utils.MathUtils.minimum; +import static com.unascribed.blockrenderer.utils.StringUtils.getTooltipFromItem; + +public class ItemStackRenderer implements IRenderer { + + private static final Minecraft client = Minecraft.getInstance(); + private static final MainWindow window = client.mainWindow; + private static final ItemRenderer itemRenderer = client.getItemRenderer(); + + private float oldZLevel; + + private TileRenderer renderer; + + @Override + public void setup(int desiredSize) { + int displayWidth = window.getFramebufferWidth(); + int displayHeight = window.getFramebufferHeight(); + + + int size = minimum(displayHeight, displayWidth, desiredSize); + renderer = TileRenderer.forSize(desiredSize, size); + + /* Push Stack */ + GlStateManager.pushMatrix(); + + /* Setup Projection */ + Rendering.setupOverlayRendering(renderer); + + /* Setup Lighting */ + RenderHelper.enableGUIStandardItemLighting(); + + /* Scale based on desired size */ + float scale = desiredSize / 16f; + GlStateManager.translatef(0, 0, -scale * 100); + GlStateManager.scalef(scale, scale, scale); + + /* Flip culling due to the flipped projection */ + GL11.glCullFace(GL11.GL_FRONT); + + /* 1.14.4 - DepthTest needs to be enabled for Enchanted Books */ + GlStateManager.enableDepthTest(); + + /* 1.14.4 - Blend needs to be enabled for Glass */ + GlStateManager.enableBlend(); + GlStateManager.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA, GL11.GL_ONE); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + /* Modify zLevel */ + oldZLevel = itemRenderer.zLevel; + itemRenderer.zLevel = -50; + } + + @Override + public void render(ItemStack value) { + /* Clear Pixel Buffer */ + renderer.buffer.clear(); + + /* Force Glint to be the same between renders by changing nano supplier */ + LongSupplier oldSupplier = Util.nanoTimeSupplier; + Util.nanoTimeSupplier = () -> 0L; + + do { + renderer.beginTile(); + + GlStateManager.pushMatrix(); + + /* Clear Framebuffer */ + GlStateManager.clearColor(0, 0, 0, 0); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); + + /* Render */ + itemRenderer.renderItemAndEffectIntoGUI(value, 0, 0); + + GlStateManager.popMatrix(); + } while (renderer.endTile()); + + /* Reset nano supplier */ + Util.nanoTimeSupplier = oldSupplier; + } + + @Override + public void teardown() { + /* Reset zLevel */ + itemRenderer.zLevel = oldZLevel; + + /* Reset Blend */ + GlStateManager.disableBlend(); + + /* Reset Depth Test */ + GlStateManager.disableDepthTest(); + + /* Reset Culling */ + GL11.glCullFace(GL11.GL_BACK); + + /* Pop Stack */ + GlStateManager.popMatrix(); + } + + @Override + @Nullable + public TileRenderer getRenderer() { + return renderer; + } + + @Override + public ResourceLocation getId(ItemStack value) { + ResourceLocation identifier = ForgeRegistries.ITEMS.getKey(value.getItem()); + + if (identifier == null) return new ResourceLocation("air"); + + return identifier; + } + + @Override + public ITextComponent getName(ItemStack value) { + return value.getDisplayName(); + } + + @Override + public void renderTooltip(ItemStack value, int displayWidth, int displayHeight) { + List list = getTooltipFromItem(value); + + // This code is copied from the tooltip renderer, so we can properly center it. + FontRenderer font = value.getItem().getFontRenderer(value); + if (font == null) font = client.fontRenderer; + + int width = 0; + for (String s : list) { + int j = font.getStringWidth(s); + if (j > width) width = j; + } + // End copied code. + + GlStateManager.translatef((displayWidth - width / 2f) - 12, displayHeight + 30, 0); + Rendering.drawHoveringText(list, 0, 0, font); + } + +} diff --git a/src/main/java/com/unascribed/blockrenderer/render/impl/package-info.java b/src/main/java/com/unascribed/blockrenderer/render/impl/package-info.java new file mode 100644 index 0000000..7fff82d --- /dev/null +++ b/src/main/java/com/unascribed/blockrenderer/render/impl/package-info.java @@ -0,0 +1,7 @@ +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +package com.unascribed.blockrenderer.render.impl; + +import com.unascribed.blockrenderer.annotation.MethodsReturnNonnullByDefault; + +import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/com/unascribed/blockrenderer/render/request/item/BulkItemRequest.java b/src/main/java/com/unascribed/blockrenderer/render/request/item/BulkItemRequest.java index 247bf7e..02a0a8b 100644 --- a/src/main/java/com/unascribed/blockrenderer/render/request/item/BulkItemRequest.java +++ b/src/main/java/com/unascribed/blockrenderer/render/request/item/BulkItemRequest.java @@ -1,7 +1,16 @@ package com.unascribed.blockrenderer.render.request.item; -import com.unascribed.blockrenderer.render.ItemStackRenderer; +import com.google.common.base.Joiner; +import com.unascribed.blockrenderer.render.BulkRenderer; +import com.unascribed.blockrenderer.render.impl.ItemStackRenderer; import com.unascribed.blockrenderer.render.request.IRequest; +import net.minecraft.item.ItemStack; + +import java.util.List; +import java.util.Set; + +import static com.unascribed.blockrenderer.utils.MiscUtils.collectStacks; +import static com.unascribed.blockrenderer.utils.StringUtils.getNamespaces; public class BulkItemRequest implements IRequest { @@ -18,7 +27,11 @@ public BulkItemRequest(int size, String namespaceSpec, boolean useId, boolean ad } public void render() { - ItemStackRenderer.bulkRender(size, namespaceSpec, useId, addSize); + Set namespaces = getNamespaces(namespaceSpec); + List renders = collectStacks(namespaces); + String joined = Joiner.on(", ").join(namespaces); + + BulkRenderer.bulkRender(new ItemStackRenderer(), joined, renders, size, useId, addSize); } } diff --git a/src/main/java/com/unascribed/blockrenderer/render/request/item/ItemRequest.java b/src/main/java/com/unascribed/blockrenderer/render/request/item/ItemRequest.java index 7f5efaf..7ea1280 100644 --- a/src/main/java/com/unascribed/blockrenderer/render/request/item/ItemRequest.java +++ b/src/main/java/com/unascribed/blockrenderer/render/request/item/ItemRequest.java @@ -1,6 +1,7 @@ package com.unascribed.blockrenderer.render.request.item; -import com.unascribed.blockrenderer.render.ItemStackRenderer; +import com.unascribed.blockrenderer.render.SingleRenderer; +import com.unascribed.blockrenderer.render.impl.ItemStackRenderer; import com.unascribed.blockrenderer.render.request.IRequest; import net.minecraft.item.ItemStack; @@ -19,7 +20,7 @@ public ItemRequest(int size, ItemStack stack, boolean useId, boolean addSize) { } public void render() { - ItemStackRenderer.renderItem(size, stack, useId, addSize); + SingleRenderer.render(new ItemStackRenderer(), stack, size, useId, addSize); } } diff --git a/src/main/java/com/unascribed/blockrenderer/utils/ImageUtils.java b/src/main/java/com/unascribed/blockrenderer/utils/ImageUtils.java index 746b07c..e8befe8 100644 --- a/src/main/java/com/unascribed/blockrenderer/utils/ImageUtils.java +++ b/src/main/java/com/unascribed/blockrenderer/utils/ImageUtils.java @@ -2,8 +2,6 @@ import com.unascribed.blockrenderer.lib.TileRenderer; -import java.awt.*; -import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; public interface ImageUtils { @@ -12,10 +10,10 @@ static BufferedImage readPixels(TileRenderer renderer) { int width = renderer.imageWidth; int height = renderer.imageHeight; - // Turn a bytebuffer into a Java object we can do things to. BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); int[] pixels = new int[width*height]; + renderer.buffer.asIntBuffer().get(pixels); img.setRGB(0, 0, width, height, pixels, 0, width); @@ -23,34 +21,4 @@ static BufferedImage readPixels(TileRenderer renderer) { return img; } - static BufferedImage createFlipped(BufferedImage image) { - AffineTransform at = new AffineTransform(); - /* - * Creates a compound affine transform, instead of just one, as we need - * to perform two transformations. - * - * The first one is to scale the image to 100% width, and -100% height. - * (That's *negative* 100%.) - */ - at.concatenate(AffineTransform.getScaleInstance(1, -1)); - /* - * We then need to translate the image back up by it's height, as flipping - * it over moves it off the bottom of the canvas. - */ - at.concatenate(AffineTransform.getTranslateInstance(0, -image.getHeight())); - return createTransformed(image, at); - } - - static BufferedImage createTransformed(BufferedImage image, AffineTransform at) { - // Create a blank image with the same dimensions as the old one... - BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); - // ...get it's renderer... - Graphics2D g = newImage.createGraphics(); - /// ...and draw the old image on top of it with our transform. - g.transform(at); - g.drawImage(image, 0, 0, null); - g.dispose(); - return newImage; - } - } diff --git a/src/main/java/com/unascribed/blockrenderer/utils/StringUtils.java b/src/main/java/com/unascribed/blockrenderer/utils/StringUtils.java index 438e28e..e7f362f 100644 --- a/src/main/java/com/unascribed/blockrenderer/utils/StringUtils.java +++ b/src/main/java/com/unascribed/blockrenderer/utils/StringUtils.java @@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TranslationTextComponent; @@ -46,6 +47,10 @@ static String sanitize(ITextComponent text) { return sanitize(text.getUnformattedComponentText()); } + static String sanitize(ResourceLocation identifier) { + return sanitize(identifier.toString()); + } + static String sanitize(String str) { return str.replaceAll("[^A-Za-z0-9-_ ]", "_"); } diff --git a/src/main/resources/assets/blockrenderer/lang/en_us.json b/src/main/resources/assets/blockrenderer/lang/en_us.json index 500608f..07c9dce 100644 --- a/src/main/resources/assets/blockrenderer/lang/en_us.json +++ b/src/main/resources/assets/blockrenderer/lang/en_us.json @@ -5,8 +5,9 @@ "msg.blockrenderer.render.fail":"Rendering failed, see game output for details", "msg.blockrenderer.render.success":"Successfully rendered to %2$s in %1$s", - "msg.blockrenderer.bulk.cancelled":"Operation cancelled, rendered %1$s from a total of %4$s items from %2$s in %3$s", - "msg.blockrenderer.bulk.finished":"Rendered %1$s items from %2$s in %3$s", + "msg.blockrenderer.bulk.cancelled":"Operation cancelled, rendered %1$s from a total of %4$s entries from %2$s in %3$s", + "msg.blockrenderer.bulk.finished":"Rendered %1$s entries from %2$s in %3$s", + "msg.blockrenderer.bulk.errored":"%1$s entries errored, See game output for details", "msg.blockrenderer.bulk.time":"Total time: %1$s seconds", "msg.blockrenderer.bulk.noItems":"No items for Namespace '%1$s'", @@ -31,8 +32,8 @@ "blockrenderer.gui.addSize.tooltip":"Add Size to Filename", "blockrenderer.gui.actualSize.tooltip":"Set to actual size (Based on GUI Scale)", - "blockrenderer.gui.rendering":"Rendering %1$s items from %2$s", - "blockrenderer.gui.rendered":"Rendered %1$s items from %2$s", + "blockrenderer.gui.rendering":"Rendering %1$s entries from %2$s", + "blockrenderer.gui.rendered":"Rendered %1$s entries from %2$s", "blockrenderer.gui.renderCancelled":"Operation cancelled", "blockrenderer.gui.progress":"(%1$s/%2$s, %3$s to go)" } \ No newline at end of file