Add overlay menu support
Co-authored-by: TheStonedTurtle <TheStonedTurtle@users.noreply.github.com>
This commit is contained in:
@@ -260,6 +260,10 @@ public enum MenuAction
|
||||
* Menu action injected by runelite for its menu items.
|
||||
*/
|
||||
RUNELITE(1500),
|
||||
/**
|
||||
* Menu action injected by runelite for overlay menu items.
|
||||
*/
|
||||
RUNELITE_OVERLAY(1501),
|
||||
|
||||
FOLLOW(2046),
|
||||
TRADE(2047),
|
||||
|
||||
@@ -60,10 +60,4 @@ public class MenuEntry
|
||||
*/
|
||||
private int param1;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "MenuEntry{" + "option=" + option + ", target=" + target + ", identifier=" + identifier + ", type=" + type + ", param0=" + param0 + ", param1=" + param1 + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
|
||||
/**
|
||||
* Event fired when an overlay menu entry is clicked.
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class OverlayMenuClicked
|
||||
{
|
||||
private OverlayMenuEntry entry;
|
||||
private Overlay overlay;
|
||||
}
|
||||
@@ -27,14 +27,20 @@ package net.runelite.client.ui.overlay;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.overlay.components.LayoutableRenderableEntity;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Overlay implements LayoutableRenderableEntity
|
||||
{
|
||||
@Nullable
|
||||
private final Plugin plugin;
|
||||
private Point preferredLocation;
|
||||
private Dimension preferredSize;
|
||||
private OverlayPosition preferredPosition;
|
||||
@@ -42,6 +48,17 @@ public abstract class Overlay implements LayoutableRenderableEntity
|
||||
private OverlayPosition position = OverlayPosition.TOP_LEFT;
|
||||
private OverlayPriority priority = OverlayPriority.NONE;
|
||||
private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS;
|
||||
private final List<OverlayMenuEntry> menuEntries = new ArrayList<>();
|
||||
|
||||
protected Overlay()
|
||||
{
|
||||
plugin = null;
|
||||
}
|
||||
|
||||
protected Overlay(Plugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay name, used for saving the overlay, needs to be unique
|
||||
|
||||
@@ -33,15 +33,20 @@ import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.RuneLiteConfig;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.OverlayMenuClicked;
|
||||
import net.runelite.client.events.PluginChanged;
|
||||
|
||||
/**
|
||||
@@ -93,11 +98,13 @@ public class OverlayManager
|
||||
private final Map<OverlayLayer, List<Overlay>> overlayLayers = new EnumMap<>(OverlayLayer.class);
|
||||
|
||||
private final ConfigManager configManager;
|
||||
private final EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private OverlayManager(final ConfigManager configManager)
|
||||
private OverlayManager(final ConfigManager configManager, final EventBus eventBus)
|
||||
{
|
||||
this.configManager = configManager;
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -107,6 +114,56 @@ public class OverlayManager
|
||||
rebuildOverlayLayers();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (event.getMenuAction() != MenuAction.RUNELITE_OVERLAY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
event.consume();
|
||||
|
||||
Optional<Overlay> optionalOverlay = overlays.stream().filter(o -> overlayId(o) == event.getId()).findAny();
|
||||
if (optionalOverlay.isPresent())
|
||||
{
|
||||
Overlay overlay = optionalOverlay.get();
|
||||
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
|
||||
Optional<OverlayMenuEntry> optionalOverlayMenuEntry = menuEntries.stream()
|
||||
.filter(me -> me.getOption().equals(event.getMenuOption()))
|
||||
.findAny();
|
||||
if (optionalOverlayMenuEntry.isPresent())
|
||||
{
|
||||
eventBus.post(new OverlayMenuClicked(optionalOverlayMenuEntry.get(), overlay));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int overlayId(Overlay overlay)
|
||||
{
|
||||
return overlays.indexOf(overlay);
|
||||
}
|
||||
|
||||
public void addMenu(Overlay overlay, MenuAction menuAction, String option, String target)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = new OverlayMenuEntry(menuAction, option, target);
|
||||
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
|
||||
menuEntries.add(overlayMenuEntry);
|
||||
}
|
||||
|
||||
public void removeMenu(Overlay overlay, String option)
|
||||
{
|
||||
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
|
||||
for (OverlayMenuEntry overlayMenuEntry : menuEntries)
|
||||
{
|
||||
if (overlayMenuEntry.getOption().equals(option))
|
||||
{
|
||||
menuEntries.remove(overlayMenuEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the overlays on a layer sorted by priority and position
|
||||
*
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.ui.overlay;
|
||||
|
||||
import lombok.Value;
|
||||
import net.runelite.api.MenuAction;
|
||||
|
||||
@Value
|
||||
public class OverlayMenuEntry
|
||||
{
|
||||
private MenuAction menuAction;
|
||||
private String option;
|
||||
private String target;
|
||||
}
|
||||
@@ -39,6 +39,9 @@ import javax.inject.Singleton;
|
||||
import javax.swing.SwingUtilities;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.events.ClientTick;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
@@ -48,6 +51,8 @@ import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.input.MouseAdapter;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@Singleton
|
||||
public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
@@ -69,6 +74,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
private final Point mousePosition = new Point();
|
||||
private Overlay movedOverlay;
|
||||
private boolean inOverlayDraggingMode;
|
||||
private MenuEntry[] menuEntries;
|
||||
|
||||
// Overlay state validation
|
||||
private Rectangle viewportBounds;
|
||||
@@ -99,9 +105,35 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
if (!event.isFocused())
|
||||
{
|
||||
inOverlayDraggingMode = false;
|
||||
menuEntries = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onClientTick(ClientTick t)
|
||||
{
|
||||
if (menuEntries == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.isMenuOpen())
|
||||
{
|
||||
menuEntries = null;
|
||||
return;
|
||||
}
|
||||
|
||||
MenuEntry[] clientMenuEntries = client.getMenuEntries();
|
||||
MenuEntry[] newEntries = new MenuEntry[clientMenuEntries.length + menuEntries.length];
|
||||
|
||||
newEntries[0] = clientMenuEntries[0]; // Keep cancel at 0
|
||||
System.arraycopy(menuEntries, 0, newEntries, 1, menuEntries.length); // Add overlay menu entries
|
||||
System.arraycopy(clientMenuEntries, 1, newEntries, menuEntries.length + 1, clientMenuEntries.length - 1); // Add remaining menu entries
|
||||
client.setMenuEntries(newEntries);
|
||||
|
||||
menuEntries = null;
|
||||
}
|
||||
|
||||
public void render(Graphics2D graphics, final OverlayLayer layer)
|
||||
{
|
||||
if (layer != OverlayLayer.ABOVE_MAP
|
||||
@@ -149,6 +181,10 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
graphics.setColor(previous);
|
||||
}
|
||||
|
||||
// Get mouse position
|
||||
final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition();
|
||||
final Point mouse = new Point(mouseCanvasPosition.getX(), mouseCanvasPosition.getY());
|
||||
|
||||
for (Overlay overlay : overlays)
|
||||
{
|
||||
OverlayPosition overlayPosition = overlay.getPosition();
|
||||
@@ -227,6 +263,11 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
graphics.draw(bounds);
|
||||
graphics.setColor(previous);
|
||||
}
|
||||
|
||||
if (menuEntries == null && !client.isMenuOpen() && bounds.contains(mouse))
|
||||
{
|
||||
menuEntries = createRightClickMenuEntries(overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -494,4 +535,26 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
|
||||
new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE),
|
||||
new Rectangle(canvasTopRightPoint, SNAP_CORNER_SIZE));
|
||||
}
|
||||
|
||||
private MenuEntry[] createRightClickMenuEntries(Overlay overlay)
|
||||
{
|
||||
List<OverlayMenuEntry> menuEntries = overlay.getMenuEntries();
|
||||
final MenuEntry[] entries = new MenuEntry[menuEntries.size()];
|
||||
|
||||
// Add in reverse order so they display correctly in the right-click menu
|
||||
for (int i = menuEntries.size() - 1; i >= 0; --i)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = menuEntries.get(i);
|
||||
|
||||
final MenuEntry entry = new MenuEntry();
|
||||
entry.setOption(overlayMenuEntry.getOption());
|
||||
entry.setTarget(ColorUtil.wrapWithColorTag(overlayMenuEntry.getTarget(), JagexColors.MENU_TARGET));
|
||||
entry.setType(MenuAction.RUNELITE_OVERLAY.getId());
|
||||
entry.setIdentifier(overlayManager.overlayId(overlay)); // overlay id
|
||||
|
||||
entries[i] = entry;
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user