Procházet zdrojové kódy

Fix #440 and brings better animations to the config menu.

Signed-off-by: shedaniel <daniel@shedaniel.me>
shedaniel před 4 roky
rodič
revize
6072bdf641

+ 1 - 1
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/ContainerScreenOverlay.java

@@ -256,7 +256,7 @@ public class ContainerScreenOverlay extends WidgetWithBounds implements REIOverl
         widgets.add(tmp = InternalWidgets.wrapLateRenderable(InternalWidgets.mergeWidgets(
                 Widgets.createButton(configButtonArea, NarratorChatListener.NO_TITLE)
                         .onClick(button -> {
-                            if (Screen.hasShiftDown()) {
+                            if (Screen.hasShiftDown() || Screen.hasControlDown()) {
                                 ClientHelper.getInstance().setCheating(!ClientHelper.getInstance().isCheating());
                                 return;
                             }

+ 81 - 40
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/DelegateScreen.java

@@ -24,6 +24,7 @@
 package me.shedaniel.rei.gui;
 
 import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.rei.utils.ImmutableLiteralText;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.components.AbstractWidget;
 import net.minecraft.client.gui.components.events.GuiEventListener;
@@ -35,6 +36,7 @@ import org.jetbrains.annotations.ApiStatus;
 import org.jetbrains.annotations.Nullable;
 
 import java.nio.file.Path;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -44,200 +46,239 @@ public class DelegateScreen extends Screen {
     protected Screen parent;
     
     public DelegateScreen(Screen parent) {
-        super(parent.getTitle());
+        super(parent == null ? null : parent.getTitle());
         this.parent = parent;
     }
     
     @Override
     public Component getTitle() {
-        return parent.getTitle();
+        return parent == null ? ImmutableLiteralText.EMPTY : parent.getTitle();
     }
     
     @Override
     public String getNarrationMessage() {
-        return parent.getNarrationMessage();
+        return parent == null ? "" : parent.getNarrationMessage();
     }
     
     @Override
     public boolean keyPressed(int i, int j, int k) {
-        return parent.keyPressed(i, j, k);
+        return parent != null && parent.keyPressed(i, j, k);
     }
     
     @Override
     public boolean shouldCloseOnEsc() {
-        return parent.shouldCloseOnEsc();
+        return parent == null || parent.shouldCloseOnEsc();
     }
     
     @Override
     public void onClose() {
-        parent.onClose();
+        if (parent != null) {
+            parent.onClose();
+        }
     }
     
     @Override
     public <T extends AbstractWidget> T addButton(T abstractWidget) {
-        return parent.addButton(abstractWidget);
+        if (parent != null) {
+            return parent.addButton(abstractWidget);
+        }
+        return abstractWidget;
     }
     
     @Override
     public <T extends GuiEventListener> T addWidget(T guiEventListener) {
-        return parent.addWidget(guiEventListener);
+        if (parent != null) {
+            return parent.addWidget(guiEventListener);
+        }
+        return guiEventListener;
     }
     
     @Override
     public List<Component> getTooltipFromItem(ItemStack itemStack) {
+        if (parent == null) {
+            return super.getTooltipFromItem(itemStack);
+        }
         return parent.getTooltipFromItem(itemStack);
     }
     
     @Override
     public void insertText(String string, boolean bl) {
-        parent.insertText(string, bl);
+        if (parent != null) {
+            parent.insertText(string, bl);
+        }
     }
     
     @Override
     public boolean handleComponentClicked(@Nullable Style style) {
-        return parent.handleComponentClicked(style);
+        return parent != null && parent.handleComponentClicked(style);
     }
     
     @Override
     public void sendMessage(String string) {
-        parent.sendMessage(string);
+        if (parent != null) {
+            parent.sendMessage(string);
+        }
     }
     
     @Override
     public void sendMessage(String string, boolean bl) {
-        parent.sendMessage(string, bl);
+        if (parent != null) {
+            parent.sendMessage(string, bl);
+        }
     }
     
     @Override
     public List<? extends GuiEventListener> children() {
-        return parent.children();
+        return parent == null ? Collections.emptyList() : parent.children();
     }
     
     @Override
     public void tick() {
-        parent.tick();
+        if (parent != null) {
+            parent.tick();
+        }
     }
     
     @Override
     public void removed() {
-        parent.removed();
+        if (parent != null) {
+            parent.removed();
+        }
     }
     
     @Override
     public boolean isPauseScreen() {
-        return parent.isPauseScreen();
+        return parent != null && parent.isPauseScreen();
     }
     
     @Override
     public boolean isValidCharacterForName(String string, char c, int i) {
-        return parent.isValidCharacterForName(string, c, i);
+        return parent != null && parent.isValidCharacterForName(string, c, i);
     }
     
     @Override
     public boolean isMouseOver(double d, double e) {
-        return parent.isMouseOver(d, e);
+        return parent != null && parent.isMouseOver(d, e);
     }
     
     @Override
     public void onFilesDrop(List<Path> list) {
-        parent.onFilesDrop(list);
+        if (parent != null) {
+            parent.onFilesDrop(list);
+        }
     }
     
     @Nullable
     @Override
     public GuiEventListener getFocused() {
-        return parent.getFocused();
+        return parent == null ? null : parent.getFocused();
     }
     
     @Override
     public void setFocused(@Nullable GuiEventListener guiEventListener) {
-        parent.setFocused(guiEventListener);
+        if (parent != null) {
+            parent.setFocused(guiEventListener);
+        }
     }
     
     @Override
     public int getBlitOffset() {
-        return parent.getBlitOffset();
+        return parent == null ? 0 : parent.getBlitOffset();
     }
     
     @Override
     public void setBlitOffset(int i) {
-        parent.setBlitOffset(i);
+        if (parent != null) {
+            parent.setBlitOffset(i);
+        }
     }
     
     @Override
     public boolean mouseClicked(double d, double e, int i) {
-        return parent.mouseClicked(d, e, i);
+        return parent != null && parent.mouseClicked(d, e, i);
     }
     
     @Override
     public boolean mouseReleased(double d, double e, int i) {
-        return parent.mouseReleased(d, e, i);
+        return parent != null && parent.mouseReleased(d, e, i);
     }
     
     @Override
     public boolean mouseDragged(double d, double e, int i, double f, double g) {
-        return parent.mouseDragged(d, e, i, f, g);
+        return parent != null && parent.mouseDragged(d, e, i, f, g);
     }
     
     @Override
     public boolean mouseScrolled(double d, double e, double f) {
-        return parent.mouseScrolled(d, e, f);
+        return parent != null && parent.mouseScrolled(d, e, f);
     }
     
     @Override
     public boolean keyReleased(int i, int j, int k) {
-        return parent.keyReleased(i, j, k);
+        return parent != null && parent.keyReleased(i, j, k);
     }
     
     @Override
     public boolean charTyped(char c, int i) {
-        return parent.charTyped(c, i);
+        return parent != null && parent.charTyped(c, i);
     }
     
     @Override
     public void setInitialFocus(@Nullable GuiEventListener guiEventListener) {
-        parent.setInitialFocus(guiEventListener);
+        if (parent != null) {
+            parent.setInitialFocus(guiEventListener);
+        }
     }
     
     @Override
     public void magicalSpecialHackyFocus(@Nullable GuiEventListener guiEventListener) {
-        parent.magicalSpecialHackyFocus(guiEventListener);
+        if (parent != null) {
+            parent.magicalSpecialHackyFocus(guiEventListener);
+        }
     }
     
     @Override
     public boolean changeFocus(boolean bl) {
-        return parent.changeFocus(bl);
+        return parent != null && parent.changeFocus(bl);
     }
     
     @Override
     public void mouseMoved(double d, double e) {
-        parent.mouseMoved(d, e);
+        if (parent != null) {
+            parent.mouseMoved(d, e);
+        }
     }
     
     @Override
     public void resize(Minecraft minecraft, int i, int j) {
-        parent.resize(minecraft, i, j);
+        if (parent != null) {
+            parent.resize(minecraft, i, j);
+        }
     }
     
     @Override
     public void init(Minecraft minecraft, int i, int j) {
-        parent.init(minecraft, i, j);
+        if (parent != null) {
+            parent.init(minecraft, i, j);
+        }
     }
     
     @Override
     public void init() {
-        parent.init();
+        if (parent != null) {
+            parent.init();
+        }
     }
     
     @Override
     public Optional<GuiEventListener> getChildAt(double d, double e) {
-        return parent.getChildAt(d, e);
+        return parent == null ? Optional.empty() : parent.getChildAt(d, e);
     }
     
     @Override
     public void render(PoseStack poseStack, int i, int j, float f) {
-        parent.render(poseStack, i, j, f);
+        if (parent != null) {
+            parent.render(poseStack, i, j, f);
+        }
     }
-    
-    
 }

+ 11 - 17
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/RecipeViewingScreen.java

@@ -25,7 +25,6 @@ package me.shedaniel.rei.gui;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.mojang.blaze3d.platform.Window;
 import com.mojang.blaze3d.systems.RenderSystem;
 import com.mojang.blaze3d.vertex.PoseStack;
 import com.mojang.blaze3d.vertex.Tesselator;
@@ -81,11 +80,8 @@ public class RecipeViewingScreen extends Screen implements RecipeScreen {
     private final Map<RecipeCategory<?>, List<RecipeDisplay>> categoriesMap;
     private final List<RecipeCategory<?>> categories;
     private final RecipeCategory<RecipeDisplay> selectedCategory;
-    public int guiWidth;
-    public int guiHeight;
     public int page;
     public int categoryPages = -1;
-    public int largestWidth, largestHeight;
     public boolean choosePageActivated = false;
     public RecipeChoosePageWidget recipeChoosePageWidget;
     private int tabsPerPage = 5;
@@ -98,8 +94,7 @@ public class RecipeViewingScreen extends Screen implements RecipeScreen {
     
     public RecipeViewingScreen(Map<RecipeCategory<?>, List<RecipeDisplay>> categoriesMap, @Nullable ResourceLocation category) {
         super(NarratorChatListener.NO_TITLE);
-        Window window = Minecraft.getInstance().getWindow();
-        this.bounds = new Rectangle(window.getGuiScaledWidth() / 2 - guiWidth / 2, window.getGuiScaledHeight() / 2 - guiHeight / 2, 176, 150);
+        this.bounds = new Rectangle(0, 0, 176, 150);
         this.categoriesMap = categoriesMap;
         this.categories = Lists.newArrayList(categoriesMap.keySet());
         RecipeCategory<?> selected = categories.get(0);
@@ -224,17 +219,21 @@ public class RecipeViewingScreen extends Screen implements RecipeScreen {
         this.tabs.clear();
         this.preWidgets.clear();
         this.widgets.clear();
-        this.largestWidth = width - 100;
-        this.largestHeight = Math.max(height - 34 - 30, 100);
+        int largestWidth = width - 100;
+        int largestHeight = Math.max(height - 34 - 30, 100);
         int maxWidthDisplay = CollectionUtils.mapAndMax(getCurrentDisplayed(), selectedCategory::getDisplayWidth, Comparator.naturalOrder()).orElse(150);
-        this.guiWidth = Math.max(maxWidthDisplay + 40, 190);
-        this.guiHeight = Mth.floor(Mth.clamp((double) (selectedCategory.getDisplayHeight() + 4) * (getRecipesPerPage() + 1) + 36, 100, largestHeight));
-        if (!ConfigObject.getInstance().shouldResizeDynamically()) this.guiHeight = largestHeight;
+        int guiWidth = Math.max(maxWidthDisplay + 40, 190);
+        int guiHeight = Mth.floor(Mth.clamp((double) (selectedCategory.getDisplayHeight() + 4) * (getRecipesPerPage() + 1) + 36, 100, largestHeight));
+        if (!ConfigObject.getInstance().shouldResizeDynamically()) guiHeight = largestHeight;
         this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - 20d) / tabSize));
         if (this.categoryPages == -1) {
             this.categoryPages = Math.max(0, categories.indexOf(selectedCategory) / tabsPerPage);
         }
         this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - guiHeight / 2, guiWidth, guiHeight);
+        if (ConfigObject.getInstance().isSubsetsEnabled()) {
+            this.bounds.setLocation(this.bounds.getX(), this.bounds.getY() + 15);
+            this.bounds.setSize(this.bounds.getWidth(), this.bounds.getHeight() - 10);
+        }
         this.page = Mth.clamp(page, 0, getTotalPages(selectedCategory) - 1);
         this.widgets.add(Widgets.createButton(new Rectangle(bounds.x, bounds.y - 16, 10, 10), new TranslatableComponent("text.rei.left_arrow"))
                 .onClick(button -> {
@@ -391,12 +390,7 @@ public class RecipeViewingScreen extends Screen implements RecipeScreen {
         if (selectedCategory.getFixedRecipesPerPage() > 0)
             return selectedCategory.getFixedRecipesPerPage() - 1;
         int height = selectedCategory.getDisplayHeight();
-        return Mth.clamp(Mth.floor(((double) largestHeight - 36) / ((double) height + 4)) - 1, 0, Math.min(ConfigObject.getInstance().getMaxRecipePerPage() - 1, selectedCategory.getMaximumRecipePerPage() - 1));
-    }
-    
-    private int getRecipesPerPageByHeight() {
-        int height = selectedCategory.getDisplayHeight();
-        return Mth.clamp(Mth.floor(((double) guiHeight - 36) / ((double) height + 4)), 0, Math.min(ConfigObject.getInstance().getMaxRecipePerPage() - 1, selectedCategory.getMaximumRecipePerPage() - 1));
+        return Mth.clamp(Mth.floor(((double) this.bounds.getHeight() - 36) / ((double) height + 4)) - 1, 0, Math.min(ConfigObject.getInstance().getMaxRecipePerPage() - 1, selectedCategory.getMaximumRecipePerPage() - 1));
     }
     
     @Override

+ 74 - 10
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/TransformingScreen.java

@@ -27,28 +27,59 @@ import com.mojang.blaze3d.systems.RenderSystem;
 import com.mojang.blaze3d.vertex.PoseStack;
 import me.shedaniel.clothconfig2.api.ScissorsScreen;
 import me.shedaniel.math.Rectangle;
+import net.minecraft.client.KeyMapping;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.screens.Screen;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.function.BooleanSupplier;
 import java.util.function.DoubleSupplier;
 
 public class TransformingScreen extends DelegateScreen implements ScissorsScreen {
     private final DoubleSupplier xTransformer;
     private final DoubleSupplier yTransformer;
-    private final Screen lastScreen;
+    private Screen lastScreen;
+    private final BooleanSupplier finished;
+    private Runnable init;
+    private boolean renderingLastScreen = false;
+    private boolean translatingLast;
     
-    public TransformingScreen(Screen parent, Screen lastScreen, Runnable init, DoubleSupplier xTransformer, DoubleSupplier yTransformer) {
+    public TransformingScreen(boolean translatingLast, Screen parent, Screen lastScreen, Runnable init, DoubleSupplier xTransformer, DoubleSupplier yTransformer, BooleanSupplier finished) {
         super(parent);
+        this.translatingLast = translatingLast;
         this.lastScreen = lastScreen;
+        this.init = init;
         this.xTransformer = xTransformer;
         this.yTransformer = yTransformer;
-        init.run();
+        this.finished = finished;
+    }
+    
+    public void setParentScreen(Screen parent) {
+        this.parent = parent;
+    }
+    
+    public void setLastScreen(Screen lastScreen) {
+        this.lastScreen = lastScreen;
     }
     
     @Override
     public void init(Minecraft minecraft, int i, int j) {
         super.init(minecraft, i, j);
+        if (init != null) {
+            init.run();
+            init = null;
+            
+            if (parent != null) {
+                minecraft.mouseHandler.releaseMouse();
+                KeyMapping.releaseAll();
+            } else {
+                minecraft.getSoundManager().resume();
+                minecraft.mouseHandler.grabMouse();
+                minecraft.screen = this;
+            }
+            
+            minecraft.updateTitle();
+        }
         if (lastScreen != null) {
             lastScreen.init(minecraft, i, j);
         }
@@ -56,21 +87,54 @@ public class TransformingScreen extends DelegateScreen implements ScissorsScreen
     
     @Override
     public void render(PoseStack poseStack, int i, int j, float f) {
-        if (lastScreen != null) {
+        if (!translatingLast) {
+            renderingLastScreen = true;
+            if (lastScreen != null) {
+                RenderSystem.pushMatrix();
+                RenderSystem.translated(0, 0, -400);
+                lastScreen.render(poseStack, -1, -1, 0);
+                RenderSystem.popMatrix();
+            }
+            renderingLastScreen = false;
+            RenderSystem.pushMatrix();
+            RenderSystem.translated(xTransformer.getAsDouble(), yTransformer.getAsDouble(), 0);
+            super.render(poseStack, i, j, f);
+            RenderSystem.popMatrix();
+        } else {
             RenderSystem.pushMatrix();
             RenderSystem.translated(0, 0, -400);
-            lastScreen.render(poseStack, -1, -1, 0);
+            super.render(poseStack, i, j, f);
             RenderSystem.popMatrix();
+            renderingLastScreen = true;
+            if (lastScreen != null) {
+                RenderSystem.pushMatrix();
+                RenderSystem.translated(xTransformer.getAsDouble(), yTransformer.getAsDouble(), 0);
+                lastScreen.render(poseStack, -1, -1, 0);
+                RenderSystem.popMatrix();
+            }
+            renderingLastScreen = false;
+        }
+    }
+    
+    @Override
+    public void tick() {
+        if (finished.getAsBoolean()) {
+            if (parent != null) {
+                parent.removed();
+            }
+            
+            Minecraft.getInstance().screen = parent;
+            if (parent != null) {
+                Minecraft.getInstance().noRender = false;
+            }
+        } else {
+            super.tick();
         }
-        RenderSystem.pushMatrix();
-        RenderSystem.translated(xTransformer.getAsDouble(), yTransformer.getAsDouble(), 0);
-        super.render(poseStack, i, j, f);
-        RenderSystem.popMatrix();
     }
     
     @Override
     public @Nullable Rectangle handleScissor(@Nullable Rectangle rectangle) {
-        if (rectangle != null)
+        if (renderingLastScreen == translatingLast && rectangle != null)
             rectangle.translate((int) xTransformer.getAsDouble(), (int) yTransformer.getAsDouble());
         return rectangle;
     }

+ 21 - 14
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/credits/CreditsScreen.java

@@ -25,21 +25,26 @@ package me.shedaniel.rei.gui.credits;
 
 import com.google.common.collect.Lists;
 import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.impl.EasingMethod;
+import me.shedaniel.rei.api.ConfigObject;
+import me.shedaniel.rei.gui.TransformingScreen;
 import me.shedaniel.rei.gui.credits.CreditsEntryListWidget.TextCreditsItem;
 import me.shedaniel.rei.gui.credits.CreditsEntryListWidget.TranslationCreditsItem;
-import me.shedaniel.rei.impl.ScreenHelper;
 import me.shedaniel.rei.utils.ImmutableLiteralText;
 import net.fabricmc.loader.api.FabricLoader;
 import net.fabricmc.loader.api.metadata.CustomValue;
-import net.minecraft.client.gui.GuiComponent;
+import net.minecraft.Util;
+import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.chat.NarratorChatListener;
 import net.minecraft.client.gui.components.AbstractButton;
+import net.minecraft.client.gui.components.Button;
 import net.minecraft.client.gui.screens.Screen;
-import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
 import net.minecraft.client.resources.language.I18n;
 import net.minecraft.network.chat.TextComponent;
 import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.util.Mth;
 import net.minecraft.util.Tuple;
+import org.apache.commons.lang3.mutable.MutableLong;
 import org.jetbrains.annotations.ApiStatus;
 
 import java.util.Comparator;
@@ -62,9 +67,7 @@ public class CreditsScreen extends Screen {
     @Override
     public boolean keyPressed(int int_1, int int_2, int int_3) {
         if (int_1 == 256 && this.shouldCloseOnEsc()) {
-            this.minecraft.setScreen(parent);
-            if (parent instanceof AbstractContainerScreen)
-                ScreenHelper.getLastOverlay().init();
+            openPrevious();
             return true;
         }
         return super.keyPressed(int_1, int_2, int_3);
@@ -117,14 +120,18 @@ public class CreditsScreen extends Screen {
         entryListWidget.creditsAddEntry(new CreditsEntryListWidget.LinkItem(new ImmutableLiteralText("Visit the project page at CurseForge."), "https://www.curseforge.com/minecraft/mc-mods/roughly-enough-items", entryListWidget.getItemWidth(), false));
         entryListWidget.creditsAddEntry(new CreditsEntryListWidget.LinkItem(new ImmutableLiteralText("Support the project via Patreon!"), "https://patreon.com/shedaniel", entryListWidget.getItemWidth(), true));
         entryListWidget.creditsAddEntry(new TextCreditsItem(NarratorChatListener.NO_TITLE));
-        children.add(buttonDone = new AbstractButton(width / 2 - 100, height - 26, 200, 20, new TranslatableComponent("gui.done")) {
-            @Override
-            public void onPress() {
-                CreditsScreen.this.minecraft.setScreen(parent);
-                if (parent instanceof AbstractContainerScreen)
-                    ScreenHelper.getLastOverlay().init();
-            }
-        });
+        children.add(buttonDone = new Button(width / 2 - 100, height - 26, 200, 20, new TranslatableComponent("gui.done"), button -> openPrevious()));
+    }
+    
+    private void openPrevious() {
+        MutableLong current = new MutableLong(0);
+        Minecraft.getInstance().setScreen(new TransformingScreen(true, parent,
+                this,
+                () -> current.setValue(current.getValue() == 0 ? Util.getMillis() + (ConfigObject.getInstance().isReducedMotion() ? -3000 : 0) : current.getValue()),
+                () -> EasingMethod.EasingMethodImpl.EXPO.apply(Mth.clamp((Util.getMillis() - current.getValue()) / 750.0, 0, 1))
+                      * Minecraft.getInstance().getWindow().getGuiScaledWidth(),
+                () -> 0,
+                () -> Util.getMillis() - current.getValue() > 800));
     }
     
     @Override

+ 3 - 5
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/gui/widget/EntryListWidget.java

@@ -550,16 +550,14 @@ public class EntryListWidget extends WidgetWithBounds {
     @Override
     public boolean mouseReleased(double mouseX, double mouseY, int button) {
         if (containsMouse(mouseX, mouseY)) {
-            for (Widget widget : children())
-                if (widget.mouseReleased(mouseX, mouseY, button))
-                    return true;
             LocalPlayer player = minecraft.player;
             if (ClientHelper.getInstance().isCheating() && player != null && player.inventory != null && !player.inventory.getCarried().isEmpty() && RoughlyEnoughItemsCore.canDeleteItems()) {
                 ClientHelper.getInstance().sendDeletePacket();
                 return true;
             }
-            if (player != null && player.inventory != null && !player.inventory.getCarried().isEmpty() && RoughlyEnoughItemsCore.hasPermissionToUsePackets())
-                return false;
+            for (Widget widget : children())
+                if (widget.mouseReleased(mouseX, mouseY, button))
+                    return true;
         }
         return false;
     }

+ 25 - 6
RoughlyEnoughItems-runtime/src/main/java/me/shedaniel/rei/impl/ConfigManagerImpl.java

@@ -221,7 +221,16 @@ public class ConfigManagerImpl implements ConfigManager {
                 screen.setParent(parent);
                 return screen;
             }
-            ConfigScreenProvider<ConfigObjectImpl> provider = (ConfigScreenProvider<ConfigObjectImpl>) AutoConfig.getConfigScreen(ConfigObjectImpl.class, parent);
+            TransformingScreen parentTranslated;
+            {
+                MutableLong current = new MutableLong(0);
+                parentTranslated = new TransformingScreen(true, null,
+                        null,
+                        () -> current.setValue(current.getValue() == 0 ? Util.getMillis() + (getConfig().isReducedMotion() ? -3000 : 0) : current.getValue()),
+                        () -> 0, () -> (EasingMethod.EasingMethodImpl.EXPO.apply(Mth.clamp((Util.getMillis() - current.getValue()) / 750.0, 0, 1)))
+                                       * Minecraft.getInstance().getWindow().getGuiScaledHeight(), () -> Util.getMillis() - current.getValue() > 800);
+            }
+            ConfigScreenProvider<ConfigObjectImpl> provider = (ConfigScreenProvider<ConfigObjectImpl>) AutoConfig.getConfigScreen(ConfigObjectImpl.class, parentTranslated);
             provider.setI13nFunction(manager -> "config.roughlyenoughitems");
             provider.setOptionFunction((baseI13n, field) -> field.isAnnotationPresent(ConfigObjectImpl.DontApplyFieldName.class) ? baseI13n : String.format("%s.%s", baseI13n, field.getName()));
             provider.setCategoryFunction((baseI13n, categoryName) -> String.format("%s.%s", baseI13n, categoryName));
@@ -233,7 +242,15 @@ public class ConfigManagerImpl implements ConfigManager {
                 }
                 return builder.setAfterInitConsumer(screen -> {
                     ((ScreenHooks) screen).cloth$addButtonWidget(new Button(screen.width - 104, 4, 100, 20, new TranslatableComponent("text.rei.credits"), button -> {
-                        Minecraft.getInstance().setScreen(new CreditsScreen(screen));
+                        MutableLong current = new MutableLong(0);
+                        CreditsScreen creditsScreen = new CreditsScreen(screen);
+                        Minecraft.getInstance().setScreen(new TransformingScreen(false, creditsScreen,
+                                screen,
+                                () -> current.setValue(current.getValue() == 0 ? Util.getMillis() + (getConfig().isReducedMotion() ? -3000 : 0) : current.getValue()),
+                                () -> (1 - EasingMethod.EasingMethodImpl.EXPO.apply(Mth.clamp((Util.getMillis() - current.getValue()) / 750.0, 0, 1)))
+                                      * Minecraft.getInstance().getWindow().getGuiScaledWidth() * 1.3,
+                                () -> 0,
+                                () -> Util.getMillis() - current.getValue() > 800));
                     }));
                 }).setSavingRunnable(() -> {
                     saveConfig();
@@ -242,12 +259,14 @@ public class ConfigManagerImpl implements ConfigManager {
                         ContainerScreenOverlay.getEntryListWidget().updateSearch(ScreenHelper.getSearchField().getText(), true);
                 }).build();
             });
-            MutableLong current = new MutableLong();
-            return new TransformingScreen(provider.get(),
+            Screen configScreen = provider.get();
+            parentTranslated.setLastScreen(configScreen);
+            MutableLong current = new MutableLong(0);
+            return new TransformingScreen(false, configScreen,
                     parent,
-                    () -> current.setValue(Util.getMillis() + (getConfig().isReducedMotion() ? -3000 : 0)),
+                    () -> current.setValue(current.getValue() == 0 ? Util.getMillis() + (getConfig().isReducedMotion() ? -3000 : 0) : current.getValue()),
                     () -> 0, () -> (1 - EasingMethod.EasingMethodImpl.EXPO.apply(Mth.clamp((Util.getMillis() - current.getValue()) / 750.0, 0, 1)))
-                                   * Minecraft.getInstance().getWindow().getGuiScaledHeight() * 1.3);
+                                   * Minecraft.getInstance().getWindow().getGuiScaledHeight() * 1.3, () -> Util.getMillis() - current.getValue() > 800);
         } catch (Exception e) {
             e.printStackTrace();
         }

+ 1 - 1
gradle.properties

@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx3G
-mod_version=5.8.3
+mod_version=5.8.4
 supported_version=1.16.2/3/4
 minecraft_version=1.16.4
 fabricloader_version=0.10.6+build.214