From aba4c079befd4bb32f732b65c746a22559644d35 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Mon, 8 Nov 2021 23:15:08 +0800 Subject: Big Visual and Functional Changes - Fix #503 - Shift Click to select page, normal click to go back to page 1 - Allow non-consuming draggable visitors - Add scale down animation when dragging a stack to the main item list to dismiss it - Make Cheat Mode not active in Display Screens - Add colors to cosmetic transfer handler errors - Implement JEI animations, fix #501 - Allow favorites dragged stacks to go back to where they are if they are ignored, instead of being at the end of the favorites - Implement favorites & entry list column and row limits - Implement display page height limit - Updated localizations --- .../me/shedaniel/rei/api/client/REIRuntime.java | 12 ++- .../rei/api/client/config/ConfigObject.java | 18 ++++- .../rei/api/client/gui/drag/DraggableStack.java | 9 ++- .../api/client/gui/drag/DraggableStackVisitor.java | 23 +++++- .../gui/drag/DraggableStackVisitorWidget.java | 25 ++++++- .../api/client/gui/drag/DraggedAcceptorResult.java | 44 +++++++++++ .../rei/api/client/gui/drag/DraggingContext.java | 11 +++ .../client/registry/transfer/TransferHandler.java | 19 ++++- .../rei/forge/RoughlyEnoughItemsForge.java | 7 +- .../shedaniel/rei/impl/client/REIRuntimeImpl.java | 21 +++++- .../rei/impl/client/config/ConfigObjectImpl.java | 40 +++++++++- .../rei/impl/client/gui/ScreenOverlayImpl.java | 86 ++++++++++++++++++---- .../client/gui/dragging/CurrentDraggingStack.java | 43 +++++++---- .../gui/screen/DefaultDisplayViewingScreen.java | 84 +++++++-------------- .../gui/widget/DefaultDisplayChoosePageWidget.java | 22 +++--- .../client/gui/widget/EntryListEntryWidget.java | 8 +- .../impl/client/gui/widget/EntryListWidget.java | 37 +++++++--- .../client/gui/widget/EntryStacksRegionWidget.java | 51 ++++++++----- .../rei/impl/client/gui/widget/EntryWidget.java | 5 +- .../client/gui/widget/FavoritesListWidget.java | 9 +++ .../impl/client/gui/widget/InternalWidgets.java | 2 +- .../rei/impl/client/gui/widget/TabWidget.java | 5 +- .../client/gui/widget/region/RealRegionEntry.java | 2 - .../gui/widget/region/RegionDraggableStack.java | 16 +++- .../gui/widget/region/RegionEntryListEntry.java | 4 + .../client/gui/widget/region/RegionListener.java | 2 + .../client/registry/screen/ExclusionZonesImpl.java | 8 +- .../client/runtime/DefaultClientRuntimePlugin.java | 4 +- .../assets/roughlyenoughitems/lang/cs_cz.json | 3 + .../assets/roughlyenoughitems/lang/en_gb.json | 30 ++++++++ .../assets/roughlyenoughitems/lang/en_us.json | 6 ++ .../assets/roughlyenoughitems/lang/zh_cn.json | 2 + .../assets/roughlyenoughitems/lang/zh_tw.json | 3 + 33 files changed, 492 insertions(+), 169 deletions(-) create mode 100644 api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggedAcceptorResult.java diff --git a/api/src/main/java/me/shedaniel/rei/api/client/REIRuntime.java b/api/src/main/java/me/shedaniel/rei/api/client/REIRuntime.java index adc1cb968..1af65d4ad 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/REIRuntime.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/REIRuntime.java @@ -24,18 +24,22 @@ package me.shedaniel.rei.api.client; import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.gui.config.SearchFieldLocation; import me.shedaniel.rei.api.client.gui.widgets.TextField; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.overlay.ScreenOverlay; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.registry.Reloadable; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.Optional; @@ -80,7 +84,13 @@ public interface REIRuntime extends Reloadable { SearchFieldLocation getContextualSearchFieldLocation(); - Rectangle calculateEntryListArea(); + @ApiStatus.ScheduledForRemoval + @Deprecated + default Rectangle calculateEntryListArea() { + return calculateEntryListArea(ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen)); + } + + Rectangle calculateEntryListArea(Rectangle bounds); Rectangle calculateFavoritesListArea(); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java index 040704236..8d35049c2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java @@ -89,6 +89,8 @@ public interface ConfigObject { int getMaxRecipePerPage(); + int getMaxRecipesPageHeight(); + boolean doesDisableRecipeBook(); boolean doesFixTabCloseContainer(); @@ -163,10 +165,22 @@ public interface ConfigObject { boolean isInventoryHighlightingAllowed(); @ApiStatus.Experimental - double getHorizontalEntriesBoundaries(); + double getHorizontalEntriesBoundariesPercentage(); + + @ApiStatus.Experimental + double getVerticalEntriesBoundariesPercentage(); + + @ApiStatus.Experimental + double getHorizontalEntriesBoundariesColumns(); + + @ApiStatus.Experimental + double getVerticalEntriesBoundariesRows(); + + @ApiStatus.Experimental + double getFavoritesHorizontalEntriesBoundariesPercentage(); @ApiStatus.Experimental - double getVerticalEntriesBoundaries(); + double getFavoritesHorizontalEntriesBoundariesColumns(); @ApiStatus.Experimental SyntaxHighlightingMode getSyntaxHighlightingMode(); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java index 6dfaa9097..b5ccc97f2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java @@ -26,13 +26,20 @@ package me.shedaniel.rei.api.client.gui.drag; import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.common.entry.EntryStack; +import org.jetbrains.annotations.ApiStatus; public interface DraggableStack { EntryStack getStack(); void drag(); - void release(boolean accepted); + @Deprecated + @ApiStatus.ScheduledForRemoval + default void release(boolean consumed) {} + + default void release(DraggedAcceptorResult result) { + release(result != DraggedAcceptorResult.PASS); + } default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { getStack().render(matrices, bounds, mouseX, mouseY, delta); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java index ae973be16..d893eccd4 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java @@ -29,6 +29,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.ApiStatus; +import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Stream; @@ -51,14 +52,14 @@ public interface DraggableStackVisitor extends Comparable context, DraggableStack stack) { + public DraggedAcceptorResult acceptDraggedStackWithResult(DraggingContext context, DraggableStack stack) { for (DraggableStackVisitor visitor : visitors.get()) { if (visitor.isHandingScreen(context.getScreen())) { - boolean visited = visitor.acceptDraggedStack(context, stack); - if (visited) return true; + DraggedAcceptorResult result = Objects.requireNonNull(visitor.acceptDraggedStackWithResult(context, stack)); + if (result != DraggedAcceptorResult.PASS) return result; } } - return false; + return DraggedAcceptorResult.PASS; } @Override @@ -84,6 +85,8 @@ public interface DraggableStackVisitor extends Comparable context, DraggableStack stack) { Optional acceptor = visitDraggedStack(context, stack); if (acceptor.isPresent()) { @@ -94,6 +97,18 @@ public interface DraggableStackVisitor extends Comparable context, DraggableStack stack) { + return acceptDraggedStack(context, stack) ? DraggedAcceptorResult.CONSUMED : DraggedAcceptorResult.PASS; + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the area is accepting entries. diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java index 7bb813d4d..4234b2b6b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java @@ -39,9 +39,12 @@ public interface DraggableStackVisitorWidget { static DraggableStackVisitorWidget from(Function, Iterable> providers) { return new DraggableStackVisitorWidget() { @Override - public boolean acceptDraggedStack(DraggingContext context, DraggableStack stack) { + public DraggedAcceptorResult acceptDraggedStackWithResult(DraggingContext context, DraggableStack stack) { return StreamSupport.stream(providers.apply(context).spliterator(), false) - .anyMatch(visitor -> visitor.acceptDraggedStack(context, stack)); + .map(visitor -> visitor.acceptDraggedStackWithResult(context, stack)) + .filter(result -> result != DraggedAcceptorResult.PASS) + .findFirst() + .orElse(DraggedAcceptorResult.PASS); } @Override @@ -66,6 +69,8 @@ public interface DraggableStackVisitorWidget { * @param stack the stack being dragged * @return whether the stack is accepted by the widget */ + @ApiStatus.ScheduledForRemoval + @Deprecated default boolean acceptDraggedStack(DraggingContext context, DraggableStack stack) { Optional acceptor = visitDraggedStack(context, stack); if (acceptor.isPresent()) { @@ -76,6 +81,18 @@ public interface DraggableStackVisitorWidget { } } + /** + * Accepts a dragged stack, implementations of this function should check if the {@code context} is within + * boundaries of the widget. + * + * @param context the context of the current dragged stack on the overlay + * @param stack the stack being dragged + * @return the result of the visitor + */ + default DraggedAcceptorResult acceptDraggedStackWithResult(DraggingContext context, DraggableStack stack) { + return acceptDraggedStack(context, stack) ? DraggedAcceptorResult.CONSUMED : DraggedAcceptorResult.PASS; + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the widget is accepting entries. @@ -95,8 +112,8 @@ public interface DraggableStackVisitorWidget { static DraggableStackVisitor toVisitor(DraggableStackVisitorWidget widget, double priority) { return new DraggableStackVisitor<>() { @Override - public boolean acceptDraggedStack(DraggingContext context, DraggableStack stack) { - return widget.acceptDraggedStack(context, stack); + public DraggedAcceptorResult acceptDraggedStackWithResult(DraggingContext context, DraggableStack stack) { + return widget.acceptDraggedStackWithResult(context, stack); } @Override diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggedAcceptorResult.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggedAcceptorResult.java new file mode 100644 index 000000000..05731ef0c --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggedAcceptorResult.java @@ -0,0 +1,44 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 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.api.client.gui.drag; + +/** + * The result of the visitor, this is used to determine if the visitor consumed the stack or not. + */ +public enum DraggedAcceptorResult { + /** + * The visitor consumed the stack, the stack will not be returned to the original stack. + */ + CONSUMED, + /** + * The visitor did not consume the stack, the stack will be returned to the original stack, + * other visitors will not be called. + */ + ACCEPTED, + /** + * The visitor did not consume the stack, the stack will be passed to the next visitor. + */ + PASS, + ; +} \ No newline at end of file diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java index 626d9aa29..20e2c1fe2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java @@ -24,6 +24,7 @@ package me.shedaniel.rei.api.client.gui.drag; import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.REIRuntime; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -82,6 +83,16 @@ public interface DraggingContext { */ void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier position); + /** + * Renders the draggable stack back to the bounds {@code bounds}. + * This may be used to animate an unaccepted draggable stack returning to its initial position. + * + * @param stack the stack to use for render + * @param initialPosition the initial bounds of the stack + * @param bounds the boundary supplier of the destination + */ + void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier bounds); + default DraggingContext cast() { return (DraggingContext) this; } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java index 3c3ea6462..9ec3a3a15 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/registry/transfer/TransferHandler.java @@ -69,7 +69,7 @@ public interface TransferHandler extends Comparable { * Creates a successful result, no further handlers will be called. */ static Result createSuccessful() { - return new ResultImpl(); + return new ResultImpl().color(0x00000000); } /** @@ -77,7 +77,7 @@ public interface TransferHandler extends Comparable { * This will also mark the handler as not applicable. */ static Result createNotApplicable() { - return new ResultImpl(false); + return new ResultImpl(false).color(0x00000000); } /** @@ -86,7 +86,7 @@ public interface TransferHandler extends Comparable { * @param error The error itself */ static Result createFailed(Component error) { - return new ResultImpl(error, new IntArrayList(), 1744764928); + return new ResultImpl(error, new IntArrayList(), 0x67ff0000); } /** @@ -107,7 +107,7 @@ public interface TransferHandler extends Comparable { * @param redSlots A list of slots to be marked as red. Will be passed to {@link TransferDisplayCategory}. */ static Result createFailed(Component error, IntList redSlots) { - return new ResultImpl(error, redSlots, 1744764928); + return new ResultImpl(error, redSlots, 0x67ff0000); } /** @@ -138,6 +138,11 @@ public interface TransferHandler extends Comparable { * @return the color in which the button should be displayed in. */ int getColor(); + + /** + * Sets the color in which the button should be displayed in. + */ + Result color(int color); /** * @return whether this handler has successfully handled the transfer. @@ -243,6 +248,12 @@ public interface TransferHandler extends Comparable { return color; } + @Override + public TransferHandler.Result color(int color) { + this.color = color; + return this; + } + @Override public boolean isSuccessful() { return successful; diff --git a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java index e6b2390db..8f67f2bff 100644 --- a/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java +++ b/forge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java @@ -29,6 +29,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fmllegacy.DatagenModLoader; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.ModFileScanData; import org.apache.commons.lang3.tuple.ImmutableTriple; @@ -50,8 +51,10 @@ public class RoughlyEnoughItemsForge { public static final Logger LOGGER = LogManager.getFormatterLogger("REI"); public RoughlyEnoughItemsForge() { - RoughlyEnoughItemsInitializer.onInitialize(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RoughlyEnoughItemsInitializer::onInitializeClient); + if (!DatagenModLoader.isRunningDataGen()) { + RoughlyEnoughItemsInitializer.onInitialize(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RoughlyEnoughItemsInitializer::onInitializeClient); + } } public static void scanAnnotation(Class clazz, Predicate> predicate, TriConsumer, Supplier, Class> consumer) { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java index b674d0099..d5d89a653 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java @@ -33,6 +33,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.gui.config.DisplayPanelLocation; import me.shedaniel.rei.api.client.gui.config.SearchFieldLocation; import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; import me.shedaniel.rei.api.client.gui.widgets.TextField; @@ -55,6 +56,8 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.entrySize; + @ApiStatus.Internal @Environment(EnvType.CLIENT) public class REIRuntimeImpl implements REIRuntime { @@ -194,8 +197,7 @@ public class REIRuntimeImpl implements REIRuntime { } @Override - public Rectangle calculateEntryListArea() { - Rectangle bounds = ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen); + public Rectangle calculateEntryListArea(Rectangle bounds) { SearchFieldLocation searchFieldLocation = getContextualSearchFieldLocation(); int yOffset = 2; @@ -212,7 +214,20 @@ public class REIRuntimeImpl implements REIRuntime { int yOffset = 8; if (!ConfigObject.getInstance().isLowerConfigButton()) yOffset += 25; - return new Rectangle(bounds.x, bounds.y + yOffset, bounds.width, bounds.height - 3 - yOffset); + bounds = new Rectangle(bounds.x, bounds.y + yOffset, bounds.width, bounds.height - 3 - yOffset); + + int widthReduction = (int) Math.round(bounds.width * (1 - ConfigObject.getInstance().getFavoritesHorizontalEntriesBoundariesPercentage())); + if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.LEFT) + bounds.x += widthReduction; + bounds.width -= widthReduction; + int maxWidth = (int) Math.ceil(entrySize() * ConfigObject.getInstance().getFavoritesHorizontalEntriesBoundariesColumns() + entrySize() * 0.75) + 8; + if (bounds.width > maxWidth) { + if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.LEFT) + bounds.x += bounds.width - maxWidth; + bounds.width = maxWidth; + } + + return bounds; } @Override diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java index 096a49e8b..73521ae30 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java @@ -169,6 +169,11 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { return advanced.layout.maxRecipesPerPage; } + @Override + public int getMaxRecipesPageHeight() { + return advanced.layout.maxRecipesPageHeight; + } + @Override public boolean doesDisableRecipeBook() { return functionality.disableRecipeBook; @@ -349,16 +354,39 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @ApiStatus.Experimental @Override - public double getHorizontalEntriesBoundaries() { + public double getHorizontalEntriesBoundariesPercentage() { return Mth.clamp(appearance.horizontalEntriesBoundaries, 0.1, 1); } @ApiStatus.Experimental @Override - public double getVerticalEntriesBoundaries() { + public double getVerticalEntriesBoundariesPercentage() { return Mth.clamp(appearance.verticalEntriesBoundaries, 0.1, 1); } + @ApiStatus.Experimental + @Override + public double getHorizontalEntriesBoundariesColumns() { + return Mth.clamp(appearance.horizontalEntriesBoundariesColumns, 1, 1000); + } + + @ApiStatus.Experimental + @Override + public double getVerticalEntriesBoundariesRows() { + return Mth.clamp(appearance.verticalEntriesBoundariesRows, 1, 1000); + } + + @ApiStatus.Experimental + @Override + public double getFavoritesHorizontalEntriesBoundariesPercentage() { + return Mth.clamp(appearance.favoritesHorizontalEntriesBoundaries, 0.1, 1); + } + + @Override + public double getFavoritesHorizontalEntriesBoundariesColumns() { + return Mth.clamp(appearance.favoritesHorizontalEntriesBoundariesColumns, 1, 1000); + } + @Override public SyntaxHighlightingMode getSyntaxHighlightingMode() { return appearance.syntaxHighlightingMode; @@ -469,6 +497,10 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double horizontalEntriesBoundaries = 1.0; @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double verticalEntriesBoundaries = 1.0; + private int horizontalEntriesBoundariesColumns = 50; + private int verticalEntriesBoundariesRows = 1000; + @UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") private double favoritesHorizontalEntriesBoundaries = 1.0; + private int favoritesHorizontalEntriesBoundariesColumns = 50; @UseSpecialSearchFilterSyntaxHighlightingScreen private SyntaxHighlightingMode syntaxHighlightingMode = SyntaxHighlightingMode.COLORFUL; } @@ -506,7 +538,9 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData { @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) private EntryPanelOrderingConfig entryPanelOrdering = EntryPanelOrderingConfig.REGISTRY_ASCENDING; @Comment("Declares the maximum amount of recipes displayed in a page if possible.") @ConfigEntry.BoundedDiscrete(min = 2, max = 99) - private int maxRecipesPerPage = 3; + private int maxRecipesPerPage = 8; + @Comment("Declares the maximum amount of recipes displayed in a page if possible.") @ConfigEntry.BoundedDiscrete(min = 100, max = 1000) + private int maxRecipesPageHeight = 300; @Comment("Declares whether entry rendering time should be debugged.") private boolean debugRenderTimeRequired = false; @Comment("Merges displays with equal contents under 1 display.") private boolean mergeDisplayUnderOne = true; } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java index bc53fca48..f95afd48b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java @@ -37,10 +37,12 @@ import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; +import me.shedaniel.rei.api.client.gui.config.DisplayPanelLocation; import me.shedaniel.rei.api.client.gui.config.SearchFieldLocation; import me.shedaniel.rei.api.client.gui.drag.DraggableStackProvider; import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; import me.shedaniel.rei.api.client.gui.widgets.Button; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.Widget; @@ -63,11 +65,7 @@ import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.craftable.CraftableFilter; import me.shedaniel.rei.impl.client.gui.dragging.CurrentDraggingStack; import me.shedaniel.rei.impl.client.gui.modules.Menu; -import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; -import me.shedaniel.rei.impl.client.gui.widget.EntryListWidget; -import me.shedaniel.rei.impl.client.gui.widget.FavoritesListWidget; -import me.shedaniel.rei.impl.client.gui.widget.InternalWidgets; -import me.shedaniel.rei.impl.client.gui.widget.LateRenderable; +import me.shedaniel.rei.impl.client.gui.widget.*; import me.shedaniel.rei.impl.client.gui.widget.search.OverlaySearchField; import me.shedaniel.rei.impl.common.util.Weather; import net.minecraft.client.Minecraft; @@ -97,6 +95,8 @@ import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; +import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.entrySize; + @ApiStatus.Internal public class ScreenOverlayImpl extends ScreenOverlay { private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("roughlyenoughitems", "textures/gui/recipecontainer.png"); @@ -112,6 +112,8 @@ public class ScreenOverlayImpl extends ScreenOverlay { private Button leftButton, rightButton; private Widget configButton; private CurrentDraggingStack draggingStack = new CurrentDraggingStack(); + @Nullable + public DefaultDisplayChoosePageWidget choosePageWidget; @Nullable private ScreenOverlayImpl.OverlayMenu overlayMenu = null; @@ -231,7 +233,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { this.children().clear(); this.closeOverlayMenu(); this.window = Minecraft.getInstance().getWindow(); - this.bounds = ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen); + this.bounds = calculateOverlayBounds(); widgets.add(ENTRY_LIST_WIDGET); if (ConfigObject.getInstance().isFavoritesEnabled()) { if (favoritesListWidget == null) { @@ -240,7 +242,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { favoritesListWidget.favoritePanel.resetRows(); widgets.add(favoritesListWidget); } - ENTRY_LIST_WIDGET.updateArea(REIRuntimeImpl.getSearchField() == null ? "" : REIRuntimeImpl.getSearchField().getText()); + ENTRY_LIST_WIDGET.updateArea(this.bounds, REIRuntimeImpl.getSearchField() == null ? "" : REIRuntimeImpl.getSearchField().getText()); REIRuntimeImpl.getSearchField().getBounds().setBounds(getSearchFieldArea()); this.widgets.add(REIRuntimeImpl.getSearchField()); REIRuntimeImpl.getSearchField().setResponder(s -> ENTRY_LIST_WIDGET.updateSearch(s, false)); @@ -280,7 +282,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { ConfigManager.getInstance().openConfigScreen(REIRuntime.getInstance().getPreviousScreen()); }) .onRender((matrices, button) -> { - if (ClientHelper.getInstance().isCheating() && ClientHelperImpl.getInstance().hasOperatorPermission()) { + if (ClientHelper.getInstance().isCheating() && !(Minecraft.getInstance().screen instanceof DisplayScreen) && ClientHelperImpl.getInstance().hasOperatorPermission()) { button.setTint(ClientHelperImpl.getInstance().hasPermissionToUsePackets() ? 721354752 : 1476440063); } else { button.removeTint(); @@ -326,9 +328,16 @@ public class ScreenOverlayImpl extends ScreenOverlay { } if (!ConfigObject.getInstance().isEntryListWidgetScrolled()) { widgets.add(Widgets.createClickableLabel(new Point(bounds.x + (bounds.width / 2), bounds.y + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.TOP_SIDE ? 24 : 0) + 10), NarratorChatListener.NO_TITLE, label -> { - ENTRY_LIST_WIDGET.setPage(0); - ENTRY_LIST_WIDGET.updateEntriesPosition(); - }).tooltipLine(I18n.get("text.rei.go_back_first_page")).focusable(false).onRender((matrices, label) -> { + if (!Screen.hasShiftDown()) { + ENTRY_LIST_WIDGET.setPage(0); + ENTRY_LIST_WIDGET.updateEntriesPosition(); + } else { + ScreenOverlayImpl.getInstance().choosePageWidget = new DefaultDisplayChoosePageWidget(page -> { + ENTRY_LIST_WIDGET.setPage(page); + ENTRY_LIST_WIDGET.updateEntriesPosition(); + }, ENTRY_LIST_WIDGET.getPage(), ENTRY_LIST_WIDGET.getTotalPages()); + } + }).tooltipLine(I18n.get("text.rei.go_back_first_page") + "\n \n§7" + I18n.get("text.rei.shift_click_to", I18n.get("text.rei.choose_page"))).focusable(false).onRender((matrices, label) -> { label.setClickable(ENTRY_LIST_WIDGET.getTotalPages() > 1); label.setMessage(new TextComponent(String.format("%s/%s", ENTRY_LIST_WIDGET.getPage() + 1, Math.max(ENTRY_LIST_WIDGET.getTotalPages(), 1)))); }).rainbow(new Random().nextFloat() < 1.0E-4D || ClientHelperImpl.getInstance().isAprilFools.get())); @@ -464,7 +473,7 @@ public class ScreenOverlayImpl extends ScreenOverlay { @Override public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { - if (shouldReload) { + if (shouldReload || !calculateOverlayBounds().equals(bounds)) { ENTRY_LIST_WIDGET.updateSearch(REIRuntimeImpl.getSearchField().getText(), true); init(); } else { @@ -515,6 +524,23 @@ public class ScreenOverlayImpl extends ScreenOverlay { } } + private static Rectangle calculateOverlayBounds() { + Rectangle bounds = ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen); + + int widthReduction = (int) Math.round(bounds.width * (1 - ConfigObject.getInstance().getHorizontalEntriesBoundariesPercentage())); + if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.RIGHT) + bounds.x += widthReduction; + bounds.width -= widthReduction; + int maxWidth = (int) Math.ceil(entrySize() * ConfigObject.getInstance().getHorizontalEntriesBoundariesColumns() + entrySize() * 0.75); + if (bounds.width > maxWidth) { + if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.RIGHT) + bounds.x += bounds.width - maxWidth; + bounds.width = maxWidth; + } + + return bounds; + } + public void lateRender(PoseStack matrices, int mouseX, int mouseY, float delta) { if (REIRuntime.getInstance().isOverlayVisible()) { REIRuntimeImpl.getSearchField().laterRender(matrices, mouseX, mouseY, delta); @@ -532,9 +558,15 @@ public class ScreenOverlayImpl extends ScreenOverlay { overlayMenu.wrappedMenu.render(matrices, mouseX, mouseY, delta); } } + if (choosePageWidget != null) { + setBlitOffset(500); + this.fillGradient(matrices, 0, 0, window.getGuiScaledWidth(), window.getGuiScaledHeight(), -1072689136, -804253680); + setBlitOffset(0); + choosePageWidget.render(matrices, mouseX, mouseY, delta); + } } Screen currentScreen = Minecraft.getInstance().screen; - if (!(currentScreen instanceof DefaultDisplayViewingScreen) || !((DefaultDisplayViewingScreen) currentScreen).choosePageActivated) { + if (choosePageWidget == null) { for (Tooltip tooltip : TOOLTIPS) { if (tooltip != null) renderTooltip(matrices, tooltip); @@ -611,6 +643,12 @@ public class ScreenOverlayImpl extends ScreenOverlay { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (REIRuntime.getInstance().isOverlayVisible()) { + if (keyCode == 256 && choosePageWidget != null) { + choosePageWidget = null; + return true; + } + if (choosePageWidget != null) + return choosePageWidget.keyPressed(keyCode, scanCode, modifiers); if (REIRuntimeImpl.getSearchField().keyPressed(keyCode, scanCode, modifiers)) return true; for (GuiEventListener listener : widgets) @@ -655,6 +693,9 @@ public class ScreenOverlayImpl extends ScreenOverlay { public boolean charTyped(char char_1, int int_1) { if (!REIRuntime.getInstance().isOverlayVisible()) return false; + if (choosePageWidget != null) { + return choosePageWidget.charTyped(char_1, int_1); + } if (REIRuntimeImpl.getSearchField().charTyped(char_1, int_1)) return true; for (GuiEventListener listener : widgets) @@ -671,6 +712,15 @@ public class ScreenOverlayImpl extends ScreenOverlay { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { boolean visible = REIRuntime.getInstance().isOverlayVisible(); + if (choosePageWidget != null) { + if (choosePageWidget.containsMouse(mouseX, mouseY)) { + return choosePageWidget.mouseClicked(mouseX, mouseY, button); + } else { + choosePageWidget = null; + init(); + return false; + } + } if (visible && configButton.mouseClicked(mouseX, mouseY, button)) { this.setFocused(configButton); if (button == 0) @@ -756,9 +806,19 @@ public class ScreenOverlayImpl extends ScreenOverlay { public boolean mouseDragged(double double_1, double double_2, int int_1, double double_3, double double_4) { if (!REIRuntime.getInstance().isOverlayVisible()) return false; + if (choosePageWidget != null) { + return choosePageWidget.mouseDragged(double_1, double_2, int_1, double_3, double_4); + } return (this.getFocused() != null && this.isDragging() && int_1 == 0) && this.getFocused().mouseDragged(double_1, double_2, int_1, double_3, double_4); } + @Override + public GuiEventListener getFocused() { + if (choosePageWidget != null) + return choosePageWidget; + return super.getFocused(); + } + public boolean isInside(double mouseX, double mouseY) { return bounds.contains(mouseX, mouseY) && isNotInExclusionZones(mouseX, mouseY); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java index 742a5bc39..4d8bb74f8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java @@ -28,10 +28,7 @@ import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; -import me.shedaniel.rei.api.client.gui.drag.DraggableStack; -import me.shedaniel.rei.api.client.gui.drag.DraggableStackProvider; -import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitor; -import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.drag.*; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.common.util.Animator; import me.shedaniel.rei.impl.client.gui.widget.LateRenderable; @@ -118,12 +115,12 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag while (iterator.hasNext()) { RenderBackEntry renderBackEntry = iterator.next(); renderBackEntry.update(delta); - if (Math.abs(renderBackEntry.x.doubleValue() - renderBackEntry.x.target()) <= 2 && Math.abs(renderBackEntry.y.doubleValue() - renderBackEntry.y.target()) <= 2) { + if (renderBackEntry.width.doubleValue() < 2 || renderBackEntry.height.doubleValue() < 2 || (Math.abs(renderBackEntry.x.doubleValue() - renderBackEntry.x.target()) <= 2 && Math.abs(renderBackEntry.y.doubleValue() - renderBackEntry.y.target()) <= 2 && Math.abs(renderBackEntry.width.doubleValue() - renderBackEntry.width.target()) <= 1 && Math.abs(renderBackEntry.height.doubleValue() - renderBackEntry.height.target()) <= 1)) { iterator.remove(); } else { matrices.pushPose(); matrices.translate(0, 0, 600); - renderBackEntry.stack.render(matrices, new Rectangle(renderBackEntry.x.intValue(), renderBackEntry.y.intValue(), 16, 16), mouseX, mouseY, delta); + renderBackEntry.stack.render(matrices, new Rectangle(Math.round(renderBackEntry.x.floatValue()), Math.round(renderBackEntry.y.floatValue()), Math.round(renderBackEntry.width.floatValue()), Math.round(renderBackEntry.height.floatValue())), mouseX, mouseY, delta); matrices.popPose(); } } @@ -156,8 +153,8 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag private boolean drop() { if (entry != null && entry.dragging) { - boolean released = visitor.acceptDraggedStack(this, entry.stack); - entry.stack.release(released); + DraggedAcceptorResult result = visitor.acceptDraggedStackWithResult(this, entry.stack); + entry.stack.release(result); entry = null; return true; } @@ -185,7 +182,15 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag @Override public void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier position) { - backToOriginals.add(new RenderBackEntry(stack, initialPosition, position)); + backToOriginals.add(new RenderBackEntry(stack, new Rectangle(initialPosition.x - 8, initialPosition.y - 8, 16, 16), () -> { + Point point = position.get(); + return new Rectangle(point.x, point.y, 16, 16); + })); + } + + @Override + public void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier bounds) { + backToOriginals.add(new RenderBackEntry(stack, initialPosition, bounds)); } private class DraggableEntry { @@ -238,30 +243,38 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag private static class RenderBackEntry { private final DraggableStack stack; - private final Supplier position; + private final Supplier position; private Animator x = new Animator(); private Animator y = new Animator(); + private Animator width = new Animator(); + private Animator height = new Animator(); private int lastDestination = -1; - public RenderBackEntry(DraggableStack stack, Point initialPosition, Supplier position) { + public RenderBackEntry(DraggableStack stack, Rectangle initialPosition, Supplier position) { this.stack = stack; - this.x.setAs(initialPosition.x - 8); - this.y.setAs(initialPosition.y - 8); + this.x.setAs(initialPosition.x); + this.y.setAs(initialPosition.y); + this.width.setAs(initialPosition.width); + this.height.setAs(initialPosition.height); this.position = position; } - public Point getPosition() { + public Rectangle getPosition() { return position.get(); } public void update(double delta) { this.x.update(delta); this.y.update(delta); - Point position = getPosition(); + this.width.update(delta); + this.height.update(delta); + Rectangle position = getPosition(); if (lastDestination != position.hashCode()) { lastDestination = position.hashCode(); this.x.setTo(position.x, 200); this.y.setTo(position.y, 200); + this.width.setTo(position.width, 200); + this.height.setTo(position.height, 200); } } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java index 3478a2cc3..37e329a95 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java @@ -51,6 +51,7 @@ import me.shedaniel.rei.api.common.util.ImmutableTextComponent; import me.shedaniel.rei.impl.client.ClientHelperImpl; import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.RecipeDisplayExporter; +import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.widget.DefaultDisplayChoosePageWidget; import me.shedaniel.rei.impl.client.gui.widget.EntryWidget; import me.shedaniel.rei.impl.client.gui.widget.InternalWidgets; @@ -60,6 +61,7 @@ import me.shedaniel.rei.impl.display.DisplaySpec; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.chat.NarratorChatListener; import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.sounds.SimpleSoundInstance; @@ -84,8 +86,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { private final List tabs = Lists.newArrayList(); public int page; public int categoryPages = -1; - public boolean choosePageActivated = false; - public DefaultDisplayChoosePageWidget choosePageWidget; @Nullable private Panel workingStationsBaseWidget; private Button recipeBack, recipeNext, categoryBack, categoryNext; @@ -107,20 +107,12 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (keyCode == 256 && choosePageActivated) { - choosePageActivated = false; - init(); - return true; - } if (keyCode == 258 && !minecraft.options.keyInventory.matches(keyCode, scanCode)) { boolean next = !hasShiftDown(); if (!this.changeFocus(next)) this.changeFocus(next); return true; - } - if (choosePageActivated) - return choosePageWidget.keyPressed(keyCode, scanCode, modifiers); - else if (ConfigObject.getInstance().getNextPageKeybind().matchesKey(keyCode, scanCode)) { + } else if (ConfigObject.getInstance().getNextPageKeybind().matchesKey(keyCode, scanCode)) { if (recipeNext.isEnabled()) recipeNext.onClick(); return recipeNext.isEnabled(); @@ -155,9 +147,9 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { this.tabs.clear(); this.preWidgets.clear(); this.widgets.clear(); - int largestHeight = Math.max(height - 34 - 30, 100); + int largestHeight = Math.min(Math.max(height - 34 - 30, 100), ConfigObject.getInstance().getMaxRecipesPageHeight()); int maxWidthDisplay = CollectionUtils.mapAndMax(getCurrentDisplayed(), display -> getCurrentCategory().getDisplayWidth(display.provideInternalDisplay()), Comparator.naturalOrder()).orElse(150); - int maxHeight = Math.min(largestHeight, CollectionUtils., Integer>mapAndMax(categories, + int maxHeight = Math.min(largestHeight, CollectionUtils., Integer>mapAndMax(categories, category -> (category.getDisplayHeight() + 4) * Math.max(1, Math.min(getRecipesPerPage(largestHeight, category) + 1, Math.max(categoryMap.get(category).size(), ConfigObject.getInstance().getMaxRecipePerPage()))) + 36, Comparator.naturalOrder()).orElse(66)); int totalDisplayHeight = (getCurrentCategory().getDisplayHeight() + 4) * Math.max(1, getRecipesPerPage(maxHeight, getCurrentCategory()) + 1) + 36; int guiWidth = Math.max(maxWidthDisplay + 10, 190); @@ -166,7 +158,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { this.bounds.setLocation(this.bounds.getX(), this.bounds.getY() + 15); this.bounds.setSize(this.bounds.getWidth(), this.bounds.getHeight() - 10); } - + boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs(); int tabSize = isCompactTabs ? 24 : 28; this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - 20d) / tabSize)); @@ -200,7 +192,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { .onClick(button -> nextCategory()).tooltipLine(new TranslatableComponent("text.rei.next_category"))); this.categoryBack.setEnabled(categories.size() > 1); this.categoryNext.setEnabled(categories.size() > 1); - + this.widgets.add(recipeBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 19, 12, 12), new TranslatableComponent("text.rei.left_arrow")) .onClick(button -> { page--; @@ -209,12 +201,19 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { DefaultDisplayViewingScreen.this.init(); }).tooltipLine(new TranslatableComponent("text.rei.previous_page"))); this.widgets.add(Widgets.createClickableLabel(new Point(bounds.getCenterX(), bounds.getY() + 21), NarratorChatListener.NO_TITLE, label -> { - DefaultDisplayViewingScreen.this.choosePageActivated = true; - DefaultDisplayViewingScreen.this.init(); + if (!Screen.hasShiftDown()) { + page = 0; + DefaultDisplayViewingScreen.this.init(); + } else { + ScreenOverlayImpl.getInstance().choosePageWidget = new DefaultDisplayChoosePageWidget(page -> { + DefaultDisplayViewingScreen.this.page = page; + DefaultDisplayViewingScreen.this.init(); + }, page, getCurrentTotalPages()); + } }).onRender((matrices, label) -> { label.setMessage(new ImmutableTextComponent(String.format("%d/%d", page + 1, getCurrentTotalPages()))); label.setClickable(getCurrentTotalPages() > 1); - }).tooltipSupplier(label -> label.isClickable() ? I18n.get("text.rei.choose_page") : null)); + }).tooltipSupplier(label -> label.isClickable() ? I18n.get("text.rei.go_back_first_page") + "\n \n§7" + I18n.get("text.rei.shift_click_to", I18n.get("text.rei.choose_page")) : null)); this.widgets.add(recipeNext = Widgets.createButton(new Rectangle(bounds.getMaxX() - 17, bounds.getY() + 19, 12, 12), new TranslatableComponent("text.rei.right_arrow")) .onClick(button -> { page++; @@ -238,8 +237,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { tab.setRenderer(categories.get(tabIndex), categories.get(tabIndex).getIcon(), categories.get(tabIndex).getTitle(), tab.getId() + categoryPages * tabsPerPage == selectedCategoryIndex); } } - - choosePageWidget = choosePageActivated ? new DefaultDisplayChoosePageWidget(this, page, getCurrentTotalPages()) : null; initDisplays(); initWorkstations(preWidgets); @@ -392,12 +389,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { } } } - if (choosePageActivated) { - setBlitOffset(500); - this.fillGradient(matrices, 0, 0, this.width, this.height, -1072689136, -804253680); - setBlitOffset(0); - choosePageWidget.render(matrices, mouseX, mouseY, delta); - } } @Override @@ -425,9 +416,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { @Override public boolean charTyped(char char_1, int int_1) { - if (choosePageActivated) { - return choosePageWidget.charTyped(char_1, int_1); - } for (GuiEventListener listener : children()) if (listener.charTyped(char_1, int_1)) return true; @@ -436,9 +424,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { @Override public boolean mouseDragged(double double_1, double double_2, int int_1, double double_3, double double_4) { - if (choosePageActivated) { - return choosePageWidget.mouseDragged(double_1, double_2, int_1, double_3, double_4); - } for (GuiEventListener entry : children()) if (entry.mouseDragged(double_1, double_2, int_1, double_3, double_4)) return true; @@ -447,17 +432,13 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (choosePageActivated) { - return choosePageWidget.mouseReleased(mouseX, mouseY, button); - } else { - ModifierKeyCode export = ConfigObject.getInstance().getExportImageKeybind(); - if (export.matchesMouse(button)) { - for (Map.Entry> entry : recipeBounds.entrySet()) { - Rectangle bounds = entry.getKey(); - if (bounds.contains(PointHelper.ofMouse())) { - RecipeDisplayExporter.exportRecipeDisplay(bounds, entry.getValue()); - break; - } + ModifierKeyCode export = ConfigObject.getInstance().getExportImageKeybind(); + if (export.matchesMouse(button)) { + for (Map.Entry> entry : recipeBounds.entrySet()) { + Rectangle bounds = entry.getKey(); + if (bounds.contains(PointHelper.ofMouse())) { + RecipeDisplayExporter.exportRecipeDisplay(bounds, entry.getValue()); + break; } } } @@ -494,15 +475,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (choosePageActivated) { - if (choosePageWidget.containsMouse(mouseX, mouseY)) { - return choosePageWidget.mouseClicked(mouseX, mouseY, button); - } else { - choosePageActivated = false; - init(); - return false; - } - } else if (ConfigObject.getInstance().getNextPageKeybind().matchesMouse(button)) { + if (ConfigObject.getInstance().getNextPageKeybind().matchesMouse(button)) { if (recipeNext.isEnabled()) recipeNext.onClick(); return recipeNext.isEnabled(); @@ -521,13 +494,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen { return super.mouseClicked(mouseX, mouseY, button); } - @Override - public GuiEventListener getFocused() { - if (choosePageActivated) - return choosePageWidget; - return super.getFocused(); - } - public static class WorkstationSlotWidget extends EntryWidget { public WorkstationSlotWidget(int x, int y, EntryIngredient widgets) { super(new Point(x, y)); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java index 60b798978..810a622f8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DefaultDisplayChoosePageWidget.java @@ -33,7 +33,7 @@ import me.shedaniel.rei.api.client.gui.widgets.Button; import me.shedaniel.rei.api.client.gui.widgets.Panel; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.Widgets; -import me.shedaniel.rei.impl.client.gui.screen.DefaultDisplayViewingScreen; +import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.widget.basewidgets.TextFieldWidget; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.TranslatableComponent; @@ -43,6 +43,7 @@ import org.jetbrains.annotations.ApiStatus; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.function.IntConsumer; @ApiStatus.Internal public class DefaultDisplayChoosePageWidget extends DraggableWidget { @@ -51,14 +52,14 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { private int maxPage; private Rectangle bounds, grabBounds, dragBounds; private List widgets; - private DefaultDisplayViewingScreen screen; + private IntConsumer callback; private TextFieldWidget textFieldWidget; private Panel base1, base2; private Button btnDone; - public DefaultDisplayChoosePageWidget(DefaultDisplayViewingScreen screen, int currentPage, int maxPage) { + public DefaultDisplayChoosePageWidget(IntConsumer callback, int currentPage, int maxPage) { super(getPointFromConfig()); - this.screen = screen; + this.callback = callback; this.currentPage = currentPage; this.maxPage = maxPage; initWidgets(getMidPoint()); @@ -110,7 +111,7 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { this.widgets.add(base2 = Widgets.createCategoryBase(bounds)); this.widgets.add(new Widget() { - private TranslatableComponent text; + private TranslatableComponent text = new TranslatableComponent("text.rei.choose_page"); @Override public List children() { @@ -119,7 +120,6 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { @Override public void render(PoseStack matrices, int i, int i1, float v) { - text = new TranslatableComponent("text.rei.choose_page"); font.draw(matrices, text.getVisualOrderText(), bounds.x + 5, bounds.y + 5, REIRuntime.getInstance().isDarkThemeEnabled() ? 0xFFBBBBBB : 0xFF404040); String endString = String.format(" /%d", maxPage); int width = font.width(endString); @@ -145,9 +145,8 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { textFieldWidget.setText(String.valueOf(currentPage + 1)); widgets.add(btnDone = Widgets.createButton(new Rectangle(bounds.x + bounds.width - 45, bounds.y + bounds.height + 3, 40, 20), new TranslatableComponent("gui.done")) .onClick(button -> { - screen.page = Mth.clamp(getIntFromString(textFieldWidget.getText()).orElse(0) - 1, 0, screen.getCurrentTotalPages() - 1); - screen.choosePageActivated = false; - screen.init(); + callback.accept(Mth.clamp(getIntFromString(textFieldWidget.getText()).orElse(0) - 1, 0, maxPage - 1)); + ScreenOverlayImpl.getInstance().choosePageWidget = null; })); textFieldWidget.setFocused(true); } @@ -183,9 +182,8 @@ public class DefaultDisplayChoosePageWidget extends DraggableWidget { @Override public boolean keyPressed(int int_1, int int_2, int int_3) { if (int_1 == 335 || int_1 == 257) { - screen.page = Mth.clamp(getIntFromString(textFieldWidget.getText()).orElse(0) - 1, 0, screen.getCurrentTotalPages() - 1); - screen.choosePageActivated = false; - screen.init(); + callback.accept(Mth.clamp(getIntFromString(textFieldWidget.getText()).orElse(0) - 1, 0, maxPage - 1)); + ScreenOverlayImpl.getInstance().choosePageWidget = null; return true; } for (Widget widget : widgets) diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListEntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListEntryWidget.java index 143d93662..4ab46773c 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListEntryWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListEntryWidget.java @@ -28,8 +28,10 @@ import dev.architectury.fluid.FluidStack; import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.ClientHelper; import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.gui.screen.DisplayScreen; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -51,7 +53,7 @@ public abstract class EntryListEntryWidget extends EntryWidget { @Override public void queueTooltip(PoseStack matrices, int mouseX, int mouseY, float delta) { - if (ClientHelper.getInstance().isCheating() && !minecraft.player.containerMenu.getCarried().isEmpty()) { + if (ClientHelper.getInstance().isCheating() && !(Minecraft.getInstance().screen instanceof DisplayScreen) && !minecraft.player.containerMenu.getCarried().isEmpty()) { return; } super.queueTooltip(matrices, mouseX, mouseY, delta); @@ -74,7 +76,7 @@ publ