From 09949d344e8d47dd97dfed8fb250d74ee80655e0 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 16 May 2022 23:30:34 -0400 Subject: [PATCH] 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),