Skip to content

Commit

Permalink
Merge pull request #3787 from mezz/1.20.1-backport
Browse files Browse the repository at this point in the history
Backport features from 1.21.1
  • Loading branch information
mezz authored Oct 1, 2024
2 parents 4fa7b98 + 64b14c4 commit b7f27fd
Show file tree
Hide file tree
Showing 79 changed files with 2,164 additions and 1,043 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import mezz.jei.api.gui.drawable.IDrawableStatic;

public record DrawableBlank(int width, int height) implements IDrawableStatic, IDrawableAnimated {
public static final DrawableBlank EMPTY = new DrawableBlank(0, 0);

@Override
public int getWidth() {
return width;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mezz.jei.common.gui.elements;

import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.drawable.IDrawableAnimated;
import net.minecraft.client.gui.GuiGraphics;

import java.util.List;

public class DrawableCombined implements IDrawableAnimated {
private final List<IDrawable> drawables;
private final int width;
private final int height;

public DrawableCombined(IDrawable... drawables) {
this(List.of(drawables));
}

public DrawableCombined(List<IDrawable> drawables) {
IDrawable first = drawables.get(0);
this.width = first.getWidth();
this.height = first.getHeight();
for (int i = 1; i < drawables.size(); i++) {
IDrawable drawable = drawables.get(i);
if (drawable.getWidth() != width || drawable.getHeight() != height) {
throw new IllegalArgumentException("Drawables must have the same width and height. Expected " + width + " x " + height + " but got " + drawable.getWidth() + " x " + drawable.getHeight());
}
}
this.drawables = drawables;
}

@Override
public int getWidth() {
return width;
}

@Override
public int getHeight() {
return height;
}

@Override
public void draw(GuiGraphics guiGraphics) {
for (IDrawable drawable : drawables) {
drawable.draw(guiGraphics);
}
}

@Override
public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) {
for (IDrawable drawable : drawables) {
drawable.draw(guiGraphics, xOffset, yOffset);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package mezz.jei.common.gui.elements;

import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.common.util.StringUtil;
import mezz.jei.core.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.util.FormattedCharSequence;

import java.util.List;

public class DrawableWrappedText implements IDrawable {
private static final int lineSpacing = 2;

private final List<FormattedText> descriptionLines;
private final int lineHeight;
private final int width;
private final int height;

public DrawableWrappedText(List<FormattedText> text, int maxWidth) {
Minecraft minecraft = Minecraft.getInstance();
Font font = minecraft.font;
this.lineHeight = font.lineHeight + lineSpacing;
Pair<List<FormattedText>, Boolean> result = StringUtil.splitLines(font, text, maxWidth, Integer.MAX_VALUE);
this.descriptionLines = result.first();
this.width = maxWidth;
this.height = lineHeight * descriptionLines.size() - lineSpacing;
}

@Override
public int getWidth() {
return width;
}

@Override
public int getHeight() {
return height;
}

@Override
public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) {
Language language = Language.getInstance();
Minecraft minecraft = Minecraft.getInstance();
Font font = minecraft.font;

int yPos = 0;
for (FormattedText descriptionLine : descriptionLines) {
FormattedCharSequence charSequence = language.getVisualOrder(descriptionLine);
guiGraphics.drawString(font, charSequence, xOffset, yPos + yOffset, 0xFF000000, false);
yPos += lineHeight;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package mezz.jei.common.gui.elements;

import net.minecraft.client.gui.GuiGraphics;
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;

/**
* Draws with a built-in offset.
*/
public class OffsetDrawable implements IDrawable {
public class OffsetDrawable implements IDrawable, IPlaceable<OffsetDrawable> {
public static IDrawable create(IDrawable drawable, int xOffset, int yOffset) {
if (xOffset == 0 && yOffset == 0) {
return drawable;
Expand All @@ -15,10 +17,10 @@ public static IDrawable create(IDrawable drawable, int xOffset, int yOffset) {
}

private final IDrawable drawable;
private final int xOffset;
private final int yOffset;
private int xOffset;
private int yOffset;

private OffsetDrawable(IDrawable drawable, int xOffset, int yOffset) {
public OffsetDrawable(IDrawable drawable, int xOffset, int yOffset) {
this.drawable = drawable;
this.xOffset = xOffset;
this.yOffset = yOffset;
Expand Down Expand Up @@ -47,4 +49,15 @@ public void draw(GuiGraphics guiGraphics, int xOffset, int yOffset) {
public void draw(GuiGraphics guiGraphics) {
this.drawable.draw(guiGraphics, this.xOffset, this.yOffset);
}

@Override
public OffsetDrawable setPosition(int xPos, int yPos) {
this.xOffset = xPos;
this.yOffset = yPos;
return this;
}

public ImmutableRect2i getArea() {
return new ImmutableRect2i(xOffset, yOffset, getWidth(), getHeight());
}
}
183 changes: 183 additions & 0 deletions Common/src/main/java/mezz/jei/common/gui/elements/TextWidget.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package mezz.jei.common.gui.elements;

import mezz.jei.api.gui.builder.ITooltipBuilder;
import mezz.jei.api.gui.placement.HorizontalAlignment;
import mezz.jei.api.gui.placement.VerticalAlignment;
import mezz.jei.api.gui.widgets.IRecipeWidget;
import mezz.jei.api.gui.widgets.ITextWidget;
import mezz.jei.common.config.DebugConfig;
import mezz.jei.common.util.ImmutableRect2i;
import mezz.jei.common.util.StringUtil;
import mezz.jei.core.util.Pair;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.navigation.ScreenPosition;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.util.FormattedCharSequence;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public class TextWidget implements ITextWidget, IRecipeWidget {
private final List<FormattedText> text;
private ImmutableRect2i availableArea;

private HorizontalAlignment horizontalAlignment;
private VerticalAlignment verticalAlignment;
private Font font;
private int color;
private boolean shadow;
private int lineSpacing;

private @Nullable List<FormattedText> wrappedText;
private boolean truncated = false;

public TextWidget(List<FormattedText> text, int xPos, int yPos, int maxWidth, int maxHeight) {
this.availableArea = new ImmutableRect2i(xPos, yPos, maxWidth, maxHeight);
Minecraft minecraft = Minecraft.getInstance();
this.font = minecraft.font;
this.color = 0xFF000000;
this.text = text;
this.lineSpacing = 2;
this.horizontalAlignment = HorizontalAlignment.LEFT;
this.verticalAlignment = VerticalAlignment.TOP;
}

private void invalidateCachedValues() {
wrappedText = null;
truncated = false;
}

@Override
public int getWidth() {
return availableArea.width();
}

@Override
public int getHeight() {
return availableArea.height();
}

@Override
public TextWidget setPosition(int xPos, int yPos) {
this.availableArea = this.availableArea.setPosition(xPos, yPos);
invalidateCachedValues();
return this;
}

@Override
public TextWidget setTextAlignment(HorizontalAlignment horizontalAlignment) {
if (this.horizontalAlignment.equals(horizontalAlignment)) {
return this;
}
this.horizontalAlignment = horizontalAlignment;
invalidateCachedValues();
return this;
}

@Override
public TextWidget setTextAlignment(VerticalAlignment verticalAlignment) {
if (this.verticalAlignment.equals(verticalAlignment)) {
return this;
}
this.verticalAlignment = verticalAlignment;
invalidateCachedValues();
return this;
}

@Override
public ITextWidget setFont(Font font) {
this.font = font;
invalidateCachedValues();
return this;
}

@Override
public ITextWidget setColor(int color) {
this.color = color;
invalidateCachedValues();
return this;
}

@Override
public ITextWidget setLineSpacing(int lineSpacing) {
this.lineSpacing = lineSpacing;
invalidateCachedValues();
return this;
}

@Override
public ITextWidget setShadow(boolean shadow) {
this.shadow = shadow;
invalidateCachedValues();
return this;
}

@Override
public ScreenPosition getPosition() {
return availableArea.getScreenPosition();
}

private List<FormattedText> calculateWrappedText() {
if (wrappedText != null) {
return wrappedText;
}
int lineHeight = getLineHeight();
int maxLines = availableArea.height() / lineHeight;
if (maxLines * lineHeight + font.lineHeight <= availableArea.height()) {
maxLines++;
}
Pair<List<FormattedText>, Boolean> result = StringUtil.splitLines(font, text, availableArea.width(), maxLines);
this.wrappedText = result.first();
this.truncated = result.second();
return wrappedText;
}

private int getLineHeight() {
return font.lineHeight + lineSpacing;
}

@Override
public void drawWidget(GuiGraphics guiGraphics, double mouseX, double mouseY) {
Language language = Language.getInstance();

final int lineHeight = getLineHeight();
List<FormattedText> lines = calculateWrappedText();
int yPos = getYPosStart(lineHeight, lines);
for (FormattedText line : lines) {
FormattedCharSequence charSequence = language.getVisualOrder(line);
int xPos = getXPos(charSequence);
guiGraphics.drawString(font, charSequence, xPos, yPos, color, shadow);
yPos += lineHeight;
}

if (DebugConfig.isDebugGuisEnabled()) {
guiGraphics.fill(0,0, availableArea.width(), availableArea.height(), 0xAAAAAA00);
}
}

@Override
public void getTooltip(ITooltipBuilder tooltip, double mouseX, double mouseY) {
if (mouseX >= 0 && mouseX < availableArea.width() && mouseY >= 0 && mouseY < availableArea.height()) {
calculateWrappedText();
if (truncated) {
tooltip.addAll(text);
}
}
}

private int getXPos(FormattedCharSequence text) {
return getXPos(font.width(text));
}

private int getXPos(int lineWidth) {
return horizontalAlignment.getXPos(this.availableArea.width(), lineWidth);
}

private int getYPosStart(int lineHeight, List<FormattedText> text) {
int linesHeight = (lineHeight * text.size()) - lineSpacing - 1;
return verticalAlignment.getYPos(this.availableArea.height(), linesHeight);
}
}
Loading

0 comments on commit b7f27fd

Please sign in to comment.