From 428832bcf907f00bd76725a19cb672abf58d259c Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Wed, 22 Aug 2018 19:14:58 +0200 Subject: [PATCH] Make RuneScape widgets layoutable Instead of making RuneScape widgets detached, make them layoutable - Add new snap corner CANVAS_TOP_RIGHT that is basically minimap position - Make WidgetOverlay use standard overlay layouting - Adjust paddings in the OverlayRenderer to match game more closely Signed-off-by: Tomas Slusny --- .../client/ui/overlay/OverlayBounds.java | 13 ++- .../client/ui/overlay/OverlayPosition.java | 16 +-- .../client/ui/overlay/OverlayRenderer.java | 69 ++++++++----- .../client/ui/overlay/OverlayUtil.java | 2 + .../client/ui/overlay/WidgetOverlay.java | 97 ++++++------------- 5 files changed, 98 insertions(+), 99 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayBounds.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayBounds.java index 72bfe78ddb..b29966bf5d 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayBounds.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayBounds.java @@ -32,6 +32,7 @@ import lombok.Value; import static net.runelite.client.ui.overlay.OverlayPosition.ABOVE_CHATBOX_RIGHT; import static net.runelite.client.ui.overlay.OverlayPosition.BOTTOM_LEFT; import static net.runelite.client.ui.overlay.OverlayPosition.BOTTOM_RIGHT; +import static net.runelite.client.ui.overlay.OverlayPosition.CANVAS_TOP_RIGHT; import static net.runelite.client.ui.overlay.OverlayPosition.TOP_LEFT; import static net.runelite.client.ui.overlay.OverlayPosition.TOP_RIGHT; @@ -39,7 +40,7 @@ import static net.runelite.client.ui.overlay.OverlayPosition.TOP_RIGHT; @Value class OverlayBounds { - private final Rectangle topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight; + private final Rectangle topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight, canvasTopRight; OverlayBounds(OverlayBounds other) { @@ -48,6 +49,7 @@ class OverlayBounds bottomLeft = new Rectangle(other.bottomLeft); bottomRight = new Rectangle(other.bottomRight); aboveChatboxRight = new Rectangle(other.aboveChatboxRight); + canvasTopRight = new Rectangle(other.canvasTopRight); } OverlayBounds translated(final int x, final int y) @@ -57,6 +59,7 @@ class OverlayBounds translated.getBottomLeft().translate(0, y); translated.getBottomRight().translate(x, y); translated.getAboveChatboxRight().translate(x, y); + translated.getCanvasTopRight().translate(x, 0); return translated; } @@ -74,6 +77,8 @@ class OverlayBounds return bottomRight; case ABOVE_CHATBOX_RIGHT: return aboveChatboxRight; + case CANVAS_TOP_RIGHT: + return canvasTopRight; default: throw new IllegalArgumentException(); } @@ -101,6 +106,10 @@ class OverlayBounds { return ABOVE_CHATBOX_RIGHT; } + else if (bounds == canvasTopRight) + { + return CANVAS_TOP_RIGHT; + } else { throw new IllegalArgumentException(); @@ -109,6 +118,6 @@ class OverlayBounds Collection getBounds() { - return Arrays.asList(topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight); + return Arrays.asList(topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight, canvasTopRight); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java index 8acc04d148..dc489cf7e2 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayPosition.java @@ -35,27 +35,31 @@ public enum OverlayPosition */ DYNAMIC, /** - * Place overlay in the top left most area possible + * Place overlay in the top left viewport area */ TOP_LEFT, /** - * Place overlay in the top right most area possible + * Place overlay in the top right viewport area */ TOP_RIGHT, /** - * Place overlay in the bottom left most area possible + * Place overlay in the bottom left viewport area */ BOTTOM_LEFT, /** - * Place overlay in the bottom right most area possible + * Place overlay in the bottom right viewport area */ BOTTOM_RIGHT, /** - * Place overlay directly above right most area of chatbox possible + * Place overlay directly above right side of chatbox */ ABOVE_CHATBOX_RIGHT, + /** + * Place overlay in the top right most area possible + */ + CANVAS_TOP_RIGHT, /** * Tooltip overlay */ - TOOLTIP; + TOOLTIP } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index fbbdac120c..876268d97c 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -52,13 +52,8 @@ import net.runelite.client.ui.FontManager; @Singleton public class OverlayRenderer extends MouseListener implements KeyListener { - private static final int BORDER_LEFT_RESIZABLE = 5; - private static final int BORDER_TOP_RESIZABLE = 20; - private static final int FRAME_OFFSET = 4; - private static final int BORDER_LEFT_FIXED = BORDER_LEFT_RESIZABLE + FRAME_OFFSET; - private static final int BORDER_TOP_FIXED = BORDER_TOP_RESIZABLE + FRAME_OFFSET; - private static final int BORDER_RIGHT = 2; - private static final int BORDER_BOTTOM = 2; + private static final int BORDER = 5; + private static final int BORDER_TOP = BORDER + 15; private static final int PADDING = 2; private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80); private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50); @@ -78,6 +73,7 @@ public class OverlayRenderer extends MouseListener implements KeyListener // Overlay state validation private Rectangle viewportBounds; private Rectangle chatboxBounds; + private int viewportOffset; private boolean chatboxHidden; private boolean isResizeable; private OverlayBounds snapCorners; @@ -155,12 +151,21 @@ public class OverlayRenderer extends MouseListener implements KeyListener overlayPosition = overlay.getPreferredPosition(); } - if (overlayPosition == OverlayPosition.ABOVE_CHATBOX_RIGHT && !isResizeable) + if (!isResizeable) { // On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as - // BOTTOM_RIGHT. Just use BOTTOM_RIGHT to prevent overlays from + // BOTTOM_RIGHT and CANVAST_TOP_RIGHT is same as TOP_RIGHT. + // Just use BOTTOM_RIGHT and TOP_RIGHT to prevent overlays from // drawing over each other. - overlayPosition = OverlayPosition.BOTTOM_RIGHT; + switch (overlayPosition) + { + case CANVAS_TOP_RIGHT: + overlayPosition = OverlayPosition.TOP_RIGHT; + break; + case ABOVE_CHATBOX_RIGHT: + overlayPosition = OverlayPosition.BOTTOM_RIGHT; + break; + } } if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) @@ -421,43 +426,55 @@ public class OverlayRenderer extends MouseListener implements KeyListener changed = true; } + final boolean viewportOffsetChanged = client.getViewportXOffset() != viewportOffset; + + if (viewportOffsetChanged) + { + viewportOffset = client.getViewportXOffset(); + changed = true; + } + return changed; } private OverlayBounds buildSnapCorners() { final Point topLeftPoint = new Point( - isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED, - isResizeable ? BORDER_TOP_RESIZABLE : BORDER_TOP_FIXED); + viewportOffset + BORDER, + viewportOffset + BORDER_TOP); final Point topRightPoint = new Point( - viewportBounds.x + viewportBounds.width - BORDER_RIGHT, - BORDER_TOP_FIXED); + viewportOffset + viewportBounds.width - BORDER, + viewportOffset + BORDER); final Point bottomLeftPoint = new Point( - isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED, - viewportBounds.y + viewportBounds.height - BORDER_BOTTOM); - - final Point bottomRightPoint = new Point( - viewportBounds.x + viewportBounds.width - BORDER_RIGHT, - viewportBounds.y + viewportBounds.height - BORDER_BOTTOM); - - final Point rightChatboxPoint = new Point( - viewportBounds.x + chatboxBounds.width - BORDER_RIGHT, - viewportBounds.y + viewportBounds.height - BORDER_BOTTOM); + topLeftPoint.x, + viewportOffset + viewportBounds.height - BORDER); // Check to see if chat box is minimized if (isResizeable && chatboxHidden) { - rightChatboxPoint.y += chatboxBounds.height; bottomLeftPoint.y += chatboxBounds.height; } + final Point bottomRightPoint = new Point( + topRightPoint.x, + bottomLeftPoint.y); + + final Point rightChatboxPoint = isResizeable ? new Point( + viewportOffset + chatboxBounds.width - BORDER, + bottomLeftPoint.y) : bottomRightPoint; + + final Point canvasTopRightPoint = isResizeable ? new Point( + client.getCanvas().getWidth(), + 0) : topRightPoint; + return new OverlayBounds( new Rectangle(topLeftPoint, SNAP_CORNER_SIZE), new Rectangle(topRightPoint, SNAP_CORNER_SIZE), new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE), new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE), - new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE)); + new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE), + new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE)); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index b9db556320..b22e20108f 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -204,6 +204,7 @@ public class OverlayUtil case TOP_LEFT: result.y += dimension.height + (dimension.height == 0 ? 0 : padding); break; + case CANVAS_TOP_RIGHT: case TOP_RIGHT: result.y += dimension.height + (dimension.height == 0 ? 0 : padding); break; @@ -232,6 +233,7 @@ public class OverlayUtil case ABOVE_CHATBOX_RIGHT: result.y = result.y - dimension.height; // FALLTHROUGH + case CANVAS_TOP_RIGHT: case TOP_RIGHT: result.x = result.x - dimension.width; break; diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java index 138719edbf..4037261150 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/WidgetOverlay.java @@ -24,10 +24,11 @@ */ package net.runelite.client.ui.overlay; -import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableMap; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Rectangle; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -37,29 +38,29 @@ import net.runelite.api.widgets.WidgetInfo; public class WidgetOverlay extends Overlay { - private static final Set WIDGETS = ImmutableSet.of( - WidgetInfo.RESIZABLE_MINIMAP_WIDGET, - WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, - WidgetInfo.EXPERIENCE_TRACKER_WIDGET, - WidgetInfo.FOSSIL_ISLAND_OXYGENBAR - ); + private static final Map WIDGETS = ImmutableMap + .builder() + .put(WidgetInfo.FOSSIL_ISLAND_OXYGENBAR, OverlayPosition.TOP_LEFT) + .put(WidgetInfo.EXPERIENCE_TRACKER_WIDGET, OverlayPosition.TOP_RIGHT) + .put(WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT) + .put(WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT) + .build(); public static Set createOverlays(final Client client) { - return WIDGETS.stream().map(w -> new WidgetOverlay(client, w)).collect(Collectors.toSet()); + return WIDGETS.entrySet().stream().map(w -> new WidgetOverlay(client, w.getKey(), w.getValue())).collect(Collectors.toSet()); } private final Client client; private final WidgetInfo widgetInfo; - private Integer toRestoreX; - private Integer toRestoreY; - private WidgetOverlay(final Client client, final WidgetInfo widgetInfo) + private WidgetOverlay(final Client client, final WidgetInfo widgetInfo, final OverlayPosition overlayPosition) { this.client = client; this.widgetInfo = widgetInfo; + setPriority(OverlayPriority.HIGHEST); setLayer(OverlayLayer.UNDER_WIDGETS); - setPosition(OverlayPosition.DETACHED); + setPosition(overlayPosition); } @Override @@ -68,73 +69,39 @@ public class WidgetOverlay extends Overlay return Objects.toString(widgetInfo); } - @Override - public Rectangle getBounds() - { - final Widget widget = client.getWidget(widgetInfo); - - if (widget != null && !widget.isHidden()) - { - return new Rectangle( - widget.getOriginalX() + widget.getRelativeX(), - widget.getOriginalY() + widget.getRelativeY(), - widget.getWidth(), widget.getHeight()); - } - - return new Rectangle(); - } - @Override public Dimension render(Graphics2D graphics) { final Widget widget = client.getWidget(widgetInfo); - if (widget == null || widget.isHidden()) { return null; } - if (getPreferredLocation() == null) - { - if (toRestoreX != null) - { - widget.setRelativeX(toRestoreX); - toRestoreX = null; - } - - if (toRestoreY != null) - { - widget.setRelativeY(toRestoreY); - toRestoreY = null; - } - - return null; - } - final Rectangle bounds = getBounds(); - int x = getPreferredLocation().x - widget.getOriginalX(); - int y = getPreferredLocation().y - widget.getOriginalY(); - x = Math.max(0, x); - y = Math.max(0, y); + final Rectangle parent = getParentBounds(widget); + int x = bounds.x; + int y = bounds.y; + x = Math.max(parent.x, x); + y = Math.max(parent.y, y); + x = Math.min((int)parent.getMaxX() - bounds.width, x); + y = Math.min((int)parent.getMaxY() - bounds.height, y); + bounds.setLocation(x, y); + widget.setOriginalX(0); + widget.setRelativeX(0); + widget.setRelativeX(bounds.x - parent.x); + widget.setRelativeY(bounds.y - parent.y); + return new Dimension(widget.getWidth(), widget.getHeight()); + } + private Rectangle getParentBounds(final Widget widget) + { final Widget parent = widget.getParent(); - final Dimension dimensions = parent == null ? client.getRealDimensions() : new Dimension(parent.getWidth(), parent.getHeight()); - x = Math.min(dimensions.width - bounds.width, x); - y = Math.min(dimensions.height - bounds.height, y); - - if (toRestoreX == null) + if (parent == null) { - toRestoreX = widget.getRelativeX(); + return new Rectangle(client.getRealDimensions()); } - if (toRestoreY == null) - { - toRestoreY = widget.getRelativeY(); - } - - widget.setRelativeX(x); - widget.setRelativeY(y); - - return null; + return new Rectangle(parent.getCanvasLocation().getX(), parent.getCanvasLocation().getY(), parent.getWidth(), parent.getHeight()); } }