diff options
author | isXander <isxander@users.noreply.github.com> | 2022-09-19 19:11:13 +0100 |
---|---|---|
committer | isXander <isxander@users.noreply.github.com> | 2022-09-19 19:11:13 +0100 |
commit | de1c8a317226b58fe03497027136eaed1adfd808 (patch) | |
tree | 5f97d6d91bc37f83d8de8c6f4a335d06a014cee0 /src/main/java/dev/isxander | |
parent | 904e4d61b6cf84c807a99e66fc70527b01ae6fcc (diff) | |
download | YetAnotherConfigLib-de1c8a317226b58fe03497027136eaed1adfd808.tar.gz YetAnotherConfigLib-de1c8a317226b58fe03497027136eaed1adfd808.tar.bz2 YetAnotherConfigLib-de1c8a317226b58fe03497027136eaed1adfd808.zip |
1.4.0
improved tooltips
`ButtonOption` now consumes itself, so you can access it when building.
Diffstat (limited to 'src/main/java/dev/isxander')
11 files changed, 81 insertions, 125 deletions
diff --git a/src/main/java/dev/isxander/yacl/api/ButtonOption.java b/src/main/java/dev/isxander/yacl/api/ButtonOption.java index 519131e..1124a9a 100644 --- a/src/main/java/dev/isxander/yacl/api/ButtonOption.java +++ b/src/main/java/dev/isxander/yacl/api/ButtonOption.java @@ -9,14 +9,15 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -public interface ButtonOption extends Option<Consumer<YACLScreen>> { +public interface ButtonOption extends Option<BiConsumer<YACLScreen, ButtonOption>> { /** * Action to be executed upon button press */ - Consumer<YACLScreen> action(); + BiConsumer<YACLScreen, ButtonOption> action(); static Builder createBuilder() { return new Builder(); @@ -26,8 +27,8 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { 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; + private Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> controlGetter; + private BiConsumer<YACLScreen, ButtonOption> action; private Builder() { @@ -59,15 +60,23 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { return this; } + public Builder action(@NotNull BiConsumer<YACLScreen, ButtonOption> action) { + Validate.notNull(action, "`action` cannot be null"); + + this.action = action; + return this; + } + /** * Action to be executed upon button press * * @see ButtonOption#action() */ + @Deprecated public Builder action(@NotNull Consumer<YACLScreen> action) { Validate.notNull(action, "`action` cannot be null"); - this.action = action; + this.action = (screen, button) -> action.accept(screen); return this; } @@ -87,7 +96,7 @@ public interface ButtonOption extends Option<Consumer<YACLScreen>> { * * @see dev.isxander.yacl.gui.controllers */ - public Builder controller(@NotNull Function<ButtonOption, Controller<Consumer<YACLScreen>>> control) { + public Builder controller(@NotNull Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> control) { Validate.notNull(control, "`control` cannot be null"); this.controlGetter = control; diff --git a/src/main/java/dev/isxander/yacl/api/Option.java b/src/main/java/dev/isxander/yacl/api/Option.java index 1df90a8..fe11778 100644 --- a/src/main/java/dev/isxander/yacl/api/Option.java +++ b/src/main/java/dev/isxander/yacl/api/Option.java @@ -48,6 +48,13 @@ public interface Option<T> { boolean available(); /** + * Sets if the option can be configured after being built + * + * @see Option#available() + */ + void setAvailable(boolean available); + + /** * Class of the option type. * Used by some controllers. */ diff --git a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java b/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java index fa1e0f9..b5c010c 100644 --- a/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/CategoryListWidget.java @@ -80,7 +80,7 @@ public class CategoryListWidget extends ElementListWidget<CategoryListWidget.Cat } private void postRender(MatrixStack matrices, int mouseX, int mouseY, float tickDelta) { - categoryButton.renderHoveredTooltip(matrices, mouseX, mouseY); + categoryButton.renderHoveredTooltip(matrices); } @Override diff --git a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java index a947f61..08007c3 100644 --- a/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/OptionListWidget.java @@ -5,7 +5,6 @@ import dev.isxander.yacl.api.ConfigCategory; import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.OptionGroup; import dev.isxander.yacl.api.utils.Dimension; -import dev.isxander.yacl.impl.YACLConstants; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.MultilineText; import net.minecraft.client.font.TextRenderer; @@ -14,10 +13,8 @@ import net.minecraft.client.gui.Selectable; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.screen.narration.NarrationPart; -import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ElementListWidget; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.Nullable; @@ -296,13 +293,10 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> public class GroupSeparatorEntry extends Entry { private final OptionGroup group; private final MultilineText wrappedName; - private final List<OrderedText> wrappedTooltip; + private final MultilineText wrappedTooltip; private final LowProfileButtonWidget expandMinimizeButton; - private float hoveredTicks = 0; - private int prevMouseX, prevMouseY; - private final Screen screen; private final TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; @@ -310,11 +304,13 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> private List<OptionEntry> optionEntries; + private int y; + private GroupSeparatorEntry(OptionGroup group, Screen screen) { this.group = group; this.screen = screen; this.wrappedName = MultilineText.create(textRenderer, group.name(), getRowWidth() - 45); - this.wrappedTooltip = textRenderer.wrapLines(group.tooltip(), screen.width / 2); + this.wrappedTooltip = MultilineText.create(textRenderer, group.tooltip(), screen.width / 3 * 2); this.groupExpanded = !group.collapsed(); this.expandMinimizeButton = new LowProfileButtonWidget(0, 0, 20, 20, Text.empty(), btn -> { setExpanded(!isExpanded()); @@ -324,26 +320,19 @@ public class OptionListWidget extends ElementListWidget<OptionListWidget.Entry> @Override public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + this.y = y; + expandMinimizeButton.x = x; expandMinimizeButton.y = y + entryHeight / 2 - expandMinimizeButton.getHeight() / 2; expandMinimizeButton.render(matrices, mouseX, mouseY, tickDelta); - hovered &= !expandMinimizeButton.isMouseOver(mouseX, mouseY); - if (hovered && (!YACLConstants.HOVER_MOUSE_RESET || (mouseX == prevMouseX && mouseY == prevMouseY))) - hoveredTicks += tickDelta; - else - hoveredTicks = 0; - wrappedName.drawCenterWithShadow(matrices, x + entryWidth / 2, y + getYPadding()); - - prevMouseX = mouseX; - prevMouseY = mouseY; } @Override public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { - if (hoveredTicks >= YACLConstants.HOVER_TICKS) { - screen.renderOrderedTooltip(matrices, wrappedTooltip, mouseX, mouseY); + if (isHovered() && !expandMinimizeButton.isMouseOver(mouseX, mouseY)) { + YACLScreen.renderMultilineTooltip(matrices, textRenderer, wrappedTooltip, getRowLeft() + getRowWidth() / 2, y - 3, y + getItemHeight() + 3, screen.width, screen.height); } } diff --git a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java b/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java index 0f34e61..e59c06c 100644 --- a/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/TooltipButtonWidget.java @@ -1,19 +1,13 @@ 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; -import net.minecraft.text.OrderedText; import net.minecraft.text.Text; -import java.util.List; - public class TooltipButtonWidget extends ButtonWidget { - protected float hoveredTicks = 0; - protected int prevMouseX, prevMouseY; protected final Screen screen; protected MultilineText wrappedDescription; @@ -24,27 +18,13 @@ public class TooltipButtonWidget extends ButtonWidget { setTooltip(tooltip); } - @Override - public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { - super.render(matrices, mouseX, mouseY, delta); - - if (isHovered() && (!YACLConstants.HOVER_MOUSE_RESET || (prevMouseX == mouseX && prevMouseY == mouseY))) { - hoveredTicks += delta; - } else { - hoveredTicks = 0; - } - - prevMouseX = mouseX; - prevMouseY = mouseY; - } - - public void renderHoveredTooltip(MatrixStack matrices, int mouseX, int mouseY) { - if (hoveredTicks >= YACLConstants.HOVER_TICKS) { - YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, mouseX, mouseY, screen.width, screen.height); + public void renderHoveredTooltip(MatrixStack matrices) { + if (isHovered()) { + YACLScreen.renderMultilineTooltip(matrices, MinecraftClient.getInstance().textRenderer, wrappedDescription, x + width / 2, y - 4, y + height + 4, screen.width, screen.height); } } public void setTooltip(Text tooltip) { - wrappedDescription = MultilineText.create(MinecraftClient.getInstance().textRenderer, tooltip, screen.width / 2); + wrappedDescription = MultilineText.create(MinecraftClient.getInstance().textRenderer, tooltip, screen.width / 3); } } diff --git a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java index cef8fec..6b5a2e4 100644 --- a/src/main/java/dev/isxander/yacl/gui/YACLScreen.java +++ b/src/main/java/dev/isxander/yacl/gui/YACLScreen.java @@ -4,21 +4,17 @@ import com.mojang.blaze3d.systems.RenderSystem; import dev.isxander.yacl.api.*; 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; -import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -118,7 +114,7 @@ public class YACLScreen extends Screen { for (Element child : children()) { if (child instanceof TooltipButtonWidget tooltipButtonWidget) { - tooltipButtonWidget.renderHoveredTooltip(matrices, mouseX, mouseY); + tooltipButtonWidget.renderHoveredTooltip(matrices); } } } @@ -220,21 +216,24 @@ public class YACLScreen extends Screen { client.setScreen(parent); } - public static void renderMultilineTooltip(MatrixStack matrices, TextRenderer textRenderer, MultilineText text, int x, int y, int screenWidth, int screenHeight) { + public static void renderMultilineTooltip(MatrixStack matrices, TextRenderer textRenderer, MultilineText text, int centerX, int yAbove, int yBelow, int screenWidth, int screenHeight) { if (text.count() > 0) { int maxWidth = text.getMaxWidth(); int lineHeight = textRenderer.fontHeight + 1; int height = text.count() * lineHeight - 1; + int belowY = yBelow + 12; + int aboveY = yAbove - height + 12; + int maxBelow = screenHeight - (belowY + height); + int minAbove = aboveY - height; + int y = belowY; + if (maxBelow < -8) + y = maxBelow > minAbove ? belowY : aboveY; + + int x = centerX - text.getMaxWidth() / 2 - 12; + 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(); 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 3550072..673b614 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/ActionController.java @@ -9,13 +9,13 @@ import net.minecraft.text.Text; import org.jetbrains.annotations.ApiStatus; import org.lwjgl.glfw.GLFW; -import java.util.function.Consumer; +import java.util.function.BiConsumer; /** * Simple controller that simply runs the button action on press * and renders a {@link} Text on the right. */ -public class ActionController implements Controller<Consumer<YACLScreen>> { +public class ActionController implements Controller<BiConsumer<YACLScreen, ButtonOption>> { public static final Text DEFAULT_TEXT = Text.translatable("yacl.control.action.execute"); private final ButtonOption option; @@ -75,7 +75,7 @@ public class ActionController implements Controller<Consumer<YACLScreen>> { public void executeAction() { playDownSound(); - control.option().action().accept(screen); + control.option().action().accept(screen, control.option()); } @Override 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 cd70872..dded9c1 100644 --- a/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java +++ b/src/main/java/dev/isxander/yacl/gui/controllers/ControllerWidget.java @@ -4,16 +4,12 @@ import dev.isxander.yacl.api.Controller; 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; -import net.minecraft.text.OrderedText; import net.minecraft.text.Text; -import java.util.List; - public abstract class ControllerWidget<T extends Controller<?>> extends AbstractWidget { protected final T control; protected MultilineText wrappedTooltip; @@ -21,9 +17,6 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract protected boolean focused = false; protected boolean hovered = false; - protected float hoveredTicks = 0; - - private int prevMouseX, prevMouseY; public ControllerWidget(T control, YACLScreen screen, Dimension<Integer> dim) { super(dim); @@ -36,11 +29,6 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract @Override public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) { hovered = isMouseOver(mouseX, mouseY); - if (hovered && (!YACLConstants.HOVER_MOUSE_RESET || (mouseX == prevMouseX && mouseY == prevMouseY))) { - hoveredTicks += delta; - } else { - hoveredTicks = 0; - } Text name = control.option().name(); String nameString = name.getString(); @@ -65,15 +53,12 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract if (isHovered()) { drawHoveredControl(matrices, mouseX, mouseY, delta); } - - prevMouseX = mouseX; - prevMouseY = mouseY; } @Override public void postRender(MatrixStack matrices, int mouseX, int mouseY, float delta) { - if (hoveredTicks >= YACLConstants.HOVER_TICKS) { - YACLScreen.renderMultilineTooltip(matrices, textRenderer, wrappedTooltip, mouseX, mouseY, screen.width, screen.height); + if (hovered) { + YACLScreen.renderMultilineTooltip(matrices, textRenderer, wrappedTooltip, dim.centerX(), dim.y() - 5, dim.yLimit() + 5, screen.width, screen.height); } } @@ -96,7 +81,7 @@ public abstract class ControllerWidget<T extends Controller<?>> extends Abstract } private void updateTooltip() { - this.wrappedTooltip = MultilineText.create(textRenderer, control.option().tooltip(), screen.width / 2); + this.wrappedTooltip = MultilineText.create(textRenderer, control.option().tooltip(), screen.width / 3 * 2); } protected int getControlWidth() { diff --git a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java index 51c94b0..f6c8b6d 100644 --- a/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/ButtonOptionImpl.java @@ -16,17 +16,17 @@ import java.util.function.Function; 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; + private final BiConsumer<YACLScreen, ButtonOption> action; + private boolean available; + private final Controller<BiConsumer<YACLScreen, ButtonOption>> controller; + private final Binding<BiConsumer<YACLScreen, ButtonOption>> binding; public ButtonOptionImpl( @NotNull Text name, @Nullable Text tooltip, - @NotNull Consumer<YACLScreen> action, + @NotNull BiConsumer<YACLScreen, ButtonOption> action, boolean available, - @NotNull Function<ButtonOption, Controller<Consumer<YACLScreen>>> controlGetter + @NotNull Function<ButtonOption, Controller<BiConsumer<YACLScreen, ButtonOption>>> controlGetter ) { this.name = name; this.tooltip = tooltip; @@ -47,7 +47,7 @@ public class ButtonOptionImpl implements ButtonOption { } @Override - public Consumer<YACLScreen> action() { + public BiConsumer<YACLScreen, ButtonOption> action() { return action; } @@ -57,17 +57,22 @@ public class ButtonOptionImpl implements ButtonOption { } @Override - public @NotNull Controller<Consumer<YACLScreen>> controller() { + public void setAvailable(boolean available) { + this.available = available; + } + + @Override + public @NotNull Controller<BiConsumer<YACLScreen, ButtonOption>> controller() { return controller; } @Override - public @NotNull Binding<Consumer<YACLScreen>> binding() { + public @NotNull Binding<BiConsumer<YACLScreen, ButtonOption>> binding() { return binding; } @Override - public @NotNull Class<Consumer<YACLScreen>> typeClass() { + public @NotNull Class<BiConsumer<YACLScreen, ButtonOption>> typeClass() { throw new UnsupportedOperationException(); } @@ -87,12 +92,12 @@ public class ButtonOptionImpl implements ButtonOption { } @Override - public @NotNull Consumer<YACLScreen> pendingValue() { + public @NotNull BiConsumer<YACLScreen, ButtonOption> pendingValue() { throw new UnsupportedOperationException(); } @Override - public void requestSet(Consumer<YACLScreen> value) { + public void requestSet(BiConsumer<YACLScreen, ButtonOption> value) { throw new UnsupportedOperationException(); } @@ -112,23 +117,23 @@ public class ButtonOptionImpl implements ButtonOption { } @Override - public void addListener(BiConsumer<Option<Consumer<YACLScreen>>, Consumer<YACLScreen>> changedListener) { + public void addListener(BiConsumer<Option<BiConsumer<YACLScreen, ButtonOption>>, BiConsumer<YACLScreen, ButtonOption>> changedListener) { } - private static class EmptyBinderImpl implements Binding<Consumer<YACLScreen>> { + private static class EmptyBinderImpl implements Binding<BiConsumer<YACLScreen, ButtonOption>> { @Override - public void setValue(Consumer<YACLScreen> value) { + public void setValue(BiConsumer<YACLScreen, ButtonOption> value) { } @Override - public Consumer<YACLScreen> getValue() { + public BiConsumer<YACLScreen, ButtonOption> getValue() { throw new UnsupportedOperationException(); } @Override - public Consumer<YACLScreen> defaultValue() { + public BiConsumer<YACLScreen, ButtonOption> defaultValue() { throw new UnsupportedOperationException(); } } diff --git a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java index 1cf2a79..36cb217 100644 --- a/src/main/java/dev/isxander/yacl/impl/OptionImpl.java +++ b/src/main/java/dev/isxander/yacl/impl/OptionImpl.java @@ -22,7 +22,7 @@ public class OptionImpl<T> implements Option<T> { private final Function<T, Text> tooltipGetter; private final Controller<T> controller; private final Binding<T> binding; - private final boolean available; + private boolean available; private final ImmutableSet<OptionFlag> flags; @@ -80,6 +80,11 @@ public class OptionImpl<T> implements Option<T> { } @Override + public void setAvailable(boolean available) { + this.available = available; + } + + @Override public @NotNull Class<T> typeClass() { return typeClass; } diff --git a/src/main/java/dev/isxander/yacl/impl/YACLConstants.java b/src/main/java/dev/isxander/yacl/impl/YACLConstants.java deleted file mode 100644 index 28d6a65..0000000 --- a/src/main/java/dev/isxander/yacl/impl/YACLConstants.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.isxander.yacl.impl; - -import org.jetbrains.annotations.ApiStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YACLConstants { - /** - * Logger used by YACL - */ - @ApiStatus.Internal - public static final Logger LOGGER = LoggerFactory.getLogger("YetAnotherConfigLib"); - - /** - * Amount of ticks to hover before showing tooltips. - */ - public static final int HOVER_TICKS = 20; - - /** - * Reset hover ticks back to 0 when the mouse is moved. - */ - public static final boolean HOVER_MOUSE_RESET = true; -} |