overlay: better handle picking up overlapping overlays

findManagedOverlay needs to iterate in roughly the reverse drawing
order. Also adjust the moveable tli layers to be by priority in render
oder.
This commit is contained in:
Adam
2022-05-13 11:16:17 -04:00
parent 3fcf4c4217
commit 570907ea11
3 changed files with 26 additions and 22 deletions

View File

@@ -24,7 +24,6 @@
*/ */
package net.runelite.client.ui.overlay; package net.runelite.client.ui.overlay;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import java.awt.Dimension; import java.awt.Dimension;
@@ -64,7 +63,6 @@ public class OverlayManager
private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize"; private static final String OVERLAY_CONFIG_PREFERRED_SIZE = "_preferredSize";
private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value(); private static final String RUNELITE_CONFIG_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value();
@VisibleForTesting
static final Comparator<Overlay> OVERLAY_COMPARATOR = (a, b) -> static final Comparator<Overlay> OVERLAY_COMPARATOR = (a, b) ->
{ {
final OverlayPosition aPos = MoreObjects.firstNonNull(a.getPreferredPosition(), a.getPosition()); final OverlayPosition aPos = MoreObjects.firstNonNull(a.getPreferredPosition(), a.getPosition());
@@ -82,7 +80,7 @@ public class OverlayManager
// For non-dynamic overlays, higher priority means // For non-dynamic overlays, higher priority means
// draw *earlier* so that they are closer to their // draw *earlier* so that they are closer to their
// defined position. // defined position.
return aPos == OverlayPosition.DYNAMIC return aPos == OverlayPosition.DYNAMIC || aPos == OverlayPosition.DETACHED
? a.getPriority().compareTo(b.getPriority()) ? a.getPriority().compareTo(b.getPriority())
: b.getPriority().compareTo(a.getPriority()); : b.getPriority().compareTo(a.getPriority());
}; };

View File

@@ -25,6 +25,7 @@
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;
@@ -40,6 +41,7 @@ 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;
@@ -502,22 +504,24 @@ public class OverlayRenderer extends MouseAdapter
{ {
synchronized (overlayManager) synchronized (overlayManager)
{ {
for (Overlay overlay : overlayManager.getOverlays()) // 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);
if (overlay.getPosition() == OverlayPosition.DYNAMIC || overlay.getPosition() == OverlayPosition.TOOLTIP) return overlayManager.getOverlays()
{ .stream()
// never allow moving dynamic or tooltip overlays // ABOVE_SCENE overlays aren't managed
continue; .filter(c -> layerOrder.contains(c.getLayer()))
} // never allow moving dynamic or tooltip overlays
.filter(c -> c.getPosition() != OverlayPosition.DYNAMIC && c.getPosition() != OverlayPosition.TOOLTIP)
final Rectangle bounds = overlay.getBounds(); .sorted(
if (bounds.contains(mousePoint)) Comparator.<Overlay>comparingInt(c -> layerOrder.indexOf(c.getLayer()))
{ .thenComparing(OverlayManager.OVERLAY_COMPARATOR)
return overlay; // pick order is reversed from render order
} .reversed()
} )
.filter(o -> o.getBounds().contains(mousePoint))
.findFirst()
.orElse(null);
} }
return null;
} }
@Override @Override

View File

@@ -42,14 +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(
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_CHATBOX_PARENT, OverlayPosition.DETACHED), // 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_INVENTORY_PARENT, OverlayPosition.DETACHED),
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_CHATBOX_PARENT, OverlayPosition.DETACHED), new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.DETACHED, OverlayPriority.MED),
// modern resizable
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_TABS1, OverlayPosition.DETACHED), 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_TABS2, OverlayPosition.DETACHED),
new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DETACHED), new WidgetOverlay(client, WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_INVENTORY_PARENT, OverlayPosition.DETACHED),
new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT), new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.DETACHED, OverlayPriority.MED),
new WidgetOverlay(client, WidgetInfo.RESIZABLE_MINIMAP_STONES_WIDGET, OverlayPosition.CANVAS_TOP_RIGHT),
// 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),