diff options
19 files changed, 236 insertions, 39 deletions
diff --git a/build.gradle.kts b/build.gradle.kts index 113b2e2..ca4c855 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ plugins { val ciRun = System.getenv().containsKey("GITHUB_ACTIONS") group = "dev.isxander" -version = "1.1.2" +version = "1.2.0" if (ciRun) version = "$version-SNAPSHOT" diff --git a/src/main/java/dev/isxander/yacl/api/ButtonOption.java b/src/main/java/dev/isxander/yacl/api/ButtonOption.java index f3d1e6b..519131e 100644 --- a/src/main/java/dev/isxander/yacl/api/ButtonOption.java +++ b/src/main/java/dev/isxander/yacl/api/ButtonOption.java @@ -13,6 +13,9 @@ import java.util.function.Consumer; import java.util.function.Function; public interface ButtonOption extends Option<Consumer<YACLScreen>> { + /** + * Action to be executed upon button press + */ Consumer<YACLScreen> action(); static Builder createBuilder() { @@ -22,6 +25,7 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { class Builder { private Text name; private final List<Text> tooltipLines = new ArrayList<>(); + private boolean available = true; private Function<ButtonOption, Controller<Consumer<YACLScreen>>> controlGetter; private Consumer<YACLScreen> action; @@ -29,6 +33,11 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { } + /** + * Sets the name to be used by the option. + * + * @see Option#name() + */ public Builder name(@NotNull Text name) { Validate.notNull(name, "`name` cannot be null"); @@ -36,13 +45,25 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { return this; } + /** + * Sets the tooltip to be used by the option. + * Can be invoked twice to append more lines. + * No need to wrap the text yourself, the gui does this itself. + * + * @param tooltips text lines - merged with a new-line on {@link Option.Builder#build()}. + */ public Builder tooltip(@NotNull Text... tooltips) { - Validate.notEmpty(tooltips, "`tooltips` cannot be empty"); + Validate.notNull(tooltips, "`tooltips` cannot be empty"); tooltipLines.addAll(List.of(tooltips)); return this; } + /** + * Action to be executed upon button press + * + * @see ButtonOption#action() + */ public Builder action(@NotNull Consumer<YACLScreen> action) { Validate.notNull(action, "`action` cannot be null"); @@ -50,6 +71,22 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { return this; } + /** + * Sets if the option can be configured + * + * @see Option#available() + */ + public Builder available(boolean available) { + this.available = available; + return this; + } + + /** + * Sets the controller for the option. + * This is how you interact and change the options. + * + * @see dev.isxander.yacl.gui.controllers + */ public Builder controller(@NotNull Function<ButtonOption, Controller<Consumer<YACLScreen>>> control) { Validate.notNull(control, "`control` cannot be null"); @@ -71,7 +108,7 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { concatenatedTooltip.append(line); } - return new ButtonOptionImpl(name, concatenatedTooltip, action, controlGetter); + return new ButtonOptionImpl(name, concatenatedTooltip, action, available, controlGetter); } } } diff --git a/src/main/java/dev/isxander/yacl/api/Option.java b/src/main/java/dev/isxander/yacl/api/Option.java index 10f2d10..ff72c4c 100644 --- a/src/main/java/dev/isxander/yacl/api/Option.java +++ b/src/main/java/dev/isxander/yacl/api/Option.java @@ -41,6 +41,11 @@ public interface Option<T> { @NotNull Binding<T> binding(); /** + * If the option can be configured + */ + boolean available(); + + /** * Class of the option type. * Used by some controllers. */ @@ -109,6 +114,8 @@ public interface Option<T> { private Binding<T> binding; + private boolean available = true; + private final Set<OptionFlag> flags = new HashSet<>(); private final Class<T> typeClass; @@ -188,6 +195,16 @@ public interface Option<T> { } /** + * Sets if the option can be configured + * + * @see Option#available() + */ + public Builder<T> available(boolean available) { + this.available = available; + return this; + } + + /** * Adds a flag to the option. * Upon applying changes, all flags are executed. * {@link Option#flags()} @@ -236,7 +253,7 @@ public interface Option<T> { concatenatedTooltip.append(line); } - return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, ImmutableSet.copyOf(flags), typeClass); + return new OptionImpl<>(name, concatenatedTooltip, controlGetter, binding, available, ImmutableSet.copyOf(flags), typeClass); } } } diff --git a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java b/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java index f81cc99..f0f43d3 100644 --- a/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/AbstractWidget.java @@ -12,13 +12,15 @@ import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.client.sound.SoundManager; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; +import java.awt.*; + public abstract class AbstractWidget implements Element, Drawable, Selectable { protected final MinecraftClient client = MinecraftClient.getInstance(); protected final TextRenderer textRenderer = client.textRenderer; + protected final int inactiveColor = 0xFFA0A0A0; protected Dimension<Integer> dim; @@ -56,7 +58,7 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { } - protected void drawButtonRect(MatrixStack matrices, int x1, int y1, int x2, int y2, boolean hovered) { + protected void drawButtonRect(MatrixStack matrices, int x1, int y1, int x2, int y2, boolean hovered, boolean enabled) { if (x1 > x2) { int xx1 = x1; x1 = x2; @@ -73,7 +75,7 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderTexture(0, ClickableWidget.WIDGETS_TEXTURE); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - int i = hovered ? 2 : 1; + int i = !enabled ? 0 : hovered ? 2 : 1; RenderSystem.enableBlend(); RenderSystem.defaultBlendFunc(); RenderSystem.enableDepthTest(); @@ -81,6 +83,15 @@ public abstract class AbstractWidget implements Element, Drawable, Selectable { DrawableHelper.drawTexture(matrices, x1 + width / 2, y1, 0, 200 - width / 2f, 46 + i * 20, width / 2, height, 256, 256); } + protected int multiplyColor(int hex, float amount) { + Color color = new Color(hex, true); + + return new Color(Math.max((int)(color.getRed() *amount), 0), + Math.max((int)(color.getGreen()*amount), 0), + Math.max((int)(color.getBlue() *amount), 0), + color.getAlpha()).getRGB(); + } + public void playDownSound() { MinecraftClient.getInstance().getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F)); } diff --git a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java b/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java index 9291329..fa1e0f9 100644 --- a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java @@ -33,6 +33,12 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat RenderSystem.disableScissor(); } + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { + for (CategoryEntry entry : children()) { + entry.postRender(matrices, mouseX, mouseY, delta); + } + } + @Override public int getRowWidth() { return width - width / 10; @@ -73,6 +79,10 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat categoryButton.render(matrices, mouseX, mouseY, tickDelta); } + private void postRender(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) { + categoryButton.renderHoveredTooltip(matrices, mouseX, mouseY); + } + @Override public List<? extends Element> children() { return ImmutableList.of(categoryButton); diff --git a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java index 466c44c..0c9baf5 100644 --- a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -140,9 +140,7 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> } } - @Override - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - super.render(matrices, mouseX, mouseY, delta); + public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { for (Entry entry : children()) { entry.postRender(matrices, mouseX, mouseY, delta); } diff --git a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java b/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java index 3131c97..0f34e61 100644 --- a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java @@ -2,6 +2,7 @@ package dev.isxander.yacl.gui; import dev.isxander.yacl.impl.YACLConstants; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.MultilineText; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; @@ -15,7 +16,7 @@ public class TooltipButtonWidget extends ButtonWidget { protected int prevMouseX, prevMouseY; protected final Screen screen; - protected List<OrderedText> wrappedDescription; + protected MultilineText wrappedDescription; public TooltipButtonWidget(Screen screen, int x, int y, int width, int height, Text message, Text tooltip, PressAction onPress) { super(x, y, width, height, message, onPress); @@ -37,13 +38,13 @@ public class TooltipButtonWidget extends ButtonWidget { prevMouseY = mouseY; } - public void renderTooltip(MatrixStack matrices, int mouseX, int mouseY) { + public void renderHoveredTooltip(MatrixStack matrices, int mouseX, int mouseY) { if (hoveredTicks >= YACLConstants.HOVER_TICKS) { - screen.renderOrderedTooltip(matrices, wrappedDescription, mouseX, mouseY); + YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, mouseX, mouseY, screen.width, screen.height); } } public void setTooltip(Text tooltip) { - wrappedDescription = MinecraftClient.getInstance().textRenderer.wrapLines(tooltip, screen.width / 2); + wrappedDescription = MultilineText.create(MinecraftClient.getInstance().textRenderer, tooltip, screen.width / 2); } } diff --git a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java index 53fa2bf..3fb1ad5 100644 --- a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java @@ -1,5 +1,6 @@ package dev.isxander.yacl.gui; +import com.mojang.blaze3d.systems.RenderSystem; import dev.isxander.yacl.api.ConfigCategory; import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.OptionFlag; @@ -7,11 +8,16 @@ import dev.isxander.yacl.api.YetAnotherConfigLib; import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.api.utils.OptionUtils; import dev.isxander.yacl.impl.YACLConstants; +import net.minecraft.client.font.MultilineText; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.render.*; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.math.Matrix4f; import java.util.ArrayList; import java.util.HashSet; @@ -130,12 +136,14 @@ public class YACLScreen extends Screen { super.render(matrices, mouseX, mouseY, delta); categoryList.render(matrices, mouseX, mouseY, delta); searchFieldWidget.render(matrices, mouseX, mouseY, delta); - optionList.render(matrices, mouseX, mouseY, delta); + categoryList.postRender(matrices, mouseX, mouseY, delta); + optionList.postRender(matrices, mouseX, mouseY, delta); + for (Element child : children()) { if (child instanceof TooltipButtonWidget tooltipButtonWidget) { - tooltipButtonWidget.renderTooltip(matrices, mouseX, mouseY); + tooltipButtonWidget.renderHoveredTooltip(matrices, mouseX, mouseY); } } } @@ -232,4 +240,50 @@ public class YACLScreen extends Screen { public void close() { client.setScreen(parent); } + + public static void renderMultilineTooltip(MatrixStack matrices, TextRenderer textRenderer, MultilineText text, int x, int y, int screenWidth, int screenHeight) { + if (text.count() > 0) { + int maxWidth = text.getMaxWidth(); + int lineHeight = textRenderer.fontHeight + 1; + int height = text.count() * lineHeight; + + int drawX = x + 12; + int drawY = y - 12; + if (drawX + maxWidth > screenWidth) { + drawX -= 28 + maxWidth; + } + + if (drawY + height + 6 > screenHeight) { + drawY = screenHeight - height - 6; + } + + matrices.push(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + bufferBuilder.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR); + Matrix4f matrix4f = matrices.peek().getPositionMatrix(); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 4, drawX + maxWidth + 3, drawY - 3, 400, -267386864, -267386864); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 3, drawX + maxWidth + 3, drawY + height + 4, 400, -267386864, -267386864); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY + height + 3, 400, -267386864, -267386864); + fillGradient(matrix4f, bufferBuilder, drawX - 4, drawY - 3, drawX - 3, drawY + height + 3, 400, -267386864, -267386864); + fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 3, drawY - 3, drawX + maxWidth + 4, drawY + height + 3, 400, -267386864, -267386864); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3 + 1, drawX - 3 + 1, drawY + height + 3 - 1, 400, 1347420415, 1344798847); + fillGradient(matrix4f, bufferBuilder, drawX + maxWidth + 2, drawY - 3 + 1, drawX + maxWidth + 3, drawY + height + 3 - 1, 400, 1347420415, 1344798847); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY - 3, drawX + maxWidth + 3, drawY - 3 + 1, 400, 1347420415, 1347420415); + fillGradient(matrix4f, bufferBuilder, drawX - 3, drawY + height + 2, drawX + maxWidth + 3, drawY + height + 3, 400, 1344798847, 1344798847); + RenderSystem.enableDepthTest(); + RenderSystem.disableTexture(); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + BufferRenderer.drawWithShader(bufferBuilder.end()); + RenderSystem.disableBlend(); + RenderSystem.enableTexture(); + matrices.translate(0.0, 0.0, 400.0); + + text.drawWithShadow(matrices, drawX, drawY, lineHeight, -1); + + matrices.pop(); + } + } } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java b/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java index e337ee3..3550072 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java @@ -80,7 +80,7 @@ public class ActionController implements Controller<Consumer<YACLScreen>> { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (isMouseOver(mouseX, mouseY)) { + if (isMouseOver(mouseX, mouseY) && isAvailable()) { executeAction(); return true; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java b/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java index 38be6db..bb5304b 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/BooleanController.java @@ -115,7 +115,7 @@ public class BooleanController implements Controller<Boolean> { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (!isMouseOver(mouseX, mouseY)) + if (!isMouseOver(mouseX, mouseY) || !isAvailable()) return false; toggleSetting(); diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java b/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java index 54c426d..1c986e4 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java @@ -5,6 +5,7 @@ import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.gui.AbstractWidget; import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.impl.YACLConstants; +import net.minecraft.client.font.MultilineText; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.util.math.MatrixStack; @@ -15,7 +16,7 @@ import java.util.List; public abstract class ControllerWidget<T extends Controller<?>> extends AbstractWidget { protected final T control; - protected final List<OrderedText> wrappedTooltip; + protected final MultilineText wrappedTooltip; protected final YACLScreen screen; protected boolean focused = false; @@ -28,7 +29,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract super(dim); this.control = control; this.screen = screen; - this.wrappedTooltip = textRenderer.wrapLines(control.option().tooltip(), screen.width / 2); + this.wrappedTooltip = MultilineText.create(textRenderer, control.option().tooltip(), screen.width / 2); } @Override @@ -53,10 +54,10 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract Text shortenedName = Text.literal(nameString).fillStyle(name.getStyle()); - drawButtonRect(matrices, dim.x(), dim.y(), dim.xLimit(), dim.yLimit(), isHovered()); + drawButtonRect(matrices, dim.x(), dim.y(), dim.xLimit(), dim.yLimit(), isHovered(), isAvailable()); matrices.push(); matrices.translate(dim.x() + getXPadding(), getTextY(), 0); - textRenderer.drawWithShadow(matrices, shortenedName, 0, 0, -1); + textRenderer.drawWithShadow(matrices, shortenedName, 0, 0, getValueColor()); matrices.pop(); drawValueText(matrices, mouseX, mouseY, delta); @@ -71,7 +72,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract @Override public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { if (hoveredTicks > YACLConstants.HOVER_TICKS) { - screen.renderOrderedTooltip(matrices, wrappedTooltip, mouseX, mouseY); + YACLScreen.renderMultilineTooltip(matrices, textRenderer, wrappedTooltip, mouseX, mouseY, screen.width, screen.height); } } @@ -83,7 +84,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract Text valueText = getValueText(); matrices.push(); matrices.translate(dim.xLimit() - textRenderer.getWidth(valueText) - getXPadding(), getTextY(), 0); - textRenderer.drawWithShadow(matrices, valueText, 0, 0, -1); + textRenderer.drawWithShadow(matrices, valueText, 0, 0, getValueColor()); matrices.pop(); } @@ -98,7 +99,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract } public boolean isHovered() { - return hovered || focused; + return isAvailable() && (hovered || focused); } protected abstract int getHoveredControlWidth(); @@ -119,6 +120,14 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract return control.formatValue(); } + protected boolean isAvailable() { + return control.option().available(); + } + + protected int getValueColor() { + return isAvailable() ? -1 : inactiveColor; + } + protected void drawOutline(MatrixStack matrices, int x1, int y1, int x2, int y2, int width, int color) { DrawableHelper.fill(matrices, x1, y1, x2, y1 + width, color); DrawableHelper.fill(matrices, x2, y1, x2 - width, y2, color); @@ -132,6 +141,9 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract @Override public boolean changeFocus(boolean lookForwards) { + if (!isAvailable()) + return false; + this.focused = !this.focused; return this.focused; } diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java b/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java index 9d8e59c..261c067 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/EnumController.java @@ -98,7 +98,7 @@ public class EnumController<T extends Enum<T>> implements Controller<T> { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (!isMouseOver(mouseX, mouseY) || (button != 0 && button != 1)) + if (!isMouseOver(mouseX, mouseY) || (button != 0 && button != 1) || !isAvailable()) return false; playDownSound(); diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java index 33ca176..57927f5 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/LabelController.java @@ -57,7 +57,7 @@ public class LabelController implements Controller<Text> { public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { updateText(); - wrappedText.drawWithShadow(matrices, dim.x(), dim.y() + getYPadding(), textRenderer.fontHeight, -1); + wrappedText.drawWithShadow(matrices, dim.x(), dim.y() + getYPadding(), textRenderer.fontHeight, option().available() ? -1 : 0xFFA0A0A0); } private int getYPadding() { diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java b/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java index df0ae83..d7864e0 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/TickBoxController.java @@ -63,23 +63,27 @@ public class TickBoxController implements Controller<Boolean> { int outlineY1 = dim.centerY() - outlineSize / 2; int outlineX2 = dim.xLimit() - getXPadding(); int outlineY2 = dim.centerY() + outlineSize / 2; - drawOutline(matrices, outlineX1 + 1, outlineY1 + 1, outlineX2 + 1, outlineY2 + 1, 1, 0xFF404040); - drawOutline(matrices, outlineX1, outlineY1, outlineX2, outlineY2, 1, -1); + + int color = getValueColor(); + int shadowColor = multiplyColor(color, 0.25f); + + drawOutline(matrices, outlineX1 + 1, outlineY1 + 1, outlineX2 + 1, outlineY2 + 1, 1, shadowColor); + drawOutline(matrices, outlineX1, outlineY1, outlineX2, outlineY2, 1, color); if (control.option().pendingValue()) { - DrawableHelper.fill(matrices, outlineX1 + 3, outlineY1 + 3, outlineX2 - 1, outlineY2 - 1, 0xFF404040); - DrawableHelper.fill(matrices, outlineX1 + 2, outlineY1 + 2, outlineX2 - 2, outlineY2 - 2, -1); + DrawableHelper.fill(matrices, outlineX1 + 3, outlineY1 + 3, outlineX2 - 1, outlineY2 - 1, shadowColor); + DrawableHelper.fill(matrices, outlineX1 + 2, outlineY1 + 2, outlineX2 - 2, outlineY2 - 2, color); } } @Override protected void drawValueText(MatrixStack matrices, int mouseX, int mouseY, float delta) { - if (!hovered) + if (!isHovered()) drawHoveredControl(matrices, mouseX, mouseY, delta); } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (!isMouseOver(mouseX, mouseY)) + if (!isMouseOver(mouseX, mouseY) || !isAvailable()) return false; toggleSetting(); diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java b/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java index fa763b7..d07377a 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/slider/SliderControllerElement.java @@ -51,7 +51,7 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override protected void drawValueText(MatrixStack matrices, int mouseX, int mouseY, float delta) { matrices.push(); - if (hovered || focused) + if (isHovered()) matrices.translate(-(sliderBounds.width() + 6 + getThumbWidth() / 2f), 0, 0); super.drawValueText(matrices, mouseX, mouseY, delta); matrices.pop(); @@ -59,7 +59,7 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (button != 0 || !sliderBounds.isPointInside((int) mouseX, (int) mouseY)) + if (!isAvailable() || button != 0 || !sliderBounds.isPointInside((int) mouseX, (int) mouseY)) return false; mouseDown = true; @@ -70,7 +70,7 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { - if (button != 0 || !mouseDown) + if (!isAvailable() || button != 0 || !mouseDown) return false; setValueFromMouse(mouseX); @@ -84,7 +84,7 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override public boolean mouseScrolled(double mouseX, double mouseY, double amount) { - if ((!isMouseOver(mouseX, mouseY)) || (!Screen.hasShiftDown() && !Screen.hasControlDown())) + if (!isAvailable() || (!isMouseOver(mouseX, mouseY)) || (!Screen.hasShiftDown() && !Screen.hasControlDown())) return false; incrementValue(amount); @@ -93,7 +93,7 @@ public class SliderControllerElement extends ControllerWidget<ISliderController< @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (mouseDown) + if (isAvailable() && mouseDown) playDownSound(); mouseDown = false; diff --git a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java index c606d69..8598172 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/string/StringControllerElement.java @@ -56,7 +56,7 @@ public class StringControllerElement extends ControllerWidget<IStringController< @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - if (inputFieldBounds.isPointInside((int) mouseX, (int) mouseY)) { + if (isAvailable() && inputFieldBounds.isPointInside((int) mouseX, (int) mouseY)) { if (!inputFieldFocused) { inputFieldFocused = true; caretPos = getDefaultCarotPos(); diff --git a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java index 2cdc8a6..a600bc3 100644 --- a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java @@ -19,6 +19,7 @@ public class ButtonOptionImpl implements ButtonOption { private final Text name; private final Text tooltip; private final Consumer<YACLScreen> action; + private final boolean available; private final Controller<Consumer<YACLScreen>> controller; private final Binding<Consumer<YACLScreen>> binding; @@ -26,11 +27,13 @@ public class ButtonOptionImpl implements ButtonOption { @NotNull Text name, @Nullable Text tooltip, @NotNull Consumer<YACLScreen> action, + boolean available, @NotNull Function<ButtonOption, Controller<Consumer<YACLScreen>>> controlGetter ) { this.name = name; this.tooltip = tooltip; this.action = action; + this.available = available; this.controller = controlGetter.apply(this); this.binding = new EmptyBinderImpl(); } @@ -51,6 +54,11 @@ public class ButtonOptionImpl implements ButtonOption { } @Override + public boolean available() { + return available; + } + + @Override public @NotNull Controller<Consumer<YACLScreen>> controller() { return controller; } diff --git a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java index 445420e..5a31a70 100644 --- a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java @@ -18,6 +18,7 @@ public class OptionImpl<T> implements Option<T> { private final Text tooltip; private final Controller<T> controller; private final Binding<T> binding; + private final boolean available; private final ImmutableSet<OptionFlag> flags; @@ -30,6 +31,7 @@ public class OptionImpl<T> implements Option<T> { @Nullable Text tooltip, @NotNull Function<Option<T>, Controller<T>> controlGetter, @NotNull Binding<T> binding, + boolean available, ImmutableSet<OptionFlag> flags, @NotNull Class<T> typeClass ) { @@ -37,6 +39,7 @@ public class OptionImpl<T> implements Option<T> { this.tooltip = tooltip; this.controller = controlGetter.apply(this); this.binding = binding; + this.available = available; this.flags = flags; this.typeClass = typeClass; this.pendingValue = binding().getValue(); @@ -63,6 +66,11 @@ public class OptionImpl<T> implements Option<T> { } @Override + public boolean available() { + return available; + } + + @Override public @NotNull Class<T> typeClass() { return typeClass; } diff --git a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java index d1ef4d0..df81768 100644 --- a/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java +++ b/src/testmod/java/dev/isxander/yacl/test/ModMenuIntegration.java @@ -39,6 +39,11 @@ public class ModMenuIntegration implements ModMenuApi { .controller(ActionController::new) .action(screen -> MinecraftClient.getInstance().setScreen(getWikiGroups(screen))) .build()) + .option(ButtonOption.createBuilder() + .name(Text.of("Unavailable Test Suite")) + .controller(ActionController::new) + .action(screen -> MinecraftClient.getInstance().setScreen(getDisabledTest(screen))) + .build()) .build()) .build().generateScreen(parent); } @@ -311,6 +316,38 @@ public class ModMenuIntegration implements ModMenuApi { .build().generateScreen(parent); } + private Screen getDisabledTest(Screen parent) { + return YetAnotherConfigLib.createBuilder() + .title(Text.empty()) + .category(ConfigCategory.createBuilder() + .name(Text.of("Disabled Test")) + .option(Option.createBuilder(int.class) + .name(Text.of("Slider")) + .binding(Binding.immutable(0)) + .controller(opt -> new IntegerSliderController(opt, 0, 5, 1)) + .available(false) + .build()) + .option(Option.createBuilder(boolean.class) + .name(Text.of("Tick Box")) + .binding(Binding.immutable(true)) + .controller(TickBoxController::new) + .available(false) + .build()) + .option(Option.createBuilder(boolean.class) + .name(Text.of("Tick Box (Enabled)")) + .binding(Binding.immutable(true)) + .controller(TickBoxController::new) + .build()) + .option(Option.createBuilder(String.class) + .name(Text.of("Text Field")) + .binding(Binding.immutable("hi")) + .controller(StringController::new) + .available(false) + .build()) + .build()) + .build().generateScreen(parent); + } + private Screen getWikiBasic(Screen parent) { return YetAnotherConfigLib.createBuilder() .title(Text.of("Mod Name")) |