diff options
Diffstat (limited to 'api/src/main/java/me/shedaniel')
17 files changed, 783 insertions, 27 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java new file mode 100644 index 000000000..c6d1a35cf --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableBoundsProvider.java @@ -0,0 +1,70 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag; + +import me.shedaniel.math.Rectangle; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; + +import java.util.stream.StreamSupport; + +@FunctionalInterface +public interface DraggableBoundsProvider { + static VoxelShape fromRectangle(Rectangle bounds) { + return Shapes.box(bounds.x, bounds.y, 0, bounds.getMaxX(), bounds.getMaxY(), 0.1); + } + + static DraggableBoundsProvider ofRectangle(Rectangle bounds) { + return ofShape(fromRectangle(bounds)); + } + + static DraggableBoundsProvider ofRectangles(Iterable<Rectangle> bounds) { + VoxelShape shape = StreamSupport.stream(bounds.spliterator(), false) + .map(DraggableBoundsProvider::fromRectangle) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static DraggableBoundsProvider ofShape(VoxelShape shape) { + return () -> shape; + } + + static DraggableBoundsProvider ofShapes(Iterable<VoxelShape> shapes) { + VoxelShape shape = StreamSupport.stream(shapes.spliterator(), false) + .reduce(Shapes.empty(), Shapes::or); + return ofShape(shape); + } + + static DraggableBoundsProvider empty() { + return Shapes::empty; + } + + static DraggableBoundsProvider concat(Iterable<DraggableBoundsProvider> providers) { + return () -> StreamSupport.stream(providers.spliterator(), false) + .map(DraggableBoundsProvider::bounds) + .reduce(Shapes.empty(), Shapes::or); + } + + VoxelShape bounds(); +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java index dc3311055..713347743 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStack.java @@ -24,17 +24,64 @@ package me.shedaniel.rei.api.client.gui.drag; import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.common.entry.EntryStack; -public interface DraggableStack { +public interface DraggableStack extends DraggableComponent<EntryStack<?>> { + static DraggableStack from(DraggableComponent<EntryStack<?>> component) { + return component instanceof DraggableStack ? (DraggableStack) component : new DraggableStack() { + @Override + public EntryStack<?> getStack() { + return component.get(); + } + + @Override + public void drag() { + component.drag(); + } + + @Override + public void release(DraggedAcceptorResult result) { + component.release(result); + } + + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + component.render(matrices, bounds, mouseX, mouseY, delta); + } + + @Override + public void render(PoseStack matrices, Point position, int mouseX, int mouseY, float delta) { + component.render(matrices, position, mouseX, mouseY, delta); + } + }; + } + EntryStack<?> getStack(); + @Override + default EntryStack<?> get() { + return getStack(); + } + void drag(); + @Override + default int getWidth() { + return 18; + } + + @Override + default int getHeight() { + return 18; + } + default void release(DraggedAcceptorResult result) { } + @Override default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { getStack().render(matrices, bounds, mouseX, mouseY, delta); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java index 57569b405..e11805d0a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProvider.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProvider; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -31,7 +34,7 @@ import java.util.function.Supplier; /** * A provider for supplying {@link DraggableStack} to the screen. */ -public interface DraggableStackProvider<T extends Screen> extends Comparable<DraggableStackProvider<T>> { +public interface DraggableStackProvider<T extends Screen> extends DraggableComponentProvider<T, EntryStack<?>> { static <T extends Screen> DraggableStackProvider<T> from(Supplier<Iterable<DraggableStackProvider<T>>> providers) { return new DraggableStackProvider<T>() { @Override @@ -61,8 +64,16 @@ public interface DraggableStackProvider<T extends Screen> extends Comparable<Dra @Nullable DraggableStack getHoveredStack(DraggingContext<T> context, double mouseX, double mouseY); + @Override + @Nullable + default DraggableComponent<EntryStack<?>> getHovered(DraggingContext<T> context, double mouseX, double mouseY) { + return getHoveredStack(context, mouseX, mouseY); + } + + @Override <R extends Screen> boolean isHandingScreen(R screen); + @Override default DraggingContext<T> getContext() { return DraggingContext.getInstance().cast(); } @@ -72,11 +83,11 @@ public interface DraggableStackProvider<T extends Screen> extends Comparable<Dra * * @return the priority */ + @Override default double getPriority() { return 0f; } - @Override default int compareTo(DraggableStackProvider<T> o) { return Double.compare(getPriority(), o.getPriority()); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java index 29d375118..d0ae7227c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackProviderWidget.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -33,7 +36,7 @@ import java.util.function.Function; * {@link DraggableStack}. */ @FunctionalInterface -public interface DraggableStackProviderWidget { +public interface DraggableStackProviderWidget extends DraggableComponentProviderWidget<EntryStack<?>> { static DraggableStackProviderWidget from(Function<DraggingContext<Screen>, Iterable<DraggableStackProviderWidget>> providers) { return (context, mouseX, mouseY) -> { for (DraggableStackProviderWidget provider : providers.apply(context)) { @@ -47,6 +50,12 @@ public interface DraggableStackProviderWidget { @Nullable DraggableStack getHoveredStack(DraggingContext<Screen> context, double mouseX, double mouseY); + @Override + @Nullable + default DraggableComponent<EntryStack<?>> getHovered(DraggingContext<Screen> context, double mouseX, double mouseY) { + return getHoveredStack(context, mouseX, mouseY); + } + static DraggableStackProvider<Screen> toProvider(DraggableStackProviderWidget widget) { return toProvider(widget, 0D); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java index 8b8f9c220..dfbf5d69b 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitor.java @@ -24,11 +24,16 @@ package me.shedaniel.rei.api.client.gui.drag; import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitor; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; +import java.util.List; import java.util.Objects; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -36,7 +41,7 @@ import java.util.stream.StreamSupport; /** * A visitor for accepting {@link DraggableStack} to the screen. */ -public interface DraggableStackVisitor<T extends Screen> extends Comparable<DraggableStackVisitor<T>> { +public interface DraggableStackVisitor<T extends Screen> extends DraggableComponentVisitor<T> { static <T extends Screen> DraggableStackVisitor<T> from(Supplier<Iterable<DraggableStackVisitor<T>>> visitors) { return new DraggableStackVisitor<T>() { @Override @@ -81,6 +86,13 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag return DraggedAcceptorResult.PASS; } + @Override + default DraggedAcceptorResult acceptDragged(DraggingContext<T> context, DraggableComponent<?> component) { + return component.<EntryStack<?>>getIf() + .map(comp -> acceptDraggedStack(context, DraggableStack.from(comp))) + .orElse(DraggedAcceptorResult.PASS); + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the area is accepting entries. @@ -93,8 +105,18 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag return Stream.empty(); } + @Override + default Stream<DraggableBoundsProvider> getDraggableAcceptingBounds(DraggingContext<T> context, DraggableComponent<?> component) { + return component.<EntryStack<?>>getIf() + .map(comp -> getDraggableAcceptingBounds(context, DraggableStack.from(comp))) + .orElse(Stream.empty()) + .map(Function.identity()); + } + + @Override <R extends Screen> boolean isHandingScreen(R screen); + @Override default DraggingContext<T> getContext() { return DraggingContext.getInstance().cast(); } @@ -104,11 +126,11 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag * * @return the priority */ + @Override default double getPriority() { return 0.0; } - @Override default int compareTo(DraggableStackVisitor<T> o) { return Double.compare(getPriority(), o.getPriority()); } @@ -119,30 +141,25 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag } @FunctionalInterface - interface BoundsProvider { + interface BoundsProvider extends DraggableBoundsProvider { static VoxelShape fromRectangle(Rectangle bounds) { - return Shapes.box(bounds.x, bounds.y, 0, bounds.getMaxX(), bounds.getMaxY(), 0.1); + return DraggableBoundsProvider.fromRectangle(bounds); } static BoundsProvider ofRectangle(Rectangle bounds) { - return ofShape(fromRectangle(bounds)); + return DraggableBoundsProvider.ofRectangle(bounds)::bounds; } static BoundsProvider ofRectangles(Iterable<Rectangle> bounds) { - VoxelShape shape = StreamSupport.stream(bounds.spliterator(), false) - .map(BoundsProvider::fromRectangle) - .reduce(Shapes.empty(), Shapes::or); - return ofShape(shape); + return DraggableBoundsProvider.ofRectangles(bounds)::bounds; } static BoundsProvider ofShape(VoxelShape shape) { - return () -> shape; + return DraggableBoundsProvider.ofShape(shape)::bounds; } static BoundsProvider ofShapes(Iterable<VoxelShape> shapes) { - VoxelShape shape = StreamSupport.stream(shapes.spliterator(), false) - .reduce(Shapes.empty(), Shapes::or); - return ofShape(shape); + return DraggableBoundsProvider.ofShapes(shapes)::bounds; } static BoundsProvider empty() { @@ -150,11 +167,11 @@ public interface DraggableStackVisitor<T extends Screen> extends Comparable<Drag } static BoundsProvider concat(Iterable<BoundsProvider> providers) { - return () -> StreamSupport.stream(providers.spliterator(), false) - .map(BoundsProvider::bounds) - .reduce(Shapes.empty(), Shapes::or); + return DraggableBoundsProvider.concat((List<DraggableBoundsProvider>) + (List<? extends DraggableBoundsProvider>) providers)::bounds; } + @Override VoxelShape bounds(); } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java index 9181b82d2..34d49f53a 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggableStackVisitorWidget.java @@ -23,6 +23,9 @@ package me.shedaniel.rei.api.client.gui.drag; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; +import me.shedaniel.rei.api.common.entry.EntryStack; import net.minecraft.client.gui.screens.Screen; import java.util.function.Function; @@ -33,7 +36,7 @@ import java.util.stream.StreamSupport; * An interface to be implemented on {@link me.shedaniel.rei.api.client.gui.widgets.Widget} to accept * incoming {@link DraggableStack}. */ -public interface DraggableStackVisitorWidget { +public interface DraggableStackVisitorWidget extends DraggableComponentVisitorWidget { static DraggableStackVisitorWidget from(Function<DraggingContext<Screen>, Iterable<DraggableStackVisitorWidget>> providers) { return new DraggableStackVisitorWidget() { @Override @@ -65,6 +68,13 @@ public interface DraggableStackVisitorWidget { return DraggedAcceptorResult.PASS; } + @Override + default DraggedAcceptorResult acceptDragged(DraggingContext<Screen> context, DraggableComponent<?> component) { + return component.<EntryStack<?>>getIf() + .map(comp -> acceptDraggedStack(context, DraggableStack.from(comp))) + .orElse(DraggedAcceptorResult.PASS); + } + /** * Returns the accepting bounds for the dragging stack, this should only be called once on drag. * The bounds are used to overlay to indicate to the users that the widget is accepting entries. @@ -77,6 +87,14 @@ public interface DraggableStackVisitorWidget { return Stream.empty(); } + @Override + default Stream<DraggableBoundsProvider> getDraggableAcceptingBounds(DraggingContext<Screen> context, DraggableComponent<?> component) { + return component.<EntryStack<?>>getIf() + .map(comp -> getDraggableAcceptingBounds(context, DraggableStack.from(comp))) + .orElse(Stream.empty()) + .map(Function.identity()); + } + static DraggableStackVisitor<Screen> toVisitor(DraggableStackVisitorWidget widget) { return toVisitor(widget, 0.0); } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java index 30e6549c3..ea96128c7 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/DraggingContext.java @@ -23,9 +23,12 @@ package me.shedaniel.rei.api.client.gui.drag; +import com.google.common.base.MoreObjects; 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.gui.drag.component.DraggableComponent; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -54,6 +57,15 @@ public interface DraggingContext<S extends Screen> { return getCurrentStack() != null; } + /** + * Returns whether a draggable component is present. + * + * @return whether a draggable component is present + */ + default boolean isDraggingComponent() { + return getDragged() != null; + } + S getScreen(); /** @@ -65,6 +77,14 @@ public interface DraggingContext<S extends Screen> { DraggableStack getCurrentStack(); /** + * Returns the current dragged component, may be null. + * + * @return the current dragged component, may be null + */ + @Nullable + DraggableComponent<?> getDragged(); + + /** * Returns the current position of the dragged stack, this is usually the position of the mouse pointer, * but you should use this regardless to account for future changes. * @@ -74,6 +94,15 @@ public interface DraggingContext<S extends Screen> { Point getCurrentPosition(); /** + * Returns the current bounds of the dragged stack, this is usually on the mouse pointer, + * but you should use this regardless to account for future changes. + * + * @return the current bounds of the dragged stack + */ + @Nullable + Rectangle getCurrentBounds(); + + /** * Renders the draggable stack back to the position {@code position}. * This may be used to animate an unaccepted draggable stack returning to its initial position. * @@ -81,7 +110,9 @@ public interface DraggingContext<S extends Screen> { * @param initialPosition the initial position of the stack * @param position the position supplier of the destination */ - void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier<Point> position); + default void renderBackToPosition(DraggableStack stack, Point initialPosition, Supplier<Point> position) { + renderBack(stack, initialPosition, position); + } /** * Renders the draggable stack back to the bounds {@code bounds}. @@ -91,12 +122,40 @@ public interface DraggingContext<S extends Screen> { * @param initialPosition the initial bounds of the stack * @param bounds the boundary supplier of the destination */ - void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier<Rectangle> bounds); + default void renderBackToPosition(DraggableStack stack, Rectangle initialPosition, Supplier<Rectangle> bounds) { + renderBack(stack, initialPosition, bounds); + } default void renderToVoid(DraggableStack stack) { - Point currentPosition = getCurrentPosition(); - Rectangle targetBounds = new Rectangle(currentPosition.x, currentPosition.y, 1, 1); - renderBackToPosition(stack, new Rectangle(currentPosition.x - 8, currentPosition.y - 8, 16, 16), () -> targetBounds); + this.renderToVoid((DraggableComponent<?>) stack); + } + + /** + * Renders the draggable component back to the position {@code position}. + * This may be used to animate an unaccepted draggable component returning to its initial position. + * + * @param component the component to use for render + * @param initialPosition the initial position of the component + * @param position the position supplier of the destination + */ + void renderBack(DraggableComponent<?> component, Point initialPosition, Supplier<Point> position); + + /** + * Renders the draggable component back to the bounds {@code bounds}. + * This may be used to animate an unaccepted draggable component returning to its initial position. + * + * @param component the component to use for render + * @param initialPosition the initial bounds of the component + * @param bounds the boundary supplier of the destination + */ + void renderBack(DraggableComponent<?> component, Rectangle initialPosition, Supplier<Rectangle> bounds); + + default void renderToVoid(DraggableComponent<?> component) { + Rectangle currentBounds = MoreObjects.firstNonNull(getCurrentBounds(), component.getOriginBounds(PointHelper.ofMouse())); + Rectangle targetBounds = new Rectangle(currentBounds.getCenterX(), currentBounds.getCenterY(), 1, 1); + int width = component.getWidth(); + int height = component.getHeight(); + renderBack(component, currentBounds, () -> targetBounds); } default <T extends Screen> DraggingContext<T> cast() { diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java new file mode 100644 index 000000000..e1153a408 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponent.java @@ -0,0 +1,83 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import com.mojang.blaze3d.vertex.PoseStack; +import me.shedaniel.math.Point; +import me.shedaniel.math.Rectangle; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; + +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public interface DraggableComponent<T> extends Supplier<T> { + default <A> Optional<DraggableComponent<A>> getIf(A... typeHack) { + if (typeHack.length != 0) throw new IllegalStateException("array must be empty!"); + if (typeHack.getClass().getComponentType().isInstance(get())) { + return Optional.of((DraggableComponent<A>) this); + } else { + return Optional.empty(); + } + } + + default <A> boolean ifMatches(Consumer<A> consumer, A... typeHack) { + Optional<DraggableComponent<A>> optional = getIf(typeHack); + optional.ifPresent(comp -> consumer.accept(comp.get())); + return optional.isPresent(); + } + + default <A> boolean ifMatches(Predicate<A> consumer, A... typeHack) { + Optional<DraggableComponent<A>> optional = getIf(typeHack); + return optional.map(comp -> consumer.test(comp.get())).orElse(false); + } + + int getWidth(); + + int getHeight(); + + /** + * Returns the bounds of the component. This is the bounds that the origin of the component is at. + * + * @param mouse the mouse position + * @return the bounds of the component + */ + default Rectangle getOriginBounds(Point mouse) { + return new Rectangle(mouse.x - getWidth() / 2, mouse.y - getHeight() / 2, getWidth(), getHeight()); + } + + default void drag() { + } + + default void release(DraggedAcceptorResult result) { + } + + default void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + } + + default void render(PoseStack matrices, Point position, int mouseX, int mouseY, float delta) { + render(matrices, new Rectangle(position.x - getWidth() / 2, position.y - getHeight() / 2, getWidth(), getHeight()), mouseX, mouseY, delta); + } +} diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java new file mode 100644 index 000000000..b52728b53 --- /dev/null +++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/drag/component/DraggableComponentProvider.java @@ -0,0 +1,84 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022 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.api.client.gui.drag.component; + +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import net.minecraft.client.gui.screens.Screen; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +/** + * A provider for supplying {@link DraggableComponent} to the screen. + */ +public interface DraggableComponentProvider<T extends Screen, A> extends Comparable<DraggableComponentProvider<T, A>> { + static <T extends Screen, A> DraggableComponentProvider<T, A> from(Supplier<? extends Iterable<? extends DraggableComponentProvider<T, A>>> providers) { + return new DraggableComponentProvider<T, A>() { + @Override + public <R extends Screen> boolean isHandingScreen(R screen) { + for (DraggableComponentProvider<T, A> provider : providers.get()) { + if (provider.isHandingScreen(screen)) { + return true; + } + } + return false; + } + + @Override + @Nullable + public DraggableComponent<A> getHovered(DraggingContext<T> context, double mouseX, double mouseY) { + for (DraggableComponentProvider<T, A> provider : providers.get()) { + if (provider.isHandingScreen(context.getScreen())) { + DraggableComponent<A> component = provider.getHovered(context, mouseX, mouseY); + if (component != null) return component; + } + } + return null; + } + }; + } |
