diff options
| author | shedaniel <daniel@shedaniel.me> | 2021-11-07 18:01:38 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2021-11-07 18:01:38 +0800 |
| commit | 7879ac1cc61876bfa0578e34a96239830530a00b (patch) | |
| tree | f8901af1f4ed947ead3f9beb60617aef11c26960 /runtime/src/main/java | |
| parent | f8fc41207ca444c0a90ae10d78a821831b245bc2 (diff) | |
| download | RoughlyEnoughItems-7879ac1cc61876bfa0578e34a96239830530a00b.tar.gz RoughlyEnoughItems-7879ac1cc61876bfa0578e34a96239830530a00b.tar.bz2 RoughlyEnoughItems-7879ac1cc61876bfa0578e34a96239830530a00b.zip | |
Modularize region rendering
Diffstat (limited to 'runtime/src/main/java')
12 files changed, 869 insertions, 574 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java index 98f5aab24..2069d8139 100644 --- a/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java +++ b/runtime/src/main/java/me/shedaniel/rei/RoughlyEnoughItemsCoreClient.java @@ -283,6 +283,7 @@ public class RoughlyEnoughItemsCoreClient { reloadPlugins(endReload, Platform.isFabric() ? ReloadStage.END : null); }); ClientGuiEvent.INIT_POST.register((screen, access) -> { + REIRuntime.getInstance().getOverlay(false, true); REIRuntimeImpl.getInstance().setPreviousScreen(screen); if (ConfigObject.getInstance().doesDisableRecipeBook() && screen instanceof AbstractContainerScreen) { access.getRenderables().removeIf(widget -> widget instanceof ImageButton button && button.resourceLocation.equals(recipeButtonTex)); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java index e80e5f572..b674d0099 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/REIRuntimeImpl.java @@ -137,8 +137,8 @@ public class REIRuntimeImpl implements REIRuntime { } @Override - public Optional<ScreenOverlay> getOverlay(boolean reset) { - if (overlay == null || reset) { + public Optional<ScreenOverlay> getOverlay(boolean reset, boolean init) { + if ((overlay == null && init) || reset) { overlay = new ScreenOverlayImpl(); overlay.init(); getSearchField().setFocused(false); @@ -240,7 +240,7 @@ public class REIRuntimeImpl implements REIRuntime { return EventResult.pass(); }); ClientTickEvent.CLIENT_POST.register(minecraft -> { - if (isOverlayVisible()) { + if (isOverlayVisible() && REIRuntime.getInstance().getOverlay().isPresent()) { ScreenOverlayImpl.getInstance().tick(); } }); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java index 0bd0765d8..f0f8a47c1 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/craftable/CraftableFilter.java @@ -48,7 +48,7 @@ public class CraftableFilter { return true; } - return Minecraft.getInstance().player.containerMenu != null; + return false; } public void tick() { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java index 0bc72e96f..f992145bc 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryListWidget.java @@ -420,7 +420,7 @@ public class EntryListWidget extends WidgetWithBounds implements OverlayListWidg } FavoritesListWidget favoritesListWidget = ScreenOverlayImpl.getFavoritesListWidget(); if (favoritesListWidget != null) { - favoritesListWidget.updateEntriesPosition(entry -> true); + favoritesListWidget.getRegion().updateEntriesPosition(entry -> true); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java new file mode 100644 index 000000000..f403ef6fe --- /dev/null +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/EntryStacksRegionWidget.java @@ -0,0 +1,451 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.shedaniel.rei.impl.client.gui.widget; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.mojang.blaze3d.vertex.PoseStack; +import it.unimi.dsi.fastutil.ints.*; +import it.unimi.dsi.fastutil.objects.ObjectIterator; +import me.shedaniel.clothconfig2.ClothConfigInitializer; +import me.shedaniel.clothconfig2.api.ScissorsHandler; +import me.shedaniel.clothconfig2.api.ScrollingContainer; +import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget; +import me.shedaniel.math.Point; +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.entry.region.RegionEntry; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggableStackVisitorWidget; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.widgets.Widget; +import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; +import me.shedaniel.rei.api.common.entry.EntrySerializer; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.util.CollectionUtils; +import me.shedaniel.rei.impl.client.gui.widget.region.RealRegionEntry; +import me.shedaniel.rei.impl.client.gui.widget.region.RegionDraggableStack; +import me.shedaniel.rei.impl.client.gui.widget.region.RegionEntryListEntry; +import me.shedaniel.rei.impl.client.gui.widget.region.RegionListener; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.util.Mth; +import net.minecraft.util.Tuple; +import net.minecraft.util.Unit; +import org.jetbrains.annotations.Nullable; + +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.entrySize; +import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.notSteppingOnExclusionZones; + +public class EntryStacksRegionWidget<T extends RegionEntry<T>> extends WidgetWithBounds implements DraggableStackVisitorWidget { + private final RegionListener<T> listener; + protected int blockedCount; + private Rectangle bounds = new Rectangle(), innerBounds; + protected final ScrollingContainer scrolling = new ScrollingContainer() { + @Override + public Rectangle getBounds() { + return EntryStacksRegionWidget.this.getBounds(); + } + + @Override + public int getMaxScrollHeight() { + return Mth.ceil((entries.size() + blockedCount) / (innerBounds.width / (float) entrySize())) * entrySize(); + } + + @Override + public int getScrollBarX() { + if (!ConfigObject.getInstance().isLeftHandSidePanel()) + return bounds.x + 1; + return bounds.getMaxX() - 7; + } + }; + private final Int2ObjectMap<RealRegionEntry<T>> entries = new Int2ObjectLinkedOpenHashMap<>(); + private final Int2ObjectMap<RealRegionEntry<T>> removedEntries = new Int2ObjectLinkedOpenHashMap<>(); + private List<RegionEntryListEntry<T>> entriesList = Lists.newArrayList(); + private List<Widget> children = Lists.newArrayList(); + + public EntryStacksRegionWidget(RegionListener<T> listener) { + this.listener = listener; + } + + @Override + public Rectangle getBounds() { + return bounds; + } + + @Override + public void render(PoseStack poses, int mouseX, int mouseY, float delta) { + if (bounds.isEmpty()) return; + + int entrySize = entrySize(); + boolean fastEntryRendering = ConfigObject.getInstance().doesFastEntryRendering(); + updateEntriesPosition(entry -> true); + for (RealRegionEntry<T> entry : entries.values()) { + entry.update(delta); + } + ObjectIterator<RealRegionEntry<T>> removedEntriesIterator = removedEntries.values().iterator(); + while (removedEntriesIterator.hasNext()) { + RealRegionEntry<T> removedEntry = removedEntriesIterator.next(); + removedEntry.update(delta); + + if (removedEntry.size.doubleValue() <= 300) { + removedEntriesIterator.remove(); + this.entriesList.remove(removedEntry.getWidget()); + this.children.remove(removedEntry.getWidget()); + } + } + + ScissorsHandler.INSTANCE.scissor(bounds); + + Stream<RegionEntryListEntry<T>> entryStream = this.entriesList.stream() + .filter(entry -> entry.getBounds().getMaxY() >= this.bounds.getY() && entry.getBounds().y <= this.bounds.getMaxY()); + + new BatchedEntryRendererManager(entryStream.collect(Collectors.toList())) + .render(poses, mouseX, mouseY, delta); + + updatePosition(delta); + scrolling.renderScrollBar(0, 1, REIRuntime.getInstance().isDarkThemeEnabled() ? 0.8f : 1f); + ScissorsHandler.INSTANCE.removeLastScissor(); + } + + @Override + public List<Widget> children() { + return children; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (scrolling.updateDraggingState(mouseX, mouseY, button)) { + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + if (containsMouse(mouseX, mouseY)) { + scrolling.offset(ClothConfigInitializer.getScrollStep() * -amount, true); + return true; + } + return super.mouseScrolled(mouseX, mouseY, amount); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (scrolling.mouseDragged(mouseX, mouseY, button, deltaX, deltaY, ConfigObject.getInstance().doesSnapToRows(), entrySize())) + return true; + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + private void updatePosition(float delta) { + if (ConfigObject.getInstance().doesSnapToRows() && scrolling.scrollTarget >= 0 && scrolling.scrollTarget <= scrolling.getMaxScroll()) { + double nearestRow = Math.round(scrolling.scrollTarget / (double) entrySize()) * (double) entrySize(); + if (!DynamicNewSmoothScrollingEntryListWidget.Precision.almostEquals(scrolling.scrollTarget, nearestRow, DynamicNewSmoothScrollingEntryListWidget.Precision.FLOAT_EPSILON)) + scrolling.scrollTarget += (nearestRow - scrolling.scrollTarget) * Math.min(delta / 2.0, 1.0); + else + scrolling.scrollTarget = nearestRow; + } + scrolling.updatePosition(delta); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + if (containsMouse(PointHelper.ofMouse())) + for (Widget widget : children()) + if (widget.keyPressed(keyCode, scanCode, modifiers)) + return true; + return false; + } + + @Nullable + public DraggableStack getHoveredStack(DraggingContext<Screen> context, double mouseX, double mouseY) { + if (innerBounds.contains(mouseX, mouseY)) { + for (RealRegionEntry<T> entry : entries.values()) { + if (entry.getWidget().containsMouse(mouseX, mouseY)) { + return new RegionDraggableStack<>(entry, null); + } + } + } + return null; + } + + public EntryStack<?> getFocusedStack() { + Point mouse = PointHelper.ofMouse(); + if (innerBounds.contains(mouse)) { + for (RealRegionEntry<T> entry : entries.values()) { + if (entry.getWidget().containsMouse(mouse)) { + return entry.getWidget().getCurrentEntry().copy(); + } + } + } + return EntryStack.empty(); + } + + public Stream<EntryStack<?>> getEntries() { + return (Stream<EntryStack<?>>) (Stream<? extends EntryStack<?>>) entriesList.stream() + .filter(entry -> entry.getBounds().getMaxY() >= this.bounds.getY() && entry.getBounds().y <= this.bounds.getMaxY()) + .map(EntryWidget::getCurrentEntry) + .filter(entry -> !entry.isEmpty()); + } + + @Override + public boolean acceptDraggedStack(DraggingContext<Screen> context, DraggableStack stack) { + return checkDraggedStacks(context, stack) + .filter(entry -> innerBounds.contains(context.getCurrentPosition())) + .map(entry -> { + drop(entry); + return Unit.INSTANCE; + }).isPresent(); + } + + public Optional<RealRegionEntry<T>> checkDraggedStacks(DraggingContext<Screen> context, DraggableStack stack) { + EntrySerializer<?> serializer = stack.getStack().getDefinition().getSerializer(); + if (stack instanceof RegionDraggableStack || (serializer.supportReading() && serializer.supportSaving())) { + try { + T regionEntry = stack instanceof RegionDraggableStack ? ((RegionDraggableStack<T>) stack).getEntry().getEntry().copy() + : listener.convertDraggableStack(context, stack); + if (regionEntry == null) return Optional.empty(); + RealRegionEntry<T> entry = new RealRegionEntry<>(this, regionEntry, entrySize()); + entry.size.setAs(entrySize() * 100); + return Optional.of(entry); + } catch (Throwable ignored) { + } + } + return Optional.empty(); + } + + public void setEntries(List<T> newEntries) { + newEntries = Lists.newArrayList(newEntries); + newEntries.removeIf(entry -> entry == null || entry.isEntryInvalid()); + + int entrySize = entrySize(); + IntSet newFavoritesHash = new IntOpenHashSet(CollectionUtils.mapToInt(newEntries, T::hashCode)); + List<RealRegionEntry<T>> removedEntries = Lists.newArrayList(this.entries.values()); + removedEntries.removeIf(entry -> newFavoritesHash.contains(entry.hashIgnoreAmount())); + + for (RealRegionEntry<T> removedEntry : removedEntries) { + removedEntry.remove(); + this.removedEntries.put(removedEntry.hashIgnoreAmount(), removedEntry); + } + + Int2ObjectMap<RealRegionEntry<T>> prevEntries = new Int2ObjectOpenHashMap<>(entries); + this.entries.clear(); + + for (T regionEntry : newEntries) { + RealRegionEntry<T> realEntry = prevEntries.get(regionEntry.hashCode()); + + if (realEntry == null) { + realEntry = new RealRegionEntry<>(this, regionEntry, entrySize); + } + + if (!ConfigObject.getInstance().isFavoritesAnimated()) realEntry.size.setAs(entrySize * 100); + else realEntry.size.setTo(entrySize * 100, 300); + entries.put(realEntry.hashIgnoreAmount(), realEntry); + } + + applyNewEntriesList(); + updateEntriesPosition(entry -> prevEntries.containsKey(entry.hashIgnoreAmount())); + } + + public void applyNewEntriesList() { + this.entriesList = Stream.concat(entries.values().stream().map(RealRegionEntry::getWidget), removedEntries.values().stream().map(RealRegionEntry::getWidget)).collect(Collectors.toList()); + this.children = Stream.<Stream<Widget>>of( + entries.values().stream().map(RealRegionEntry::getWidget), + removedEntries.values().stream().map(RealRegionEntry::getWidget) + ).flatMap(Function.identity()).collect(Collectors.toList()); + } + + public void updateEntriesPosition(Predicate<RealRegionEntry<T>> animated) { + int entrySize = entrySize(); + this.blockedCount = 0; + this.innerBounds = updateInnerBounds(bounds); + int width = innerBounds.width / entrySize; + int currentX = 0; + int currentY = 0; + int releaseIndex = getReleaseIndex(); + + int slotIndex = 0; + for (RealRegionEntry<T> entry : this.entries.values()) { + while (true) { + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + + currentX++; + if (currentX >= width) { + currentX = 0; + currentY++; + } + + if (notSteppingOnExclusionZones(xPos, yPos - (int) scrolling.scrollAmount, entrySize, entrySize, innerBounds)) { + if (slotIndex++ == releaseIndex) { + continue; + } + + entry.moveTo(animated.test(entry), xPos, yPos); + break; + } else { + blockedCount++; + } + } + } + } + + private int getReleaseIndex() { + DraggingContext<?> context = DraggingContext.getInstance(); + Point position = context.getCurrentPosition(); + if (context.isDraggingStack() && bounds.contains(position) && checkDraggedStacks(context.cast(), context.getCurrentStack()).isPresent()) { + int entrySize = entrySize(); + int width = innerBounds.width / entrySize; + int currentX = 0; + int currentY = 0; + List<Tuple<RealRegionEntry<T>, Point>> entriesPoints = Lists.newArrayList(); + for (RealRegionEntry<T> entry : this.entries.values()) { + while (true) { + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + + currentX++; + if (currentX >= width) { + currentX = 0; + currentY++; + } + + if (notSteppingOnExclusionZones(xPos, yPos - (int) scrolling.scrollAmount, entrySize, entrySize, innerBounds)) { + entriesPoints.add(new Tuple<>(entry, new Point(xPos, yPos))); + break; + } else { + blockedCount++; + } + } + } + + int maxSize = entriesPoints.size(); + if (currentX != 0) { + int xPos = currentX * entrySize + innerBounds.x; + int yPos = currentY * entrySize + innerBounds.y; + + if (notSteppingOnExclusionZones(xPos, yPos - (int) scrolling.scrollAmount, entrySize, entrySize, innerBounds)) { + entriesPoints.add(new Tuple<>(null, new Point(xPos, yPos))); + } + } + + double x = position.x - 8; + double y = position.y + scrolling.scrollAmount - 8; + + return Mth.clamp(entriesPoints.stream() + .filter(value -> { + double otherY = value.getB().y; + + return otherY <= y + entrySize / 2 && otherY + entrySize > y + entrySize / 2; + }) + .min(Comparator.comparingDouble(value -> { + double otherX = value.getB().x; + double otherY = value.getB().y; + + return (x - otherX) * (x - otherX) + (y - otherY) * (y - otherY); + })) + .map(entriesPoints::indexOf) + .orElse(maxSize), + 0, entriesPoints.size()); + } + + return -2; + } + + private static Rectangle updateInnerBounds(Rectangle bounds) { + int entrySize = entrySize(); + int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize), 1); + if (!ConfigObject.getInstance().isLeftHandSidePanel()) + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) + 3), bounds.y, width * entrySize, bounds.height); + return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) - 3), bounds.y, width * entrySize, bounds.height); + } + + public void drop(RealRegionEntry<T> entry) { + DraggingContext<?> context = DraggingContext.getInstance(); + double x = context.getCurrentPosition().x; + double y = context.getCurrentPosition().y + scrolling.scrollAmount; + entry.startedDraggingPosition = null; + + entry.x.setAs(x - 8); + entry.y.setAs(y - 8); + + boolean contains = bounds.contains(PointHelper.ofMouse()); + int newIndex = contains ? getReleaseIndex() : Math.max(0, Iterables.indexOf(entries.values(), e -> e == entry)); + + if (entries.size() - 1 <= newIndex) { + RealRegionEntry<T> remove = this.entries.remove(entry.hashIgnoreAmount()); + if (remove != null) { + remove.remove(); + this.removedEntries.put(remove.hashIgnoreAmount(), remove); + } + this.entries.put(entry.hashIgnoreAmount(), entry); + } else { + Int2ObjectMap<RealRegionEntry<T>> prevEntries = new Int2ObjectLinkedOpenHashMap<>(entries); + this.entries.clear(); + + int index = 0; + for (Int2ObjectMap.Entry<RealRegionEntry<T>> entryEntry : prevEntries.int2ObjectEntrySet()) { + if (index == newIndex) { + this.entries.put(entry.hashIgnoreAmount(), entry); + } + if (entryEntry.getIntKey() != entry.hashIgnoreAmount()) { + this.entries.put(entryEntry.getIntKey(), entryEntry.getValue()); + index++; + } + } + } + + applyNewEntriesList(); + + listener.onDrop(this.entries.values().stream() + .map(RealRegionEntry::getEntry)); + + setEntries(this.entries.values().stream() + .map(RealRegionEntry::getEntry) + .collect(Collectors.toList())); + } + + public void remove(RealRegionEntry<T> entry) { + entries.remove(entry.hashIgnoreAmount()); + setEntries(CollectionUtils.map(entries.values(), RealRegionEntry::getEntry)); + } + + public double getScrollAmount() { + return scrolling.scrollAmount; + } + + public boolean has(RealRegionEntry<T> entry) { + int hash = entry.hashIgnoreAmount(); + return entries.containsKey(hash) && !removedEntries.containsKey(hash); + } +} diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java index 5041887a4..c98d689b3 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/FavoritesListWidget.java @@ -23,18 +23,13 @@ package me.shedaniel.rei.impl.client.gui.widget; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; +import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.math.Vector4f; -import it.unimi.dsi.fastutil.ints.*; -import it.unimi.dsi.fastutil.objects.ObjectIterator; import me.shedaniel.clothconfig2.ClothConfigInitializer; import me.shedaniel.clothconfig2.api.LazyResettable; import me.shedaniel.clothconfig2.api.ScissorsHandler; import me.shedaniel.clothconfig2.api.ScrollingContainer; -import me.shedaniel.clothconfig2.gui.widget.DynamicNewSmoothScrollingEntryListWidget; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.math.impl.PointHelper; @@ -43,26 +38,25 @@ import me.shedaniel.rei.api.client.config.ConfigManager; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; -import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; import me.shedaniel.rei.api.client.gui.AbstractContainerEventHandler; -import me.shedaniel.rei.api.client.gui.drag.*; +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.DraggingContext; 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; import me.shedaniel.rei.api.client.overlay.OverlayListWidget; import me.shedaniel.rei.api.client.overlay.ScreenOverlay; -import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.util.ClientEntryStacks; -import me.shedaniel.rei.api.common.entry.EntrySerializer; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.Animator; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.ImmutableTextComponent; import me.shedaniel.rei.impl.client.config.ConfigManagerImpl; import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; -import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; -import me.shedaniel.rei.impl.client.gui.modules.Menu; -import me.shedaniel.rei.impl.client.gui.modules.MenuEntry; +import me.shedaniel.rei.impl.client.gui.widget.region.RealRegionEntry; +import me.shedaniel.rei.impl.client.gui.widget.region.RegionDraggableStack; +import me.shedaniel.rei.impl.client.gui.widget.region.RegionListener; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; @@ -70,81 +64,42 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.Mth; -import net.minecraft.util.Tuple; -import net.minecraft.util.Unit; -import net.minecraft.world.phys.shapes.BooleanOp; -import net.minecraft.world.phys.shapes.Shapes; -import net.minecraft.world.phys.shapes.VoxelShape; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.*; -import java.util.function.Function; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.entrySize; import static me.shedaniel.rei.impl.client.gui.widget.EntryListWidget.notSteppingOnExclusionZones; @ApiStatus.Internal -public class FavoritesListWidget extends WidgetWithBounds implements DraggableStackProviderWidget, DraggableStackVisitorWidget, OverlayListWidget { - protected final ScrollingContainer scrolling = new ScrollingContainer() { - @Override - public Rectangle getBounds() { - return currentBounds; - } - - @Override - public int getMaxScrollHeight() { - return Mth.ceil((entries.size() + blockedCount) / (innerBounds.width / (float) entrySize())) * entrySize(); - } - - @Override - public int getScrollBarX() { - if (!ConfigObject.getInstance().isLeftHandSidePanel()) - return fullBounds.x + 1; - return fullBounds.getMaxX() - 7; - } - }; - protected int blockedCount; - private Rectangle fullBounds, currentBounds = new Rectangle(), innerBounds; - private final Int2ObjectMap<Entry> entries = new Int2ObjectLinkedOpenHashMap<>(); - private final Int2ObjectMap<Entry> removedEntries = new Int2ObjectLinkedOpenHashMap<>(); - private List<EntryListEntry> entriesList = Lists.newArrayList(); - private List<Widget> children = Lists.newArrayList(); +public class FavoritesListWidget extends WidgetWithBounds implements DraggableStackProviderWidget, OverlayListWidget, RegionListener<FavoriteEntry> { + private Rectangle fullBounds; + private EntryStacksRegionWidget<FavoriteEntry> region = new EntryStacksRegionWidget<>(this); public final AddFavoritePanel favoritePanel = new AddFavoritePanel(this); public final ToggleAddFavoritePanelButton favoritePanelButton = new ToggleAddFavoritePanelButton(this); - - private static Rectangle updateInnerBounds(Rectangle bounds) { - int entrySize = entrySize(); - int width = Math.max(Mth.floor((bounds.width - 2 - 6) / (float) entrySize), 1); - if (!ConfigObject.getInstance().isLeftHandSidePanel()) - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) + 3), bounds.y, width * entrySize, bounds.height); - return new Rectangle((int) (bounds.getCenterX() - width * (entrySize / 2f) - 3), bounds.y, width * entrySize, bounds.height); - } + private List<Widget> children = ImmutableList.of(favoritePanel, favoritePanelButton, region); @Override - public boolean mouseScrolled(double double_1, double double_2, double double_3) { - if (currentBounds.contains(double_1, double_2)) { + public boolean mouseScrolled(double mouseX, double mouseY, double amount) { + if (fullBounds.contains(mouseX, mouseY)) { if (Screen.hasControlDown()) { ConfigObjectImpl config = ConfigManagerImpl.getInstance().getConfig(); - if (config.setEntrySize(config.getEntrySize() + double_3 * 0.075)) { + if (config.setEntrySize(config.getEntrySize() + amount * 0.075)) { ConfigManager.getInstance().saveConfig(); REIRuntime.getInstance().getOverlay().ifPresent(ScreenOverlay::queueReloadOverlay); return true; } - } else { - if (favoritePanel.mouseScrolled(double_1, double_2, double_3)) { - return true; - } - scrolling.offset(ClothConfigInitializer.getScrollStep() * -double_3, true); |
