From 8c13c015031a0de865d2e767cd8e879754f803e2 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Fri, 5 Aug 2022 01:30:08 +0800 Subject: More work --- .../client/gui/tooltip/MissingStacksTooltip.java | 106 ++++ .../gui/tooltip/MissingStacksTooltipProvider.java | 27 + .../client/gui/widget/basewidgets/ArrowWidget.java | 97 ++++ .../basewidgets/BatchedEntryRendererManager.java | 361 ++++++++++++ .../gui/widget/basewidgets/BurningFireWidget.java | 97 ++++ .../gui/widget/basewidgets/ButtonWidget.java | 335 +++++++++++ .../basewidgets/DelegateWidgetWithTranslate.java | 133 +++++ .../gui/widget/basewidgets/DrawableWidget.java | 50 ++ .../basewidgets/FillRectangleDrawableConsumer.java | 65 +++ .../gui/widget/basewidgets/ForwardingList.java | 166 ++++++ .../client/gui/widget/basewidgets/LabelWidget.java | 310 ++++++++++ .../gui/widget/basewidgets/MergedWidget.java | 119 ++++ .../client/gui/widget/basewidgets/NoOpWidget.java | 53 ++ .../gui/widget/basewidgets/OverflowWidget.java | 160 ++++++ .../gui/widget/basewidgets/PaddedCenterWidget.java | 58 ++ .../gui/widget/basewidgets/PaddedWidget.java | 51 ++ .../client/gui/widget/basewidgets/PanelWidget.java | 160 ++++++ .../widget/basewidgets/RendererWrappedWidget.java | 72 +++ .../gui/widget/basewidgets/TextFieldWidget.java | 633 +++++++++++++++++++++ .../basewidgets/TexturedDrawableConsumer.java | 75 +++ .../widget/basewidgets/VanillaWrappedWidget.java | 82 +++ .../gui/widget/basewidgets/WidgetsProvider.java | 166 ++++++ .../gui/widget/basewidgets/package-info.java | 27 + 23 files changed, 3403 insertions(+) create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltip.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltipProvider.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ArrowWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BatchedEntryRendererManager.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BurningFireWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ButtonWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/DelegateWidgetWithTranslate.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/DrawableWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/FillRectangleDrawableConsumer.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ForwardingList.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/LabelWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/MergedWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/NoOpWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/OverflowWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/PaddedCenterWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/PaddedWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/PanelWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/RendererWrappedWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/TextFieldWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/TexturedDrawableConsumer.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/VanillaWrappedWidget.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/WidgetsProvider.java create mode 100644 runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/package-info.java (limited to 'runtime-frontend/widgets/src/main/java/me') diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltip.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltip.java new file mode 100644 index 000000000..696384d03 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltip.java @@ -0,0 +1,106 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.tooltip; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.math.Matrix4f; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.SimpleDisplayRenderer; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.entry.EntryStack; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.util.Mth; +import net.minecraft.world.inventory.tooltip.TooltipComponent; + +import java.util.List; + +public class MissingStacksTooltip implements ClientTooltipComponent, TooltipComponent { + private static final int MAX_WIDTH = 200; + private final List stacks; + + public MissingStacksTooltip(List stacks) { + this.stacks = SimpleDisplayRenderer.simplify(stacks); + } + + @Override + public int getHeight() { + int entrySize = 18; + int w = Math.max(1, MAX_WIDTH / entrySize); + int height = Math.min(6, Mth.ceil(stacks.size() / (float) w)) * entrySize + 2; + height += 12; + return height; + } + + @Override + public int getWidth(Font font) { + int entrySize = 18; + int w = Math.max(1, MAX_WIDTH / entrySize); + int size = stacks.size(); + int width = Math.min(size, w) * entrySize; + width = Math.max(width, font.width(new TranslatableComponent("text.rei.missing"))); + return width; + } + + @Override + public void renderImage(Font font, int x, int y, PoseStack poses, ItemRenderer renderer, int z) { + int entrySize = 18; + int w = Math.max(1, MAX_WIDTH / entrySize); + int i = 0; + poses.pushPose(); + poses.translate(0, 0, z + 50); + for (EntryIngredient entry : stacks) { + int x1 = x + (i % w) * entrySize; + int y1 = y + 13 + (i / w) * entrySize; + i++; + if (i / w > 5) { + MultiBufferSource.BufferSource source = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + Component text = new TextComponent("+" + (stacks.size() - w * 6 + 1)).withStyle(ChatFormatting.GRAY); + font.drawInBatch(text, x1 + entrySize / 2 - font.width(text) / 2, y1 + entrySize / 2 - 1, -1, true, poses.last().pose(), source, false, 0, 15728880); + source.endBatch(); + break; + } else { + EntryStack stack; + if (entry.isEmpty()) stack = EntryStack.empty(); + else if (entry.size() == 1) stack = entry.get(0); + else stack = entry.get(Mth.floor((System.currentTimeMillis() / 1000 % (double) entry.size()))); + stack.render(poses, new Rectangle(x1, y1, entrySize, entrySize), -1000, -1000, 0); + } + } + poses.popPose(); + } + + @Override + public void renderText(Font font, int x, int y, Matrix4f pose, MultiBufferSource.BufferSource buffers) { + font.drawInBatch(new TranslatableComponent("text.rei.missing").withStyle(ChatFormatting.GRAY), + x, y + 2, -1, true, pose, buffers, false, 0, 15728880); + } +} diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltipProvider.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltipProvider.java new file mode 100644 index 000000000..19ed4dfc1 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/tooltip/MissingStacksTooltipProvider.java @@ -0,0 +1,27 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.tooltip; + +public class MissingStacksTooltipProvider { +} diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ArrowWidget.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ArrowWidget.java new file mode 100644 index 000000000..aba9ae7b8 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ArrowWidget.java @@ -0,0 +1,97 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget.basewidgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.clothconfig2.api.animator.NumberAnimator; +import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.gui.widgets.Arrow; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.util.Mth; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +final class ArrowWidget extends Arrow { + private Rectangle bounds; + private double animationDuration = -1; + private final NumberAnimator darkBackgroundAlpha = ValueAnimator.ofFloat() + .withConvention(() -> REIRuntime.getInstance().isDarkThemeEnabled() ? 1.0F : 0.0F, ValueAnimator.typicalTransitionTime()) + .asFloat(); + + public ArrowWidget(Rectangle bounds) { + this.bounds = new Rectangle(Objects.requireNonNull(bounds)); + } + + @Override + public double getAnimationDuration() { + return animationDuration; + } + + @Override + public void setAnimationDuration(double animationDurationMS) { + this.animationDuration = animationDurationMS; + if (this.animationDuration <= 0) + this.animationDuration = -1; + } + + @Override + public Rectangle getBounds() { + return bounds; + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + this.darkBackgroundAlpha.update(delta); + renderBackground(matrices, false, 1.0F); + if (darkBackgroundAlpha.value() > 0.0F) { + renderBackground(matrices, true, this.darkBackgroundAlpha.value()); + } + } + + public void renderBackground(PoseStack matrices, boolean dark, float alpha) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha); + RenderSystem.setShaderTexture(0, REIRuntime.getInstance().getDefaultDisplayTexture(dark)); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(770, 771, 1, 0); + RenderSystem.blendFunc(770, 771); + if (getAnimationDuration() > 0) { + int width = Mth.ceil((System.currentTimeMillis() / (animationDuration / 24) % 24d)); + blit(matrices, getX() + width, getY(), 106 + width, 91, 24 - width, 17); + blit(matrices, getX(), getY(), 82, 91, width, 17); + } else { + blit(matrices, getX(), getY(), 106, 91, 24, 17); + } + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + + @Override + public List children() { + return Collections.emptyList(); + } +} diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BatchedEntryRendererManager.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BatchedEntryRendererManager.java new file mode 100644 index 000000000..2a0e46726 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BatchedEntryRendererManager.java @@ -0,0 +1,361 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget.basewidgets; + +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.Iterables; +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import me.shedaniel.math.Point; +import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer; +import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer; +import me.shedaniel.rei.api.client.gui.widgets.BatchedSlots; +import me.shedaniel.rei.api.client.gui.widgets.Slot; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.util.CrashReportUtils; +import net.minecraft.CrashReport; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.renderer.MultiBufferSource; +import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.mutable.MutableLong; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +final class BatchedEntryRendererManager extends BatchedSlots implements ForwardingList { + private boolean fastEntryRendering = ConfigObject.getInstance().doesFastEntryRendering(); + private Int2ObjectMap> grouping = new Int2ObjectOpenHashMap<>(); + private List toRender = new ArrayList<>(); + private List delegateList = new DelegatedSlotList(); + private int size; + public boolean debug; + public MutableInt debugSize = new MutableInt(); + public MutableLong debugTime = new MutableLong(); + + public BatchedEntryRendererManager() { + } + + public BatchedEntryRendererManager(Collection widgets) { + addAll(widgets); + } + + public boolean isFastEntryRendering() { + return fastEntryRendering; + } + + @Override + public List delegate() { + return delegateList; + } + + @Override + public void addAllUnbatched(Collection slots) { + this.toRender.addAll(slots); + this.size += slots.size(); + } + + @Override + public boolean isBatched() { + return isFastEntryRendering(); + } + + @Override + public void addDebugger(MutableInt size, MutableLong time) { + this.debug = true; + this.debugSize = size; + this.debugTime = time; + } + + @Override + public void addUnbatched(Slot slot) { + this.toRender.add(slot); + this.size++; + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + if (this.debug) { + render(false, null, null, matrices, mouseX, mouseY, delta); + } else { + render(true, debugSize, debugTime, matrices, mouseX, mouseY, delta); + } + } + + public void render(boolean debugTime, MutableInt size, MutableLong time, PoseStack matrices, int mouseX, int mouseY, float delta) { + if (fastEntryRendering) { + for (List entries : grouping.values()) { + Object[] extraData = new Object[entries.size() / 2]; + for (int i = 0; i < extraData.length; i++) { + extraData[i] = entries.get(i * 2 + 1); + } + renderBatched(debugTime, size, time, matrices, mouseX, mouseY, delta, groupingsAsList(), extraData); + } + } + if (!toRender.isEmpty()) { + renderSlow(debugTime, size, time, matrices, mouseX, mouseY, delta, toRender); + } + } + + public List groupingsAsList() { + return CollectionUtils.concatUnmodifiable((Iterable>) () -> new AbstractIterator<>() { + Iterator> groups = grouping.values().iterator(); + + @Nullable + @Override + protected List computeNext() { + if (groups.hasNext()) { + return groupingAsList(groups.next()); + } + return endOfData(); + } + }); + } + + public List groupingAsList(List entries) { + return new AbstractList<>() { + @Override + public Slot get(int index) { + return (Slot) entries.get(index * 2); + } + + @Override + public Iterator iterator() { + return new AbstractIterator<>() { + public int i = 0; + + @Override + protected Slot computeNext() { + if (i >= entries.size()) { + return endOfData(); + } + Slot widget = (Slot) entries.get(i); + i += 2; + return widget; + } + }; + } + + @Override + public int size() { + return entries.size() / 2; + } + }; + } + + public static void renderEntries(boolean debugTime, MutableInt size, MutableLong time, boolean fastEntryRendering, PoseStack matrices, int mouseX, int mouseY, float delta, Collection entries) { + if (fastEntryRendering) { + Slot firstWidget = Iterables.getFirst(entries, null); + if (firstWidget == null) return; + EntryRenderer renderer = firstWidget.getCurrentEntry().getRenderer(); + if (renderer instanceof BatchedEntryRenderer) { + BatchedEntryRenderer firstRenderer = (BatchedEntryRenderer) renderer; + Object[] extraData = new Object[entries.size()]; + int i = 0; + for (Slot entry : entries) { + EntryStack currentEntry = entry.getCurrentEntry(); + extraData[i++] = ((BatchedEntryRenderer) currentEntry.getRenderer()).getExtraData(currentEntry.cast()); + } + renderBatched(debugTime, size, time, matrices, mouseX, mouseY, delta, entries, extraData); + return; + } + } + renderSlow(debugTime, size, time, matrices, mouseX, mouseY, delta, entries); + } + + private static void renderBatched(boolean debugTime, MutableInt size, MutableLong time, PoseStack matrices, int mouseX, int mouseY, float delta, Iterable entries, Object[] extraData) { + Slot firstWidget = Iterables.getFirst(entries, null); + if (firstWidget == null) return; + @SuppressWarnings("rawtypes") + EntryStack first = firstWidget.getCurrentEntry(); + EntryRenderer renderer = first.getRenderer(); + BatchedEntryRenderer firstRenderer = (BatchedEntryRenderer) renderer; + matrices = firstRenderer.batchModifyMatrices(matrices); + long l = debugTime ? System.nanoTime() : 0; + MultiBufferSource.BufferSource immediate = Minecraft.getInstance().renderBuffers().bufferSource(); + int i = 0; + for (Slot entry : entries) { + try { + entry.drawBackground(matrices, mouseX, mouseY, delta); + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Rendering entry background"); + CrashReportUtils.renderer(report, entry); + CrashReportUtils.catchReport(report); + return; + } + } + firstRenderer.startBatch(first, extraData[0], matrices, delta); + for (Slot entry : entries) { + try { + @SuppressWarnings("rawtypes") + EntryStack currentEntry = entry.getCurrentEntry(); + currentEntry.setZ(100); + firstRenderer.renderBase(currentEntry, extraData[i++], matrices, immediate, entry.getInnerBounds(), mouseX, mouseY, delta); + if (debugTime && !currentEntry.isEmpty()) size.increment(); + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Rendering entry base"); + CrashReportUtils.renderer(report, entry); + CrashReportUtils.catchReport(report); + return; + } + } + immediate.endBatch(); + firstRenderer.afterBase(first, extraData[0], matrices, delta); + i = 0; + for (Slot entry : entries) { + try { + @SuppressWarnings("rawtypes") + EntryStack currentEntry = entry.getCurrentEntry(); + firstRenderer.renderOverlay(currentEntry, extraData[i++], matrices, immediate, entry.getInnerBounds(), mouseX, mouseY, delta); + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Rendering entry base"); + CrashReportUtils.renderer(report, entry); + CrashReportUtils.catchReport(report); + return; + } + } + immediate.endBatch(); + for (Slot entry : entries) { + try { + if (entry.containsMouse(mouseX, mouseY)) { + Tooltip tooltip = entry.getCurrentTooltip(TooltipContext.of(new Point(mouseX, mouseY))); + if (tooltip != null) { + tooltip.queue(); + } + + if (entry.isHighlightEnabled()) { + entry.drawHighlighted(matrices, mouseX, mouseY, delta); + } + } + + entry.drawExtra(matrices, mouseX, mouseY, delta); + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Rendering entry extra"); + CrashReportUtils.renderer(report, entry); + CrashReportUtils.catchReport(report); + return; + } + } + if (debugTime) time.add(System.nanoTime() - l); + firstRenderer.endBatch(first, extraData[0], matrices, delta); + } + + public static void renderSlow(boolean debugTime, MutableInt size, MutableLong time, PoseStack matrices, int mouseX, int mouseY, float delta, Iterable entries) { + for (Slot entry : entries) { + if (entry.getCurrentEntry().isEmpty()) + continue; + try { + if (debugTime) { + size.increment(); + long l = System.nanoTime(); + entry.render(matrices, mouseX, mouseY, delta); + time.add(System.nanoTime() - l); + } else entry.render(matrices, mouseX, mouseY, delta); + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Rendering entry"); + CrashReportUtils.renderer(report, entry); + CrashReportUtils.catchReport(report); + return; + } + } + } + + @Override + public List children() { + return null; + } + + private class DelegatedSlotList extends AbstractList { + private final List unmodifiable = CollectionUtils.concatUnmodifiable(toRender, + groupingsAsList()); + + @Override + public void add(int index, Slot element) { + add(element); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean add(Slot widget) { + if (fastEntryRendering) { + EntryStack currentEntry = widget.getCurrentEntry(); + try { + EntryRenderer renderer = currentEntry.getRenderer(); + if (renderer instanceof BatchedEntryRenderer) { + BatchedEntryRenderer batchedRenderer = (BatchedEntryRenderer) renderer; + EntryStack cast = currentEntry.cast(); + if (batchedRenderer.isBatched(cast)) { + Object extraData = batchedRenderer.getExtraData(cast); + int hash = batchedRenderer.getBatchIdentifier(cast, widget.getBounds(), extraData) + ^ widget.getCurrentEntry().getType().hashCode(); + List entries = grouping.get(hash); + if (entries == null) { + grouping.put(hash, entries = new ArrayList<>()); + } + entries.add(widget); + entries.add(extraData); + size++; + return true; + } + } + } catch (Throwable throwable) { + CrashReport report = CrashReportUtils.essential(throwable, "Adding entry"); + CrashReportUtils.renderer(report, currentEntry); + CrashReportUtils.catchReport(report); + return false; + } + } + + addUnbatched(widget); + return true; + } + + @Override + public Slot get(int index) { + return unmodifiable.get(index); + } + + @Override + public boolean addAll(Collection widgets) { + if (fastEntryRendering) { + for (Slot widget : widgets) { + add(widget); + } + } else { + addAllUnbatched(widgets); + } + + return true; + } + } +} diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BurningFireWidget.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BurningFireWidget.java new file mode 100644 index 000000000..550f98626 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/BurningFireWidget.java @@ -0,0 +1,97 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget.basewidgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.clothconfig2.api.animator.NumberAnimator; +import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.gui.widgets.BurningFire; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.util.Mth; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +final class BurningFireWidget extends BurningFire { + private Rectangle bounds; + private double animationDuration = -1; + private final NumberAnimator darkBackgroundAlpha = ValueAnimator.ofFloat() + .withConvention(() -> REIRuntime.getInstance().isDarkThemeEnabled() ? 1.0F : 0.0F, ValueAnimator.typicalTransitionTime()) + .asFloat(); + + public BurningFireWidget(Rectangle bounds) { + this.bounds = new Rectangle(Objects.requireNonNull(bounds)); + } + + @Override + public double getAnimationDuration() { + return animationDuration; + } + + @Override + public void setAnimationDuration(double animationDurationMS) { + this.animationDuration = animationDurationMS; + if (this.animationDuration <= 0) + this.animationDuration = -1; + } + + @Override + public Rectangle getBounds() { + return bounds; + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + this.darkBackgroundAlpha.update(delta); + renderBackground(matrices, false, 1.0F); + if (darkBackgroundAlpha.value() > 0) { + renderBackground(matrices, true, this.darkBackgroundAlpha.value()); + } + } + + public void renderBackground(PoseStack matrices, boolean dark, float alpha) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha); + RenderSystem.setShaderTexture(0, REIRuntime.getInstance().getDefaultDisplayTexture(dark)); + RenderSystem.enableBlend(); + RenderSystem.blendFuncSeparate(770, 771, 1, 0); + RenderSystem.blendFunc(770, 771); + if (getAnimationDuration() > 0) { + int height = 14 - Mth.ceil((System.currentTimeMillis() / (animationDuration / 14) % 14d)); + blit(matrices, getX(), getY(), 1, 74, 14, 14 - height); + blit(matrices, getX(), getY() + 14 - height, 82, 77 + (14 - height), 14, height); + } else { + blit(matrices, getX(), getY(), 1, 74, 14, 14); + } + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + + @Override + public List children() { + return Collections.emptyList(); + } +} diff --git a/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ButtonWidget.java b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ButtonWidget.java new file mode 100644 index 000000000..f7efdc712 --- /dev/null +++ b/runtime-frontend/widgets/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/ButtonWidget.java @@ -0,0 +1,335 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget.basewidgets; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Matrix4f; +import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.clothconfig2.api.animator.ValueProvider; +import me.shedaniel.math.Color; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.REIRuntime; +import me.shedaniel.rei.api.client.gui.widgets.Button; +import me.shedaniel.rei.api.client.gui.widgets.Tooltip; +import net.minecraft.client.gui.GuiComponent; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvents; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; + +final class ButtonWidget extends Button { + private static final ResourceLocation BUTTON_LOCATION = new ResourceLocation("roughlyenoughitems", "textures/gui/button.png"); + private static final ResourceLocation BUTTON_LOCATION_DARK = new ResourceLocation("roughlyenoughitems", "textures/gui/button_dark.png"); + private Rectangle bounds; + private boolean enabled = true; + private Component text; + @Nullable + private Integer tint; + @Nullable + private Consumer