Skip to content

Commit 1bae8b5

Browse files
committed
Add convenience methods and make scrolling grids of ingredients much easier to create
1 parent dee2eaf commit 1bae8b5

37 files changed

+339
-124
lines changed

Common/src/main/java/mezz/jei/common/gui/elements/OffsetDrawable.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import mezz.jei.api.gui.drawable.IDrawable;
44
import mezz.jei.api.gui.placement.IPlaceable;
5+
import mezz.jei.common.util.ImmutableRect2i;
56
import net.minecraft.client.gui.GuiGraphics;
67

78
/**
@@ -55,4 +56,8 @@ public OffsetDrawable setPosition(int xPos, int yPos) {
5556
this.yOffset = yPos;
5657
return this;
5758
}
59+
60+
public ImmutableRect2i getArea() {
61+
return new ImmutableRect2i(xOffset, yOffset, getWidth(), getHeight());
62+
}
5863
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
package mezz.jei.common.util;
22

3-
public record ImmutablePoint2i(int x, int y) {}
3+
public record ImmutablePoint2i(int x, int y) {
4+
public static final ImmutablePoint2i ORIGIN = new ImmutablePoint2i(0, 0);
5+
}

Common/src/main/java/mezz/jei/common/util/MathUtil.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ public static double distance(Vec2 start, Vec2 end) {
112112
* Illegal matrix math assumes the pose is only scaling and translation.
113113
* If we get rotating GUI elements we're doomed, I hope nobody wants those.
114114
*/
115-
public static ScreenRectangle transform(ScreenRectangle rect, Matrix4f pose) {
116-
Vector3f topLeft = new Vector3f(rect.left(), rect.top(), 1.0f);
117-
Vector3f bottomRight = new Vector3f(rect.right(), rect.bottom(), 1.0f);
115+
public static ScreenRectangle transform(ImmutableRect2i rect, Matrix4f pose) {
116+
Vector3f topLeft = new Vector3f(rect.x(), rect.y(), 1.0f);
117+
Vector3f bottomRight = new Vector3f(rect.x() + rect.width(), rect.y() + rect.getHeight(), 1.0f);
118118

119119
topLeft = pose.transformPosition(topLeft);
120120
bottomRight = pose.transformPosition(bottomRight);

CommonApi/src/main/java/mezz/jei/api/gui/builder/IRecipeLayoutBuilder.java

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package mezz.jei.api.gui.builder;
22

33
import mezz.jei.api.gui.placement.IPlaceable;
4-
import mezz.jei.api.gui.widgets.ISlottedWidgetFactory;
4+
import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder;
55
import mezz.jei.api.recipe.IFocusGroup;
66
import mezz.jei.api.recipe.RecipeIngredientRole;
77
import mezz.jei.api.recipe.category.IRecipeCategory;
@@ -29,6 +29,18 @@ default IRecipeSlotBuilder addInputSlot(int x, int y) {
2929
.setPosition(x, y);
3030
}
3131

32+
/**
33+
* Convenience function to add an input slot.
34+
* Set its position using {@link IPlaceable} methods on {@link IRecipeSlotBuilder}.
35+
*
36+
* @return a {@link IRecipeSlotBuilder} that has further methods for adding ingredients, setting position, etc.
37+
*
38+
* @since 19.19.3
39+
*/
40+
default IRecipeSlotBuilder addInputSlot() {
41+
return addSlot(RecipeIngredientRole.INPUT);
42+
}
43+
3244
/**
3345
* Convenience function to add an output slot that will be drawn at the given position relative to the recipe layout.
3446
*
@@ -43,6 +55,18 @@ default IRecipeSlotBuilder addOutputSlot(int x, int y) {
4355
.setPosition(x, y);
4456
}
4557

58+
/**
59+
* Convenience function to add an output slot.
60+
* Set its position using {@link IPlaceable} methods on {@link IRecipeSlotBuilder}.
61+
*
62+
* @return a {@link IRecipeSlotBuilder} that has further methods for adding ingredients, setting position, etc.
63+
*
64+
* @since 19.19.3
65+
*/
66+
default IRecipeSlotBuilder addOutputSlot() {
67+
return addSlot(RecipeIngredientRole.OUTPUT);
68+
}
69+
4670
/**
4771
* Add a slot that will be drawn at the given position relative to the recipe layout.
4872
*
@@ -59,7 +83,7 @@ default IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) {
5983
}
6084

6185
/**
62-
* Add a slot and set its position using {@link IPlaceable} methods.
86+
* Add a slot and set its position using {@link IPlaceable} methods on {@link IRecipeSlotBuilder}.
6387
*
6488
* @param role the {@link RecipeIngredientRole} of this slot (for lookups).
6589
* @return a {@link IRecipeSlotBuilder} that has further methods for adding ingredients, etc.
@@ -69,14 +93,17 @@ default IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) {
6993
IRecipeSlotBuilder addSlot(RecipeIngredientRole role);
7094

7195
/**
72-
* Assign this slot to a {@link ISlottedWidgetFactory},
96+
* Assign this slot to a {@link mezz.jei.api.gui.widgets.ISlottedWidgetFactory},
7397
* so that the widget can manage this slot instead the recipe category.
7498
*
75-
* @param widgetFactory the {@link ISlottedWidgetFactory} to assign this slot to.
99+
* @param widgetFactory the {@link mezz.jei.api.gui.widgets.ISlottedWidgetFactory} to assign this slot to.
76100
*
77101
* @since 19.7.0
102+
* @deprecated there are easier ways to create slotted widgets now. Use {@link IRecipeExtrasBuilder#addSlottedWidget}.
78103
*/
79-
IRecipeSlotBuilder addSlotToWidget(RecipeIngredientRole role, ISlottedWidgetFactory<?> widgetFactory);
104+
@Deprecated(since = "19.19.3", forRemoval = true)
105+
@SuppressWarnings("removal")
106+
IRecipeSlotBuilder addSlotToWidget(RecipeIngredientRole role, mezz.jei.api.gui.widgets.ISlottedWidgetFactory<?> widgetFactory);
80107

81108
/**
82109
* Add ingredients that are important for recipe lookup, but are not displayed on the recipe layout.

CommonApi/src/main/java/mezz/jei/api/gui/ingredient/IRecipeSlotDrawable.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,12 @@ public interface IRecipeSlotDrawable extends IRecipeSlotView {
107107
default void addTooltipCallback(IRecipeSlotTooltipCallback tooltipCallback) {
108108

109109
}
110+
111+
/**
112+
* Get the area that this recipe slot draws on, including the area covered by its background texture.
113+
* Useful for laying out other recipe elements relative to the slot.
114+
*
115+
* @since 19.19.3
116+
*/
117+
Rect2i getAreaIncludingBackground();
110118
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package mezz.jei.api.gui.ingredient;
2+
3+
import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
4+
import mezz.jei.api.recipe.RecipeIngredientRole;
5+
import org.jetbrains.annotations.Unmodifiable;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Optional;
10+
11+
/**
12+
* Represents all the drawn ingredients in slots that are part of a recipe.
13+
*
14+
* This view is meant as a source of information for drawing, positioning, and tooltips.
15+
*
16+
* @see IRecipeSlotsView for a view with less access to drawable properties of the slots.
17+
*
18+
* @since 19.19.3
19+
*/
20+
public interface IRecipeSlotDrawablesView {
21+
/**
22+
* Get all slots for a recipe.
23+
*
24+
* @since 19.19.3
25+
*/
26+
@Unmodifiable
27+
List<IRecipeSlotDrawable> getSlots();
28+
29+
/**
30+
* Get the list of slots for the given {@link RecipeIngredientRole} for a recipe.
31+
*
32+
* @since 19.19.3
33+
*/
34+
default List<IRecipeSlotDrawable> getSlots(RecipeIngredientRole role) {
35+
List<IRecipeSlotDrawable> list = new ArrayList<>();
36+
for (IRecipeSlotDrawable slotView : getSlots()) {
37+
if (slotView.getRole() == role) {
38+
list.add(slotView);
39+
}
40+
}
41+
return list;
42+
}
43+
44+
/**
45+
* Get a recipe slot by its name set with {@link IRecipeSlotBuilder#setSlotName(String)}.
46+
*
47+
* @since 19.19.3
48+
*/
49+
default Optional<IRecipeSlotDrawable> findSlotByName(String slotName) {
50+
return getSlots().stream()
51+
.filter(slot ->
52+
slot.getSlotName()
53+
.map(slotName::equals)
54+
.orElse(false)
55+
)
56+
.findFirst();
57+
}
58+
}

CommonApi/src/main/java/mezz/jei/api/gui/widgets/IRecipeExtrasBuilder.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package mezz.jei.api.gui.widgets;
22

33
import mezz.jei.api.gui.drawable.IDrawable;
4+
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawable;
5+
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawablesView;
46
import mezz.jei.api.gui.inputs.IJeiGuiEventListener;
57
import mezz.jei.api.gui.inputs.IJeiInputHandler;
68
import mezz.jei.api.gui.placement.IPlaceable;
@@ -26,8 +28,16 @@
2628
* @since 19.6.0
2729
*/
2830
public interface IRecipeExtrasBuilder {
31+
32+
/**
33+
* Get the recipe slots that were created in {@link IRecipeCategory#setRecipe}.
34+
*
35+
* @since 19.19.3
36+
*/
37+
IRecipeSlotDrawablesView getRecipeSlots();
38+
2939
/**
30-
* Add a {@link IDrawable} for the recipe category.
40+
* Add a {@link IDrawable} for the recipe category at the given position.
3141
*
3242
* @since 19.19.0
3343
*/
@@ -47,6 +57,14 @@ public interface IRecipeExtrasBuilder {
4757
*/
4858
void addWidget(IRecipeWidget widget);
4959

60+
/**
61+
* Add a {@link ISlottedRecipeWidget} for the recipe category, and
62+
* mark that the slots are going to be handled by the slotted widget.
63+
*
64+
* @since 19.19.3
65+
*/
66+
void addSlottedWidget(ISlottedRecipeWidget widget, List<IRecipeSlotDrawable> slots);
67+
5068
/**
5169
* Add a {@link IJeiInputHandler} for the recipe category.
5270
*
@@ -71,6 +89,18 @@ public interface IRecipeExtrasBuilder {
7189
*/
7290
IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos);
7391

92+
/**
93+
* Create and add a new scroll grid widget.
94+
* Handles displaying ingredients in a scrolling area with a scrollbar, similar to the vanilla creative menu.
95+
*
96+
* Get slots for this from {@link #getRecipeSlots()}.
97+
*
98+
* You can move the resulting grid by using the {@link IScrollGridWidget}'s {@link IPlaceable} methods.
99+
*
100+
* @since 19.19.3
101+
*/
102+
IScrollGridWidget addScrollGridWidget(List<IRecipeSlotDrawable> slots, int columns, int visibleRows);
103+
74104
/**
75105
* Add a vanilla-style recipe arrow to the recipe layout.
76106
*
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package mezz.jei.api.gui.widgets;
2+
3+
import mezz.jei.api.gui.placement.IPlaceable;
4+
import net.minecraft.client.gui.navigation.ScreenRectangle;
5+
6+
/**
7+
* A scrolling area for ingredients with a scrollbar.
8+
* Modeled after the vanilla creative menu.
9+
*
10+
* Create one with {@link IRecipeExtrasBuilder#addScrollGridWidget}.
11+
* @since 19.19.3
12+
*/
13+
public interface IScrollGridWidget extends ISlottedRecipeWidget, IPlaceable<IScrollGridWidget> {
14+
/**
15+
* Get the position and size of this widget, relative to its parent element.
16+
*
17+
* @since 19.19.3
18+
*/
19+
ScreenRectangle getScreenRectangle();
20+
}

CommonApi/src/main/java/mezz/jei/api/gui/widgets/IScrollGridWidgetFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
* Get an instance from {@link IGuiHelper#createScrollGridFactory(int, int)}
1010
*
1111
* @since 19.7.0
12+
* @deprecated use {@link IRecipeExtrasBuilder#addScrollGridWidget} instead, it's much simpler
1213
*/
14+
@SuppressWarnings({"DeprecatedIsStillUsed", "removal"})
15+
@Deprecated(since = "19.19.3", forRemoval = true)
1316
public interface IScrollGridWidgetFactory<R> extends ISlottedWidgetFactory<R> {
1417
/**
1518
* @since 19.7.0

CommonApi/src/main/java/mezz/jei/api/gui/widgets/ISlottedRecipeWidget.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
11
package mezz.jei.api.gui.widgets;
22

3-
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
43
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawable;
54
import mezz.jei.api.gui.inputs.RecipeSlotUnderMouse;
6-
import mezz.jei.api.recipe.category.IRecipeCategory;
75

6+
import java.util.List;
87
import java.util.Optional;
98

109
/**
1110
* Like {@link IRecipeWidget}, but it also manages {@link IRecipeSlotDrawable}s.
1211
*
13-
* These must be created by an {@link ISlottedWidgetFactory}.
14-
* Pass the factory to {@link IRecipeLayoutBuilder#addSlotToWidget}
15-
* when creating slots in {@link IRecipeCategory#setRecipe}
16-
*
17-
* Once the slots are built, the factory will be called to create your complete {@link ISlottedRecipeWidget}.
12+
* Add one to a recipe category by using {@link IRecipeExtrasBuilder#addSlottedWidget(ISlottedRecipeWidget, List)}
1813
*
1914
* @since 19.7.0
2015
*/

0 commit comments

Comments
 (0)