From c7c1b70a30e2ebdb42c410ec7e38ddd37fe87873 Mon Sep 17 00:00:00 2001 From: Stefan Zopfi Date: Mon, 16 May 2022 15:19:11 +0200 Subject: [PATCH 01/10] itemcharges: add imbued ring of wealth --- .../runelite/client/plugins/itemcharges/ItemWithCharge.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java index 733440c6d0..25883f06d2 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemcharges/ItemWithCharge.java @@ -308,6 +308,11 @@ enum ItemWithCharge ROW3(TELEPORT, RING_OF_WEALTH_3, 3), ROW4(TELEPORT, RING_OF_WEALTH_4, 4), ROW5(TELEPORT, RING_OF_WEALTH_5, 5), + ROWI1(TELEPORT, RING_OF_WEALTH_I1, 1), + ROWI2(TELEPORT, RING_OF_WEALTH_I2, 2), + ROWI3(TELEPORT, RING_OF_WEALTH_I3, 3), + ROWI4(TELEPORT, RING_OF_WEALTH_I4, 4), + ROWI5(TELEPORT, RING_OF_WEALTH_I5, 5), SACK_CABBAGES1(SACK, CABBAGES1, 1), SACK_CABBAGES2(SACK, CABBAGES2, 2), SACK_CABBAGES3(SACK, CABBAGES3, 3), From 5732e3f6bd5e76a1db81fe08ccd5fe92de2c82a1 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 May 2022 09:50:09 -0400 Subject: [PATCH 02/10] widget overlay: change minimap position back to top_right Otherwise layouted overlays don't get layouted around the minimap --- .../java/net/runelite/client/ui/overlay/WidgetOverlay.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 77a00e59ec..b0a0067964 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 @@ -46,12 +46,12 @@ public class WidgetOverlay extends Overlay new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DETACHED, OverlayPriority.HIGH), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DETACHED, OverlayPriority.HIGH), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_PARENT, OverlayPosition.DETACHED), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.DETACHED, OverlayPriority.MED), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), // modern resizable new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS1, OverlayPosition.DETACHED), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS2, OverlayPosition.DETACHED), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DETACHED), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.DETACHED, OverlayPriority.MED), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), // The client forces the oxygen bar below the xp tracker, so set its priority lower new WidgetOverlay(client, WidgetInfo.FOSSIL_ISLAND_OXYGENBAR, OverlayPosition.TOP_CENTER, OverlayPriority.HIGH), new XpTrackerWidgetOverlay(overlayManager, client, WidgetInfo.EXPERIENCE_TRACKER_WIDGET, OverlayPosition.TOP_RIGHT), From 11ce994b72859d706fe0edeb326b299b4b03a317 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 May 2022 10:58:49 -0400 Subject: [PATCH 03/10] overlay: add movable and snappable overlay flags This merges DETACHED and DYNAMIC into one position, DYNAMIC. And, allows detached/dynamic overlays to be snappable. --- .../ScreenMarkerCreationOverlay.java | 3 +- .../screenmarkers/ScreenMarkerOverlay.java | 3 +- .../ScreenMarkerWidgetHighlightOverlay.java | 3 +- .../runelite/client/ui/overlay/Overlay.java | 36 +++- .../client/ui/overlay/OverlayManager.java | 32 ++-- .../client/ui/overlay/OverlayPosition.java | 2 + .../client/ui/overlay/OverlayRenderer.java | 165 ++++++++---------- .../client/ui/overlay/WidgetOverlay.java | 16 +- 8 files changed, 147 insertions(+), 113 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerCreationOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerCreationOverlay.java index 98b2c9a73b..81e25192ed 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerCreationOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerCreationOverlay.java @@ -42,9 +42,10 @@ class ScreenMarkerCreationOverlay extends Overlay private ScreenMarkerCreationOverlay(final ScreenMarkerPlugin plugin) { this.plugin = plugin; - setPosition(OverlayPosition.DETACHED); + setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_WIDGETS); setPriority(OverlayPriority.HIGH); + setMovable(true); } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java index c991f58f2e..5341f75af8 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerOverlay.java @@ -45,9 +45,10 @@ public class ScreenMarkerOverlay extends Overlay { this.marker = marker; this.screenMarkerRenderable = new ScreenMarkerRenderable(); - setPosition(OverlayPosition.DETACHED); + setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ALWAYS_ON_TOP); setPriority(OverlayPriority.HIGH); + setMovable(true); setResizable(true); setMinimumSize(16); setResettable(false); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java index 718ea93903..9868b0f322 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenmarkers/ScreenMarkerWidgetHighlightOverlay.java @@ -51,9 +51,10 @@ class ScreenMarkerWidgetHighlightOverlay extends Overlay { this.plugin = plugin; this.client = client; - setPosition(OverlayPosition.DETACHED); + setPosition(OverlayPosition.DYNAMIC); setLayer(OverlayLayer.ABOVE_WIDGETS); setPriority(OverlayPriority.HIGH); + setMovable(true); } @Override diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java index dd36bf167e..a63dca7d2d 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/Overlay.java @@ -64,12 +64,25 @@ public abstract class Overlay implements LayoutableRenderableEntity @Setter(AccessLevel.PROTECTED) private boolean dragTargetable; + /** + * Whether this overlay can be moved with alt + */ + @Setter(AccessLevel.PROTECTED) + private boolean movable = true; + + /** + * Whether this overlay can be moved to a snap corner + * and have its preferredPosition changed + */ + @Setter(AccessLevel.PROTECTED) + private boolean snappable = true; + protected Overlay() { plugin = null; } - protected Overlay(Plugin plugin) + protected Overlay(@Nullable Plugin plugin) { this.plugin = plugin; } @@ -161,4 +174,25 @@ public abstract class Overlay implements LayoutableRenderableEntity public void revalidate() { } + + public void setPosition(OverlayPosition position) + { + this.position = position; + + switch (position) + { + case TOOLTIP: + case DYNAMIC: + movable = false; + snappable = false; + break; + case DETACHED: + movable = true; + snappable = false; + break; + default: + movable = true; + snappable = true; + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java index 5811f98936..4ad59bf541 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayManager.java @@ -313,21 +313,29 @@ public class OverlayManager private void loadOverlay(final Overlay overlay) { final Point location = loadOverlayLocation(overlay); - overlay.setPreferredLocation(location); final Dimension size = loadOverlaySize(overlay); - overlay.setPreferredSize(size); final OverlayPosition position = loadOverlayPosition(overlay); - if (position != null) + + if (overlay.isMovable()) { - if (overlay.getPosition() != OverlayPosition.DYNAMIC && overlay.getPosition() != OverlayPosition.TOOLTIP) - { - overlay.setPreferredPosition(position); - } - else - { - log.info("Resetting preferred position of dynamic overlay {}", overlay.getClass().getSimpleName()); - saveOverlayPosition(overlay); - } + overlay.setPreferredLocation(location); + } + else + { + log.info("Resetting preferred location of non-movable overlay {} (class {})", overlay.getName(), overlay.getClass().getName()); + saveOverlayLocation(overlay); + } + + overlay.setPreferredSize(size); + + if (overlay.isSnappable()) + { + overlay.setPreferredPosition(position); + } + else + { + log.info("Resetting preferred position of non-snappable overlay {} (class {})", overlay.getName(), overlay.getClass().getName()); + saveOverlayPosition(overlay); } } 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 14edc0dd05..9464c87520 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 @@ -28,7 +28,9 @@ public enum OverlayPosition { /** * Not attached anywhere, but still movable + * Deprecated. Use DYNAMIC and setMovable(true) */ + @Deprecated DETACHED, /** * Overlay places itself where it wants 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 9cd09225ee..2217a8d3ec 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 @@ -256,7 +256,7 @@ public class OverlayRenderer extends MouseAdapter OverlayUtil.setGraphicProperties(graphics); // Draw snap corners - if (inOverlayDraggingMode && layer == OverlayLayer.UNDER_WIDGETS && currentManagedOverlay != null && currentManagedOverlay.getPosition() != OverlayPosition.DETACHED) + if (inOverlayDraggingMode && layer == OverlayLayer.UNDER_WIDGETS && currentManagedOverlay != null && currentManagedOverlay.isSnappable()) { final OverlayBounds translatedSnapCorners = snapCorners.translated( -SNAP_CORNER_SIZE.width, @@ -288,102 +288,87 @@ public class OverlayRenderer extends MouseAdapter for (Overlay overlay : overlays) { final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay); + final Rectangle bounds = overlay.getBounds(); + final Dimension dimension = bounds.getSize(); + final Point preferredLocation = overlay.getPreferredLocation(); + Point location; + Rectangle snapCorner = null; - if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP) + // If the final position is not modified, layout it + if (overlayPosition != OverlayPosition.DYNAMIC && overlayPosition != OverlayPosition.TOOLTIP + && overlayPosition != OverlayPosition.DETACHED && preferredLocation == null) { - safeRender(client, overlay, layer, graphics, new Point()); - - // Restore graphics2d properties - graphics.setTransform(transform); - graphics.setStroke(stroke); - graphics.setComposite(composite); - graphics.setPaint(paint); - graphics.setRenderingHints(renderingHints); - graphics.setBackground(background); + snapCorner = snapCorners.forPosition(overlayPosition); + final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); // offset from corner + // Target x/y to draw the overlay + int destX = snapCorner.x + translation.x; + int destY = snapCorner.y + translation.y; + // Clamp the target position to ensure it is on screen or within parent bounds + location = clampOverlayLocation(destX, destY, dimension.width, dimension.height, overlay); } else { - final Rectangle bounds = overlay.getBounds(); - final Dimension dimension = bounds.getSize(); - final Point preferredLocation = overlay.getPreferredLocation(); - Point location; - Rectangle snapCorner = null; + location = preferredLocation != null ? preferredLocation : bounds.getLocation(); - // If the final position is not modified, layout it - if (overlayPosition != OverlayPosition.DETACHED && (preferredLocation == null || overlay.getPreferredPosition() != null)) + // Clamp the overlay position to ensure it is on screen or within parent bounds + location = clampOverlayLocation(location.x, location.y, dimension.width, dimension.height, overlay); + } + + if (overlay.getPreferredSize() != null) + { + bounds.setSize(overlay.getPreferredSize()); + } + + safeRender(client, overlay, layer, graphics, location); + + // Adjust snap corner based on where the overlay was drawn + if (snapCorner != null && bounds.width + bounds.height > 0) + { + OverlayUtil.shiftSnapCorner(overlayPosition, snapCorner, bounds, PADDING); + } + + // Restore graphics2d properties prior to drawing bounds + graphics.setTransform(transform); + graphics.setStroke(stroke); + graphics.setComposite(composite); + graphics.setPaint(paint); + graphics.setRenderingHints(renderingHints); + graphics.setBackground(background); + + if (!bounds.isEmpty()) + { + if (inOverlayManagingMode) { - snapCorner = snapCorners.forPosition(overlayPosition); - final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); // offset from corner - // Target x/y to draw the overlay - int destX = snapCorner.x + translation.x; - int destY = snapCorner.y + translation.y; - // Clamp the target position to ensure it is on screen or within parent bounds - location = clampOverlayLocation(destX, destY, dimension.width, dimension.height, overlay); - } - else - { - location = preferredLocation != null ? preferredLocation : bounds.getLocation(); - - // Clamp the overlay position to ensure it is on screen or within parent bounds - location = clampOverlayLocation(location.x, location.y, dimension.width, dimension.height, overlay); - } - - if (overlay.getPreferredSize() != null) - { - bounds.setSize(overlay.getPreferredSize()); - } - - safeRender(client, overlay, layer, graphics, location); - - // Adjust snap corner based on where the overlay was drawn - if (snapCorner != null && bounds.width + bounds.height > 0) - { - OverlayUtil.shiftSnapCorner(overlayPosition, snapCorner, bounds, PADDING); - } - - // Restore graphics2d properties prior to drawing bounds - graphics.setTransform(transform); - graphics.setStroke(stroke); - graphics.setComposite(composite); - graphics.setPaint(paint); - graphics.setRenderingHints(renderingHints); - graphics.setBackground(background); - - if (!bounds.isEmpty()) - { - if (inOverlayManagingMode) + Color boundsColor; + if (inOverlayResizingMode && currentManagedOverlay == overlay) { - Color boundsColor; - if (inOverlayResizingMode && currentManagedOverlay == overlay) - { - boundsColor = MOVING_OVERLAY_RESIZING_COLOR; - } - else if (inOverlayDraggingMode && currentManagedOverlay == overlay) - { - boundsColor = MOVING_OVERLAY_ACTIVE_COLOR; - } - else if (inOverlayDraggingMode && overlay.isDragTargetable() && currentManagedOverlay.isDragTargetable() - && currentManagedOverlay.getBounds().intersects(bounds)) - { - boundsColor = MOVING_OVERLAY_TARGET_COLOR; - assert currentManagedOverlay != overlay; - dragTargetOverlay = overlay; - } - else - { - boundsColor = MOVING_OVERLAY_COLOR; - } - - graphics.setColor(boundsColor); - graphics.draw(bounds); - graphics.setPaint(paint); + boundsColor = MOVING_OVERLAY_RESIZING_COLOR; + } + else if (inOverlayDraggingMode && currentManagedOverlay == overlay) + { + boundsColor = MOVING_OVERLAY_ACTIVE_COLOR; + } + else if (inOverlayDraggingMode && overlay.isDragTargetable() && currentManagedOverlay.isDragTargetable() + && currentManagedOverlay.getBounds().intersects(bounds)) + { + boundsColor = MOVING_OVERLAY_TARGET_COLOR; + assert currentManagedOverlay != overlay; + dragTargetOverlay = overlay; + } + else + { + boundsColor = MOVING_OVERLAY_COLOR; } - if (!client.isMenuOpen() && !client.getSpellSelected() && bounds.contains(mouse)) - { - hoveredOverlay = overlay; - overlay.onMouseOver(); - } + graphics.setColor(boundsColor); + graphics.draw(bounds); + graphics.setPaint(paint); + } + + if (!client.isMenuOpen() && !client.getSpellSelected() && bounds.contains(mouse)) + { + hoveredOverlay = overlay; + overlay.onMouseOver(); } } } @@ -511,7 +496,7 @@ public class OverlayRenderer extends MouseAdapter // ABOVE_SCENE overlays aren't managed .filter(c -> layerOrder.contains(c.getLayer())) // never allow moving dynamic or tooltip overlays - .filter(c -> c.getPosition() != OverlayPosition.DYNAMIC && c.getPosition() != OverlayPosition.TOOLTIP) + .filter(Overlay::isMovable) .sorted( Comparator.comparingInt(c -> layerOrder.indexOf(c.getLayer())) .thenComparing(OverlayManager.OVERLAY_COMPARATOR) @@ -686,8 +671,8 @@ public class OverlayRenderer extends MouseAdapter } } - // Check if the overlay is over a snapcorner and move it if so, unless it is a detached overlay - if (currentManagedOverlay.getPosition() != OverlayPosition.DETACHED && inOverlayDraggingMode) + // Check if the overlay is over a snapcorner and snap it if so + if (currentManagedOverlay.isSnappable() && inOverlayDraggingMode) { final OverlayBounds snapCorners = this.emptySnapCorners.translated(-SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height); 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 b0a0067964..5d2080dcbd 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 @@ -43,14 +43,14 @@ public class WidgetOverlay extends Overlay { return Arrays.asList( // classic resizable - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DETACHED, OverlayPriority.HIGH), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DETACHED, OverlayPriority.HIGH), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_PARENT, OverlayPosition.DETACHED), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DYNAMIC, OverlayPriority.HIGH), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DYNAMIC, OverlayPriority.HIGH), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_PARENT, OverlayPosition.DYNAMIC), new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), // modern resizable - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS1, OverlayPosition.DETACHED), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS2, OverlayPosition.DETACHED), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DETACHED), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS1, OverlayPosition.DYNAMIC), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS2, OverlayPosition.DYNAMIC), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DYNAMIC), new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), // The client forces the oxygen bar below the xp tracker, so set its priority lower new WidgetOverlay(client, WidgetInfo.FOSSIL_ISLAND_OXYGENBAR, OverlayPosition.TOP_CENTER, OverlayPriority.HIGH), @@ -84,7 +84,7 @@ public class WidgetOverlay extends Overlay new WidgetOverlay(client, WidgetInfo.TEMPOROSS_STATUS_INDICATOR, OverlayPosition.TOP_LEFT), new WidgetOverlay(client, WidgetInfo.BA_HEAL_TEAMMATES, OverlayPosition.BOTTOM_LEFT), new WidgetOverlay(client, WidgetInfo.BA_TEAM, OverlayPosition.TOP_RIGHT), - new WidgetOverlay(client, WidgetInfo.PVP_WILDERNESS_SKULL_CONTAINER, OverlayPosition.DETACHED) + new WidgetOverlay(client, WidgetInfo.PVP_WILDERNESS_SKULL_CONTAINER, OverlayPosition.DYNAMIC) ); } @@ -105,6 +105,8 @@ public class WidgetOverlay extends Overlay setPriority(overlayPriority); setLayer(OverlayLayer.UNDER_WIDGETS); setPosition(overlayPosition); + setMovable(true); + setSnappable(true); // It's almost possible to drawAfterInterface(widgetInfo.getGroupId()) here, but that fires // *after* the native components are drawn, which is too late. } From 30fb555809011546256df65d303f228c37ef7466 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 May 2022 12:32:41 -0400 Subject: [PATCH 04/10] overlay: disallow transformPosition with dynamic/tooltip --- .../main/java/net/runelite/client/ui/overlay/OverlayUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 89d9e3c803..e49c8c4140 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 @@ -240,8 +240,6 @@ public class OverlayUtil switch (position) { - case DYNAMIC: - case TOOLTIP: case TOP_LEFT: break; case TOP_CENTER: @@ -258,6 +256,8 @@ public class OverlayUtil case TOP_RIGHT: result.x = -dimension.width; break; + default: + throw new IllegalArgumentException(); } return result; From b90d793eb71e0b7c2d3ee502865fe3d078bee3f6 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 May 2022 12:22:48 -0400 Subject: [PATCH 05/10] overlay: set g2d clip per layer --- .../client/ui/overlay/OverlayRenderer.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) 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 2217a8d3ec..3a08e1508a 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 @@ -244,7 +244,7 @@ public class OverlayRenderer extends MouseAdapter overlayManager.setWidgetItems(Collections.emptyList()); } - private void renderOverlays(Graphics2D graphics, Collection overlays, OverlayLayer layer) + private void renderOverlays(final Graphics2D graphics, Collection overlays, final OverlayLayer layer) { if (overlays == null || overlays.isEmpty() @@ -285,6 +285,9 @@ public class OverlayRenderer extends MouseAdapter final RenderingHints renderingHints = graphics.getRenderingHints(); final Color background = graphics.getBackground(); + final Rectangle clip = clipBounds(layer); + graphics.setClip(clip); + for (Overlay overlay : overlays) { final OverlayPosition overlayPosition = getCorrectedOverlayPosition(overlay); @@ -319,7 +322,7 @@ public class OverlayRenderer extends MouseAdapter bounds.setSize(overlay.getPreferredSize()); } - safeRender(client, overlay, layer, graphics, location); + safeRender(overlay, graphics, location); // Adjust snap corner based on where the overlay was drawn if (snapCorner != null && bounds.width + bounds.height > 0) @@ -334,6 +337,10 @@ public class OverlayRenderer extends MouseAdapter graphics.setPaint(paint); graphics.setRenderingHints(renderingHints); graphics.setBackground(background); + if (!graphics.getClip().equals(clip)) + { + graphics.setClip(clip); + } if (!bounds.isEmpty()) { @@ -702,20 +709,23 @@ public class OverlayRenderer extends MouseAdapter return mouseEvent; } - private void safeRender(Client client, Overlay overlay, OverlayLayer layer, Graphics2D graphics, Point point) + private Rectangle clipBounds(OverlayLayer layer) { if (!isResizeable && (layer == OverlayLayer.ABOVE_SCENE || layer == OverlayLayer.UNDER_WIDGETS)) { - graphics.setClip(client.getViewportXOffset(), + return new Rectangle(client.getViewportXOffset(), client.getViewportYOffset(), client.getViewportWidth(), client.getViewportHeight()); } else { - graphics.setClip(0, 0, client.getCanvasWidth(), client.getCanvasHeight()); + return new Rectangle(0, 0, client.getCanvasWidth(), client.getCanvasHeight()); } + } + private void safeRender(Overlay overlay, Graphics2D graphics, Point point) + { final OverlayPosition position = overlay.getPosition(); // Set font based on configuration From 6b81e0c7d1c0a436ddd9a8fc989d97104d8fd0bb Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 15 May 2022 20:28:25 -0400 Subject: [PATCH 06/10] overlay: worldmap: prefer rect2d as g2d clip shape --- .../ui/overlay/worldmap/WorldMapOverlay.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java index 16ca444f8a..d4241daa10 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/worldmap/WorldMapOverlay.java @@ -31,6 +31,7 @@ import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Rectangle; +import java.awt.Shape; import java.awt.geom.Area; import java.awt.image.BufferedImage; import java.util.List; @@ -119,10 +120,10 @@ public class WorldMapOverlay extends Overlay bottomBar.setHasListener(true); final Rectangle worldMapRectangle = widget.getBounds(); - final Area mapViewArea = getWorldMapClipArea(worldMapRectangle); + final Shape mapViewArea = getWorldMapClipArea(worldMapRectangle); final Rectangle canvasBounds = new Rectangle(0, 0, client.getCanvasWidth(), client.getCanvasHeight()); - final Area canvasViewArea = getWorldMapClipArea(canvasBounds); - Area currentClip = null; + final Shape canvasViewArea = getWorldMapClipArea(canvasBounds); + Shape currentClip = null; Point mousePos = client.getMouseCanvasPosition(); if (!mapViewArea.contains(mousePos.getX(), mousePos.getY())) @@ -297,24 +298,29 @@ public class WorldMapOverlay extends Overlay * @return An {@link Area} representing baseRectangle, with the area * of visible widgets overlaying the world map clipped from it. */ - private Area getWorldMapClipArea(Rectangle baseRectangle) + private Shape getWorldMapClipArea(Rectangle baseRectangle) { final Widget overview = client.getWidget(WidgetInfo.WORLD_MAP_OVERVIEW_MAP); final Widget surfaceSelector = client.getWidget(WidgetInfo.WORLD_MAP_SURFACE_SELECTOR); Area clipArea = new Area(baseRectangle); + boolean subtracted = false; if (overview != null && !overview.isHidden()) { clipArea.subtract(new Area(overview.getBounds())); + subtracted = true; } if (surfaceSelector != null && !surfaceSelector.isHidden()) { clipArea.subtract(new Area(surfaceSelector.getBounds())); + subtracted = true; } - return clipArea; + // The sun g2d implementation is much more efficient at applying clips which are subclasses of rectangle2d, + // so use that as the clip shape if possible + return subtracted ? clipArea : baseRectangle; } private void drawTooltip(Graphics2D graphics, WorldMapPoint worldPoint) @@ -336,7 +342,7 @@ public class WorldMapOverlay extends Overlay drawPoint = new Point(drawPoint.getX() + TOOLTIP_OFFSET_WIDTH, drawPoint.getY() + TOOLTIP_OFFSET_HEIGHT); final Rectangle bounds = new Rectangle(0, 0, client.getCanvasWidth(), client.getCanvasHeight()); - final Area mapArea = getWorldMapClipArea(bounds); + final Shape mapArea = getWorldMapClipArea(bounds); graphics.setClip(mapArea); graphics.setColor(JagexColors.TOOLTIP_BACKGROUND); graphics.setFont(FontManager.getRunescapeFont()); From 1ed37f561dcbf5357ab34b08c279569a73cc2a81 Mon Sep 17 00:00:00 2001 From: Max Weber Date: Sun, 15 May 2022 18:31:05 -0600 Subject: [PATCH 07/10] overlay: do not move snap points backwards because WidgetOverlays in their default position render in the vanilla position it can cause other overlays to occlude previous overlays when they should not --- .../java/net/runelite/client/ui/overlay/OverlayUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 e49c8c4140..a9f68d6b92 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 @@ -213,19 +213,19 @@ public class OverlayUtil switch (overlayPosition) { case BOTTOM_LEFT: - sX = bounds.x + bounds.width + padding; + sX = Math.max(sX, bounds.x + bounds.width + padding); break; case BOTTOM_RIGHT: - sX = bounds.x - padding; + sX = Math.min(sX, bounds.x - padding); break; case TOP_LEFT: case TOP_CENTER: case CANVAS_TOP_RIGHT: case TOP_RIGHT: - sY = bounds.y + bounds.height + padding; + sY = Math.max(sY, bounds.y + bounds.height + padding); break; case ABOVE_CHATBOX_RIGHT: - sY = bounds.y - padding; + sY = Math.min(sY, bounds.y - padding); break; default: throw new IllegalArgumentException(); From cbb0730a3872b721b2df6a7a60ec34dba03e4c7f Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Thu, 12 May 2022 12:06:51 -0700 Subject: [PATCH 08/10] chat commands: Update clear word and clear line defaults Ctrl + backspace is an overwhelmingly common keybind for clearing the word before the cursor. Meanwhile, clearing the current line is not as common a keybind, so having an unset default is more sensible here for users to decide for themselves what keybind they would prefer. --- .../client/plugins/chatcommands/ChatCommandsConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java index 859aa9f9d1..4ed53b575f 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsConfig.java @@ -197,7 +197,7 @@ public interface ChatCommandsConfig extends Config ) default Keybind clearSingleWord() { - return new Keybind(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK); + return new Keybind(KeyEvent.VK_BACK_SPACE, InputEvent.CTRL_DOWN_MASK); } @ConfigItem( @@ -208,6 +208,6 @@ public interface ChatCommandsConfig extends Config ) default Keybind clearChatBox() { - return new Keybind(KeyEvent.VK_BACK_SPACE, InputEvent.CTRL_DOWN_MASK); + return Keybind.NOT_SET; } } From 573a66abf1dc1c0486ff5e3a5b0541a31defe7dc Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 16 May 2022 18:05:53 -0400 Subject: [PATCH 09/10] devtools: allow pgup/down to cycle through previous commands Co-authored-by: Max Weber --- .../client/plugins/devtools/DevToolsPlugin.java | 10 ++++++++++ runelite-client/src/main/scripts/CommandScript.rs2asm | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java index 0fc56b8f50..52151e61ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java @@ -48,6 +48,7 @@ import net.runelite.api.VarbitComposition; import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.MenuEntryAdded; +import net.runelite.api.events.ScriptCallbackEvent; import net.runelite.api.events.StatChanged; import net.runelite.api.events.VarbitChanged; import net.runelite.api.kit.KitType; @@ -488,4 +489,13 @@ public class DevToolsPlugin extends Plugin entry.setTarget(entry.getTarget() + " " + ColorUtil.prependColorTag("(" + info + ")", JagexColors.MENU_TARGET)); } } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent ev) + { + if ("devtoolsEnabled".equals(ev.getEventName())) + { + client.getIntStack()[client.getIntStackSize() - 1] = 1; + } + } } diff --git a/runelite-client/src/main/scripts/CommandScript.rs2asm b/runelite-client/src/main/scripts/CommandScript.rs2asm index 0cb44b4ee8..073d229c35 100644 --- a/runelite-client/src/main/scripts/CommandScript.rs2asm +++ b/runelite-client/src/main/scripts/CommandScript.rs2asm @@ -870,6 +870,9 @@ LABEL724: if_icmpgt LABEL728 jump LABEL791 LABEL728: + ; move chatout_add under if ($length2 > 2) to only add for :: commands + get_varc_string 335 + invoke 77 ; chatout_add get_varc_string 335 sconst "::toggleroof" iconst 0 @@ -962,8 +965,11 @@ LABEL798: iload 9 invoke 5517 LABEL804: + ; see comment above + jump AFTER_CHATOUT_ADD get_varc_string 335 invoke 77 +AFTER_CHATOUT_ADD: sconst "" set_varc_string 335 LABEL808: @@ -975,6 +981,8 @@ LABEL809: jump LABEL819 LABEL813: iload 3 + sconst "devtoolsEnabled" + runelite_callback iconst 1 if_icmpeq LABEL817 jump LABEL818 @@ -989,6 +997,8 @@ LABEL819: jump LABEL829 LABEL823: iload 3 + sconst "devtoolsEnabled" + runelite_callback iconst 1 if_icmpeq LABEL827 jump LABEL828 From 09949d344e8d47dd97dfed8fb250d74ee80655e0 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 16 May 2022 23:30:34 -0400 Subject: [PATCH 10/10] overlay: use hovered overlay for picking managed overlay Hovered overlay already accounts for render order, with the exception of the vanilla WidgetOverlays which are drawn prior to any of our overlays being drawn. Instead we order them in render-order, which works for the dynamic-layer ones. The minimap must be top_right so that our overlays layout around it correctly, which currently causes it to be picked up first over dynamic overlays due to the way overlay sorting is done. --- .../client/ui/overlay/OverlayRenderer.java | 80 ++++++------------- .../client/ui/overlay/WidgetOverlay.java | 10 +-- 2 files changed, 29 insertions(+), 61 deletions(-) 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 3a08e1508a..81fad24a4f 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 @@ -25,7 +25,6 @@ package net.runelite.client.ui.overlay; import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; import com.google.common.primitives.Ints; import java.awt.Color; import java.awt.Composite; @@ -41,7 +40,6 @@ import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; @@ -104,7 +102,8 @@ public class OverlayRenderer extends MouseAdapter private boolean inOverlayResizingMode; private boolean inOverlayDraggingMode; private boolean startedMovingOverlay; - private Overlay hoveredOverlay; // for building menu entries + private Overlay curHoveredOverlay; // for building menu entries + private Overlay lastHoveredOverlay; // for off-thread access // Overlay state validation private Rectangle viewportBounds; @@ -166,14 +165,16 @@ public class OverlayRenderer extends MouseAdapter resetOverlayManagementMode(); } - hoveredOverlay = null; + curHoveredOverlay = null; } } @Subscribe protected void onClientTick(ClientTick t) { - final Overlay overlay = hoveredOverlay; + lastHoveredOverlay = curHoveredOverlay; + + final Overlay overlay = curHoveredOverlay; if (overlay == null || client.isMenuOpen()) { return; @@ -207,7 +208,7 @@ public class OverlayRenderer extends MouseAdapter @Subscribe public void onBeforeRender(BeforeRender event) { - hoveredOverlay = null; + curHoveredOverlay = null; if (client.getGameState() == GameState.LOGGED_IN) { @@ -273,10 +274,6 @@ public class OverlayRenderer extends MouseAdapter graphics.setColor(previous); } - // Get mouse position - final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition(); - final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY()); - // Save graphics2d properties so we can restore them later final AffineTransform transform = graphics.getTransform(); final Stroke stroke = graphics.getStroke(); @@ -372,9 +369,9 @@ public class OverlayRenderer extends MouseAdapter graphics.setPaint(paint); } - if (!client.isMenuOpen() && !client.getSpellSelected() && bounds.contains(mouse)) + if (!client.isMenuOpen() && !client.getSpellSelected() && bounds.contains(mousePosition)) { - hoveredOverlay = overlay; + curHoveredOverlay = overlay; overlay.onMouseOver(); } } @@ -384,17 +381,16 @@ public class OverlayRenderer extends MouseAdapter @Override public MouseEvent mousePressed(MouseEvent mouseEvent) { + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + if (!inOverlayManagingMode) { return mouseEvent; } - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - // See if we've clicked on an overlay - currentManagedOverlay = findMangedOverlay(mousePoint); - + currentManagedOverlay = lastHoveredOverlay; if (currentManagedOverlay == null) { return mouseEvent; @@ -430,17 +426,17 @@ public class OverlayRenderer extends MouseAdapter @Override public MouseEvent mouseMoved(MouseEvent mouseEvent) { + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + if (!inOverlayManagingMode) { return mouseEvent; } - final Point mousePoint = mouseEvent.getPoint(); - mousePosition.setLocation(mousePoint); - if (!inOverlayResizingMode && !inOverlayDraggingMode) { - currentManagedOverlay = findMangedOverlay(mousePoint); + currentManagedOverlay = lastHoveredOverlay; } if (currentManagedOverlay == null || !currentManagedOverlay.isResizable()) @@ -487,46 +483,17 @@ public class OverlayRenderer extends MouseAdapter return mouseEvent; } - /** - * Find an overlay to manage which is under the given mouse point - * @param mousePoint - * @return - */ - private Overlay findMangedOverlay(Point mousePoint) - { - synchronized (overlayManager) - { - // render order is roughly: under -> manual -> above -> always on top - final List layerOrder = ImmutableList.of(OverlayLayer.UNDER_WIDGETS, OverlayLayer.MANUAL, OverlayLayer.ABOVE_WIDGETS, OverlayLayer.ALWAYS_ON_TOP); - return overlayManager.getOverlays() - .stream() - // ABOVE_SCENE overlays aren't managed - .filter(c -> layerOrder.contains(c.getLayer())) - // never allow moving dynamic or tooltip overlays - .filter(Overlay::isMovable) - .sorted( - Comparator.comparingInt(c -> layerOrder.indexOf(c.getLayer())) - .thenComparing(OverlayManager.OVERLAY_COMPARATOR) - // pick order is reversed from render order - .reversed() - ) - .filter(o -> o.getBounds().contains(mousePoint)) - .findFirst() - .orElse(null); - } - } - @Override public MouseEvent mouseDragged(MouseEvent mouseEvent) { + final Point p = mouseEvent.getPoint(); + mousePosition.setLocation(p); + if (!inOverlayManagingMode) { return mouseEvent; } - final Point p = mouseEvent.getPoint(); - mousePosition.setLocation(p); - if (currentManagedOverlay == null) { return mouseEvent; @@ -661,13 +628,14 @@ public class OverlayRenderer extends MouseAdapter @Override public MouseEvent mouseReleased(MouseEvent mouseEvent) { + final Point mousePoint = mouseEvent.getPoint(); + mousePosition.setLocation(mousePoint); + if (!inOverlayManagingMode || currentManagedOverlay == null || (!inOverlayDraggingMode && !inOverlayResizingMode)) { return mouseEvent; } - mousePosition.setLocation(-1, -1); - if (dragTargetOverlay != null) { if (dragTargetOverlay.onDrag(currentManagedOverlay)) @@ -685,7 +653,7 @@ public class OverlayRenderer extends MouseAdapter for (Rectangle snapCorner : snapCorners.getBounds()) { - if (snapCorner.contains(mouseEvent.getPoint())) + if (snapCorner.contains(mousePoint)) { OverlayPosition position = snapCorners.fromBounds(snapCorner); 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 5d2080dcbd..5806234f65 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 @@ -42,16 +42,16 @@ public class WidgetOverlay extends Overlay public static Collection createOverlays(final OverlayManager overlayManager, final Client client) { return Arrays.asList( - // classic resizable - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DYNAMIC, OverlayPriority.HIGH), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DYNAMIC, OverlayPriority.HIGH), + // classic resizable - these are in render order for managed overlay picking + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DYNAMIC), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_INVENTORY_PARENT, OverlayPosition.DYNAMIC), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT), // modern resizable + new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DYNAMIC), + new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS1, OverlayPosition.DYNAMIC), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS2, OverlayPosition.DYNAMIC), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DYNAMIC), - new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT, OverlayPriority.MED), // The client forces the oxygen bar below the xp tracker, so set its priority lower new WidgetOverlay(client, WidgetInfo.FOSSIL_ISLAND_OXYGENBAR, OverlayPosition.TOP_CENTER, OverlayPriority.HIGH), new XpTrackerWidgetOverlay(overlayManager, client, WidgetInfo.EXPERIENCE_TRACKER_WIDGET, OverlayPosition.TOP_RIGHT),