aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRuleOptionsScreen.java122
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/SearchFilteringRule.java83
2 files changed, 198 insertions, 7 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRuleOptionsScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRuleOptionsScreen.java
index 154c34445..fac731ecf 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRuleOptionsScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/entries/FilteringRuleOptionsScreen.java
@@ -23,8 +23,12 @@
package me.shedaniel.rei.impl.client.config.entries;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import me.shedaniel.clothconfig2.gui.widget.DynamicElementListWidget;
+import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.impl.client.entry.filtering.FilteringRule;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button;
@@ -32,16 +36,21 @@ import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.FormattedCharSequence;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Supplier;
public abstract class FilteringRuleOptionsScreen<T extends FilteringRule<?>> extends Screen {
private final FilteringEntry entry;
@@ -258,4 +267,117 @@ public abstract class FilteringRuleOptionsScreen<T extends FilteringRule<?>> ext
return Collections.singletonList(widget);
}
}
+
+ public static class SubRulesEntry extends RuleEntry {
+ private static final ResourceLocation CONFIG_TEX = new ResourceLocation("cloth-config2", "textures/gui/cloth_config.png");
+ private final CategoryLabelWidget widget;
+ private final List<RuleEntry> rules;
+ private final List<GuiEventListener> children;
+ private boolean expanded;
+ private Supplier<Component> name;
+
+ public SubRulesEntry(FilteringRule<?> rule, Supplier<Component> name, List<RuleEntry> rules) {
+ super(rule);
+ this.rules = rules;
+ this.widget = new CategoryLabelWidget();
+ this.name = name;
+ this.expanded = true;
+ this.children = new ArrayList<>(rules);
+ this.children.add(widget);
+ }
+
+ public List<RuleEntry> getRules() {
+ return rules;
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ RenderSystem.setShaderTexture(0, CONFIG_TEX);
+ RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
+ this.widget.rectangle.x = x + 3;
+ this.widget.rectangle.y = y;
+ this.widget.rectangle.width = entryWidth - 6;
+ this.widget.rectangle.height = 24;
+ this.blit(matrices, x + 3, y + 5, 24, (this.widget.rectangle.contains(mouseX, mouseY) ? 18 : 0) + (this.expanded ? 9 : 0), 9, 9);
+ Minecraft.getInstance().font.drawShadow(matrices, this.name.get().getVisualOrderText(), (float) x + 3 + 15, (float) (y + 6), this.widget.rectangle.contains(mouseX, mouseY) ? -1638890 : -1);
+
+ for (RuleEntry performanceEntry : this.rules) {
+ performanceEntry.setParent(this.getParent());
+ }
+
+ if (this.expanded) {
+ int yy = y + 24;
+
+ RuleEntry entry;
+ for (Iterator<RuleEntry> iterator = this.rules.iterator(); iterator.hasNext(); yy += entry.getItemHeight()) {
+ entry = iterator.next();
+ entry.render(matrices, -1, yy, x + 3 + 15, entryWidth - 15 - 3, entry.getItemHeight(), mouseX, mouseY, isHovered && this.getFocused() == entry, delta);
+ }
+ }
+ }
+
+ @Override
+ public int getMorePossibleHeight() {
+ if (!this.expanded) {
+ return -1;
+ } else {
+ List<Integer> list = new ArrayList<>();
+ int i = 24;
+
+ for (RuleEntry entry : this.rules) {
+ i += entry.getItemHeight();
+ if (entry.getMorePossibleHeight() >= 0) {
+ list.add(i + entry.getMorePossibleHeight());
+ }
+ }
+
+ list.add(i);
+ return list.stream().max(Integer::compare).orElse(0) - this.getItemHeight();
+ }
+ }
+
+ @Override
+ public int getItemHeight() {
+ if (!this.expanded) {
+ return 24;
+ } else {
+ int i = 24;
+
+ RuleEntry entry;
+ for (Iterator<RuleEntry> iterator = this.rules.iterator(); iterator.hasNext(); i += entry.getItemHeight()) {
+ entry = iterator.next();
+ }
+
+ return i;
+ }
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return children;
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return Collections.emptyList();
+ }
+
+ public class CategoryLabelWidget implements GuiEventListener {
+ private final Rectangle rectangle = new Rectangle();
+
+ public CategoryLabelWidget() {
+ }
+
+ @Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (this.rectangle.contains(mouseX, mouseY)) {
+ SubRulesEntry.this.expanded = !SubRulesEntry.this.expanded;
+ Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/SearchFilteringRule.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/SearchFilteringRule.java
index 5f5969674..0e48f1b97 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/SearchFilteringRule.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/entry/filtering/rules/SearchFilteringRule.java
@@ -25,35 +25,49 @@ package me.shedaniel.rei.impl.client.entry.filtering.rules;
import com.google.common.base.Suppliers;
import com.google.common.collect.Lists;
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.ScissorsHandler;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.REIRuntime;
+import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
import me.shedaniel.rei.api.client.search.SearchFilter;
import me.shedaniel.rei.api.client.search.SearchProvider;
import me.shedaniel.rei.api.common.entry.EntryStack;
import me.shedaniel.rei.api.common.util.CollectionUtils;
import me.shedaniel.rei.impl.client.config.entries.FilteringEntry;
import me.shedaniel.rei.impl.client.config.entries.FilteringRuleOptionsScreen;
+import me.shedaniel.rei.impl.client.config.entries.FilteringScreen;
import me.shedaniel.rei.impl.client.entry.filtering.AbstractFilteringRule;
import me.shedaniel.rei.impl.client.entry.filtering.FilteringCache;
import me.shedaniel.rei.impl.client.entry.filtering.FilteringContext;
import me.shedaniel.rei.impl.client.entry.filtering.FilteringResult;
+import me.shedaniel.rei.impl.client.gui.widget.BatchedEntryRendererManager;
+import me.shedaniel.rei.impl.client.gui.widget.EntryWidget;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.util.Mth;
import net.minecraft.util.StringUtil;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiFunction;
import java.util.function.Consumer;
+import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.entrySize;
@Environment(EnvType.CLIENT)
public class SearchFilteringRule extends AbstractFilteringRule<SearchFilteringRule> {
@@ -115,7 +129,7 @@ public class SearchFilteringRule extends AbstractFilteringRule<SearchFilteringRu
@Override
public SearchFilteringRule createNew() {
- return new SearchFilteringRule("", true);
+ return new SearchFilteringRule("", false);
}
private void processList(Collection<EntryStack<?>> stacks, List<CompletableFuture<List<EntryStack<?>>>> completableFutures) {
@@ -147,21 +161,34 @@ public class SearchFilteringRule extends AbstractFilteringRule<SearchFilteringRu
return Optional.of((entry, screen) -> new FilteringRuleOptionsScreen<SearchFilteringRule>(entry, this, screen) {
TextFieldRuleEntry entry = null;
BooleanRuleEntry show = null;
-
+ List<EntryWidget> entryStacks = new ArrayList<>();
+
@Override
public void addEntries(Consumer<RuleEntry> entryConsumer) {
addEmpty(entryConsumer, 10);
addText(entryConsumer, new TranslatableComponent("rule.roughlyenoughitems.filtering.search.filter").withStyle(ChatFormatting.GRAY));
entryConsumer.accept(entry = new TextFieldRuleEntry(width - 36, rule, widget -> {
widget.setMaxLength(9999);
+ widget.setResponder(searchTerm -> {
+ SearchFilter filter = SearchProvider.getInstance().createFilter(searchTerm);
+ entryStacks = EntryRegistry.getInstance().getEntryStacks().parallel()
+ .filter(filter)
+ .map(EntryStack::normalize)
+ .map(stack -> new EntryWidget(new Rectangle(0, 0, 18,18)).noBackground().entry(stack))
+ .collect(Collectors.toList());
+ });
if (entry != null) widget.setValue(entry.getWidget().getValue());
else widget.setValue(rule.filterStr);
}));
addEmpty(entryConsumer, 10);
addText(entryConsumer, new TranslatableComponent("rule.roughlyenoughitems.filtering.search.show").withStyle(ChatFormatting.GRAY));
- entryConsumer.accept(show = new BooleanRuleEntry(width - 36, show == null ? rule.show : show.getBoolean(), rule, bool -> {
+ Function<Boolean, Component> function = bool -> {
return new TranslatableComponent("rule.roughlyenoughitems.filtering.search.show." + bool);
- }));
+ };
+ entryConsumer.accept(show = new BooleanRuleEntry(width - 36, show == null ? rule.show : show.getBoolean(), rule, function));
+ addEmpty(entryConsumer, 10);
+ entryConsumer.accept(new SubRulesEntry(rule, () -> function.apply(show == null ? rule.show : show.getBoolean()),
+ Collections.singletonList(new EntryStacksRuleEntry(rule, () -> entryStacks, entry, show))));
}
@Override
@@ -171,4 +198,46 @@ public class SearchFilteringRule extends AbstractFilteringRule<SearchFilteringRu
}
});
}
+
+ public static class EntryStacksRuleEntry extends FilteringRuleOptionsScreen.RuleEntry {
+ private final Supplier<List<EntryWidget>> entryStacks;
+ private int totalHeight;
+
+ public EntryStacksRuleEntry(SearchFilteringRule rule, Supplier<List<EntryWidget>> entryStacks, FilteringRuleOptionsScreen.TextFieldRuleEntry entry, FilteringRuleOptionsScreen.BooleanRuleEntry show) {
+ super(rule);
+ this.entryStacks = entryStacks;
+ }
+
+ @Override
+ public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float delta) {
+ BatchedEntryRendererManager manager = new BatchedEntryRendererManager();
+ int entrySize = entrySize();
+ int width = entryWidth / entrySize;
+ int i = 0;
+ for (EntryWidget stack : entryStacks.get()) {
+ stack.getBounds().setLocation(x + (i % width) * entrySize, y + (i / width) * entrySize);
+ if (stack.getBounds().getMaxY() >= 0 && stack.getBounds().getY() <= Minecraft.getInstance().getWindow().getGuiScaledHeight()) {
+ manager.add(stack);
+ }
+ i++;
+ }
+ manager.render(matrices, mouseX, mouseY, delta);
+ totalHeight = (i / width + 1) * entrySize;
+ }
+
+ @Override
+ public int getItemHeight() {
+ return totalHeight;
+ }
+
+ @Override
+ public List<? extends NarratableEntry> narratables() {
+ return Lists.newArrayList();
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return Lists.newArrayList();
+ }
+ }
}