aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/src/main/java')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java38
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java81
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java74
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabContainerWidget.java179
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabWidget.java41
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/AsyncSearchManager.java2
7 files changed, 246 insertions, 171 deletions
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 a18d7aeab..d59ece66c 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
@@ -684,7 +684,7 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
@Comment("Declares how the scrollbar in composite screen should act.") private boolean compositeScrollBarPermanent = false;
private boolean toastDisplayedOnCopyIdentifier = true;
@Comment("Declares whether REI should use compact tabs for categories.") private boolean useCompactTabs = true;
- @Comment("Declares whether REI should use compact tab buttons for categories.") private boolean useCompactTabButtons = false;
+ @Comment("Declares whether REI should use compact tab buttons for categories.") @ConfigEntry.Gui.Excluded private boolean useCompactTabButtons = false;
}
public static class Search {
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
index b2173b0c6..28050a6e3 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/AbstractDisplayViewingScreen.java
@@ -29,6 +29,7 @@ import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.datafixers.util.Pair;
import com.mojang.math.Matrix4f;
import dev.architectury.fluid.FluidStack;
+import dev.architectury.utils.value.IntValue;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.REIRuntime;
import me.shedaniel.rei.api.client.config.ConfigObject;
@@ -50,6 +51,7 @@ import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.impl.client.REIRuntimeImpl;
import me.shedaniel.rei.impl.client.gui.widget.EntryWidget;
+import me.shedaniel.rei.impl.client.gui.widget.TabContainerWidget;
import me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget;
import me.shedaniel.rei.impl.display.DisplaySpec;
import net.minecraft.ChatFormatting;
@@ -76,17 +78,17 @@ import java.util.stream.Stream;
public abstract class AbstractDisplayViewingScreen extends Screen implements DisplayScreen {
protected final Map<DisplayCategory<?>, List<DisplaySpec>> categoryMap;
protected final List<DisplayCategory<?>> categories;
+ protected final TabContainerWidget tabs = new TabContainerWidget();
protected List<EntryStack<?>> ingredientStackToNotice = new ArrayList<>();
protected List<EntryStack<?>> resultStackToNotice = new ArrayList<>();
protected int selectedCategoryIndex = 0;
- protected int tabsPerPage;
+ protected int categoryPages = -1;
protected Rectangle bounds;
- protected AbstractDisplayViewingScreen(Map<DisplayCategory<?>, List<DisplaySpec>> categoryMap, @Nullable CategoryIdentifier<?> category, int tabsPerPage) {
+ protected AbstractDisplayViewingScreen(Map<DisplayCategory<?>, List<DisplaySpec>> categoryMap, @Nullable CategoryIdentifier<?> category) {
super(Component.empty());
this.categoryMap = categoryMap;
this.categories = Lists.newArrayList(categoryMap.keySet());
- this.tabsPerPage = tabsPerPage;
if (category != null) {
selectCategory(category, false);
}
@@ -105,6 +107,7 @@ public abstract class AbstractDisplayViewingScreen extends Screen implements Dis
}
recalculateCategoryPage();
+ this.tabs.updateScroll(categories, selectedCategoryIndex, !init ? 0 : 300);
if (init) {
init();
@@ -112,6 +115,35 @@ public abstract class AbstractDisplayViewingScreen extends Screen implements Dis
}
@Override
+ public void recalculateCategoryPage() {
+ this.categoryPages = -1;
+ }
+
+ protected void initTabs() {
+ this.tabs.init(new Rectangle(bounds.x, bounds.y - 28, bounds.width, 28), categories, new IntValue() {
+ @Override
+ public void accept(int value) {
+ AbstractDisplayViewingScreen.this.categoryPages = value;
+ }
+
+ @Override
+ public int getAsInt() {
+ return AbstractDisplayViewingScreen.this.categoryPages;
+ }
+ }, new IntValue() {
+ @Override
+ public void accept(int value) {
+ AbstractDisplayViewingScreen.this.selectCategory(categories.get(value).getCategoryIdentifier());
+ }
+
+ @Override
+ public int getAsInt() {
+ return selectedCategoryIndex;
+ }
+ }, AbstractDisplayViewingScreen.this::init);
+ }
+
+ @Override
public List<GuiEventListener> children() {
List<? extends GuiEventListener> children = super.children();
children.sort(Comparator.comparingDouble(value -> value instanceof Widget widget ? widget.getZRenderingPriority() : 0).reversed());
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java
index e6c9d9348..050b91e35 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java
@@ -44,16 +44,12 @@ import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.display.Display;
import me.shedaniel.rei.api.common.entry.EntryIngredient;
import me.shedaniel.rei.impl.client.REIRuntimeImpl;
-import me.shedaniel.rei.impl.client.gui.InternalTextures;
import me.shedaniel.rei.impl.client.gui.widget.EntryWidget;
import me.shedaniel.rei.impl.client.gui.widget.InternalWidgets;
-import me.shedaniel.rei.impl.client.gui.widget.TabWidget;
import me.shedaniel.rei.impl.display.DisplaySpec;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.GuiEventListener;
-import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.Component;
-import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -68,7 +64,6 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
private final List<Widget> widgets = Lists.newArrayList();
private final List<Button> buttonList = Lists.newArrayList();
private final List<DisplayRenderer> displayRenderers = Lists.newArrayList();
- private final List<TabWidget> tabs = Lists.newArrayList();
public Rectangle scrollListBounds;
private int selectedRecipeIndex = 0;
private final ScrollingContainer scrolling = new ScrollingContainer() {
@@ -89,15 +84,14 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
private float scrollBarAlpha = 0;
private float scrollBarAlphaFuture = 0;
private long scrollBarAlphaFutureTime = -1;
- private int tabsPage = -1;
public CompositeDisplayViewingScreen(Map<DisplayCategory<?>, List<DisplaySpec>> categoryMap, @Nullable CategoryIdentifier<?> category) {
- super(categoryMap, category, 8);
+ super(categoryMap, category);
}
@Override
public void recalculateCategoryPage() {
- this.tabsPage = -1;
+ super.recalculateCategoryPage();
this.selectedRecipeIndex = 0;
}
@@ -112,19 +106,17 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
this.widgets.clear();
this.buttonList.clear();
this.displayRenderers.clear();
- this.tabs.clear();
int largestWidth = width - 100;
int largestHeight = height - 40;
DisplayCategory<Display> category = getCurrentCategory();
DisplaySpec display = categoryMap.get(category).get(selectedRecipeIndex);
int guiWidth = Mth.clamp(category.getDisplayWidth(display.provideInternalDisplay()) + 30, 0, largestWidth) + 100;
int guiHeight = Mth.clamp(category.getDisplayHeight() + 40, 166, largestHeight);
- this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - tabButtonsSize * 2d) / tabSize));
- if (this.tabsPage == -1) {
- this.tabsPage = selectedCategoryIndex / tabsPerPage;
- }
this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - guiHeight / 2, guiWidth, guiHeight);
+ this.initTabs();
+ this.widgets.addAll(this.tabs.widgets());
+
List<EntryIngredient> workstations = CategoryRegistry.getInstance().get(category.getCategoryIdentifier()).getWorkstations();
if (!workstations.isEmpty()) {
int ww = Mth.floor((bounds.width - 16) / 18f);
@@ -190,66 +182,12 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
.onRender((matrices, button) -> button.setEnabled(selectedRecipeIndex != finalIndex)));
index++;
}
- int tabV = isCompactTabs ? 166 : 192;
- for (int i = 0; i < tabsPerPage; i++) {
- int j = i + tabsPage * tabsPerPage;
- if (categories.size() > j) {
- DisplayCategory<?> tabCategory = categories.get(j);
- TabWidget tab;
- tabs.add(tab = TabWidget.create(i, tabSize, bounds.x + bounds.width / 2 - Math.min(categories.size() - tabsPage * tabsPerPage, tabsPerPage) * tabSize / 2, bounds.y, 0, tabV, widget -> {
- Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
- if (widget.selected)
- return false;
- selectCategory(tabCategory.getCategoryIdentifier());
- return true;
- }));
- tab.setRenderer(tabCategory, tabCategory.getIcon(), tabCategory.getTitle(), j == selectedCategoryIndex);
- }
- }
- Button tabLeft, tabRight;
- this.widgets.add(tabLeft = Widgets.createButton(new Rectangle(bounds.x + 2, bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), Component.literal(""))
- .onClick(button -> {
- tabsPage--;
- if (tabsPage < 0)
- tabsPage = Mth.ceil(categories.size() / (float) tabsPerPage) - 1;
- CompositeDisplayViewingScreen.this.init();
- })
- .tooltipLine(Component.translatable("text.rei.previous_page"))
- .enabled(categories.size() > tabsPerPage));
- this.widgets.add(tabRight = Widgets.createButton(new Rectangle(bounds.x + bounds.width - (isCompactTabButtons ? tabButtonsSize + 2 : tabButtonsSize + 3), bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), Component.literal(""))
- .onClick(button -> {
- tabsPage++;
- if (tabsPage > Mth.ceil(categories.size() / (float) tabsPerPage) - 1)
- tabsPage = 0;
- CompositeDisplayViewingScreen.this.init();
- })
- .tooltipLine(Component.translatable("text.rei.next_page"))
- .enabled(categories.size() > tabsPerPage));
- this.widgets.add(Widgets.withTranslate(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
- Rectangle tabLeftBounds = tabLeft.getBounds();
- Rectangle tabRightBounds = tabRight.getBounds();
- if (isCompactTabButtons) {
- matrices.pushPose();
- matrices.translate(0, 0.5, 0);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_LEFT_SMALL_TEXTURE);
- blit(matrices, tabLeftBounds.x + 2, tabLeftBounds.y + 2, 0, 0, 6, 6, 6, 6);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_RIGHT_SMALL_TEXTURE);
- blit(matrices, tabRightBounds.x + 2, tabRightBounds.y + 2, 0, 0, 6, 6, 6, 6);
- matrices.popPose();
- } else {
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_LEFT_TEXTURE);
- blit(matrices, tabLeftBounds.x + 4, tabLeftBounds.y + 4, 0, 0, 8, 8, 8, 8);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_RIGHT_TEXTURE);
- blit(matrices, tabRightBounds.x + 4, tabRightBounds.y + 4, 0, 0, 8, 8, 8, 8);
- }
- }), 0, 0, 1));
this.widgets.add(Widgets.createClickableLabel(new Point(bounds.x + 4 + scrollListBounds.width / 2, bounds.y + 6), categories.get(selectedCategoryIndex).getTitle(), label -> {
ViewSearchBuilder.builder().addAllCategories().open();
}).tooltip(Component.translatable("text.rei.view_all_categories")).noShadow().color(0xFF404040, 0xFFBBBBBB).hoveredColor(0xFF0041FF, 0xFFFFBD4D));
this.children().addAll(buttonList);
- this.widgets.addAll(tabs);
this.children().addAll(widgets);
}
@@ -316,15 +254,6 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
}
}
REIRuntimeImpl.isWithinRecipeViewingScreen = false;
- int tabSize = ConfigObject.getInstance().isUsingCompactTabs() ? 24 : 28;
- if (mouseX >= bounds.x && mouseX <= bounds.getMaxX() && mouseY >= bounds.y - tabSize && mouseY < bounds.y) {
- if (amount < 0) selectedCategoryIndex++;
- else if (amount > 0) selectedCategoryIndex--;
- if (selectedCategoryIndex < 0) selectedCategoryIndex = categories.size() - 1;
- else if (selectedCategoryIndex >= categories.size()) selectedCategoryIndex = 0;
- selectCategory(categories.get(selectedCategoryIndex).getCategoryIdentifier());
- return true;
- }
if (bounds.contains(PointHelper.ofMouse())) {
if (amount < 0 && categoryMap.get(categories.get(selectedCategoryIndex)).size() > 1) {
selectedRecipeIndex++;
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 5817338c3..37bd9d0f0 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
@@ -66,9 +66,7 @@ import net.minecraft.client.gui.screens.ConfirmScreen;
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;
import net.minecraft.network.chat.Component;
-import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -81,13 +79,12 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
private final Map<Rectangle, Pair<DisplaySpec, List<Widget>>> recipeBounds = Maps.newHashMap();
private List<Widget> widgets = Lists.newArrayList();
public int page;
- public int categoryPages = -1;
@Nullable
private Panel workingStationsBaseWidget;
private Button recipeBack, recipeNext, categoryBack, categoryNext;
public DefaultDisplayViewingScreen(Map<DisplayCategory<?>, List<DisplaySpec>> categoriesMap, @Nullable CategoryIdentifier<?> category) {
- super(categoriesMap, category, 5);
+ super(categoriesMap, category);
this.bounds = new Rectangle(0, 0, 176, 150);
}
@@ -141,37 +138,12 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
int guiWidth = Math.max(maxWidthDisplay + 10 + 14 + 14, 190);
this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - maxHeight / 2, guiWidth, maxHeight);
- boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs();
- boolean isCompactTabButtons = ConfigObject.getInstance().isUsingCompactTabButtons();
- int tabButtonsSize = isCompactTabButtons ? 10 : 16;
- int tabSize = isCompactTabs ? 24 : 28;
- this.tabsPerPage = Math.max(5, Mth.floor((guiWidth - tabButtonsSize * 2d) / tabSize));
- if (this.categoryPages == -1) {
- this.categoryPages = Math.max(0, selectedCategoryIndex / tabsPerPage);
- }
+ this.initTabs();
+ this.widgets.addAll(this.tabs.widgets());
this.page = Mth.clamp(page, 0, getCurrentTotalPages() - 1);
- Button tabLeft, tabRight;
- this.widgets.add(tabLeft = Widgets.createButton(new Rectangle(bounds.x, bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), Component.literal(""))
- .onClick(button -> {
- categoryPages--;
- if (categoryPages < 0)
- categoryPages = Mth.ceil(categories.size() / (float) tabsPerPage) - 1;
- DefaultDisplayViewingScreen.this.init();
- })
- .tooltipLine(Component.translatable("text.rei.previous_page"))
- .enabled(categories.size() > tabsPerPage));
- this.widgets.add(tabRight = Widgets.createButton(new Rectangle(bounds.x + bounds.width - tabButtonsSize - (isCompactTabButtons ? 0 : 1), bounds.y - (isCompactTabButtons ? 16 : 20), tabButtonsSize, tabButtonsSize), Component.literal(""))
- .onClick(button -> {
- categoryPages++;
- if (categoryPages > Mth.ceil(categories.size() / (float) tabsPerPage) - 1)
- categoryPages = 0;
- DefaultDisplayViewingScreen.this.init();
- })
- .tooltipLine(Component.translatable("text.rei.next_page"))
- .enabled(categories.size() > tabsPerPage));
- this.widgets.add(categoryBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 5, 12, 12), Component.literal(""))
- .onClick(button -> previousCategory()).tooltipLine(Component.translatable("text.rei.previous_category")));
+ this.widgets.add(categoryBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 5, 12, 12), ImmutableTextComponent.EMPTY)
+ .onClick(button -> previousCategory()).tooltipLine(new TranslatableComponent("text.rei.previous_category")));
this.widgets.add(Widgets.createClickableLabel(new Point(bounds.getCenterX(), bounds.getY() + 7), getCurrentCategory().getTitle(), clickableLabelWidget -> {
ViewSearchBuilder.builder().addAllCategories().open();
}).tooltip(Component.translatable("text.rei.view_all_categories")));
@@ -180,22 +152,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
this.categoryBack.setEnabled(categories.size() > 1);
this.categoryNext.setEnabled(categories.size() > 1);
this.widgets.add(Widgets.withTranslate(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
- Rectangle tabLeftBounds = tabLeft.getBounds();
- Rectangle tabRightBounds = tabRight.getBounds();
- if (isCompactTabButtons) {
- matrices.pushPose();
- matrices.translate(0, 0.5, 0);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_LEFT_SMALL_TEXTURE);
- blit(matrices, tabLeftBounds.x + 2, tabLeftBounds.y + 2, 0, 0, 6, 6, 6, 6);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_RIGHT_SMALL_TEXTURE);
- blit(matrices, tabRightBounds.x + 2, tabRightBounds.y + 2, 0, 0, 6, 6, 6, 6);
- matrices.popPose();
- } else {
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_LEFT_TEXTURE);
- blit(matrices, tabLeftBounds.x + 4, tabLeftBounds.y + 4, 0, 0, 8, 8, 8, 8);
- RenderSystem.setShaderTexture(0, InternalTextures.ARROW_RIGHT_TEXTURE);
- blit(matrices, tabRightBounds.x + 4, tabRightBounds.y + 4, 0, 0, 8, 8, 8, 8);
- }
Rectangle recipeBackBounds = recipeBack.getBounds();
Rectangle recipeNextBounds = recipeNext.getBounds();
Rectangle categoryBackBounds = categoryBack.getBounds();
@@ -242,20 +198,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
}).tooltipLine(Component.translatable("text.rei.next_page")));
this.recipeBack.setEnabled(getCurrentTotalPages() > 1);
this.recipeNext.setEnabled(getCurrentTotalPages() > 1);
- for (int id = 0; id < tabsPerPage; id++) {
- int tabIndex = id + categoryPages * tabsPerPage;
- if (categories.size() > tabIndex) {
- TabWidget tab;
- widgets.add(tab = TabWidget.create(id, tabSize, bounds.x + bounds.width / 2 - Math.min(categories.size() - categoryPages * tabsPerPage, tabsPerPage) * tabSize / 2, bounds.y, 0, isCompactTabs ? 166 : 192, widget -> {
- Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
- if (widget.getId() + categoryPages * tabsPerPage == selectedCategoryIndex)
- return false;
- selectCategory(categories.get(widget.getId() + categoryPages * tabsPerPage).getCategoryIdentifier());
- return true;
- }));
- tab.setRenderer(categories.get(tabIndex), categories.get(tabIndex).getIcon(), categories.get(tabIndex).getTitle(), tab.getId() + categoryPages * tabsPerPage == selectedCategoryIndex);
- }
- }
initDisplays();
widgets = CollectionUtils.map(widgets, widget -> Widgets.withTranslate(widget, 0, 0, 10));
widgets.add(Widgets.withTranslate(new PanelWidget(bounds), 0, 0, 5));
@@ -514,12 +456,6 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
else if (amount < 0 && recipeNext.isEnabled())
recipeNext.onClick();
}
- if ((new Rectangle(bounds.x, bounds.y - 28, bounds.width, 28)).contains(PointHelper.ofMouse())) {
- if (amount > 0 && categoryBack.isEnabled())
- categoryBack.onClick();
- else if (amount < 0 && categoryNext.isEnabled())
- categoryNext.onClick();
- }
return super.mouseScrolled(mouseX, mouseY, amount);
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabContainerWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabContainerWidget.java
new file mode 100644
index 000000000..b204b73ec
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabContainerWidget.java
@@ -0,0 +1,179 @@
+package me.shedaniel.rei.impl.client.gui.widget;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import dev.architectury.utils.value.IntValue;
+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.config.ConfigObject;
+import me.shedaniel.rei.api.client.gui.widgets.CloseableScissors;
+import me.shedaniel.rei.api.client.gui.widgets.DelegateWidget;
+import me.shedaniel.rei.api.client.gui.widgets.Widget;
+import me.shedaniel.rei.api.client.gui.widgets.Widgets;
+import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
+import net.minecraft.client.gui.GuiComponent;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.util.Mth;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class TabContainerWidget extends GuiComponent {
+ private final Rectangle bounds = new Rectangle();
+ private final List<Widget> widgets = new ArrayList<>();
+ private final NumberAnimator<Double> scrollAnimator = ValueAnimator.ofDouble();
+ private int tabsPerPage = 5;
+
+ public TabContainerWidget() {
+ }
+
+ public void setBounds(Rectangle bounds) {
+ this.bounds.setBounds(bounds);
+ }
+
+ public void updateScroll(List<DisplayCategory<?>> categories, int selectedCategory, long duration) {
+ boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs();
+ int tabSize = isCompactTabs ? 24 : 28;
+
+ double curr = scrollAnimator.doubleValue() % (tabSize * categories.size());
+ double newValue1 = selectedCategory * tabSize + Math.floor(scrollAnimator.doubleValue() / (tabSize * categories.size())) * (tabSize * categories.size());
+ double newValue2 = newValue1 - (tabSize * categories.size());
+ double newValue3 = newValue1 + (tabSize * categories.size());
+
+ Stream.of(newValue1, newValue2, newValue3).min(Comparator.comparingDouble(value -> Math.abs(value - scrollAnimator.doubleValue()))).ifPresent(newValue -> {
+ scrollAnimator.setTo(newValue, duration);
+ });
+ }
+
+ public void init(Rectangle bounds, List<DisplayCategory<?>> categories, IntValue categoryPages, IntValue selectedCategory, Runnable reInit) {
+ this.setBounds(bounds);
+ this.widgets.clear();
+
+ boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs();
+ int tabSize = isCompactTabs ? 24 : 28;
+ this.tabsPerPage = Mth.floor((this.bounds.getWidth() - 10) / tabSize);
+
+ if (categoryPages.getAsInt() == -1) {
+ categoryPages.accept(Math.max(0, selectedCategory.getAsInt() / tabsPerPage()));
+ }
+
+ this.widgets.add(new Widget() {
+ @Override
+ public void render(PoseStack poses, int mouseX, int mouseY, float delta) {
+ scrollAnimator.update(delta);
+ int absLeft = bounds.x + bounds.width / 2 - tabsPerPage() * tabSize / 2;
+ int left;
+ if (categories.size() > tabsPerPage()) {
+ left = bounds.x + bounds.width / 2 - tabSize / 2 - (int) Math.round(scrollAnimator.doubleValue());
+ updateScroll(categories, selectedCategory.getAsInt(), 300);
+ } else {
+ left = bounds.x + bounds.width / 2 - categories.size() * tabSize / 2;
+ }
+ int passed = 0;
+ for (TabWidget tab : Widgets.<TabWidget>walk(TabContainerWidget.this.widgets(), widget -> widget instanceof TabWidget)) {
+ if (categories.size() <= tabsPerPage()) {
+ tab.getBounds().x = left;
+ left += tabSize;
+ } else {
+ if (left > bounds.getMaxX()) {
+ while (left > bounds.getMaxX()) {
+ left -= tabSize * categories.size();
+ }
+ tab.getBounds().x = left;
+ left += tabSize;
+ } else if (left + tabSize < bounds.x) {
+ while (left + tabSize < bounds.x) {
+ left += tabSize * categories.size();
+ }
+ tab.getBounds().x = left;
+ left += tabSize;
+ } else {
+ tab.getBounds().x = left;
+ left += tabSize;
+ }
+ }
+ passed++;
+
+ if (tab.getBounds().x > bounds.getMaxX() || tab.getBounds().getMaxX() < bounds.x) {
+ tab.getBounds().x = -1000;
+ }
+
+ if (tab.getBounds().getCenterX() <= absLeft + 20) {
+ tab.opacity = 1 - (absLeft + 20 - tab.getBounds().getCenterX()) / 20f;
+ tab.opacity = (float) Math.pow(Mth.clamp(tab.opacity, 0, 1), 0.9);
+ } else if (tab.getBounds().getCenterX() >= absLeft + tabsPerPage() * tabSize - 20) {
+ tab.opacity = 1 - (tab.getBounds().getCenterX() - (absLeft + tabsPerPage() * tabSize - 20)) / 20f;
+ tab.opacity = (float) Math.pow(Mth.clamp(tab.opacity, 0, 1), 0.9);
+ } else {
+ tab.opacity = 1;
+ }
+
+ if (tab.opacity < 0.1) {
+ tab.opacity = 0;
+ }
+ }
+ }
+
+ @Override
+ public double getZRenderingPriority() {
+ return -1000;
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return List.of();
+ }
+
+ @Override
+ public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ if (TabContainerWidget.this.bounds.contains(mouseX, mouseY) && categories.size() > 1) {
+ int currentCategoryIndex = selectedCategory.getAsInt();
+ if (amount > 0) {
+ currentCategoryIndex--;
+ if (currentCategoryIndex < 0)
+ currentCategoryIndex = categories.size() - 1;
+ } else {
+ currentCategoryIndex++;
+ if (currentCategoryIndex >= categories.size())
+ currentCategoryIndex = 0;
+ }
+ selectedCategory.accept(currentCategoryIndex);
+
+ return true;
+ }
+ return false;
+ }
+ });
+
+ for (int id = 0; id < categories.size(); id++) {
+ int tabIndex = id;
+ DisplayCategory<?> category = categories.get(tabIndex);
+ TabWidget tab = TabWidget.create(id, tabSize, bounds.x + bounds.width / 2 - tabsPerPage * tabSize / 2, bounds.getMaxY(), 0, isCompactTabs ? 166 : 192, widget -> {
+ Widgets.produceClickSound();
+ if (tabIndex == selectedCategory.getAsInt())
+ return false;
+ selectedCategory.accept(tabIndex);
+ return true;
+ });
+ tab.setRenderer(category, category.getIcon(), category.getTitle(), tabIndex == selectedCategory.getAsInt());
+ this.widgets.add(new DelegateWidget(tab) {
+ @Override
+ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) {
+ try (CloseableScissors scissors = Widget.scissor(poseStack, new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height + 4))) {
+ super.render(poseStack, mouseX, mouseY, delta);
+ }
+ }
+ });
+ }
+ }
+
+ public List<Widget> widgets() {
+ return this.widgets;
+ }
+
+ public int tabsPerPage() {
+ return tabsPerPage;
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabWidget.java
index a1e2c0604..071ad8e2e 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabWidget.java
@@ -36,6 +36,7 @@ import me.shedaniel.rei.api.client.gui.drag.DraggableStack;
import me.shedaniel.rei.api.client.gui.drag.DraggableStackProviderWidget;
import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult;
import me.shedaniel.rei.api.client.gui.drag.DraggingContext;
+import me.shedaniel.rei.api.client.gui.widgets.CloseableScissors;
import me.shedaniel.rei.api.client.gui.widgets.Tooltip;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
@@ -56,19 +57,18 @@ import java.util.function.Predicate;
public class TabWidget extends WidgetWithBounds implements DraggableStackProviderWidget {
public boolean selected = false;
public Renderer renderer;
- public int id;
public Component categoryName;
public Rectangle bounds;
public DisplayCategory<?> category;
public int u, v;
+ public float opacity = 1.0F;
@Nullable
private Predicate<TabWidget> onClick;
private final NumberAnimator<Float> darkBackgroundAlpha = ValueAnimator.ofFloat()
.withConvention(() -> REIRuntime.getInstance().isDarkThemeEnabled() ? 1.0F : 0.0F, ValueAnimator.typicalTransitionTime())
.asFloat();
- private TabWidget(int id, Rectangle bounds, int u, int v, @Nullable Predicate<TabWidget> onClick) {
- this.id = id;
+ private TabWidget(Rectangle bounds, int u, int v, @Nullable Predicate<TabWidget> onClick) {
this.bounds = bounds;
this.u = u;
this.v = v;
@@ -77,7 +77,7 @@ public class TabWidget extends WidgetWithBounds implements DraggableStackProvide
@ApiStatus.Internal
public static TabWidget create(int id, int tabSize, int leftX, int bottomY, int u, int v, @Nullable Predicate<TabWidget> onClick) {
- return new TabWidget(id, new Rectangle(leftX + id * tabSize, bottomY - tabSize, tabSize, tabSize), u, v, onClick);
+ return new TabWidget(new Rectangle(leftX + id * tabSize, bottomY - tabSize, tabSize, tabSize), u, v, onClick);
}
@Override
@@ -96,10 +96,6 @@ public class TabWidget extends WidgetWithBounds implements DraggableStackProvide
return selected;
}
- public int getId() {
- return id;
- }
-
public boolean isShown() {
return renderer != null;
}
@@ -111,20 +107,23 @@ public class TabWidget extends WidgetWithBounds implements DraggableStackProvide
@Override
public void render(PoseStack matrices, int mouseX, int mouseY, float delta) {
+ if (bounds.getMaxX() < 0 || opacity == 0) return;
if (renderer != null) {
- darkBackgroundAlpha.update(delta);
- RenderSystem.enableBlend();
- RenderSystem.blendFuncSeparate(770, 771, 1, 0);
- RenderSystem.blendFunc(770, 771);
- RenderSystem.setShaderTexture(0, InternalTextures.CHEST_GUI_TEXTURE);
- RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
- this.blit(matrices, bounds.x, bounds.y + 2, u + (selected ? bounds.width : 0), v, bounds.width, (selected ? bounds.height + 2 : bounds.height - 1));
- RenderSystem.setShaderTexture(0, InternalTextures.CHEST_GUI_TEXTURE_DARK);
- RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, darkBackgroundAlpha.value());
- this.blit(matrices, bounds.x, bounds.y + 2, u + (selected ? bounds.width : 0), v, bounds.width, (selected ? bounds.height + 2 : bounds.height - 1));
- RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
- renderer.setZ(100);
- renderer.render(matrices, new Rectangle(bounds.getCenterX() - 8, bounds.getCenterY() - 5, 16, 16), mouseX, mouseY, delta);
+ try (CloseableScissors scissors = Widget.scissor(matrices, new Rectangle(bounds.x, bounds.y + 2, bounds.width, (selected ? bounds.height + 2 : bounds.height - 2)))) {
+ darkBackgroundAlpha.update(delta);
+ RenderSystem.enableBlend();
+ RenderSystem.blendFuncSeparate(770, 771, 1, 0);
+ RenderSystem.blendFunc(770, 771);
+ RenderSystem.setShaderTexture(0, InternalTextures.CHEST_GUI_TEXTURE);
+ RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, opacity);
+ this.blit(matrices, bounds.x, bounds.y + 2, u + (selected ? bounds.width : 0), v, bounds.width, (selected ? bounds.height + 2 : bounds.height - 2));
+ RenderSystem.setShaderTexture(0, InternalTextures.CHEST_GUI_TEXTURE_DARK);
+ RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, darkBackgroundAlpha.value() * opacity);
+ this.blit(matrices, bounds.x, bounds.y + 2, u + (selected ? bounds.width : 0), v, bounds.width, (selected ? bounds.height + 2 : bounds.height - 2));
+ RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, opacity);
+ renderer.setZ(100);
+ renderer.render(matrices, new Rectangle(bounds.getCenterX() - 8, bounds.getCenterY() - 5, 16, 16), mouseX, mouseY, delta);
+ }
if (contai