From 66ce8f7b2065f9c87e2c2d5da7f010559ef41ada Mon Sep 17 00:00:00 2001 From: viciscat <51047087+viciscat@users.noreply.github.com> Date: Mon, 21 Jul 2025 21:45:25 +0200 Subject: Strong and independent bars (#1432) * moving bars freely * some commenting * Update StatusBar.java * less magic numbers --- .../skyblock/fancybars/EditBarWidget.java | 3 +- .../skyblock/fancybars/FancyStatusBars.java | 14 +- .../skyblocker/skyblock/fancybars/StatusBar.java | 108 ++++---- .../skyblock/fancybars/StatusBarsConfigScreen.java | 285 +++++++++++++-------- 4 files changed, 251 insertions(+), 159 deletions(-) (limited to 'src/main/java/de') diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java index 912a53ce..72e07df8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/EditBarWidget.java @@ -151,10 +151,11 @@ public class EditBarWidget extends ContainerWidget { textColor.setCurrent(statusBar.getTextColor().getRGB()); } textColor.setOnChange(statusBar::setTextColor); - hideOption.active = statusBar.anchor != null; + hideOption.active = statusBar.enabled; hideOption.setRunnable(() -> { if (statusBar.anchor != null) FancyStatusBars.barPositioner.removeBar(statusBar.anchor, statusBar.gridY, statusBar); + statusBar.enabled = false; FancyStatusBars.updatePositions(true); }); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/FancyStatusBars.java b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/FancyStatusBars.java index aa2b107d..1e91ed54 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/FancyStatusBars.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/FancyStatusBars.java @@ -49,7 +49,7 @@ public class FancyStatusBars { public static boolean isBarEnabled(StatusBarType type) { StatusBar statusBar = statusBars.get(type); - return Debug.isTestEnvironment() || statusBar.anchor != null || statusBar.inMouse; + return Debug.isTestEnvironment() || statusBar.enabled || statusBar.inMouse; } @SuppressWarnings("deprecation") @@ -183,11 +183,18 @@ public class FancyStatusBars { // Put these in the corner for the config screen int offset = 0; for (StatusBar statusBar : statusBars.values()) { - if (statusBar.anchor == null) { + if (!statusBar.enabled) { statusBar.setX(5); statusBar.setY(50 + offset); statusBar.setWidth(30); offset += statusBar.getHeight(); + } else if (statusBar.anchor == null) { + statusBar.width = Math.clamp(statusBar.width, 30f / width, 1); + statusBar.x = Math.clamp(statusBar.x, 0, 1 - statusBar.width); + statusBar.y = Math.clamp(statusBar.y, 0, 1 - (float) statusBar.getHeight() / height); + statusBar.setX((int) (statusBar.x * width)); + statusBar.setY((int) (statusBar.y * height)); + statusBar.setWidth((int) (statusBar.width * width)); } } @@ -307,8 +314,7 @@ public class FancyStatusBars { Collection barCollection = statusBars.values(); for (StatusBar statusBar : barCollection) { - if (statusBar.anchor == null || !statusBar.visible) continue; - if (statusBar == statusBars.get(StatusBarType.AIR) && !player.isSubmergedInWater()) continue; + if (!statusBar.enabled || !statusBar.visible) continue; statusBar.render(context, -1, -1, client.getRenderTickCounter().getDynamicDeltaTicks()); } 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 98709993..034998ec 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBar.java @@ -32,6 +32,8 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { private static final Identifier BAR_FILL = Identifier.of(SkyblockerMod.NAMESPACE, "bars/bar_fill"); private static final Identifier BAR_BACK = Identifier.of(SkyblockerMod.NAMESPACE, "bars/bar_back"); + public static final int ICON_SIZE = 9; + private final Identifier icon; private final StatusBarType type; private Color[] colors; @@ -64,10 +66,12 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { private @Nullable OnClick onClick = null; public int gridX = 0; public int gridY = 0; + public float x = 0; + public float y = 0; + public float width = 0; public @Nullable BarPositioner.BarAnchor anchor = null; public int size = 1; - private int width = 0; public float fill = 0; public float overflowFill = 0; @@ -76,13 +80,15 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { * Used to hide the bar dynamically, like the oxygen bar */ public boolean visible = true; + public boolean enabled = true; private Object value = "???"; private @Nullable Object max = "???"; private @Nullable Object overflow = "???"; - private int x = 0; - private int y = 0; + private int renderX = 0; + private int renderY = 0; + private int renderWidth = 0; private IconPosition iconPosition = IconPosition.LEFT; private TextPosition textPosition = TextPosition.BAR_CENTER; @@ -104,19 +110,19 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { - if (width <= 0) return; + if (renderWidth <= 0) return; int transparency = transparency(-1); switch (iconPosition) { - case LEFT -> context.drawGuiTexture(RenderLayer::getGuiTextured, icon, x, y, 9, 9, transparency); - case RIGHT -> context.drawGuiTexture(RenderLayer::getGuiTextured, icon, x + width - 9, y, 9, 9, transparency); + case LEFT -> context.drawGuiTexture(RenderLayer::getGuiTextured, icon, renderX, renderY, ICON_SIZE, ICON_SIZE, transparency); + case RIGHT -> context.drawGuiTexture(RenderLayer::getGuiTextured, icon, renderX + renderWidth - ICON_SIZE, renderY, ICON_SIZE, ICON_SIZE, transparency); } - int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; - int barX = iconPosition.equals(IconPosition.LEFT) ? x + 10 : x; - context.drawGuiTexture(RenderLayer::getGuiTextured, BAR_BACK, barX, y + 1, barWith, 7, transparency); - drawBarFill(context, barX, barWith); + int barWidth = iconPosition.equals(IconPosition.OFF) ? renderWidth : renderWidth - ICON_SIZE - 1; + int barX = iconPosition.equals(IconPosition.LEFT) ? renderX + ICON_SIZE + 1 : renderX; + context.drawGuiTexture(RenderLayer::getGuiTextured, BAR_BACK, barX, renderY + 1, barWidth, 7, transparency); + drawBarFill(context, barX, barWidth); //context.drawText(MinecraftClient.getInstance().textRenderer, gridX + " " + gridY + " s:" + size , x, y-9, Colors.WHITE, true); - if (showText()) { + if (showText() && enabled) { context.getMatrices().push(); context.getMatrices().translate(0, 0, 100); renderText(context); @@ -125,11 +131,11 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { } protected void drawBarFill(DrawContext context, int barX, int barWith) { - RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * fill), 5, transparency(colors[0].getRGB())); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, renderY + 2, (int) ((barWith - 2) * fill), 5, transparency(colors[0].getRGB())); if (hasOverflow() && overflowFill > 0) { - RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, y + 2, (int) ((barWith - 2) * Math.min(overflowFill, 1)), 5, transparency(colors[1].getRGB())); + RenderHelper.renderNineSliceColored(context, BAR_FILL, barX + 1, renderY + 2, (int) ((barWith - 2) * Math.min(overflowFill, 1)), 5, transparency(colors[1].getRGB())); } } @@ -148,8 +154,8 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { public void renderText(DrawContext context) { if (!showText()) return; TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - int barWith = iconPosition.equals(IconPosition.OFF) ? width : width - 10; - int barX = iconPosition.equals(IconPosition.LEFT) ? x + 11 : x; + int barWidth = iconPosition.equals(IconPosition.OFF) ? renderWidth : renderWidth - ICON_SIZE - 1; + int barX = iconPosition.equals(IconPosition.LEFT) ? renderX + ICON_SIZE + 2 : renderX; String stringValue = this.value.toString(); MutableText text = Text.literal(stringValue).styled(style -> style.withColor((textColor == null ? colors[0] : textColor).getRGB())); @@ -165,12 +171,12 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { int textWidth = textRenderer.getWidth(text); int x; switch (textPosition) { - case RIGHT -> x = barX + barWith - textWidth; - case CENTER -> x = this.x + (width - textWidth) / 2; - case BAR_CENTER -> x = barX + (barWith - textWidth) / 2; + case RIGHT -> x = barX + barWidth - textWidth; + case CENTER -> x = this.renderX + (renderWidth - textWidth) / 2; + case BAR_CENTER -> x = barX + (barWidth - textWidth) / 2; case null, default -> x = barX; // Put on the left by default because I said so. } - int y = this.y - 3; + int y = this.renderY - 3; context.draw(consumers -> textRenderer.drawWithOutline( text.asOrderedText(), @@ -185,21 +191,18 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { } public void renderCursor(DrawContext context, int mouseX, int mouseY, float delta) { - int temp_x = x; - int temp_y = y; - int temp_width = width; + int temp_x = renderX; + int temp_y = renderY; boolean temp_ghost = inMouse; - x = mouseX; - y = mouseY; - width = 100; + renderX = mouseX; + renderY = mouseY; inMouse = false; render(context, mouseX, mouseY, delta); - x = temp_x; - y = temp_y; - width = temp_width; + renderX = temp_x; + renderY = temp_y; inMouse = temp_ghost; } @@ -207,31 +210,31 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { @Override public void setX(int x) { - this.x = x; + this.renderX = x; } @Override public void setY(int y) { - this.y = y; + this.renderY = y; } @Override public int getX() { - return x; + return renderX; } @Override public int getY() { - return y; + return renderY; } @Override public int getWidth() { - return width; + return renderWidth; } public void setWidth(int width) { - this.width = width; + this.renderWidth = width; } @Override @@ -246,7 +249,7 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { @Override public boolean isMouseOver(double mouseX, double mouseY) { - return mouseX >= x && mouseX <= x + getWidth() && mouseY >= y && mouseY <= y + getHeight(); + return mouseX >= renderX && mouseX <= renderX + getWidth() && mouseY >= renderY && mouseY <= renderY + getHeight(); } @Override @@ -291,9 +294,9 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { .append("gridX", gridX) .append("gridY", gridY) .append("size", size) - .append("x", x) - .append("y", y) - .append("width", width) + .append("x", renderX) + .append("y", renderY) + .append("width", renderWidth) .append("anchor", anchor) .toString(); } @@ -378,9 +381,18 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { String maybeAnchor = object.get("anchor").getAsString().trim(); this.anchor = maybeAnchor.equals("null") ? null : BarPositioner.BarAnchor.valueOf(maybeAnchor); - this.size = object.get("size").getAsInt(); - this.gridX = object.get("x").getAsInt(); - this.gridY = object.get("y").getAsInt(); + if (!object.has("enabled")) { + enabled = anchor != null; + } else enabled = object.get("enabled").getAsBoolean(); + if (anchor != null) { + this.size = object.get("size").getAsInt(); + this.gridX = object.get("x").getAsInt(); + this.gridY = object.get("y").getAsInt(); + } else { + this.width = object.get("size").getAsFloat(); + this.x = object.get("x").getAsFloat(); + this.y = object.get("y").getAsFloat(); + } // these are optional too, why not if (object.has("icon_position")) this.iconPosition = IconPosition.valueOf(object.get("icon_position").getAsString().trim()); // backwards compat teehee @@ -388,7 +400,6 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { if (object.has("text_position")) this.textPosition = TextPosition.valueOf(object.get("text_position").getAsString().trim()); if (object.has("show_max")) this.showMax = object.get("show_max").getAsBoolean(); if (object.has("show_overflow")) this.showOverflow = object.get("show_overflow").getAsBoolean(); - } public JsonObject toJson() { @@ -401,16 +412,23 @@ public class StatusBar implements Widget, Drawable, Element, Selectable { if (textColor != null) { object.addProperty("text_color", Integer.toHexString(textColor.getRGB()).substring(2)); } - object.addProperty("size", size); if (anchor != null) { object.addProperty("anchor", anchor.toString()); } else object.addProperty("anchor", "null"); - object.addProperty("x", gridX); - object.addProperty("y", gridY); + if (anchor != null) { + object.addProperty("x", gridX); + object.addProperty("y", gridY); + object.addProperty("size", size); + } else { + object.addProperty("size", width); + object.addProperty("x", x); + object.addProperty("y", y); + } object.addProperty("icon_position", iconPosition.asString()); object.addProperty("text_position", textPosition.asString()); object.addProperty("show_max", showMax); object.addProperty("show_overflow", showOverflow); + object.addProperty("enabled", enabled); 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 619f06ac..d4baf3c7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/fancybars/StatusBarsConfigScreen.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.objects.ObjectBooleanMutablePair; import it.unimi.dsi.fastutil.objects.ObjectBooleanPair; import it.unimi.dsi.fastutil.objects.ObjectObjectMutablePair; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.gui.ScreenRect; @@ -22,33 +23,49 @@ import de.hysky.skyblocker.skyblock.fancybars.BarPositioner.BarLocation; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; public class StatusBarsConfigScreen extends Screen { private static final Identifier HOTBAR_TEXTURE = Identifier.ofVanilla("hud/hotbar"); - - public static final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); - - private final Map rectToBarLocation = new HashMap<>(); private static final int HOTBAR_WIDTH = 182; + private static final float RESIZE_THRESHOLD = 0.75f; + private static final int BAR_MINIMUM_WIDTH = 30; + public static final long RESIZE_CURSOR = GLFW.glfwCreateStandardCursor(GLFW.GLFW_HRESIZE_CURSOR); + // prioritize left and right cuz they are much smaller than up and down + private static final NavigationDirection[] DIRECTION_CHECK_ORDER = new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT, NavigationDirection.UP, NavigationDirection.DOWN}; - private @Nullable StatusBar cursorBar = null; - - public StatusBarsConfigScreen() { - super(Text.of("Status Bars Config")); + private static boolean resizeCursor = false; + private static void setResizeCursor(boolean bl) { + if (bl != resizeCursor) { + resizeCursor = bl; + Window window = MinecraftClient.getInstance().getWindow(); + if (resizeCursor) { + GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + } else { + GLFW.glfwSetCursor(window.getHandle(), 0); + } + } } - private BarLocation currentInsertLocation = new BarLocation(null, 0, 0); + private final Map> rectToBar = new HashMap<>(); + /** + * Contains the hovered bar and a boolean that is true if hovering the right side or false otherwise. + */ + private final ObjectBooleanPair<@Nullable StatusBar> resizeHover = new ObjectBooleanMutablePair<>(null, false); + private final Pair<@Nullable StatusBar, @Nullable StatusBar> resizedBars = ObjectObjectMutablePair.of(null, null); - private final ObjectBooleanPair resizeHover = new ObjectBooleanMutablePair<>(BarLocation.NULL, false); + private @Nullable StatusBar cursorBar = null; + private ScreenPos cursorOffset = new ScreenPos(0, 0); + private BarLocation currentInsertLocation = new BarLocation(null, 0, 0); - private final Pair resizedBars = ObjectObjectMutablePair.of(BarLocation.NULL, BarLocation.NULL); private boolean resizing = false; - private EditBarWidget editBarWidget; - // prioritize left and right cuz they are much smaller space than up and down - private static final NavigationDirection[] DIRECTION_CHECK_ORDER = new NavigationDirection[]{NavigationDirection.LEFT, NavigationDirection.RIGHT, NavigationDirection.UP, NavigationDirection.DOWN}; + public StatusBarsConfigScreen() { + super(Text.of("Status Bars Config")); + } + @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { @@ -67,50 +84,64 @@ public class StatusBarsConfigScreen extends Screen { ScreenRect mouseRect = new ScreenRect(new ScreenPos(mouseX - scaleFactor / 2, mouseY - scaleFactor / 2), scaleFactor, scaleFactor); if (cursorBar != null) { - cursorBar.renderCursor(context, mouseX, mouseY, delta); + cursorBar.renderCursor(context, mouseX + cursorOffset.x(), mouseY + cursorOffset.y(), delta); boolean inserted = false; + boolean updatePositions = false; rectLoop: - for (ScreenRect screenRect : rectToBarLocation.keySet()) { + for (ScreenRect screenRect : rectToBar.keySet()) { for (NavigationDirection direction : DIRECTION_CHECK_ORDER) { boolean overlaps = screenRect.getBorder(direction).add(direction).overlaps(mouseRect); if (overlaps) { - BarLocation barSnap = rectToBarLocation.get(screenRect); + Pair barPair = rectToBar.get(screenRect); + BarLocation barSnap = barPair.right(); if (barSnap.barAnchor() == null) break; if (direction.getAxis().equals(NavigationAxis.VERTICAL)) { int neighborInsertY = getNeighborInsertY(barSnap, !direction.isPositive()); + inserted = true; if (!currentInsertLocation.equals(barSnap.barAnchor(), barSnap.x(), neighborInsertY)) { if (cursorBar.anchor != null) FancyStatusBars.barPositioner.removeBar(cursorBar.anchor, cursorBar.gridY, cursorBar); FancyStatusBars.barPositioner.addRow(barSnap.barAnchor(), neighborInsertY); FancyStatusBars.barPositioner.addBar(barSnap.barAnchor(), neighborInsertY, cursorBar); currentInsertLocation = BarLocation.of(cursorBar); - inserted = true; + updatePositions = true; } } else { int neighborInsertX = getNeighborInsertX(barSnap, direction.isPositive()); + inserted = true; if (!currentInsertLocation.equals(barSnap.barAnchor(), neighborInsertX, barSnap.y())) { if (cursorBar.anchor != null) FancyStatusBars.barPositioner.removeBar(cursorBar.anchor, cursorBar.gridY, cursorBar); FancyStatusBars.barPositioner.addBar(barSnap.barAnchor(), barSnap.y(), neighborInsertX, cursorBar); currentInsertLocation = BarLocation.of(cursorBar); - inserted = true; + updatePositions = true; } } break rectLoop; } } } - if (inserted) { + if (updatePositions) { FancyStatusBars.updatePositions(true); return; } // check for hovering empty anchors for (BarPositioner.BarAnchor barAnchor : BarPositioner.BarAnchor.allAnchors()) { - if (FancyStatusBars.barPositioner.getRowCount(barAnchor) != 0) continue; ScreenRect anchorHitbox = barAnchor.getAnchorHitbox(barAnchor.getAnchorPosition(width, height)); + if (FancyStatusBars.barPositioner.getRowCount(barAnchor) != 0) { + // this fixes flickering + if (FancyStatusBars.barPositioner.getRowCount(barAnchor) == 1) { + LinkedList row = FancyStatusBars.barPositioner.getRow(barAnchor, 0); + if (row.size() == 1 && row.getFirst() == cursorBar && anchorHitbox.overlaps(mouseRect)) inserted = true; + } + continue; + } + context.fill(anchorHitbox.getLeft(), anchorHitbox.getTop(), anchorHitbox.getRight(), anchorHitbox.getBottom(), 0x99FFFFFF); - if (anchorHitbox.overlaps(mouseRect) && currentInsertLocation.barAnchor() != barAnchor) { + if (anchorHitbox.overlaps(mouseRect)) { + inserted = true; + if (currentInsertLocation.barAnchor() == barAnchor) continue; if (cursorBar.anchor != null) FancyStatusBars.barPositioner.removeBar(cursorBar.anchor, cursorBar.gridY, cursorBar); FancyStatusBars.barPositioner.addRow(barAnchor); @@ -119,96 +150,107 @@ public class StatusBarsConfigScreen extends Screen { FancyStatusBars.updatePositions(true); } } - } else { + if (!inserted) { + if (cursorBar.anchor != null) FancyStatusBars.barPositioner.removeBar(cursorBar.anchor, cursorBar.gridY, cursorBar); + currentInsertLocation = BarLocation.NULL; + FancyStatusBars.updatePositions(true); + cursorBar.setX(width + 5); + } + } else { // Not dragging around a bar if (resizing) { // actively resizing one or 2 bars - int middleX; + int middleX; // the point between the 2 bars - BarLocation left = resizedBars.left(); - BarLocation right = resizedBars.right(); - boolean hasRight = right.barAnchor() != null; - boolean hasLeft = left.barAnchor() != null; + StatusBar rightBar = resizedBars.right(); + StatusBar leftBar = resizedBars.left(); + boolean hasRight = rightBar != null; + boolean hasLeft = leftBar != null; BarPositioner.BarAnchor barAnchor; if (!hasRight) { - barAnchor = left.barAnchor(); - StatusBar bar = FancyStatusBars.barPositioner.getBar(barAnchor, left.y(), left.x()); - middleX = bar.getX() + bar.getWidth(); + barAnchor = leftBar.anchor; + middleX = leftBar.getX() + leftBar.getWidth(); } else { - barAnchor = right.barAnchor(); - middleX = FancyStatusBars.barPositioner.getBar(barAnchor, right.y(), right.x()).getX(); + barAnchor = rightBar.anchor; + middleX = rightBar.getX(); } - boolean doResize = true; - StatusBar rightBar = null; - StatusBar leftBar = null; - - BarPositioner.SizeRule sizeRule = barAnchor.getSizeRule(); - - float widthPerSize; - if (sizeRule.isTargetSize()) - widthPerSize = (float) sizeRule.totalWidth() / sizeRule.targetSize(); - else - widthPerSize = sizeRule.widthPerSize(); + if (barAnchor != null) { // If is on an anchor + BarPositioner.SizeRule sizeRule = barAnchor.getSizeRule(); + boolean doResize = true; + + float widthPerSize; + if (sizeRule.isTargetSize()) + widthPerSize = (float) sizeRule.totalWidth() / sizeRule.targetSize(); + else + widthPerSize = sizeRule.widthPerSize(); + + // resize towards the left + if (mouseX < middleX) { + if (middleX - mouseX > widthPerSize / RESIZE_THRESHOLD) { + if (hasRight) { + if (rightBar.size + 1 > sizeRule.maxSize()) doResize = false; + } + if (hasLeft) { + if (leftBar.size - 1 < sizeRule.minSize()) doResize = false; + } - // resize towards the left - if (mouseX < middleX) { - if (middleX - mouseX > widthPerSize / .75f) { - if (hasRight) { - rightBar = FancyStatusBars.barPositioner.getBar(barAnchor, right.y(), right.x()); - if (rightBar.size + 1 > sizeRule.maxSize()) doResize = false; - } - if (hasLeft) { - leftBar = FancyStatusBars.barPositioner.getBar(barAnchor, left.y(), left.x()); - if (leftBar.size - 1 < sizeRule.minSize()) doResize = false; + if (doResize) { + if (hasRight) rightBar.size++; + if (hasLeft) leftBar.size--; + FancyStatusBars.updatePositions(true); + } } + } else { // towards the right + if (mouseX - middleX > widthPerSize / RESIZE_THRESHOLD) { + if (hasRight) { + if (rightBar.size - 1 < sizeRule.minSize()) doResize = false; + } + if (hasLeft) { + if (leftBar.size + 1 > sizeRule.maxSize()) doResize = false; + } - if (doResize) { - if (hasRight) rightBar.size++; - if (hasLeft) leftBar.size--; - FancyStatusBars.updatePositions(true); + if (doResize) { + if (hasRight) rightBar.size--; + if (hasLeft) leftBar.size++; + FancyStatusBars.updatePositions(true); + } } } - } else { // towards the right - if (mouseX - middleX > widthPerSize / .75f) { - if (hasRight) { - rightBar = FancyStatusBars.barPositioner.getBar(barAnchor, right.y(), right.x()); - if (rightBar.size - 1 < sizeRule.minSize()) doResize = false; - } - if (hasLeft) { - leftBar = FancyStatusBars.barPositioner.getBar(barAnchor, left.y(), left.x()); - if (leftBar.size + 1 > sizeRule.maxSize()) doResize = false; - } - - if (doResize) { - if (hasRight) rightBar.size--; - if (hasLeft) leftBar.size++; - FancyStatusBars.updatePositions(true); - } + } else { // Freely moving around + if (hasLeft) { + leftBar.setWidth(Math.max(BAR_MINIMUM_WIDTH, mouseX - leftBar.getX())); + } else if (hasRight) { + int endX = rightBar.getX() + rightBar.getWidth(); + rightBar.setX(Math.min(endX - BAR_MINIMUM_WIDTH, mouseX)); + rightBar.setWidth(endX - rightBar.getX()); } } } else { // hovering bars rectLoop: - for (ScreenRect screenRect : rectToBarLocation.keySet()) { + for (ScreenRect screenRect : rectToBar.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)) { - BarLocation barLocation = rectToBarLocation.get(screenRect); - if (barLocation.barAnchor() == null) break; + Pair barPair = rectToBar.get(screenRect); + BarLocation barLocation = barPair.right(); + StatusBar bar = barPair.left(); + if (!bar.enabled) break; boolean right = direction.equals(NavigationDirection.RIGHT); - // can't resize on the edge of a target size row! - if (barLocation.barAnchor().getSizeRule().isTargetSize() && !FancyStatusBars.barPositioner.hasNeighbor(barLocation.barAnchor(), barLocation.y(), barLocation.x(), right)) { - break; + if (barLocation.barAnchor() != null) { + if (barLocation.barAnchor().getSizeRule().isTargetSize() && !FancyStatusBars.barPositioner.hasNeighbor(barLocation.barAnchor(), barLocation.y(), barLocation.x(), right)) { + break; + } + if (!barLocation.barAnchor().getSizeRule().isTargetSize() && barLocation.x() == 0 && barLocation.barAnchor().isRight() != right) + break; } - if (!barLocation.barAnchor().getSizeRule().isTargetSize() && barLocation.x() == 0 && barLocation.barAnchor().isRight() != right) - break; - resizeHover.first(barLocation); + resizeHover.first(bar); resizeHover.right(right); - GLFW.glfwSetCursor(window.getHandle(), RESIZE_CURSOR); + setResizeCursor(true); break rectLoop; } else { - resizeHover.first(BarLocation.NULL); - GLFW.glfwSetCursor(window.getHandle(), 0); + resizeHover.first(null); + setResizeCursor(false); } } } @@ -272,7 +314,7 @@ public class StatusBarsConfigScreen extends Screen { if (cursorBar != null) cursorBar.inMouse = false; FancyStatusBars.updatePositions(false); assert client != null; - GLFW.glfwSetCursor(client.getWindow().getHandle(), 0); + setResizeCursor(false); FancyStatusBars.saveBarConfig(); } @@ -283,8 +325,10 @@ public class StatusBarsConfigScreen extends Screen { private void onBarClick(StatusBar statusBar, int button, int mouseX, int mouseY) { if (button == 0) { + cursorOffset = new ScreenPos(statusBar.getX() - mouseX, statusBar.getY() - mouseY); cursorBar = statusBar; cursorBar.inMouse = true; + cursorBar.enabled = true; currentInsertLocation = BarLocation.of(cursorBar); if (statusBar.anchor != null) FancyStatusBars.barPositioner.removeBar(statusBar.anchor, statusBar.gridY, statusBar); @@ -302,12 +346,12 @@ public class StatusBarsConfigScreen extends Screen { } private void updateScreenRects() { - rectToBarLocation.clear(); + rectToBar.clear(); FancyStatusBars.statusBars.values().forEach(statusBar1 -> { - if (statusBar1.anchor == null) return; - rectToBarLocation.put( + if (!statusBar1.enabled) return; + rectToBar.put( new ScreenRect(new ScreenPos(statusBar1.getX(), statusBar1.getY()), statusBar1.getWidth(), statusBar1.getHeight()), - BarLocation.of(statusBar1)); + Pair.of(statusBar1, BarLocation.of(statusBar1))); }); } @@ -315,15 +359,29 @@ public class StatusBarsConfigScreen extends Screen { public boolean mouseReleased(double mouseX, double mouseY, int button) { if (cursorBar != null) { cursorBar.inMouse = false; - currentInsertLocation = BarLocation.of(cursorBar); + if (currentInsertLocation == BarLocation.NULL) { + cursorBar.x = (float) ((mouseX + cursorOffset.x()) / width); + cursorBar.y = (float) ((mouseY + cursorOffset.y()) / height); + cursorBar.width = Math.clamp(cursorBar.width, (float) BAR_MINIMUM_WIDTH / width, 1); + } + currentInsertLocation = BarLocation.NULL; cursorBar = null; FancyStatusBars.updatePositions(true); updateScreenRects(); return true; } else if (resizing) { resizing = false; - resizedBars.left(BarLocation.NULL); - resizedBars.right(BarLocation.NULL); + + // update x and width if bar has no anchor + StatusBar bar = null; + if (resizedBars.left() != null) bar = resizedBars.left(); + else if (resizedBars.right() != null) bar = resizedBars.right(); + if (bar != null && bar.anchor == null) { + bar.x = (float) bar.getX() / width; + bar.width = (float) bar.getWidth() / width; + } + resizedBars.left(null); + resizedBars.right(null); updateScreenRects(); return true; } @@ -332,23 +390,32 @@ public class StatusBarsConfigScreen extends Screen { @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { - BarLocation first = resizeHover.first(); + StatusBar first = resizeHover.first(); // want the right click thing to have priority - if (!editBarWidget.isMouseOver(mouseX, mouseY) && button == 0 && !first.equals(BarLocation.NULL)) { - BarPositioner.BarAnchor barAnchor = first.barAnchor(); - assert barAnchor != null; - if (resizeHover.rightBoolean()) { - resizedBars.left(first); - - if (FancyStatusBars.barPositioner.hasNeighbor(barAnchor, first.y(), first.x(), true)) { - resizedBars.right(new BarLocation(barAnchor, first.x() + (barAnchor.isRight() ? 1 : -1), first.y())); - } else resizedBars.right(BarLocation.NULL); - } else { - resizedBars.right(first); + if (!editBarWidget.isMouseOver(mouseX, mouseY) && button == 0 && first != null) { + BarPositioner.BarAnchor barAnchor = first.anchor; + if (barAnchor != null) { + if (resizeHover.rightBoolean()) { + resizedBars.left(first); + + if (FancyStatusBars.barPositioner.hasNeighbor(barAnchor, first.gridY, first.gridX, true)) { + resizedBars.right(FancyStatusBars.barPositioner.getBar(barAnchor, first.gridY, first.gridX + (barAnchor.isRight() ? 1 : -1))); + } else resizedBars.right(null); + } else { + resizedBars.right(first); - if (FancyStatusBars.barPositioner.hasNeighbor(barAnchor, first.y(), first.x(), false)) { - resizedBars.left(new BarLocation(barAnchor, first.x() + (barAnchor.isRight() ? -1 : 1), first.y())); - } else resizedBars.left(BarLocation.NULL); + if (FancyStatusBars.barPositioner.hasNeighbor(barAnchor, first.gridY, first.gridX, false)) { + resizedBars.left(FancyStatusBars.barPositioner.getBar(barAnchor, first.gridY, first.gridX + (barAnchor.isRight() ? -1 : 1))); + } else resizedBars.left(null); + } + } else { // if they have no anchor no need to do any checking + if (resizeHover.rightBoolean()) { + resizedBars.left(first); + resizedBars.right(null); + } else { + resizedBars.right(first); + resizedBars.left(null); + } } resizing = true; return true; -- cgit