From 8f7d698e7d5acda7e34ca2e527bada134862f0ce Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 27 May 2022 07:42:41 -0400 Subject: [PATCH] Add option to cache item grid rendering (#250) * Add option to cache item grid rendering * Fix highlighting for bookmarks * Tweak GL state slightly * Fix focus box being in the wrong place * Fix flickering for one frame when searching * Prevent potion effects from rendering over NEI slots Fixes #231 * Invalidate the buffer if `invalidSlotMap` changes * Clean up imports * Delay blitting until after the buffer is refreshed but still avoid waiting for the next frame * Refactor slot focus logic to handle highlighting multiple slots * Refresh grid when sorting bookmarks * Minor code cleanup, fix some more hovering issues * Remove `slotNeedsOutline`, it is now redundant * Remove focus parameter from drawItem --- .../java/codechicken/nei/BookmarkPanel.java | 54 ++++++---- src/main/java/codechicken/nei/ItemPanel.java | 18 ++-- src/main/java/codechicken/nei/ItemsGrid.java | 100 ++++++++++++++++-- .../java/codechicken/nei/NEIClientConfig.java | 8 ++ .../codechicken/nei/NEIPotionGuiHandler.java | 48 +++++++++ .../java/codechicken/nei/api/GuiInfo.java | 2 + src/main/resources/assets/nei/lang/en_US.lang | 3 + 7 files changed, 192 insertions(+), 41 deletions(-) create mode 100644 src/main/java/codechicken/nei/NEIPotionGuiHandler.java diff --git a/src/main/java/codechicken/nei/BookmarkPanel.java b/src/main/java/codechicken/nei/BookmarkPanel.java index 46da70b5..392af4c8 100644 --- a/src/main/java/codechicken/nei/BookmarkPanel.java +++ b/src/main/java/codechicken/nei/BookmarkPanel.java @@ -19,6 +19,8 @@ import net.minecraft.nbt.NBTTagCompound; import org.apache.commons.io.IOUtils; import org.lwjgl.opengl.GL11; +import javax.annotation.Nullable; + import static codechicken.lib.gui.GuiDraw.getMousePosition; import static codechicken.lib.gui.GuiDraw.drawRect; @@ -98,11 +100,13 @@ public class BookmarkPanel extends PanelWidget { realItems.add(stackA); metadata.add(meta); + refreshBuffer = true; } public void replaceItem(int idx, ItemStack stack) { realItems.set(idx, stack); + refreshBuffer = true; } public void removeRecipe(int idx, boolean removeFullRecipe) @@ -136,6 +140,7 @@ public class BookmarkPanel extends PanelWidget { realItems.remove(idx); metadata.remove(idx); + refreshBuffer = true; return true; } @@ -161,40 +166,45 @@ public class BookmarkPanel extends PanelWidget { realItems.add(dst, realItems.remove(src)); metadata.add(dst, metadata.remove(src)); + refreshBuffer = true; + } + + private boolean isPartOfFocusedRecipe(ItemPanelSlot focused, int myIdx) { + return (NEIClientUtils.shiftKey() + && LayoutManager.bookmarkPanel.sortedStackIndex == -1 + && focused != null + && getRecipeId(focused.slotIndex) != null + && getRecipeId(myIdx) != null + && getRecipeId(focused.slotIndex).equals(getRecipeId(myIdx))); } @Override - protected void drawItem(Rectangle4i rect, int idx, ItemPanelSlot focus) - { - - if (LayoutManager.bookmarkPanel.sortedNamespaceIndex == LayoutManager.bookmarkPanel.activeNamespaceIndex && LayoutManager.bookmarkPanel.sortedStackIndex == idx) { + protected void drawSlotOutline(@Nullable ItemPanelSlot focus, int idx, Rectangle4i rect) { + if(LayoutManager.bookmarkPanel.sortedNamespaceIndex == LayoutManager.bookmarkPanel.activeNamespaceIndex && LayoutManager.bookmarkPanel.sortedStackIndex == idx) { drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight - } else { + } else if(focus != null) { + BookmarkStackMeta meta = getMetadata(idx); + if (isPartOfFocusedRecipe(focus, idx)) { + drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient? 0x88b3b300: 0x88009933);//highlight recipe + } else if(focus.slotIndex == idx) { + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + } + } + } + + @Override + protected void drawItem(Rectangle4i rect, int idx) + { + if (LayoutManager.bookmarkPanel.sortedNamespaceIndex != LayoutManager.bookmarkPanel.activeNamespaceIndex || LayoutManager.bookmarkPanel.sortedStackIndex != idx) { final ItemStack stack = getItem(idx); final BookmarkStackMeta meta = getMetadata(idx); - if (focus != null) { - - if ( - LayoutManager.bookmarkPanel.sortedStackIndex == -1 && //disabled when sorting - NEIClientUtils.shiftKey() && //show only with shift key - getRecipeId(focus.slotIndex) != null && getRecipeId(idx) != null && getRecipeId(focus.slotIndex).equals(getRecipeId(idx))//is some recipeId - ) { - drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient? 0x88b3b300: 0x88009933);//highlight recipe - } else if (focus.slotIndex == idx) { - drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight - } - - } - GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, stack, true, meta.factor < 0 || meta.fluidDisplay? "": String.valueOf(stack.stackSize)); if (meta.recipeId != null && !meta.ingredient && NEIClientConfig.showRecipeMarker()) { drawRecipeMarker(rect.x, rect.y, GuiContainerManager.getFontRenderer(stack)); } - } - } protected void drawRecipeMarker(int offsetX, int offsetY, FontRenderer fontRenderer ) @@ -757,6 +767,7 @@ public class BookmarkPanel extends PanelWidget if (stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 250)) { sortedNamespaceIndex = activeNamespaceIndex; sortedStackIndex = mouseDownSlot; + grid.refreshBuffer = true; } } else { @@ -837,6 +848,7 @@ public class BookmarkPanel extends PanelWidget sortedNamespaceIndex = -1; sortedStackIndex = -1; mouseDownSlot = -1; + grid.refreshBuffer = true; /* make sure grid redraws the new item */ saveBookmarks(); } else { super.mouseUp(mousex, mousey, button); diff --git a/src/main/java/codechicken/nei/ItemPanel.java b/src/main/java/codechicken/nei/ItemPanel.java index a918ff31..9b717ae7 100644 --- a/src/main/java/codechicken/nei/ItemPanel.java +++ b/src/main/java/codechicken/nei/ItemPanel.java @@ -4,6 +4,8 @@ import codechicken.lib.vec.Rectangle4i; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.item.ItemStack; +import javax.annotation.Nullable; + import static codechicken.lib.gui.GuiDraw.drawRect; import java.util.ArrayList; @@ -67,23 +69,21 @@ public class ItemPanel extends PanelWidget if (newItems != null) { realItems = newItems; newItems = null; + refreshBuffer = true; } super.refresh(gui); } @Override - protected void drawItem(Rectangle4i rect, int idx, ItemPanelSlot focus) - { - - if (PresetsWidget.inEditMode() && !PresetsWidget.isHidden(getItem(idx))) { - drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555); + protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) { + if (PresetsWidget.inEditMode()) { + if(!PresetsWidget.isHidden(getItem(slotIdx))) + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555); + } else { + super.drawSlotOutline(focused, slotIdx, rect); } - - super.drawItem(rect, idx, PresetsWidget.inEditMode()? null: focus); } - - } public ItemPanel() diff --git a/src/main/java/codechicken/nei/ItemsGrid.java b/src/main/java/codechicken/nei/ItemsGrid.java index 868f0c83..f42d0515 100644 --- a/src/main/java/codechicken/nei/ItemsGrid.java +++ b/src/main/java/codechicken/nei/ItemsGrid.java @@ -5,10 +5,18 @@ import codechicken.nei.api.GuiInfo; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.StackInfo; import codechicken.nei.ItemPanel.ItemPanelSlot; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.shader.Framebuffer; import net.minecraft.item.ItemStack; +import org.lwjgl.opengl.GL11; +import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; import static codechicken.lib.gui.GuiDraw.drawRect; @@ -38,6 +46,10 @@ public class ItemsGrid protected boolean[] validSlotMap; protected boolean[] invalidSlotMap; + @Nullable + private Framebuffer framebuffer = null; + protected boolean refreshBuffer = true; + public ArrayList getItems() { return realItems; @@ -92,6 +104,8 @@ public class ItemsGrid public void setGridSize(int mleft, int mtop, int w, int h) { + if(width != w || height != h || mleft != marginLeft || mtop != marginTop) + refreshBuffer = true; marginLeft = mleft; marginTop = mtop; @@ -126,6 +140,8 @@ public class ItemsGrid } page = Math.max(0, Math.min(page, numPages - 1)); + if(shift != 0) + refreshBuffer = true; } public void refresh(GuiContainer gui) @@ -136,12 +152,15 @@ public class ItemsGrid private void updateGuiOverlapSlots(GuiContainer gui) { + boolean[] oldSlotMap = invalidSlotMap; invalidSlotMap = new boolean[rows * columns]; perPage = columns * rows; checkGuiOverlap(gui, 0, columns - 2, 1); checkGuiOverlap(gui, columns - 1, 1, -1); - + if(NEIClientConfig.shouldCacheItemRendering() && !Arrays.equals(oldSlotMap, invalidSlotMap)) { + refreshBuffer = true; + } } private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir) @@ -180,36 +199,95 @@ public class ItemsGrid return invalidSlotMap[idx]; } + private void drawSlotOutlines(int mousex, int mousey) + { + ItemPanelSlot focused = getSlotMouseOver(mousex, mousey); + int idx = page * perPage; + for (int i = 0; i < rows * columns && idx < size(); i++) { + if(!invalidSlotMap[i]) { + drawSlotOutline(focused, idx, getSlotRect(i)); + idx++; + } + } + } + + protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) { + if(focused != null && focused.slotIndex == slotIdx) + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + } + + private void blitExistingBuffer() { + Minecraft minecraft = Minecraft.getMinecraft(); + GL11.glEnable(GL11.GL_BLEND); + OpenGlHelper.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + framebuffer.bindFramebufferTexture(); + GL11.glEnable(GL11.GL_TEXTURE_2D); + ScaledResolution res = new ScaledResolution(minecraft, minecraft.displayWidth, minecraft.displayHeight); + Tessellator tessellator = Tessellator.instance; + tessellator.startDrawingQuads(); + tessellator.addVertexWithUV(0, res.getScaledHeight_double(), 0.0, 0, 0); + tessellator.addVertexWithUV(res.getScaledWidth_double(), res.getScaledHeight_double(), 0.0, 1, 0); + tessellator.addVertexWithUV(res.getScaledWidth_double(), 0, 0.0, 1, 1); + tessellator.addVertexWithUV(0, 0, 0, 0, 1); + tessellator.draw(); + OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + } + public void draw(int mousex, int mousey) { if (getPerPage() == 0) { return; } - ItemPanelSlot slot = getSlotMouseOver(mousex, mousey); + boolean shouldCache = NEIClientConfig.shouldCacheItemRendering() && !PresetsWidget.inEditMode(); + if(shouldCache) { + Minecraft minecraft = Minecraft.getMinecraft(); + if (framebuffer == null) { + framebuffer = new Framebuffer(minecraft.displayWidth, minecraft.displayHeight, true); + framebuffer.framebufferColor[0] = 0.0F; + framebuffer.framebufferColor[1] = 0.0F; + framebuffer.framebufferColor[2] = 0.0F; + } + drawSlotOutlines(mousex, mousey); + if (refreshBuffer) { + framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight); + framebuffer.framebufferClear(); + framebuffer.bindFramebuffer(false); + /* Set up some rendering state needed for items to work correctly */ + GL11.glDisable(GL11.GL_BLEND); + GL11.glDepthMask(true); + OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + } else { + blitExistingBuffer(); + return; + } + } else { + drawSlotOutlines(mousex, mousey); + } GuiContainerManager.enableMatrixStackLogging(); int idx = page * perPage; for (int i = 0; i < rows * columns && idx < size(); i++) { - if (!invalidSlotMap[i]) { - drawItem(getSlotRect(i), idx, slot); + drawItem(getSlotRect(i), idx); idx ++; } - } GuiContainerManager.disableMatrixStackLogging(); + + if (refreshBuffer && shouldCache) { + refreshBuffer = false; + Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false); + blitExistingBuffer(); + } } - protected void drawItem(Rectangle4i rect, int idx, ItemPanelSlot focus) + protected void drawItem(Rectangle4i rect, int idx) { - - if (focus != null && focus.slotIndex == idx) { - drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight - } - GuiContainerManager.drawItem(rect.x + 1, rect.y + 1, getItem(idx)); } diff --git a/src/main/java/codechicken/nei/NEIClientConfig.java b/src/main/java/codechicken/nei/NEIClientConfig.java index 1651f36a..475a5f07 100644 --- a/src/main/java/codechicken/nei/NEIClientConfig.java +++ b/src/main/java/codechicken/nei/NEIClientConfig.java @@ -34,6 +34,7 @@ import codechicken.obfuscator.ObfuscationRun; import com.google.common.base.Objects; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -182,6 +183,9 @@ public class NEIClientConfig { return isMouseScrollTransferEnabled(); } }); + + tag.getTag("inventory.cacheItemRendering").getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.cacheItemRendering", true)); tag.getTag("itemLoadingTimeout").getIntValue(500); @@ -550,6 +554,10 @@ public class NEIClientConfig { return !getBooleanSetting("inventory.invertMouseScrollTransfer"); } + public static boolean shouldCacheItemRendering() { + return getBooleanSetting("inventory.cacheItemRendering") && OpenGlHelper.framebufferSupported; + } + public static boolean getMagnetMode() { return enabledActions.contains("magnet"); } diff --git a/src/main/java/codechicken/nei/NEIPotionGuiHandler.java b/src/main/java/codechicken/nei/NEIPotionGuiHandler.java new file mode 100644 index 00000000..af50d82a --- /dev/null +++ b/src/main/java/codechicken/nei/NEIPotionGuiHandler.java @@ -0,0 +1,48 @@ +package codechicken.nei; + +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.api.INEIGuiAdapter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.InventoryEffectRenderer; +import net.minecraft.potion.PotionEffect; + +import java.util.Collection; + +/** + * Inspired by InventoryEffectRendererGuiHandler.java in JEI + */ +public class NEIPotionGuiHandler extends INEIGuiAdapter { + @Override + public boolean hideItemPanelSlot(GuiContainer guiContainer, int slotX, int slotY, int slotW, int slotH) { + if(guiContainer instanceof InventoryEffectRenderer) { + int x = guiContainer.guiLeft - 124; + int y = guiContainer.guiTop; + Minecraft minecraft = guiContainer.mc; + if (minecraft == null) { + return false; + } + EntityPlayerSP player = minecraft.thePlayer; + if (player == null) { + return false; + } + Collection activePotionEffects = player.getActivePotionEffects(); + if (activePotionEffects.isEmpty()) { + return false; + } + int height = 33; + if (activePotionEffects.size() > 5) { + height = 132 / (activePotionEffects.size() - 1); + } + Rectangle4i slotRect = new Rectangle4i(slotX, slotY, slotW, slotH); + for (PotionEffect potioneffect : activePotionEffects) { + Rectangle4i box = new Rectangle4i(x, y, 140, 32); + if(box.intersects(slotRect)) + return true; + y += height; + } + } + return false; + } +} diff --git a/src/main/java/codechicken/nei/api/GuiInfo.java b/src/main/java/codechicken/nei/api/GuiInfo.java index d59688a9..8695d38f 100644 --- a/src/main/java/codechicken/nei/api/GuiInfo.java +++ b/src/main/java/codechicken/nei/api/GuiInfo.java @@ -4,6 +4,7 @@ import codechicken.lib.vec.Rectangle4i; import codechicken.nei.NEIChestGuiHandler; import codechicken.nei.NEICreativeGuiHandler; import codechicken.nei.NEIDummySlotHandler; +import codechicken.nei.NEIPotionGuiHandler; import codechicken.nei.recipe.GuiRecipeCatalyst; import codechicken.nei.recipe.SearchInputDropHandler; import codechicken.nei.recipe.FillFluidContainerHandler; @@ -33,6 +34,7 @@ public class GuiInfo { API.registerNEIGuiHandler(new SearchInputDropHandler()); API.registerNEIGuiHandler(new FillFluidContainerHandler()); API.registerNEIGuiHandler(new CheatItemHandler()); + API.registerNEIGuiHandler(new NEIPotionGuiHandler()); customSlotGuis.add(GuiContainerCreative.class); } diff --git a/src/main/resources/assets/nei/lang/en_US.lang b/src/main/resources/assets/nei/lang/en_US.lang index 767702b7..b8088fe3 100644 --- a/src/main/resources/assets/nei/lang/en_US.lang +++ b/src/main/resources/assets/nei/lang/en_US.lang @@ -179,6 +179,9 @@ nei.options.inventory.disableMouseScrollTransfer.false=False nei.options.inventory.invertMouseScrollTransfer=Invert Mouse Wheel Transfer Direction nei.options.inventory.invertMouseScrollTransfer.true=True nei.options.inventory.invertMouseScrollTransfer.false=False +nei.options.inventory.cacheItemRendering=Cache Item Rendering +nei.options.inventory.cacheItemRendering.true=True +nei.options.inventory.cacheItemRendering.false=False nei.options.command=Commands nei.options.command.creative=Gamemode