102 lines
3 KiB
Java
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);
|
|
});
|
|
}
|
|
|
|
}
|