aboutsummaryrefslogtreecommitdiff
path: root/runtime/src/main/java/me
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2022-11-12 13:26:56 +0800
committershedaniel <daniel@shedaniel.me>2023-05-29 21:19:41 +0800
commitde4df53457cd010003ff5ccb672d981d328d2895 (patch)
treeb4689f4d9f1632dd062c2eb907fe8eede50deca7 /runtime/src/main/java/me
parentf9ab00af5858b06c72695a375edfa9fc11d1b63a (diff)
downloadRoughlyEnoughItems-de4df53457cd010003ff5ccb672d981d328d2895.tar.gz
RoughlyEnoughItems-de4df53457cd010003ff5ccb672d981d328d2895.tar.bz2
RoughlyEnoughItems-de4df53457cd010003ff5ccb672d981d328d2895.zip
Fix #1207
Diffstat (limited to 'runtime/src/main/java/me')
-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.java4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/CompositeDisplayViewingScreen.java6
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/DefaultDisplayViewingScreen.java52
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/TabContainerWidget.java160
5 files changed, 145 insertions, 79 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 42d08935f..746e11b54 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
@@ -683,7 +683,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.") @ConfigEntry.Gui.Excluded private boolean useCompactTabButtons = false;
+ @Comment("Declares whether REI should use compact tab buttons for categories.") 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 877d6c357..f904d5616 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
@@ -109,8 +109,8 @@ public abstract class AbstractDisplayViewingScreen extends Screen implements Dis
this.categoryPages = -1;
}
- protected void initTabs() {
- this.tabs.init(new Rectangle(bounds.x, bounds.y - 28, bounds.width, 28), categories, new IntValue() {
+ protected void initTabs(int width) {
+ this.tabs.init(new Rectangle(bounds.getCenterX() - width / 2, bounds.y - 28, width, 28), new Rectangle(bounds.getCenterX() - width / 2, bounds.y - 28, width, 28), categories, new IntValue() {
@Override
public void accept(int value) {
AbstractDisplayViewingScreen.this.categoryPages = value;
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 e5489261a..097e90f62 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
@@ -100,10 +100,6 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
@Override
public void init() {
super.init();
- boolean isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs();
- boolean isCompactTabButtons = ConfigObject.getInstance().isUsingCompactTabButtons();
- int tabButtonsSize = isCompactTabButtons ? 10 : 16;
- int tabSize = isCompactTabs ? 24 : 28;
this.children().clear();
this.widgets.clear();
this.buttonList.clear();
@@ -116,7 +112,7 @@ public class CompositeDisplayViewingScreen extends AbstractDisplayViewingScreen
int guiHeight = Mth.clamp(category.getDisplayHeight() + 40, 166, largestHeight);
this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - guiHeight / 2, guiWidth, guiHeight);
- this.initTabs();
+ this.initTabs(this.bounds.width);
this.widgets.addAll(this.tabs.widgets());
List<EntryIngredient> workstations = CategoryRegistry.getInstance().get(category.getCategoryIdentifier()).getWorkstations();
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 c18f6979e..f7e9ebf1c 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
@@ -39,6 +39,7 @@ import me.shedaniel.math.Rectangle;
import me.shedaniel.math.impl.PointHelper;
import me.shedaniel.rei.api.client.REIRuntime;
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.Button;
import me.shedaniel.rei.api.client.gui.widgets.Panel;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
@@ -76,20 +77,37 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.*;
+import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
@ApiStatus.Internal
public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
+ private static final int INNER_PADDING_Y = 36;
+ private static final int OUTER_PADDING_TOP = 2;
+ private static final int OUTER_PADDING_BOTTOM = 2;
+ private static final int DISPLAY_GAP = 4;
private final Map<Rectangle, Pair<DisplaySpec, List<Widget>>> recipeBounds = Maps.newHashMap();
private List<Widget> widgets = Lists.newArrayList();
public int page;
@Nullable
private Panel workingStationsBaseWidget;
private Button recipeBack, recipeNext, categoryBack, categoryNext;
+ private final int bestWidthDisplay;
public DefaultDisplayViewingScreen(Map<DisplayCategory<?>, List<DisplaySpec>> categoriesMap, @Nullable CategoryIdentifier<?> category) {
super(categoriesMap, category);
this.bounds = new Rectangle(0, 0, 176, 150);
+ //noinspection RedundantCast
+ List<Integer> list = CollectionUtils.mapAndFilter(categoriesMap.entrySet(), Objects::nonNull, entry -> ((Optional<Integer>) CollectionUtils.<DisplaySpec, Integer>mapAndMax(entry.getValue(),
+ display -> ((DisplayCategory<Display>) entry.getKey()).getDisplayWidth(display.provideInternalDisplay()), Comparator.naturalOrder())).orElse(null));
+ list.sort(Comparator.naturalOrder());
+ int mode = list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream()
+ .max(Map.Entry.comparingByValue())
+ .map(Map.Entry::getKey)
+ .orElse(150);
+ int median = list.size() % 2 == 0 ? (list.get(list.size() / 2) + list.get(list.size() / 2 - 1)) / 2 : list.get(list.size() / 2);
+ this.bestWidthDisplay = (int) Math.round((mode * 0.5 + median * 1.5) / 2.0);
}
@Override
@@ -134,24 +152,28 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
this.children().clear();
this.recipeBounds.clear();
this.widgets.clear();
- int largestHeight = Math.min(Math.max(height - 34 - 30, 100), ConfigObject.getInstance().getMaxRecipesPageHeight());
- int maxWidthDisplay = CollectionUtils.<DisplaySpec, Integer>mapAndMax(getCurrentDisplayed(), display -> getCurrentCategory().getDisplayWidth(display.provideInternalDisplay()), Comparator.naturalOrder()).orElse(150);
+// int maxWidthDisplay = CollectionUtils.<DisplaySpec, Integer>mapAndMax(getCurrentDisplayed(), display -> getCurrentCategory().getDisplayWidth(display.provideInternalDisplay()), Comparator.naturalOrder()).orElse(150);
+// int guiWidth = Math.max(maxWidthDisplay + 10 + 14 + 14, 190);
+ int guiWidth = Math.max(bestWidthDisplay + 10 + 14 + 14, 190);
+ this.tabs.initTabsSize(guiWidth);
+
+ int topMargin = OUTER_PADDING_TOP + this.tabs.tabSize() - 2 + (categories.size() > this.tabs.tabsPerPage() ? 16 : 0);
+ int bottomMargin = OUTER_PADDING_BOTTOM + (ConfigObject.getInstance().getSearchFieldLocation() == SearchFieldLocation.CENTER ? 22 : 0);
+ int largestHeight = Math.min(Math.max(height - topMargin - bottomMargin, 100), ConfigObject.getInstance().getMaxRecipesPageHeight());
int maxHeight = Math.min(largestHeight, CollectionUtils.<DisplayCategory<?>, 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 + 14 + 14, 190);
- this.bounds = new Rectangle(width / 2 - guiWidth / 2, height / 2 - maxHeight / 2, guiWidth, maxHeight);
+ category -> INNER_PADDING_Y + (category.getDisplayHeight() + DISPLAY_GAP) * Math.max(1, Math.min(getRecipesPerPage(largestHeight, category) + 1, Math.max(categoryMap.get(category).size(), ConfigObject.getInstance().getMaxRecipePerPage()))), Comparator.naturalOrder()).orElse(66));
+ this.bounds = new Rectangle(width / 2 - guiWidth / 2, topMargin + (height - topMargin - bottomMargin) / 2 - maxHeight / 2, guiWidth, maxHeight);
- this.initTabs();
+ this.initTabs(guiWidth);
this.widgets.addAll(this.tabs.widgets());
this.page = Mth.clamp(page, 0, getCurrentTotalPages() - 1);
- this.widgets.add(categoryBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 5, 12, 12), ImmutableTextComponent.EMPTY)
+ this.widgets.add(categoryBack = Widgets.createButton(new Rectangle(bounds.getCenterX() - guiWidth / 2 + 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(new TranslatableComponent("text.rei.view_all_categories")));
- this.widgets.add(categoryNext = Widgets.createButton(new Rectangle(bounds.getMaxX() - 17, bounds.getY() + 5, 12, 12), ImmutableTextComponent.EMPTY)
+ this.widgets.add(categoryNext = Widgets.createButton(new Rectangle(bounds.getCenterX() + guiWidth / 2 - 17, bounds.getY() + 5, 12, 12), ImmutableTextComponent.EMPTY)
.onClick(button -> nextCategory()).tooltipLine(new TranslatableComponent("text.rei.next_category")));
this.categoryBack.setEnabled(categories.size() > 1);
this.categoryNext.setEnabled(categories.size() > 1);
@@ -172,7 +194,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
matrices.popPose();
}), 0, 0, 1));
- this.widgets.add(recipeBack = Widgets.createButton(new Rectangle(bounds.getX() + 5, bounds.getY() + 19, 12, 12), ImmutableTextComponent.EMPTY)
+ this.widgets.add(recipeBack = Widgets.createButton(new Rectangle(bounds.getCenterX() - guiWidth / 2 + 5, bounds.getY() + 19, 12, 12), ImmutableTextComponent.EMPTY)
.onClick(button -> {
page--;
if (page < 0)
@@ -193,7 +215,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
label.setMessage(new ImmutableTextComponent(String.format("%d/%d", page + 1, getCurrentTotalPages())));
label.setClickable(getCurrentTotalPages() > 1);
}).tooltipFunction(label -> label.isClickable() ? new Component[]{new TranslatableComponent("text.rei.go_back_first_page"), new TextComponent(" "), new TranslatableComponent("text.rei.shift_click_to", new TranslatableComponent("text.rei.choose_page")).withStyle(ChatFormatting.GRAY)} : null));
- this.widgets.add(recipeNext = Widgets.createButton(new Rectangle(bounds.getMaxX() - 17, bounds.getY() + 19, 12, 12), ImmutableTextComponent.EMPTY)
+ this.widgets.add(recipeNext = Widgets.createButton(new Rectangle(bounds.getCenterX() + guiWidth / 2 - 17, bounds.getY() + 19, 12, 12), ImmutableTextComponent.EMPTY)
.onClick(button -> {
page++;
if (page >= getCurrentTotalPages())
@@ -206,8 +228,8 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
widgets = CollectionUtils.map(widgets, widget -> Widgets.withTranslate(widget, 0, 0, 10));
widgets.add(Widgets.withTranslate(new PanelWidget(bounds), 0, 0, 5));
widgets.add(Widgets.withTranslate(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> {
- fill(matrices, bounds.x + 17, bounds.y + 5, bounds.x + bounds.width - 17, bounds.y + 17, darkStripesColor.value().getColor());
- fill(matrices, bounds.x + 17, bounds.y + 19, bounds.x + bounds.width - 17, bounds.y + 31, darkStripesColor.value().getColor());
+ fill(matrices, bounds.getCenterX() - guiWidth / 2 + 17, bounds.y + 5, bounds.getCenterX() + guiWidth / 2 - 17, bounds.y + 17, darkStripesColor.value().getColor());
+ fill(matrices, bounds.getCenterX() - guiWidth / 2 + 17, bounds.y + 19, bounds.getCenterX() + guiWidth / 2 - 17, bounds.y + 31, darkStripesColor.value().getColor());
}), 0, 0, 6));
initWorkstations(widgets);
@@ -222,7 +244,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
final DisplaySpec display = currentDisplayed.get(i);
final Supplier<Display> displaySupplier = display::provideInternalDisplay;
int displayWidth = getCurrentCategory().getDisplayWidth(displaySupplier.get());
- final Rectangle displayBounds = new Rectangle(getBounds().getCenterX() - displayWidth / 2, getBounds().getCenterY() + 16 - displayHeight * (getRecipesPerPage() + 1) / 2 - 2 * (getRecipesPerPage() + 1) + displayHeight * i + 4 * i, displayWidth, displayHeight);
+ final Rectangle displayBounds = new Rectangle(getBounds().getCenterX() - displayWidth / 2, getBounds().getCenterY() + 16 - displayHeight * (getRecipesPerPage() + 1) / 2 - 2 * (getRecipesPerPage() + 1) + displayHeight * i + DISPLAY_GAP * i, displayWidth, displayHeight);
List<Widget> setupDisplay;
try {
setupDisplay = getCurrentCategoryView(display.provideInternalDisplay()).setupDisplay(display.provideInternalDisplay(), displayBounds);
@@ -307,7 +329,7 @@ public class DefaultDisplayViewingScreen extends AbstractDisplayViewingScreen {
if (category.getFixedDisplaysPerPage() > 0)
return category.getFixedDisplaysPerPage() - 1;
int height = category.getDisplayHeight();
- return Mth.clamp(Mth.floor(((double) totalHeight - 36) / ((double) height + 4)) - 1, 0, Math.min(ConfigObject.getInstance().getMaxRecipePerPage() - 1, category.getMaximumDisplaysPerPage() - 1));
+ return Mth.clamp(Mth.floor(((double) totalHeight - INNER_PADDING_Y) / ((double) height + DISPLAY_GAP)) - 1, 0, Math.min(ConfigObject.getInstance().getMaxRecipePerPage() - 1, category.getMaximumDisplaysPerPage() - 1));
}
private final ValueAnimator<Color> darkStripesColor = ValueAnimator.ofColor()
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
index 950328d84..e67248c7b 100644
--- 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
@@ -23,30 +23,37 @@
package me.shedaniel.rei.impl.client.gui.widget;
+import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.blaze3d.vertex.Tesselator;
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.gui.widgets.*;
import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
+import me.shedaniel.rei.impl.client.gui.InternalTextures;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.network.chat.TextComponent;
+import net.minecraft.network.chat.TranslatableComponent;
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 boolean isCompactTabs;
+ private boolean isCompactTabButtons;
+ private int tabSize;
+ private int tabButtonsSize;
private int tabsPerPage = 5;
public TabContainerWidget() {
@@ -57,78 +64,106 @@ public class TabContainerWidget extends GuiComponent {
}
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);
- });
+ this.initTabsVariables();
+ if (categories.size() <= tabsPerPage) {
+ scrollAnimator.setAs(0d);
+ } else if (selectedCategory < tabsPerPage / 2) {
+ scrollAnimator.setTo(0d, duration);
+ } else if (selectedCategory >= categories.size() - (int) Math.ceil(tabsPerPage / 2)) {
+ scrollAnimator.setTo((categories.size() - tabsPerPage) * tabSize, duration);
+ } else {
+ scrollAnimator.setTo((selectedCategory - (tabsPerPage - 1) / 2.0) * tabSize, duration);
+ }
+ }
+
+ private void initTabsVariables() {
+ this.isCompactTabs = ConfigObject.getInstance().isUsingCompactTabs();
+ this.isCompactTabButtons = ConfigObject.getInstance().isUsingCompactTabButtons();
+ this.tabSize = isCompactTabs ? 24 : 28;
+ this.tabButtonsSize = isCompactTabButtons ? 10 : 16;
+ }
+
+ public void initTabsSize(int width) {
+ this.initTabsVariables();
+ this.tabsPerPage = Mth.floor((width - 6) / tabSize);
+ if (this.tabsPerPage % 2 == 0)
+ this.tabsPerPage--;
}
- public void init(Rectangle bounds, List<DisplayCategory<?>> categories, IntValue categoryPages, IntValue selectedCategory, Runnable reInit) {
+ public void init(Rectangle scissorsBounds, 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);
+ initTabsSize(bounds.width);
if (categoryPages.getAsInt() == -1) {
categoryPages.accept(Math.max(0, selectedCategory.getAsInt() / tabsPerPage()));
}
+ if (categories.size() > tabsPerPage) {
+ Button tabLeft, tabRight;
+ this.widgets.add(tabLeft = Widgets.createButton(new Rectangle(bounds.x, bounds.getMaxY() - tabSize + 1 - tabButtonsSize, tabButtonsSize, tabButtonsSize), new TextComponent(""))
+ .onClick(button -> {
+ int currentCategoryPage = selectedCategory.getAsInt() / tabsPerPage();
+ currentCategoryPage = Math.floorMod(currentCategoryPage - 1, categories.size() / tabsPerPage() + 1);
+ selectedCategory.accept(Mth.clamp(currentCategoryPage * tabsPerPage() + tabsPerPage() / 2,
+ tabsPerPage() / 2, categories.size() - (int) Math.ceil(tabsPerPage() / 2.0)));
+ })
+ .tooltipLine(new TranslatableComponent("text.rei.previous_page")));
+ this.widgets.add(tabRight = Widgets.createButton(new Rectangle(bounds.x + bounds.width - tabButtonsSize - (isCompactTabButtons ? 0 : 1), bounds.getMaxY() - tabSize + 1 - tabButtonsSize, tabButtonsSize, tabButtonsSize), new TextComponent(""))
+ .onClick(button -> {
+ int currentCategoryPage = selectedCategory.getAsInt() / tabsPerPage();
+ currentCategoryPage = Math.floorMod(currentCategoryPage + 1, categories.size() / tabsPerPage() + 1);
+ selectedCategory.accept(Mth.clamp(currentCategoryPage * tabsPerPage() + tabsPerPage() / 2,
+ tabsPerPage() / 2, categories.size() - (int) Math.ceil(tabsPerPage() / 2.0)));
+ })
+ .tooltipLine(new TranslatableComponent("text.rei.next_page")));
+
+ 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(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 absRight = 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());
+ left = bounds.x + bounds.width / 2 - Math.min(categories.size(), tabsPerPage()) * 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;
- }
+ tab.getBounds().x = left;
+ left += tabSize;
- 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);
+ if (tab.isSelected()) {
+ tab.opacity = 1;
+ } else if (tab.getBounds().getCenterX() <= absLeft) {
+ tab.opacity = 1 - (absLeft - tab.getBounds().getCenterX()) / 20f;
+ tab.opacity = (float) Math.pow(Mth.clamp(tab.opacity, 0, 1), 1.2);
+ } else if (tab.getBounds().getCenterX() >= absRight) {
+ tab.opacity = 1 - (tab.getBounds().getCenterX() - absRight) / 20f;
+ tab.opacity = (float) Math.pow(Mth.clamp(tab.opacity, 0, 1), 1.2);
} else {
tab.opacity = 1;
}
@@ -136,6 +171,11 @@ public class TabContainerWidget extends GuiComponent {
if (tab.opacity < 0.1) {
tab.opacity = 0;
}
+
+ if (tab.opacity == 0 || tab.getBounds().x > bounds.getMaxX() || tab.getBounds().getMaxX() < bounds.x) {
+ tab.getBounds().x = -1000;
+ tab.opacity = 0;
+ }
}
}
@@ -184,7 +224,7 @@ public class TabContainerWidget extends GuiComponent {
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))) {
+ try (CloseableScissors scissors = Widget.scissor(poseStack, new Rectangle(scissorsBounds.x, scissorsBounds.y, scissorsBounds.width, scissorsBounds.height + 4))) {
super.render(poseStack, mouseX, mouseY, delta);
}
}
@@ -199,4 +239,12 @@ public class TabContainerWidget extends GuiComponent {
public int tabsPerPage() {
return tabsPerPage;
}
+
+ public int tabButtonsSize() {
+ return tabButtonsSize;
+ }
+
+ public int tabSize() {
+ return tabSize;
+ }
}