CreateMod/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java
2021-04-23 18:11:32 +02:00

102 lines
3 KiB
Java

package com.simibubi.create.foundation.gui;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
public class ScreenOpener {
private static final Deque<Screen> backStack = new ArrayDeque<>();
private static Screen backSteppedFrom = null;
public static void open(Screen screen) {
open(Minecraft.getInstance().currentScreen, screen);
}
public static void open(@Nullable Screen current, Screen toOpen) {
backSteppedFrom = null;
if (current != null) {
if (backStack.size() >= 15) // don't go deeper than 15 steps
backStack.pollLast();
backStack.push(current);
} else
backStack.clear();
openScreen(toOpen);
}
public static void openPreviousScreen(Screen current, Optional<NavigatableSimiScreen> screenWithContext) {
if (backStack.isEmpty())
return;
backSteppedFrom = current;
Screen previousScreen = backStack.pop();
if (previousScreen instanceof NavigatableSimiScreen) {
NavigatableSimiScreen previousAbstractSimiScreen = (NavigatableSimiScreen) previousScreen;
screenWithContext.ifPresent(s -> s.shareContextWith(previousAbstractSimiScreen));
previousAbstractSimiScreen.transition.startWithValue(-0.1)
.chase(-1, .4f, LerpedFloat.Chaser.EXP);
}
openScreen(previousScreen);
}
// transitions are only supported in simiScreens atm. they take care of all the
// rendering for it
public static void transitionTo(NavigatableSimiScreen screen) {
if (tryBackTracking(screen))
return;
screen.transition.startWithValue(0.1)
.chase(1, .4f, LerpedFloat.Chaser.EXP);
open(screen);
}
private static boolean tryBackTracking(NavigatableSimiScreen screen) {
List<Screen> screenHistory = getScreenHistory();
if (screenHistory.isEmpty())
return false;
Screen previouslyRenderedScreen = screenHistory.get(0);
if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen))
return false;
if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen))
return false;
openPreviousScreen(Minecraft.getInstance().currentScreen, Optional.of(screen));
return true;
}
public static void clearStack() {
backStack.clear();
}
public static List<Screen> getScreenHistory() {
return new ArrayList<>(backStack);
}
@Nullable
public static Screen getPreviouslyRenderedScreen() {
return backSteppedFrom != null ? backSteppedFrom : backStack.peek();
}
private static void openScreen(Screen screen) {
Minecraft.getInstance()
.enqueue(() -> {
Minecraft.getInstance()
.displayGuiScreen(screen);
Screen previouslyRenderedScreen = getPreviouslyRenderedScreen();
if (previouslyRenderedScreen != null && screen instanceof NavigatableSimiScreen)
previouslyRenderedScreen.init(Minecraft.getInstance(), screen.width, screen.height);
});
}
}