Skip to content

Commit b9ce951

Browse files
committed
available property + fix category tooltips not showing
1 parent e8b6e38 commit b9ce951

19 files changed

+236
-39
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ plugins {
1616
val ciRun = System.getenv().containsKey("GITHUB_ACTIONS")
1717

1818
group = "dev.isxander"
19-
version = "1.1.2"
19+
version = "1.2.0"
2020

2121
if (ciRun)
2222
version = "$version-SNAPSHOT"

src/main/java/dev/isxander/yacl/api/ButtonOption.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import java.util.function.Function;
1414

1515
public interface ButtonOption extends Option<Consumer<YACLScreen>> {
16+
/**
17+
* Action to be executed upon button press
18+
*/
1619
Consumer<YACLScreen> action();
1720

1821
static Builder createBuilder() {
@@ -22,34 +25,68 @@ static Builder createBuilder() {
2225
class Builder {
2326
private Text name;
2427
private final List<Text> tooltipLines = new ArrayList<>();
28+
private boolean available = true;
2529
private Function<ButtonOption, Controller<Consumer<YACLScreen>>> controlGetter;
2630
private Consumer<YACLScreen> action;
2731

2832
private Builder() {
2933

3034
}
3135

36+
/**
37+
* Sets the name to be used by the option.
38+
*
39+
* @see Option#name()
40+
*/
3241
public Builder name(@NotNull Text name) {
3342
Validate.notNull(name, "`name` cannot be null");
3443

3544
this.name = name;
3645
return this;
3746
}
3847

48+
/**
49+
* Sets the tooltip to be used by the option.
50+
* Can be invoked twice to append more lines.
51+
* No need to wrap the text yourself, the gui does this itself.
52+
*
53+
* @param tooltips text lines - merged with a new-line on {@link Option.Builder#build()}.
54+
*/
3955
public Builder tooltip(@NotNull Text... tooltips) {
40-
Validate.notEmpty(tooltips, "`tooltips` cannot be empty");
56+
Validate.notNull(tooltips, "`tooltips` cannot be empty");
4157

4258
tooltipLines.addAll(List.of(tooltips));
4359
return this;
4460
}
4561

62+
/**
63+
* Action to be executed upon button press
64+
*
65+
* @see ButtonOption#action()
66+
*/
4667
public Builder action(@NotNull Consumer<YACLScreen> action) {
4768
Validate.notNull(action, "`action` cannot be null");
4869

4970
this.action = action;
5071
return this;
5172
}
5273

74+
/**
75+
* Sets if the option can be configured
76+
*
77+
* @see Option#available()
78+
*/
79+
public Builder available(boolean available) {
80+
this.available = available;
81+
return this;
82+
}
83+
84+
/**
85+
* Sets the controller for the option.
86+
* This is how you interact and change the options.
87+
*
88+
* @see dev.isxander.yacl.gui.controllers
89+
*/
5390
public Builder controller(@NotNull Function<ButtonOption, Controller<Consumer<YACLScreen>>> control) {
5491
Validate.notNull(control, "`control` cannot be null");
5592

@@ -71,7 +108,7 @@ public ButtonOption build() {
71108
concatenatedTooltip.append(line);
72109
}
73110

74-
return new ButtonOptionImpl(name, concatenatedTooltip, action, controlGetter);
111+
return new ButtonOptionImpl(name, concatenatedTooltip, action, available, controlGetter);
75112
}
76113
}
77114
}

src/main/java/dev/isxander/yacl/api/Option.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public interface Option<T> {
4040
*/
4141
@NotNull Binding<T> binding();
4242

43+
/**
44+
* If the option can be configured
45+
*/
46+
boolean available();
47+
4348
/**
4449
* Class of the option type.
4550
* Used by some controllers.
@@ -109,6 +114,8 @@ class Builder<T> {
109114

110115
private Binding<T> binding;
111116

117+
private boolean available = true;
118+
112119
private final Set<OptionFlag> flags = new HashSet<>();
113120

114121
private final Class<T> typeClass;
@@ -187,6 +194,16 @@ public Builder<T> binding(@NotNull T def, @NotNull Supplier<@NotNull T> getter,
187194
return this;
188195
}
189196

197+
/**
198+
* Sets if the option can be configured
199+
*
200+
* @see Option#available()
201+
*/
202+
public Builder<T> available(boolean available) {
203+
this.available = available;
204+
return this;
205+
}
206+
190207
/**
191208
* Adds a flag to the option.
192209
* Upon applying changes, all flags are executed.
@@ -236,7 +253,7 @@ public Option<T> build() {
236253
concatenatedTooltip.append(line);
237254
}
238255

239-
return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, ImmutableSet.copyOf(flags), typeClass);
256+
return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass);
240257
}
241258
}
242259
}

src/main/java/dev/isxander/yacl/gui/AbstractWidget.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
import net.minecraft.client.gui.widget.ClickableWidget;
1313
import net.minecraft.client.render.GameRenderer;
1414
import net.minecraft.client.sound.PositionedSoundInstance;
15-
import net.minecraft.client.sound.SoundManager;
1615
import net.minecraft.client.util.math.MatrixStack;
1716
import net.minecraft.sound.SoundEvents;
1817

18+
import java.awt.*;
19+
1920
public abstract class AbstractWidget implements Element, Drawable, Selectable {
2021
protected final MinecraftClient client = MinecraftClient.getInstance();
2122
protected final TextRenderer textRenderer = client.textRenderer;
23+
protected final int inactiveColor = 0xFFA0A0A0;
2224

2325
protected Dimension<Integer> dim;
2426

@@ -56,7 +58,7 @@ public void appendNarrations(NarrationMessageBuilder builder) {
5658

5759
}
5860

59-
protected void drawButtonRect(MatrixStack matrices, int x1, int y1, int x2, int y2, boolean hovered) {
61+
protected void drawButtonRect(MatrixStack matrices, int x1, int y1, int x2, int y2, boolean hovered, boolean enabled) {
6062
if (x1 > x2) {
6163
int xx1 = x1;
6264
x1 = x2;
@@ -73,14 +75,23 @@ protected void drawButtonRect(MatrixStack matrices, int x1, int y1, int x2, int
7375
RenderSystem.setShader(GameRenderer::getPositionTexShader);
7476
RenderSystem.setShaderTexture(0, ClickableWidget.WIDGETS_TEXTURE);
7577
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
76-
int i = hovered ? 2 : 1;
78+
int i = !enabled ? 0 : hovered ? 2 : 1;
7779
RenderSystem.enableBlend();
7880
RenderSystem.defaultBlendFunc();
7981
RenderSystem.enableDepthTest();
8082
DrawableHelper.drawTexture(matrices, x1, y1, 0, 0, 46 + i * 20, width / 2, height, 256, 256);
8183
DrawableHelper.drawTexture(matrices, x1 + width / 2, y1, 0, 200 - width / 2f, 46 + i * 20, width / 2, height, 256, 256);
8284
}
8385

86+
protected int multiplyColor(int hex, float amount) {
87+
Color color = new Color(hex, true);
88+
89+
return new Color(Math.max((int)(color.getRed() *amount), 0),
90+
Math.max((int)(color.getGreen()*amount), 0),
91+
Math.max((int)(color.getBlue() *amount), 0),
92+
color.getAlpha()).getRGB();
93+
}
94+
8495
public void playDownSound() {
8596
MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
8697
}

src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ protected void renderList(MatrixStack matrices, int mouseX, int mouseY, float de
3333
RenderSystem.disableScissor();
3434
}
3535

36+
public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) {
37+
for (CategoryEntry entry : children()) {
38+
entry.postRender(matrices, mouseX, mouseY, delta);
39+
}
40+
}
41+
3642
@Override
3743
public int getRowWidth() {
3844
return width - width / 10;
@@ -73,6 +79,10 @@ public void render(MatrixStack matrices, int index, int y, int x, int entryWidth
7379
categoryButton.render(matrices, mouseX, mouseY, tickDelta);
7480
}
7581

82+
private void postRender(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) {
83+
categoryButton.renderHoveredTooltip(matrices, mouseX, mouseY);
84+
}
85+
7686
@Override
7787
public List<? extends Element> children() {
7888
return ImmutableList.of(categoryButton);

src/main/java/dev/isxander/yacl/gui/OptionListWidget.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@ protected void renderList(MatrixStack matrices, int mouseX, int mouseY, float de
140140
}
141141
}
142142

143-
@Override
144-
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
145-
super.render(matrices, mouseX, mouseY, delta);
143+
public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) {
146144
for (Entry entry : children()) {
147145
entry.postRender(matrices, mouseX, mouseY, delta);
148146
}

src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java

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

33
import dev.isxander.yacl.impl.YACLConstants;
44
import net.minecraft.client.MinecraftClient;
5+
import net.minecraft.client.font.MultilineText;
56
import net.minecraft.client.gui.screen.Screen;
67
import net.minecraft.client.gui.widget.ButtonWidget;
78
import net.minecraft.client.util.math.MatrixStack;
@@ -15,7 +16,7 @@ public class TooltipButtonWidget extends ButtonWidget {
1516
protected int prevMouseX, prevMouseY;
1617

1718
protected final Screen screen;
18-
protected List<OrderedText> wrappedDescription;
19+
protected MultilineText wrappedDescription;
1920

2021
public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, Text tooltip, PressAction onPress) {
2122
super(x, y, width, height, message, onPress);
@@ -37,13 +38,13 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
3738
prevMouseY = mouseY;
3839
}
3940

40-
public void renderTooltip(MatrixStack matrices, int mouseX, int mouseY) {
41+
public void renderHoveredTooltip(MatrixStack matrices, int mouseX, int mouseY) {
4142
if (hoveredTicks >= YACLConstants.HOVER_TICKS) {
42-
screen.renderOrderedTooltip(matrices, wrappedDescription, mouseX, mouseY);
43+
YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, mouseX, mouseY, screen.width, screen.height);
4344
}
4445
}
4546

4647
public void setTooltip(Text tooltip) {
47-
wrappedDescription = MinecraftClient.getInstance().textRenderer.wrapLines(tooltip, screen.width / 2);
48+
wrappedDescription = MultilineText.create(MinecraftClient.getInstance().textRenderer, tooltip, screen.width / 2);
4849
}
4950
}

src/main/java/dev/isxander/yacl/gui/YACLScreen.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package dev.isxander.yacl.gui;
22

3+
import com.mojang.blaze3d.systems.RenderSystem;
34
import dev.isxander.yacl.api.ConfigCategory;
45
import dev.isxander.yacl.api.Option;
56
import dev.isxander.yacl.api.OptionFlag;
67
import dev.isxander.yacl.api.YetAnotherConfigLib;
78
import dev.isxander.yacl.api.utils.Dimension;
89
import dev.isxander.yacl.api.utils.OptionUtils;
910
import dev.isxander.yacl.impl.YACLConstants;
11+
import net.minecraft.client.font.MultilineText;
12+
import net.minecraft.client.font.TextRenderer;
1013
import net.minecraft.client.gui.Element;
1114
import net.minecraft.client.gui.screen.Screen;
15+
import net.minecraft.client.gui.tooltip.TooltipComponent;
16+
import net.minecraft.client.render.*;
1217
import net.minecraft.client.util.math.MatrixStack;
1318
import net.minecraft.text.Text;
1419
import net.minecraft.util.Formatting;
20+
import net.minecraft.util.math.Matrix4f;
1521

1622
import java.util.ArrayList;
1723
import java.util.HashSet;
@@ -130,12 +136,14 @@ public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
130136
super.render(matrices, mouseX, mouseY, delta);
131137
categoryList.render(matrices, mouseX, mouseY, delta);
132138
searchFieldWidget.render(matrices, mouseX, mouseY, delta);
133-
134139
optionList.render(matrices, mouseX, mouseY, delta);
135140

141+
categoryList.postRender(matrices, mouseX, mouseY, delta);
142+
optionList.postRender(matrices, mouseX, mouseY, delta);
143+
136144
for (Element child : children()) {
137145
if (child instanceof TooltipButtonWidget tooltipButtonWidget) {
138-
tooltipButtonWidget.renderTooltip(matrices, mouseX, mouseY);
146+
tooltipButtonWidget.renderHoveredTooltip(matrices, mouseX, mouseY);
139147
}
140148
}
141149
}
@@ -232,4 +240,50 @@ public boolean shouldCloseOnEsc() {
232240
public void close() {
233241
client.setScreen(parent);
234242
}
243+
244+
public static void renderMultilineTooltip(MatrixStack matrices, TextRenderer textRenderer, MultilineText text, int x, int y, int screenWidth, int screenHeight) {
245+
if (text.count() > 0) {
246+
int maxWidth = text.getMaxWidth();
247+
int lineHeight = textRenderer.fontHeight + 1;
248+
int height = text.count() * lineHeight;
249+
250+
int drawX = x + 12;
251+
int drawY = y - 12;
252+
if (drawX + maxWidth > screenWidth) {
253+
drawX -= 28 + maxWidth;
254+
}
255+
256+
if (drawY + height + 6 > screenHeight) {
257+
drawY = screenHeight - height - 6;
258+
}
259+
260+
matrices.push();
261+
Tessellator tessellator = Tessellator.getInstance();
262+
BufferBuilder bufferBuilder = tessellator.getBuffer();
263+
RenderSystem.setShader(GameRenderer::getPositionColorShader);
264+
bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR);
265+
Matrix4f matrix4f = matrices.peek().getPositionMatrix();
266+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 4, drawX + maxWidth + 3, drawY - 3, 400, -267386864, -267386864);
267+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 3, drawX + maxWidth + 3, drawY + height + 4, 400, -267386864, -267386864);
268+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY + height + 3, 400, -267386864, -267386864);
269+
fillGradient(matrix4f, bufferBuilder, drawX - 4, drawY - 3, drawX - 3, drawY + height + 3, 400, -267386864, -267386864);
270+
fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 3, drawY - 3, drawX + maxWidth + 4, drawY + height + 3, 400, -267386864, -267386864);
271+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3 + 1, drawX - 3 + 1, drawY + height + 3 - 1, 400, 1347420415, 1344798847);
272+
fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 2, drawY - 3 + 1, drawX + maxWidth + 3, drawY + height + 3 - 1, 400, 1347420415, 1344798847);
273+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY - 3 + 1, 400, 1347420415, 1347420415);
274+
fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 2, drawX + maxWidth + 3, drawY + height + 3, 400, 1344798847, 1344798847);
275+
RenderSystem.enableDepthTest();
276+
RenderSystem.disableTexture();
277+
RenderSystem.enableBlend();
278+
RenderSystem.defaultBlendFunc();
279+
BufferRenderer.drawWithShader(bufferBuilder.end());
280+
RenderSystem.disableBlend();
281+
RenderSystem.enableTexture();
282+
matrices.translate(0.0, 0.0, 400.0);
283+
284+
text.drawWithShadow(matrices, drawX, drawY, lineHeight, -1);
285+
286+
matrices.pop();
287+
}
288+
}
235289
}

src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void executeAction() {
8080

8181
@Override
8282
public boolean mouseClicked(double mouseX, double mouseY, int button) {
83-
if (isMouseOver(mouseX, mouseY)) {
83+
if (isMouseOver(mouseX, mouseY) && isAvailable()) {
8484
executeAction();
8585
return true;
8686
}

src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ protected void drawHoveredControl(MatrixStack matrices, int mouseX, int mouseY,
115115

116116
@Override
117117
public boolean mouseClicked(double mouseX, double mouseY, int button) {
118-
if (!isMouseOver(mouseX, mouseY))
118+
if (!isMouseOver(mouseX, mouseY) || !isAvailable())
119119
return false;
120120

121121
toggleSetting();

0 commit comments

Comments
 (0)