diff options
| author | vicisacat <victor.branchu@gmail.com> | 2024-04-14 17:36:21 +0200 |
|---|---|---|
| committer | vicisacat <victor.branchu@gmail.com> | 2024-04-20 16:09:49 +0200 |
| commit | b791e38cbd36360935164e337fa992bf514cbb36 (patch) | |
| tree | f245ad744288d6f62452c26161878d59f651971d /src/main/java/de/hysky/skyblocker/skyblock/fancybars | |
| parent | 3581365e654306cf08d0c4284ddfa454befd519d (diff) | |
| download | Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.tar.gz Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.tar.bz2 Skyblocker-b791e38cbd36360935164e337fa992bf514cbb36.zip | |
it works so cool
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/skyblock/fancybars')
5 files changed, 777 insertions, 62 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java index 93219240..384250f9 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/BarGrid.java @@ -53,6 +53,28 @@ public class BarGrid { } } + public void addRowToEnd(boolean top, boolean right) { + if (top) { + this.top.add(new LinkedList<>()); + } else { + (right ? bottomRight: bottomLeft).add(new LinkedList<>()); + } + } + + public void addToEndOfRow(int row, boolean right, StatusBar bar) { + if (row>0) { + LinkedList<StatusBar> statusBars = top.get(row - 1); + statusBars.add(bar); + bar.gridY = row; + bar.gridX = statusBars.indexOf(bar)+1; + } else if (row<0) { + LinkedList<StatusBar> statusBars = (right? bottomRight: bottomLeft).get(Math.abs(row)-1); + statusBars.add(bar); + bar.gridY = row; + bar.gridX = (statusBars.indexOf(bar)+1) * (right ? 1: -1); + } + } + public void remove(int x, int y) { System.out.println("Removing x: " + x + " y: " + y); if (y > 0) { @@ -92,6 +114,21 @@ public class BarGrid { } } + public boolean coordinatesExist(int x, int y) { + if (x == 0 || y == 0) return false; + if (y > 0) { + if (y > getTopSize()) return false; + return x <= getRow(y, false).size(); + } else { + if (Math.abs(y) > (x < 0 ? getBottomLeftSize(): getBottomRightSize())) return false; + return Math.abs(x) <= getRow(y, x > 0).size(); + } + } + + public StatusBar getBar(int x, int y) { + return getRow(y, x>0).get(Math.abs(x)-1); + } + public int getTopSize() {return top.size();} public int getBottomLeftSize() {return bottomLeft.size();} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java new file mode 100644 index 00000000..a3ce4e43 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarColorPopup.java @@ -0,0 +1,117 @@ +package de.hysky.skyblocker.skyblock.fancybars; + +import de.hysky.skyblocker.utils.render.gui.AbstractPopupScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.*; +import net.minecraft.text.Style; +import net.minecraft.text.Text; + +import java.awt.*; +import java.util.List; +import java.util.function.Consumer; + +public class EditBarColorPopup extends AbstractPopupScreen { + + private final Consumer<Color> setColor; + + private DirectionalLayoutWidget layout = DirectionalLayoutWidget.vertical(); + private BasicColorSelector colorSelector; + + protected EditBarColorPopup(Text title, Screen backgroundScreen, Consumer<Color> setColor) { + super(title, backgroundScreen); + this.setColor = setColor; + } + + @Override + protected void init() { + super.init(); + layout = DirectionalLayoutWidget.vertical(); + layout.spacing(8).getMainPositioner().alignHorizontalCenter(); + layout.add(new TextWidget(title.copy().fillStyle(Style.EMPTY.withBold(true)), MinecraftClient.getInstance().textRenderer)); + colorSelector = new BasicColorSelector(0, 0, 150, () -> done(null)); + layout.add(colorSelector); + + DirectionalLayoutWidget horizontal = DirectionalLayoutWidget.horizontal(); + ButtonWidget buttonWidget = ButtonWidget.builder(Text.literal("Cancel"), button -> close()).width(80).build(); + horizontal.add(buttonWidget); + horizontal.add(ButtonWidget.builder(Text.literal("Done"), this::done).width(80).build()); + + layout.add(horizontal); + layout.forEachChild(this::addDrawableChild); + this.layout.refreshPositions(); + SimplePositioningWidget.setPos(layout, this.getNavigationFocus()); + } + + private void done(Object object) { + if (colorSelector.validColor) setColor.accept(new Color(colorSelector.getColor())); + close(); + } + + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + super.renderBackground(context, mouseX, mouseY, delta); + drawPopupBackground(context, layout.getX(), layout.getY(), layout.getWidth(), layout.getHeight()); + } + + private static class BasicColorSelector extends ContainerWidget { + + private final EnterConfirmTextFieldWidget textFieldWidget; + + public BasicColorSelector(int x, int y, int width, Runnable onEnter) { + super(x, y, width, 15, Text.literal("edit color")); + textFieldWidget = new EnterConfirmTextFieldWidget(MinecraftClient.getInstance().textRenderer, getX() + 16, getY(), width - 16, 15, Text.empty(), onEnter); + textFieldWidget.setChangedListener(this::onTextChange); + textFieldWidget.setTextPredicate(s -> s.length() <= 6); + } + + @Override + public List<? extends Element> children() { + return List.of(textFieldWidget); + } + + public int getColor() { + return color; + } + + private int color = 0xFF000000; + private boolean validColor = false; + + private void onTextChange(String text) { + try { + color = Integer.parseInt(text, 16) | 0xFF000000; + validColor = true; + } catch (NumberFormatException e) { + color = 0; + validColor = false; + } + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + context.drawBorder(getX(), getY(), 15, 15, validColor ? -1 : 0xFFDD0000); + context.fill(getX() + 1, getY() + 1, getX() + 14, getY() + 14, color); + textFieldWidget.renderWidget(context, mouseX, mouseY, delta); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + @Override + public void setX(int x) { + super.setX(x); + textFieldWidget.setX(getX()+16); + } + + @Override + public void setY(int y) { + super.setY(y); + textFieldWidget.setY(getY()); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java new file mode 100644 index 00000000..54af7a03 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java @@ -0,0 +1,274 @@ +package de.hysky.skyblocker.skyblock.fancybars; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.tooltip.TooltipBackgroundRenderer; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.ContainerWidget; +import net.minecraft.client.gui.widget.TextWidget; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Colors; +import net.minecraft.util.Formatting; + +import java.awt.*; +import java.util.List; +import java.util.function.Consumer; + +public class EditBarWidget extends ContainerWidget { + + private final EnumCyclingOption<StatusBar.IconPosition> iconOption; + private final BooleanOption booleanOption; + + private final ColorOption color1; + private final ColorOption color2; + private final ColorOption textColor; + private final TextWidget nameWidget; + + private int contentsWidth = 0; + + public EditBarWidget(int x, int y, Screen parent) { + super(x, y, 100, 66, Text.literal("Edit bar")); + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + + nameWidget = new TextWidget(Text.empty(), textRenderer); + + MutableText translatable = Text.translatable("skyblocker.bars.config.icon"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + textRenderer.getWidth("RIGHT") + 10); + iconOption = new EnumCyclingOption<>(0, 11, getWidth(), translatable, StatusBar.IconPosition.class); + + translatable = Text.translatable("skyblocker.bars.config.showValue"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + booleanOption = new BooleanOption(0, 22, getWidth(), translatable); + + // COLO(u)RS + translatable = Text.translatable("skyblocker.bars.config.mainColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + color1 = new ColorOption(0, 33, getWidth(), translatable, parent); + + translatable = Text.translatable("skyblocker.bars.config.overflowColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + color2 = new ColorOption(0, 44, getWidth(), translatable, parent); + + translatable = Text.translatable("skyblocker.bars.config.textColor"); + contentsWidth = Math.max(contentsWidth, textRenderer.getWidth(translatable) + 9 + 10); + textColor = new ColorOption(0, 55, getWidth(), translatable, parent); + + setWidth(contentsWidth); + } + + @Override + public List<? extends Element> children() { + return List.of(iconOption, booleanOption, color1, color2, textColor); + } + + public int insideMouseX = 0; + public int insideMouseY = 0; + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isHovered()) { + insideMouseX = mouseX; + insideMouseY = mouseY; + } else { + int i = mouseX - insideMouseX; + int j = mouseY - insideMouseY; + if (i * i + j * j > 30 * 30) visible = false; + } + TooltipBackgroundRenderer.render(context, getX(), getY(), getWidth(), getHeight(), 0); + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(getX(), getY(), 0); + nameWidget.render(context, mouseX, mouseY, delta); + iconOption.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + booleanOption.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + color1.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + color2.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + textColor.renderWidget(context, mouseX - getX(), mouseY - getY(), delta); + matrices.pop(); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (!visible) return false; + if (!isHovered()) visible = false; + return super.mouseClicked(mouseX - getX(), mouseY - getY(), button); + } + + public void setStatusBar(StatusBar statusBar) { + iconOption.setCurrent(statusBar.getIconPosition()); + iconOption.setOnChange(statusBar::setIconPosition); + booleanOption.setCurrent(statusBar.showText()); + booleanOption.setOnChange(statusBar::setShowText); + + color1.setCurrent(statusBar.getColors()[0].getRGB()); + color1.setOnChange(color -> statusBar.getColors()[0] = color); + + color2.active = statusBar.hasOverflow(); + if (color2.active) { + color2.setCurrent(statusBar.getColors()[1].getRGB()); + color2.setOnChange(color -> statusBar.getColors()[1] = color); + } + + if (statusBar.getTextColor() != null) { + textColor.setCurrent(statusBar.getTextColor().getRGB()); + } + textColor.setOnChange(statusBar::setTextColor); + + MutableText formatted = statusBar.getName().copy().formatted(Formatting.BOLD); + nameWidget.setMessage(formatted); + setWidth(Math.max(MinecraftClient.getInstance().textRenderer.getWidth(formatted), contentsWidth)); + } + + @Override + public void setWidth(int width) { + super.setWidth(width); + iconOption.setWidth(width); + booleanOption.setWidth(width); + color1.setWidth(width); + color2.setWidth(width); + textColor.setWidth(width); + nameWidget.setWidth(width); + + } + + public static class EnumCyclingOption<T extends Enum<T>> extends ClickableWidget { + + private T current; + private final T[] values; + private Consumer<T> onChange = null; + + public EnumCyclingOption(int x, int y, int width, Text message, Class<T> enumClass) { + super(x, y, width, 11, message); + values = enumClass.getEnumConstants(); + current = values[0]; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, -1, true); + String string = current.toString(); + context.drawText(textRenderer, string, getRight() - textRenderer.getWidth(string) - 1, getY() + 1, -1, true); + } + + public void setCurrent(T current) { + this.current = current; + } + + @Override + public void onClick(double mouseX, double mouseY) { + current = values[(current.ordinal() + 1) % values.length]; + if (onChange != null) onChange.accept(current); + super.onClick(mouseX, mouseY); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + public void setOnChange(Consumer<T> onChange) { + this.onChange = onChange; + } + } + + public static class BooleanOption extends ClickableWidget { + + private boolean current = false; + private Consumer<Boolean> onChange = null; + + public BooleanOption(int x, int y, int width, Text message) { + super(x, y, width, 11, message); + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, -1, true); + context.drawBorder(getRight() - 10, getY() + 1, 9, 9, -1); + if (current) context.fill(getRight() - 8, getY() + 3, getRight() - 3, getY() + 8, -1); + } + + @Override + public void onClick(double mouseX, double mouseY) { + current = !current; + if (onChange != null) onChange.accept(current); + super.onClick(mouseX, mouseY); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + } + + public void setCurrent(boolean current) { + this.current = current; + } + + public void setOnChange(Consumer<Boolean> onChange) { + this.onChange = onChange; + } + } + + public static class ColorOption extends ClickableWidget { + + public void setCurrent(int current) { + this.current = current; + } + + private int current = 0; + private Consumer<Color> onChange = null; + private final Screen parent; + + public ColorOption(int x, int y, int width, Text message, Screen parent) { + super(x, y, width, 11, message); + this.parent = parent; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { + if (isMouseOver(mouseX, mouseY)) { + context.fill(getX(), getY(), getRight(), getBottom(), 0x20FFFFFF); + } + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + context.drawText(textRenderer, getMessage(), getX() + 1, getY() + 1, active ? -1 : Colors.GRAY, true); + context.drawBorder(getRight() - 10, getY() + 1, 9, 9, active ? -1 : Colors.GRAY); + context.fill(getRight() - 8, getY() + 3, getRight() - 3, getY() + 8, active ? current : Colors.GRAY); + } + + @Override + public void onClick(double mouseX, double mouseY) { + super.onClick(mouseX, mouseY); + MinecraftClient.getInstance().setScreen(new EditBarColorPopup(Text.literal("Edit ").append(getMessage()), parent, this::set)); + } + + private void set(Color color) { + current = color.getRGB(); + if (onChange != null) onChange.accept(color); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + public void setOnChange(Consumer<Color> onChange) { + this.onChange = onChange; + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java index 6d321a90..ea4a0388 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java @@ -1,5 +1,8 @@ package de.hysky.skyblocker.skyblock.fancybars; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.utils.render.RenderHelper; import net.minecraft.client.MinecraftClient; @@ -8,7 +11,7 @@ import net.minecraft.client.gui.*; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.client.gui.widget.Widget; -import net.minecraft.util.Colors; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.Nullable; @@ -21,13 +24,66 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { private static final Identifier BAR_FILL = new Identifier(SkyblockerMod.NAMESPACE, "bars/bar_fill"); private static final Identifier BAR_BACK = new Identifier(SkyblockerMod.NAMESPACE, "bars/bar_back"); + + /* public static final Codec<StatusBar> CODEC = RecordCodecBuilder.create(instance -> instance.group( + Codec.INT.fieldOf("size").forGetter(bar -> bar.size), + Codec.INT.fieldOf("x").forGetter(bar -> bar.gridX), + Codec.INT.fieldOf("y").forGetter(bar -> bar.gridY), + Codec.STRING.listOf().fieldOf("colors").xmap( + strings -> strings.stream().map(s -> Integer.parseInt(s, 16)).map(Color::new).toArray(Color[]::new), + colors -> Arrays.stream(colors).map(color -> Integer.toHexString(color.getRGB())).toList()) + .forGetter(StatusBar::getColors), + Codec.STRING.optionalFieldOf("text_color").xmap( + s -> { + if (s.isPresent()) { + return Optional.of(new Color(Integer.parseInt(s.get(), 16))); + } else return Optional.empty(); + }, + o -> o.map(object -> Integer.toHexString(((Color) object).getRGB()))) + .forGetter(bar -> { + if (bar.getTextColor() != null) { + return Optional.of(bar.getTextColor()); + } else return Optional.empty(); + }), + Codec.BOOL.optionalFieldOf("show_text", true).forGetter(StatusBar::showText), + Codec.STRING.fieldOf("icon_position").xmap( + IconPosition::valueOf, + Enum::toString + ).forGetter(bar -> bar.iconPosition) + ) + + .apply(instance, ));*/ + private final Identifier icon; - private final Color[] colors; + + public Color[] getColors() { + return colors; + } + + public boolean hasOverflow() { + return hasOverflow; + } + + public @Nullable Color getTextColor() { + return textColor; + } + + private Color[] colors; private final boolean hasOverflow; - private final @Nullable Color textColor; - private final String name; - private @Nullable Consumer<StatusBar> onClick = null; + public void setTextColor(@Nullable Color textColor) { + this.textColor = textColor; + } + + private @Nullable Color textColor; + + public Text getName() { + return name; + } + + private final Text name; + + private @Nullable OnClick onClick = null; public int gridX = 0; public int gridY = 0; @@ -37,12 +93,15 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { public float fill = 0; public float overflowFill = 0; - private Object text = ""; + private Object value = ""; private int x = 0; private int y = 0; - public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor, String name) { + private IconPosition iconPosition = IconPosition.LEFT; + private boolean showText = true; + + public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor, Text name) { this.icon = icon; this.colors = colors; this.hasOverflow = hasOverflow; @@ -50,32 +109,42 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { this.name = name; } - public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor){ - this(icon, colors, hasOverflow, textColor, "no name"); + public StatusBar(Identifier icon, Color[] colors, boolean hasOverflow, @Nullable Color textColor) { + this(icon, colors, hasOverflow, textColor, Text.empty()); } @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (width <= 0) return; - context.drawGuiTexture(icon, x, y, 9, 9); - context.drawGuiTexture(BAR_BACK, x + 10, y + 1, width - 10, 7); - RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 11, y + 2, (int) ((width - 12) * fill), 5, colors[0]); + switch (iconPosition) { + case LEFT -> context.drawGuiTexture(icon, x, y, 9, 9); + case RIGHT -> context.drawGuiTexture(icon, x + width - 9, y, 9, 9); + } + + int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; + int barX = iconPosition.equals(IconPosition.LEFT) ? x + 10 : x; + context.drawGuiTexture(BAR_BACK, barX, y + 1, barWith, 7); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * fill), 5, colors[0]); + + if (hasOverflow && overflowFill > 0) { - RenderHelper.renderNineSliceColored(context, BAR_FILL, x + 11, y + 2, (int) ((width - 12) * overflowFill), 5, colors[1]); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * overflowFill), 5, colors[1]); } - context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " ; " + gridY , x, y-9, Colors.WHITE, true); + //context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " " + gridY + " s:" + size , x, y-9, Colors.WHITE, true); } public void updateValues(float fill, float overflowFill, Object text) { - this.text = text; + this.value = text; this.fill = fill; this.overflowFill = overflowFill; } public void renderText(DrawContext context) { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - String text = this.text.toString(); - int x = this.x + 11 + (width - textRenderer.getWidth(text) - 12) / 2; + int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; + int barX = iconPosition.equals(IconPosition.LEFT) ? x + 10 : x; + String text = this.value.toString(); + int x = barX + (barWith - textRenderer.getWidth(text)) / 2; int y = this.y - 3; final int[] offsets = new int[]{-1, 1}; @@ -83,7 +152,7 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { context.drawText(textRenderer, text, x + i, y, 0, false); context.drawText(textRenderer, text, x, y + i, 0, false); } - context.drawText(textRenderer, text, x, y, (textColor == null ? colors[0]: textColor).getRGB(), false); + context.drawText(textRenderer, text, x, y, (textColor == null ? colors[0] : textColor).getRGB(), false); } public void renderCursor(DrawContext context, int mouseX, int mouseY, float delta) { @@ -135,6 +204,14 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { return 9; } + public int getMinimumSize() { + return 2; + } + + public int getMaximumSize() { + return gridY < 0 ? 6 : 12; + } + @Override public ScreenRect getNavigationFocus() { return Widget.super.getNavigationFocus(); @@ -146,11 +223,11 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { } @Override - public void forEachChild(Consumer<ClickableWidget> consumer) {} + public void forEachChild(Consumer<ClickableWidget> consumer) { + } @Override public void setFocused(boolean focused) { - } @Override @@ -167,18 +244,17 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { public boolean mouseClicked(double mouseX, double mouseY, int button) { if (!isMouseOver(mouseX, mouseY)) return false; if (onClick != null) { - onClick.accept(this); + onClick.onClick(this, button, (int) mouseX, (int) mouseY); } return true; } - public void setOnClick(@Nullable Consumer<StatusBar> onClick) { + public void setOnClick(@Nullable OnClick onClick) { this.onClick = onClick; } @Override public void appendNarrations(NarrationMessageBuilder builder) { - } @Override @@ -193,4 +269,76 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { .append("width", width) .toString(); } + + public IconPosition getIconPosition() { + return iconPosition; + } + + public void setIconPosition(IconPosition iconPosition) { + this.iconPosition = iconPosition; + } + + public boolean showText() { + return showText; + } + + public void setShowText(boolean showText) { + this.showText = showText; + } + + public enum IconPosition { + LEFT, + RIGHT, + OFF + } + + @FunctionalInterface + public interface OnClick { + + void onClick(StatusBar statusBar, int button, int mouseX, int mouseY); + } + + public void loadFromJson(JsonObject object) { + // Make colors optional, so it's easy to reset to default + if (object.has("colors")) { + JsonArray colors1 = object.get("colors").getAsJsonArray(); + if (colors1.size() < 2 && hasOverflow) { + throw new IllegalStateException("Missing second color of bar that has overflow"); + } + Color[] newColors = new Color[colors1.size()]; + for (int i = 0; i < colors1.size(); i++) { + JsonElement jsonElement = colors1.get(i); + newColors[i] = new Color(Integer.parseInt(jsonElement.getAsString(), 16)); + } + this.colors = newColors; + } + + if (object.has("text_color")) this.textColor = new Color(Integer.parseInt(object.get("text_color").getAsString(), 16)); + + this.size = object.get("size").getAsInt(); + this.gridX = object.get("x").getAsInt(); + this.gridY = object.get("y").getAsInt(); + // these are optional too, why not + if (object.has("icon_position")) this.iconPosition = IconPosition.valueOf(object.get("icon_position").getAsString()); + if (object.has("show_text")) this.showText = object.get("show_text").getAsBoolean(); + + } + + public JsonObject toJson() { + JsonObject object = new JsonObject(); + JsonArray colors1 = new JsonArray(); + for (Color color : colors) { + colors1.add(Integer.toHexString(color.getRGB()).substring(2)); + } + object.add("colors", colors1); + if (textColor != null) { + object.addProperty("text_color", Integer.toHexString(textColor.getRGB()).substring(2)); + } + object.addProperty("size", size); + object.addProperty("x", gridX); + object.addProperty("y", gridY); + object.addProperty("icon_position", iconPosition.toString()); + object.addProperty("show_text", showText); + return object; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java index 8c659029..3bcc2011 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java @@ -2,7 +2,9 @@ package de.hysky.skyblocker.skyblock.fancybars; import de.hysky.skyblocker.mixin.accessor.WindowAccessor; import de.hysky.skyblocker.skyblock.FancyStatusBars; -import net.minecraft.client.MinecraftClient; +import it.unimi.dsi.fastutil.Pair; +import it.unimi.dsi.fastutil.objects.ObjectBooleanMutablePair; +import it.unimi.dsi.fastutil.objects.ObjectObjectMutablePair; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.gui.ScreenRect; @@ -17,16 +19,16 @@ import org.lwjgl.glfw.GLFW; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; public class StatusBarsConfigScreen extends Screen { private static final Identifier HOTBAR_TEXTURE = new Identifier("hud/hotbar"); - private final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); + public static final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); private final Map<ScreenRect, int[]> meaningFullName = new HashMap<>(); + private static final int HOTBAR_WIDTH = 182; private @Nullable StatusBar cursorBar = null; @@ -35,7 +37,14 @@ public class StatusBarsConfigScreen extends Screen { FancyStatusBars.updatePositions(); } - private final int[] currentCoords = new int[]{0, 0}; + private final int[] currentCursorCoords = new int[]{0, 0}; + + private final Pair<int[], Boolean> resizeHover = new ObjectBooleanMutablePair<>(new int[]{0, 0}, false); + + private final Pair<int[], int[]> resizedBars = ObjectObjectMutablePair.of(new int[]{0, 0}, new int[]{0, 0}); + private boolean resizing = false; + + private EditBarWidget editBarWidget; @SuppressWarnings("UnreachableCode") // IntelliJ big stupid @Override @@ -44,45 +53,47 @@ public class StatusBarsConfigScreen extends Screen { context.fillGradient(screenRect.position().x(), screenRect.position().y(), screenRect.position().x() + screenRect.width(), screenRect.position().y() + screenRect.height(), 0xFFFF0000, 0xFF0000FF); } super.render(context, mouseX, mouseY, delta); - context.drawGuiTexture(HOTBAR_TEXTURE, width / 2 - 91, height - 22, 182, 22); + context.drawGuiTexture(HOTBAR_TEXTURE, width / 2 - HOTBAR_WIDTH / 2, height - 22, HOTBAR_WIDTH, 22); + editBarWidget.render(context, mouseX, mouseY, delta); + ScreenRect mouseRect = new ScreenRect(new ScreenPos(mouseX - 1, mouseY - 1), 3, 3); assert client != null; WindowAccessor window = (WindowAccessor) (Object) client.getWindow(); assert window != null; if (cursorBar != null) { cursorBar.renderCursor(context, mouseX, mouseY, delta); - context.drawText(textRenderer, currentCoords[0] + " " + currentCoords[1], 100, 5, Colors.WHITE, true); + context.drawText(textRenderer, currentCursorCoords[0] + " " + currentCursorCoords[1], 100, 5, Colors.WHITE, true); - if (FancyStatusBars.barGrid.getTopSize() == 0 && topBarZone.overlaps(mouseRect) && currentCoords[1] != 1) { + if (FancyStatusBars.barGrid.getTopSize() == 0 && topBarZone.overlaps(mouseRect) && currentCursorCoords[1] != 1) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(1, true); FancyStatusBars.barGrid.add(1, 1, cursorBar); - currentCoords[1] = 1; + currentCursorCoords[1] = 1; FancyStatusBars.updatePositions(); - } else if (FancyStatusBars.barGrid.getBottomLeftSize() == 0 && bottomLeftBarZone.overlaps(mouseRect) && (currentCoords[0] != -1 || currentCoords[1] != -1)) { + } else if (FancyStatusBars.barGrid.getBottomLeftSize() == 0 && bottomLeftBarZone.overlaps(mouseRect) && (currentCursorCoords[0] != -1 || currentCursorCoords[1] != -1)) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(-1, false); FancyStatusBars.barGrid.add(-1, -1, cursorBar); - currentCoords[0] = -1; - currentCoords[1] = -1; + currentCursorCoords[0] = -1; + currentCursorCoords[1] = -1; FancyStatusBars.updatePositions(); - } else if (FancyStatusBars.barGrid.getBottomRightSize() == 0 && bottomRightBarZone.overlaps(mouseRect) && (currentCoords[0] != 1 || currentCoords[1] != -1)) { + } else if (FancyStatusBars.barGrid.getBottomRightSize() == 0 && bottomRightBarZone.overlaps(mouseRect) && (currentCursorCoords[0] != 1 || currentCursorCoords[1] != -1)) { FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); FancyStatusBars.barGrid.addRow(-1, true); FancyStatusBars.barGrid.add(1, -1, cursorBar); - currentCoords[0] = 1; - currentCoords[1] = -1; + currentCursorCoords[0] = 1; + currentCursorCoords[1] = -1; FancyStatusBars.updatePositions(); } else rectLoop:for (ScreenRect screenRect : meaningFullName.keySet()) { for (NavigationDirection direction : NavigationDirection.values()) { - boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); if (overlaps) { int[] ints = meaningFullName.get(screenRect); + final boolean vertical = direction.getAxis().equals(NavigationAxis.VERTICAL); int offsetX = 0; int offsetY = 0; - final boolean vertical = direction.getAxis().equals(NavigationAxis.VERTICAL); if (vertical) { if (!direction.isPositive()) { offsetY = ints[1] > 0 ? 1 : 0; @@ -97,11 +108,9 @@ public class StatusBarsConfigScreen extends Screen { } } context.drawText(textRenderer, ints[0] + offsetX + " " + ints[1] + offsetY, 100, 15, Colors.WHITE, true); - if (ints[0] + offsetX != currentCoords[0] || ints[1] + offsetY != currentCoords[1]) { - currentCoords[0] = ints[0] + offsetX; - currentCoords[1] = ints[1] + offsetY; - System.out.println("Moving " + cursorBar); - System.out.println(ints[0] + " " + ints[1]); + if (ints[0] + offsetX != currentCursorCoords[0] || ints[1] + offsetY != currentCursorCoords[1]) { + currentCursorCoords[0] = ints[0] + offsetX; + currentCursorCoords[1] = ints[1] + offsetY; FancyStatusBars.barGrid.remove(cursorBar.gridX, cursorBar.gridY); @@ -114,22 +123,99 @@ public class StatusBarsConfigScreen extends Screen { FancyStatusBars.barGrid.add(ints[0] + offsetX, ints[1], cursorBar); } FancyStatusBars.updatePositions(); - System.out.println("After " + cursorBar); } break rectLoop; } } } } else { - rectLoop:for (ScreenRect screenRect : meaningFullName.keySet()) { - for (NavigationDirection direction : new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT}) { - boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + // RESIZING STATE + if (resizing) { + int middleX; + boolean bottom; - if (overlaps) { - GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); - break rectLoop; - } else { - GLFW.glfwSetCursor(window.getHandle(), 0); + int[] left = resizedBars.left(); + int[] right = resizedBars.right(); + boolean hasRight = right[0] != 0; + boolean hasLeft = left[0] != 0; + if (!hasRight) { + StatusBar bar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + middleX = bar.getX() + bar.getWidth(); + bottom = bar.gridY < 0; + } else { + middleX = FancyStatusBars.barGrid.getBar(right[0], right[1]).getX(); + bottom = right[1] < 0; + } + int i = bottom ? 20 : 10; + boolean doResize = true; + StatusBar rightBar = null; + StatusBar leftBar = null; + + context.drawText(textRenderer, Integer.toString(mouseX - middleX), 100, 25, -1, true); + + if (mouseX < middleX) { + if (middleX - mouseX > i) { + + if (hasRight) { + rightBar = FancyStatusBars.barGrid.getBar(right[0], right[1]); + if (rightBar.size + 1 > rightBar.getMaximumSize()) doResize = false; + } + if (hasLeft) { + leftBar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + if (leftBar.size - 1 < leftBar.getMinimumSize()) doResize = false; + } + + if (doResize) { + if (hasRight) rightBar.size++; + if (hasLeft) leftBar.size--; + FancyStatusBars.updatePositions(); + } + } + } else { + if (mouseX - middleX > i) { + + if (hasRight) { + rightBar = FancyStatusBars.barGrid.getBar(right[0], right[1]); + if (rightBar.size - 1 < rightBar.getMinimumSize()) doResize = false; + } + if (hasLeft) { + leftBar = FancyStatusBars.barGrid.getBar(left[0], left[1]); + if (leftBar.size + 1 > leftBar.getMaximumSize()) doResize = false; + } + context.drawText(textRenderer, leftBar.size + " " + leftBar.getMaximumSize(), 100, 35, -1, true); + + if (doResize) { + if (hasRight) rightBar.size--; + if (hasLeft) leftBar.size++; + FancyStatusBars.updatePositions(); + } + } + } + GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + } + // NOT RESIZING STATE + else { + rectLoop: + for (ScreenRect screenRect : meaningFullName.keySet()) { + for (NavigationDirection direction : new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT}) { + boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); + + if (overlaps && !editBarWidget.isMouseOver(mouseX, mouseY)) { + int[] ints = meaningFullName.get(screenRect); + boolean left = direction.equals(NavigationDirection.LEFT); + if ((ints[0] == 1 && left) || (ints[0] == -1 && !left) || (!left && ints[1] > 0 && ints[0] == FancyStatusBars.barGrid.getRow(ints[1], true).size())) { + break; + } + resizeHover.first()[0] = ints[0]; + resizeHover.first()[1] = ints[1]; + resizeHover.right(!left); + GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + break rectLoop; + } else { + resizeHover.first()[0] = 0; + resizeHover.first()[1] = 0; + GLFW.glfwSetCursor(window.getHandle(), 0); + } } } } @@ -143,13 +229,16 @@ public class StatusBarsConfigScreen extends Screen { @Override protected void init() { super.init(); + editBarWidget = new EditBarWidget(0, 0, this); + editBarWidget.visible = false; + addSelectableChild(editBarWidget); // rendering separately to have it above hotbar Collection<StatusBar> values = FancyStatusBars.statusBars.values(); values.forEach(this::setup); checkZeroCoordinates(values); updateScreenRects(); - topBarZone = new ScreenRect(width / 2 - 91, height - 22 - 15, 182, 15); - bottomLeftBarZone = new ScreenRect(width / 2 - 91 - 20, height - 22, 20, 22); - bottomRightBarZone = new ScreenRect(width / 2 + 91, height - 22, 20, 22); + topBarZone = new ScreenRect(width / 2 - HOTBAR_WIDTH / 2, height - 22 - 15, HOTBAR_WIDTH, 15); + bottomLeftBarZone = new ScreenRect(width / 2 - HOTBAR_WIDTH / 2 - 20, height - 22, 20, 22); + bottomRightBarZone = new ScreenRect(width / 2 + HOTBAR_WIDTH / 2, height - 22, 20, 22); } private void setup(StatusBar statusBar) { @@ -175,8 +264,9 @@ public class StatusBarsConfigScreen extends Screen { super.removed(); FancyStatusBars.statusBars.values().forEach(statusBar -> statusBar.setOnClick(null)); FancyStatusBars.updatePositions(); + assert client != null; GLFW.glfwSetCursor(((WindowAccessor) (Object) client.getWindow()).getHandle(), 0); - GLFW.glfwDestroyCursor(RESIZE_CURSOR); // Does it explode if I don't do that?? idk aaaaaaaaa + FancyStatusBars.saveBarConfig(); } @Override @@ -184,11 +274,20 @@ public class StatusBarsConfigScreen extends Screen { return false; } - private void onClick(StatusBar statusBar) { - cursorBar = statusBar; - FancyStatusBars.barGrid.remove(statusBar.gridX, statusBar.gridY); - FancyStatusBars.updatePositions(); - updateScreenRects(); + private void onClick(StatusBar statusBar, int button, int mouseX, int mouseY) { + if (button == 0) { + cursorBar = statusBar; + FancyStatusBars.barGrid.remove(statusBar.gridX, statusBar.gridY); + FancyStatusBars.updatePositions(); + updateScreenRects(); + } else if (button == 1) { + int x = Math.min(mouseX - 1, width - editBarWidget.getWidth()); + int y = Math.min(mouseY - 1, height - editBarWidget.getHeight()); + editBarWidget.visible = true; + editBarWidget.setStatusBar(statusBar); + editBarWidget.setX(x); + editBarWidget.setY(y); + } } private void updateScreenRects() { @@ -206,7 +305,47 @@ public class StatusBarsConfigScreen extends Screen { checkZeroCoordinates(FancyStatusBars.statusBars.values()); updateScreenRects(); return true; + } else if (resizing) { + resizing = false; + resizedBars.left()[0] = 0; + resizedBars.left()[1] = 0; + resizedBars.right()[0] = 0; + resizedBars.right()[1] = 0; + updateScreenRects(); + return true; } return super.mouseReleased(mouseX, mouseY, button); } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + int[] first = resizeHover.first(); + // want the right click thing to have priority + if (!editBarWidget.isMouseOver(mouseX, mouseY) && button == 0 && first[0] != 0 && first[1] != 0) { + if (resizeHover.right()) { + resizedBars.left()[0] = first[0]; + resizedBars.left()[1] = first[1]; + if (FancyStatusBars.barGrid.coordinatesExist(first[0] + 1, first[1])) { + resizedBars.right()[0] = first[0] + 1; + resizedBars.right()[1] = first[1]; + } else { + resizedBars.right()[0] = 0; + resizedBars.right()[1] = 0; + } + } else { + resizedBars.right()[0] = first[0]; + resizedBars.right()[1] = first[1]; + if (FancyStatusBars.barGrid.coordinatesExist(first[0] - 1, first[1])) { + resizedBars.left()[0] = first[0] - 1; + resizedBars.left()[1] = first[1]; + } else { + resizedBars.left()[0] = 0; + resizedBars.left()[1] = 0; + } + } + resizing = true; + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } } |
