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.
This commit is contained in:
Adam
2022-05-16 23:30:34 -04:00
parent 573a66abf1
commit 09949d344e
2 changed files with 29 additions and 61 deletions

View File

@@ -25,7 +25,6 @@
package net.runelite.client.ui.overlay; package net.runelite.client.ui.overlay;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.awt.Color; import java.awt.Color;
import java.awt.Composite; import java.awt.Composite;
@@ -41,7 +40,6 @@ import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -104,7 +102,8 @@ public class OverlayRenderer extends MouseAdapter
private boolean inOverlayResizingMode; private boolean inOverlayResizingMode;
private boolean inOverlayDraggingMode; private boolean inOverlayDraggingMode;
private boolean startedMovingOverlay; 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 // Overlay state validation
private Rectangle viewportBounds; private Rectangle viewportBounds;
@@ -166,14 +165,16 @@ public class OverlayRenderer extends MouseAdapter
resetOverlayManagementMode(); resetOverlayManagementMode();
} }
hoveredOverlay = null; curHoveredOverlay = null;
} }
} }
@Subscribe @Subscribe
protected void onClientTick(ClientTick t) protected void onClientTick(ClientTick t)
{ {
final Overlay overlay = hoveredOverlay; lastHoveredOverlay = curHoveredOverlay;
final Overlay overlay = curHoveredOverlay;
if (overlay == null || client.isMenuOpen()) if (overlay == null || client.isMenuOpen())
{ {
return; return;
@@ -207,7 +208,7 @@ public class OverlayRenderer extends MouseAdapter
@Subscribe @Subscribe
public void onBeforeRender(BeforeRender event) public void onBeforeRender(BeforeRender event)
{ {
hoveredOverlay = null; curHoveredOverlay = null;
if (client.getGameState() == GameState.LOGGED_IN) if (client.getGameState() == GameState.LOGGED_IN)
{ {
@@ -273,10 +274,6 @@ public class OverlayRenderer extends MouseAdapter
graphics.setColor(previous); 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 // Save graphics2d properties so we can restore them later
final AffineTransform transform = graphics.getTransform(); final AffineTransform transform = graphics.getTransform();
final Stroke stroke = graphics.getStroke(); final Stroke stroke = graphics.getStroke();
@@ -372,9 +369,9 @@ public class OverlayRenderer extends MouseAdapter
graphics.setPaint(paint); 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(); overlay.onMouseOver();
} }
} }
@@ -384,17 +381,16 @@ public class OverlayRenderer extends MouseAdapter
@Override @Override
public MouseEvent mousePressed(MouseEvent mouseEvent) public MouseEvent mousePressed(MouseEvent mouseEvent)
{ {
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
if (!inOverlayManagingMode) if (!inOverlayManagingMode)
{ {
return mouseEvent; return mouseEvent;
} }
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
// See if we've clicked on an overlay // See if we've clicked on an overlay
currentManagedOverlay = findMangedOverlay(mousePoint); currentManagedOverlay = lastHoveredOverlay;
if (currentManagedOverlay == null) if (currentManagedOverlay == null)
{ {
return mouseEvent; return mouseEvent;
@@ -430,17 +426,17 @@ public class OverlayRenderer extends MouseAdapter
@Override @Override
public MouseEvent mouseMoved(MouseEvent mouseEvent) public MouseEvent mouseMoved(MouseEvent mouseEvent)
{ {
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
if (!inOverlayManagingMode) if (!inOverlayManagingMode)
{ {
return mouseEvent; return mouseEvent;
} }
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
if (!inOverlayResizingMode && !inOverlayDraggingMode) if (!inOverlayResizingMode && !inOverlayDraggingMode)
{ {
currentManagedOverlay = findMangedOverlay(mousePoint); currentManagedOverlay = lastHoveredOverlay;
} }
if (currentManagedOverlay == null || !currentManagedOverlay.isResizable()) if (currentManagedOverlay == null || !currentManagedOverlay.isResizable())
@@ -487,46 +483,17 @@ public class OverlayRenderer extends MouseAdapter
return mouseEvent; 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<OverlayLayer> 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.<Overlay>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 @Override
public MouseEvent mouseDragged(MouseEvent mouseEvent) public MouseEvent mouseDragged(MouseEvent mouseEvent)
{ {
final Point p = mouseEvent.getPoint();
mousePosition.setLocation(p);
if (!inOverlayManagingMode) if (!inOverlayManagingMode)
{ {
return mouseEvent; return mouseEvent;
} }
final Point p = mouseEvent.getPoint();
mousePosition.setLocation(p);
if (currentManagedOverlay == null) if (currentManagedOverlay == null)
{ {
return mouseEvent; return mouseEvent;
@@ -661,13 +628,14 @@ public class OverlayRenderer extends MouseAdapter
@Override @Override
public MouseEvent mouseReleased(MouseEvent mouseEvent) public MouseEvent mouseReleased(MouseEvent mouseEvent)
{ {
final Point mousePoint = mouseEvent.getPoint();
mousePosition.setLocation(mousePoint);
if (!inOverlayManagingMode || currentManagedOverlay == null || (!inOverlayDraggingMode && !inOverlayResizingMode)) if (!inOverlayManagingMode || currentManagedOverlay == null || (!inOverlayDraggingMode && !inOverlayResizingMode))
{ {
return mouseEvent; return mouseEvent;
} }
mousePosition.setLocation(-1, -1);
if (dragTargetOverlay != null) if (dragTargetOverlay != null)
{ {
if (dragTargetOverlay.onDrag(currentManagedOverlay)) if (dragTargetOverlay.onDrag(currentManagedOverlay))
@@ -685,7 +653,7 @@ public class OverlayRenderer extends MouseAdapter
for (Rectangle snapCorner : snapCorners.getBounds()) for (Rectangle snapCorner : snapCorners.getBounds())
{ {
if (snapCorner.contains(mouseEvent.getPoint())) if (snapCorner.contains(mousePoint))
{ {
OverlayPosition position = snapCorners.fromBounds(snapCorner); OverlayPosition position = snapCorners.fromBounds(snapCorner);

View File

@@ -42,16 +42,16 @@ public class WidgetOverlay extends Overlay
public static Collection<WidgetOverlay> createOverlays(final OverlayManager overlayManager, final Client client) public static Collection<WidgetOverlay> createOverlays(final OverlayManager overlayManager, final Client client)
{ {
return Arrays.asList( return Arrays.asList(
// classic resizable // classic resizable - these are in render order for managed overlay picking
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DYNAMIC, OverlayPriority.HIGH), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DYNAMIC),
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_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 // 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_TABS1, OverlayPosition.DYNAMIC),
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS2, 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_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 // 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 WidgetOverlay(client, WidgetInfo.FOSSIL_ISLAND_OXYGENBAR, OverlayPosition.TOP_CENTER, OverlayPriority.HIGH),
new XpTrackerWidgetOverlay(overlayManager, client, WidgetInfo.EXPERIENCE_TRACKER_WIDGET, OverlayPosition.TOP_RIGHT), new XpTrackerWidgetOverlay(overlayManager, client, WidgetInfo.EXPERIENCE_TRACKER_WIDGET, OverlayPosition.TOP_RIGHT),