Skip to content

Commit

Permalink
Add convenience methods and make scrolling grids of ingredients much …
Browse files Browse the repository at this point in the history
…easier to create
  • Loading branch information
mezz committed Oct 1, 2024
1 parent dee2eaf commit 1bae8b5
Show file tree
Hide file tree
Showing 37 changed files with 339 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.placement.IPlaceable;
import mezz.jei.common.util.ImmutableRect2i;
import net.minecraft.client.gui.GuiGraphics;

/**
Expand Down Expand Up @@ -55,4 +56,8 @@ public OffsetDrawable setPosition(int xPos, int yPos) {
this.yOffset = yPos;
return this;
}

public ImmutableRect2i getArea() {
return new ImmutableRect2i(xOffset, yOffset, getWidth(), getHeight());
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package mezz.jei.common.util;

public record ImmutablePoint2i(int x, int y) {}
public record ImmutablePoint2i(int x, int y) {
public static final ImmutablePoint2i ORIGIN = new ImmutablePoint2i(0, 0);
}
6 changes: 3 additions & 3 deletions Common/src/main/java/mezz/jei/common/util/MathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ public static double distance(Vec2 start, Vec2 end) {
* Illegal matrix math assumes the pose is only scaling and translation.
* If we get rotating GUI elements we're doomed, I hope nobody wants those.
*/
public static ScreenRectangle transform(ScreenRectangle rect, Matrix4f pose) {
Vector3f topLeft = new Vector3f(rect.left(), rect.top(), 1.0f);
Vector3f bottomRight = new Vector3f(rect.right(), rect.bottom(), 1.0f);
public static ScreenRectangle transform(ImmutableRect2i rect, Matrix4f pose) {
Vector3f topLeft = new Vector3f(rect.x(), rect.y(), 1.0f);
Vector3f bottomRight = new Vector3f(rect.x() + rect.width(), rect.y() + rect.getHeight(), 1.0f);

topLeft = pose.transformPosition(topLeft);
bottomRight = pose.transformPosition(bottomRight);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mezz.jei.api.gui.builder;

import mezz.jei.api.gui.placement.IPlaceable;
import mezz.jei.api.gui.widgets.ISlottedWidgetFactory;
import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.category.IRecipeCategory;
Expand Down Expand Up @@ -29,6 +29,18 @@ default IRecipeSlotBuilder addInputSlot(int x, int y) {
.setPosition(x, y);
}

/**
* Convenience function to add an input slot.
* Set its position using {@link IPlaceable} methods on {@link IRecipeSlotBuilder}.
*
* @return a {@link IRecipeSlotBuilder} that has further methods for adding ingredients, setting position, etc.
*
* @since 19.19.3
*/
default IRecipeSlotBuilder addInputSlot() {
return addSlot(RecipeIngredientRole.INPUT);
}

/**
* Convenience function to add an output slot that will be drawn at the given position relative to the recipe layout.
*
Expand All @@ -43,6 +55,18 @@ default IRecipeSlotBuilder addOutputSlot(int x, int y) {
.setPosition(x, y);
}

/**
* Convenience function to add an output slot.
* Set its position using {@link IPlaceable} methods on {@link IRecipeSlotBuilder}.
*
* @return a {@link IRecipeSlotBuilder} that has further methods for adding ingredients, setting position, etc.
*
* @since 19.19.3
*/
default IRecipeSlotBuilder addOutputSlot() {
return addSlot(RecipeIngredientRole.OUTPUT);
}

/**
* Add a slot that will be drawn at the given position relative to the recipe layout.
*
Expand All @@ -59,7 +83,7 @@ default IRecipeSlotBuilder addSlot(RecipeIngredientRole role, int x, int y) {
}

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

/**
* Assign this slot to a {@link ISlottedWidgetFactory},
* Assign this slot to a {@link mezz.jei.api.gui.widgets.ISlottedWidgetFactory},
* so that the widget can manage this slot instead the recipe category.
*
* @param widgetFactory the {@link ISlottedWidgetFactory} to assign this slot to.
* @param widgetFactory the {@link mezz.jei.api.gui.widgets.ISlottedWidgetFactory} to assign this slot to.
*
* @since 19.7.0
* @deprecated there are easier ways to create slotted widgets now. Use {@link IRecipeExtrasBuilder#addSlottedWidget}.
*/
IRecipeSlotBuilder addSlotToWidget(RecipeIngredientRole role, ISlottedWidgetFactory<?> widgetFactory);
@Deprecated(since = "19.19.3", forRemoval = true)
@SuppressWarnings("removal")
IRecipeSlotBuilder addSlotToWidget(RecipeIngredientRole role, mezz.jei.api.gui.widgets.ISlottedWidgetFactory<?> widgetFactory);

/**
* Add ingredients that are important for recipe lookup, but are not displayed on the recipe layout.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,12 @@ public interface IRecipeSlotDrawable extends IRecipeSlotView {
default void addTooltipCallback(IRecipeSlotTooltipCallback tooltipCallback) {

}

/**
* Get the area that this recipe slot draws on, including the area covered by its background texture.
* Useful for laying out other recipe elements relative to the slot.
*
* @since 19.19.3
*/
Rect2i getAreaIncludingBackground();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package mezz.jei.api.gui.ingredient;

import mezz.jei.api.gui.builder.IRecipeSlotBuilder;
import mezz.jei.api.recipe.RecipeIngredientRole;
import org.jetbrains.annotations.Unmodifiable;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
* Represents all the drawn ingredients in slots that are part of a recipe.
*
* This view is meant as a source of information for drawing, positioning, and tooltips.
*
* @see IRecipeSlotsView for a view with less access to drawable properties of the slots.
*
* @since 19.19.3
*/
public interface IRecipeSlotDrawablesView {
/**
* Get all slots for a recipe.
*
* @since 19.19.3
*/
@Unmodifiable
List<IRecipeSlotDrawable> getSlots();

/**
* Get the list of slots for the given {@link RecipeIngredientRole} for a recipe.
*
* @since 19.19.3
*/
default List<IRecipeSlotDrawable> getSlots(RecipeIngredientRole role) {
List<IRecipeSlotDrawable> list = new ArrayList<>();
for (IRecipeSlotDrawable slotView : getSlots()) {
if (slotView.getRole() == role) {
list.add(slotView);
}
}
return list;
}

/**
* Get a recipe slot by its name set with {@link IRecipeSlotBuilder#setSlotName(String)}.
*
* @since 19.19.3
*/
default Optional<IRecipeSlotDrawable> findSlotByName(String slotName) {
return getSlots().stream()
.filter(slot ->
slot.getSlotName()
.map(slotName::equals)
.orElse(false)
)
.findFirst();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package mezz.jei.api.gui.widgets;

import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawable;
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawablesView;
import mezz.jei.api.gui.inputs.IJeiGuiEventListener;
import mezz.jei.api.gui.inputs.IJeiInputHandler;
import mezz.jei.api.gui.placement.IPlaceable;
Expand All @@ -26,8 +28,16 @@
* @since 19.6.0
*/
public interface IRecipeExtrasBuilder {

/**
* Get the recipe slots that were created in {@link IRecipeCategory#setRecipe}.
*
* @since 19.19.3
*/
IRecipeSlotDrawablesView getRecipeSlots();

/**
* Add a {@link IDrawable} for the recipe category.
* Add a {@link IDrawable} for the recipe category at the given position.
*
* @since 19.19.0
*/
Expand All @@ -47,6 +57,14 @@ public interface IRecipeExtrasBuilder {
*/
void addWidget(IRecipeWidget widget);

/**
* Add a {@link ISlottedRecipeWidget} for the recipe category, and
* mark that the slots are going to be handled by the slotted widget.
*
* @since 19.19.3
*/
void addSlottedWidget(ISlottedRecipeWidget widget, List<IRecipeSlotDrawable> slots);

/**
* Add a {@link IJeiInputHandler} for the recipe category.
*
Expand All @@ -71,6 +89,18 @@ public interface IRecipeExtrasBuilder {
*/
IScrollBoxWidget addScrollBoxWidget(int width, int height, int xPos, int yPos);

/**
* Create and add a new scroll grid widget.
* Handles displaying ingredients in a scrolling area with a scrollbar, similar to the vanilla creative menu.
*
* Get slots for this from {@link #getRecipeSlots()}.
*
* You can move the resulting grid by using the {@link IScrollGridWidget}'s {@link IPlaceable} methods.
*
* @since 19.19.3
*/
IScrollGridWidget addScrollGridWidget(List<IRecipeSlotDrawable> slots, int columns, int visibleRows);

/**
* Add a vanilla-style recipe arrow to the recipe layout.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mezz.jei.api.gui.widgets;

import mezz.jei.api.gui.placement.IPlaceable;
import net.minecraft.client.gui.navigation.ScreenRectangle;

/**
* A scrolling area for ingredients with a scrollbar.
* Modeled after the vanilla creative menu.
*
* Create one with {@link IRecipeExtrasBuilder#addScrollGridWidget}.
* @since 19.19.3
*/
public interface IScrollGridWidget extends ISlottedRecipeWidget, IPlaceable<IScrollGridWidget> {
/**
* Get the position and size of this widget, relative to its parent element.
*
* @since 19.19.3
*/
ScreenRectangle getScreenRectangle();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
* Get an instance from {@link IGuiHelper#createScrollGridFactory(int, int)}
*
* @since 19.7.0
* @deprecated use {@link IRecipeExtrasBuilder#addScrollGridWidget} instead, it's much simpler
*/
@SuppressWarnings({"DeprecatedIsStillUsed", "removal"})
@Deprecated(since = "19.19.3", forRemoval = true)
public interface IScrollGridWidgetFactory<R> extends ISlottedWidgetFactory<R> {
/**
* @since 19.7.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
package mezz.jei.api.gui.widgets;

import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.ingredient.IRecipeSlotDrawable;
import mezz.jei.api.gui.inputs.RecipeSlotUnderMouse;
import mezz.jei.api.recipe.category.IRecipeCategory;

import java.util.List;
import java.util.Optional;

/**
* Like {@link IRecipeWidget}, but it also manages {@link IRecipeSlotDrawable}s.
*
* These must be created by an {@link ISlottedWidgetFactory}.
* Pass the factory to {@link IRecipeLayoutBuilder#addSlotToWidget}
* when creating slots in {@link IRecipeCategory#setRecipe}
*
* Once the slots are built, the factory will be called to create your complete {@link ISlottedRecipeWidget}.
* Add one to a recipe category by using {@link IRecipeExtrasBuilder#addSlottedWidget(ISlottedRecipeWidget, List)}
*
* @since 19.7.0
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
* and then JEI will call {@link #createWidgetForSlots} after all the slots are built.
*
* @since 19.7.0
* @deprecated there are easier ways to create slotted widgets now. Use {@link IRecipeExtrasBuilder#addSlottedWidget}.
*/
@SuppressWarnings({"DeprecatedIsStillUsed", "removal"})
@Deprecated(since = "19.19.3", forRemoval = true)
@FunctionalInterface
public interface ISlottedWidgetFactory<R> {
/**
Expand All @@ -26,5 +29,7 @@ public interface ISlottedWidgetFactory<R> {
*
* @since 19.7.0
*/
@Deprecated(since = "19.19.3", forRemoval = true)
@SuppressWarnings("removal")
void createWidgetForSlots(IRecipeExtrasBuilder builder, R recipe, List<IRecipeSlotDrawable> slots);
}
9 changes: 5 additions & 4 deletions CommonApi/src/main/java/mezz/jei/api/helpers/IGuiHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import mezz.jei.api.gui.widgets.IRecipeExtrasBuilder;
import mezz.jei.api.gui.widgets.IRecipeWidget;
import mezz.jei.api.gui.widgets.IScrollBoxWidget;
import mezz.jei.api.gui.widgets.IScrollGridWidgetFactory;
import mezz.jei.api.gui.widgets.ISlottedWidgetFactory;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.recipe.RecipeIngredientRole;
Expand Down Expand Up @@ -176,11 +174,14 @@ default IDrawable createDrawableItemLike(ItemLike itemLike) {
* Create a scroll grid widget factory.
* Handles displaying a grid of ingredient slots in a scrolling area.
*
* Add ingredients to it using {@link IRecipeLayoutBuilder#addSlotToWidget(RecipeIngredientRole, ISlottedWidgetFactory)}
* Add ingredients to it using {@link IRecipeLayoutBuilder#addSlotToWidget(RecipeIngredientRole, mezz.jei.api.gui.widgets.ISlottedWidgetFactory)}
*
* @since 19.7.0
* @deprecated use {@link IRecipeExtrasBuilder#addScrollGridWidget} instead, it's much simpler
*/
IScrollGridWidgetFactory<?> createScrollGridFactory(int columns, int visibleRows);
@SuppressWarnings("removal")
@Deprecated(since = "19.19.3", forRemoval = true)
mezz.jei.api.gui.widgets.IScrollGridWidgetFactory<?> createScrollGridFactory(int columns, int visibleRows);

/**
* Create a scroll box widget.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import net.minecraft.world.item.crafting.RecipeHolder;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.List;

/**
Expand Down Expand Up @@ -119,9 +120,11 @@ default int getHeight() {
* information more easily than from the recipe category directly.
*
* @since 19.19.0
* @deprecated use {@link #createRecipeExtras(IRecipeExtrasBuilder, Object, IFocusGroup)}, the recipe slots are in {@link IRecipeExtrasBuilder#getRecipeSlots()} now.
*/
@Deprecated(since = "19.19.3", forRemoval = true)
default void createRecipeExtras(IRecipeExtrasBuilder builder, T recipe, IRecipeSlotsView recipeSlotsView, IFocusGroup focuses) {
createRecipeExtras(builder, recipe, focuses);

}

/**
Expand All @@ -132,11 +135,10 @@ default void createRecipeExtras(IRecipeExtrasBuilder builder, T recipe, IRecipeS
* information more easily than from the recipe category directly.
*
* @since 19.6.0
* @deprecated use {@link #createRecipeExtras(IRecipeExtrasBuilder, Object, IRecipeSlotsView, IFocusGroup)}
*/
@Deprecated(since = "19.19.0", forRemoval = true)
@SuppressWarnings("RedundantUnmodifiable")
default void createRecipeExtras(IRecipeExtrasBuilder builder, T recipe, IFocusGroup focuses) {

createRecipeExtras(builder, recipe, () -> Collections.unmodifiableList(builder.getRecipeSlots().getSlots()), focuses);
}

/**
Expand Down
Loading

0 comments on commit 1bae8b5

Please sign in to comment.