Merge pull request #989 from deathbeam/movable-overlays
Add support for movable overlays
This commit is contained in:
@@ -331,6 +331,8 @@ public interface Client extends GameEngine
|
|||||||
|
|
||||||
Dimension getStretchedDimensions();
|
Dimension getStretchedDimensions();
|
||||||
|
|
||||||
|
Dimension getRealDimensions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes world. Works only on login screen
|
* Changes world. Works only on login screen
|
||||||
* @param world world
|
* @param world world
|
||||||
|
|||||||
@@ -24,10 +24,12 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.config;
|
package net.runelite.client.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Point;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -244,6 +246,16 @@ public class ConfigManager
|
|||||||
return properties.getProperty(groupName + "." + key);
|
return properties.getProperty(groupName + "." + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> T getConfiguration(String groupName, String key, Class<T> clazz)
|
||||||
|
{
|
||||||
|
String value = getConfiguration(groupName, key);
|
||||||
|
if (!Strings.isNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
return (T) stringToObject(value, clazz);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setConfiguration(String groupName, String key, String value)
|
public void setConfiguration(String groupName, String key, String value)
|
||||||
{
|
{
|
||||||
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
||||||
@@ -289,6 +301,11 @@ public class ConfigManager
|
|||||||
eventBus.post(configChanged);
|
eventBus.post(configChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConfiguration(String groupName, String key, Object value)
|
||||||
|
{
|
||||||
|
setConfiguration(groupName, key, objectToString(value));
|
||||||
|
}
|
||||||
|
|
||||||
public void unsetConfiguration(String groupName, String key)
|
public void unsetConfiguration(String groupName, String key)
|
||||||
{
|
{
|
||||||
log.debug("Unsetting configuration value for {}.{}", groupName, key);
|
log.debug("Unsetting configuration value for {}.{}", groupName, key);
|
||||||
@@ -420,6 +437,13 @@ public class ConfigManager
|
|||||||
int height = Integer.parseInt(splitStr[1]);
|
int height = Integer.parseInt(splitStr[1]);
|
||||||
return new Dimension(width, height);
|
return new Dimension(width, height);
|
||||||
}
|
}
|
||||||
|
if (type == Point.class)
|
||||||
|
{
|
||||||
|
String[] splitStr = str.split(":");
|
||||||
|
int width = Integer.parseInt(splitStr[0]);
|
||||||
|
int height = Integer.parseInt(splitStr[1]);
|
||||||
|
return new Point(width, height);
|
||||||
|
}
|
||||||
if (type.isEnum())
|
if (type.isEnum())
|
||||||
{
|
{
|
||||||
return Enum.valueOf((Class<? extends Enum>) type, str);
|
return Enum.valueOf((Class<? extends Enum>) type, str);
|
||||||
@@ -442,6 +466,11 @@ public class ConfigManager
|
|||||||
Dimension d = (Dimension) object;
|
Dimension d = (Dimension) object;
|
||||||
return d.width + "x" + d.height;
|
return d.width + "x" + d.height;
|
||||||
}
|
}
|
||||||
|
if (object instanceof Point)
|
||||||
|
{
|
||||||
|
Point p = (Point) object;
|
||||||
|
return p.x + ":" + p.y;
|
||||||
|
}
|
||||||
return object.toString();
|
return object.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,16 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.ui.overlay;
|
package net.runelite.client.ui.overlay;
|
||||||
|
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.Rectangle;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public abstract class Overlay implements RenderableEntity
|
public abstract class Overlay implements RenderableEntity
|
||||||
{
|
{
|
||||||
|
private Point preferredLocation;
|
||||||
|
private OverlayPosition preferredPosition;
|
||||||
|
private Rectangle bounds = new Rectangle();
|
||||||
private OverlayPosition position = OverlayPosition.TOP_LEFT;
|
private OverlayPosition position = OverlayPosition.TOP_LEFT;
|
||||||
private OverlayPriority priority = OverlayPriority.NONE;
|
private OverlayPriority priority = OverlayPriority.NONE;
|
||||||
private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS;
|
private OverlayLayer layer = OverlayLayer.UNDER_WIDGETS;
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.overlay;
|
||||||
|
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Value;
|
||||||
|
import static net.runelite.client.ui.overlay.OverlayPosition.ABOVE_CHATBOX_RIGHT;
|
||||||
|
import static net.runelite.client.ui.overlay.OverlayPosition.BOTTOM_LEFT;
|
||||||
|
import static net.runelite.client.ui.overlay.OverlayPosition.BOTTOM_RIGHT;
|
||||||
|
import static net.runelite.client.ui.overlay.OverlayPosition.TOP_LEFT;
|
||||||
|
import static net.runelite.client.ui.overlay.OverlayPosition.TOP_RIGHT;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Value
|
||||||
|
class OverlayBounds
|
||||||
|
{
|
||||||
|
private final Rectangle topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight;
|
||||||
|
|
||||||
|
OverlayBounds(OverlayBounds other)
|
||||||
|
{
|
||||||
|
topLeft = new Rectangle(other.topLeft);
|
||||||
|
topRight = new Rectangle(other.topRight);
|
||||||
|
bottomLeft = new Rectangle(other.bottomLeft);
|
||||||
|
bottomRight = new Rectangle(other.bottomRight);
|
||||||
|
aboveChatboxRight = new Rectangle(other.aboveChatboxRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle forPosition(OverlayPosition overlayPosition)
|
||||||
|
{
|
||||||
|
switch (overlayPosition)
|
||||||
|
{
|
||||||
|
case TOP_LEFT:
|
||||||
|
return topLeft;
|
||||||
|
case TOP_RIGHT:
|
||||||
|
return topRight;
|
||||||
|
case BOTTOM_LEFT:
|
||||||
|
return bottomLeft;
|
||||||
|
case BOTTOM_RIGHT:
|
||||||
|
return bottomRight;
|
||||||
|
case ABOVE_CHATBOX_RIGHT:
|
||||||
|
return aboveChatboxRight;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayPosition fromBounds(Rectangle bounds)
|
||||||
|
{
|
||||||
|
if (bounds == topLeft)
|
||||||
|
{
|
||||||
|
return TOP_LEFT;
|
||||||
|
}
|
||||||
|
else if (bounds == topRight)
|
||||||
|
{
|
||||||
|
return TOP_RIGHT;
|
||||||
|
}
|
||||||
|
else if (bounds == bottomLeft)
|
||||||
|
{
|
||||||
|
return BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
else if (bounds == bottomRight)
|
||||||
|
{
|
||||||
|
return BOTTOM_RIGHT;
|
||||||
|
}
|
||||||
|
else if (bounds == aboveChatboxRight)
|
||||||
|
{
|
||||||
|
return ABOVE_CHATBOX_RIGHT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<Rectangle> getBounds()
|
||||||
|
{
|
||||||
|
return Arrays.asList(topLeft, topRight, bottomLeft, bottomRight, aboveChatboxRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -42,21 +44,28 @@ import java.util.stream.Stream;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.GameState;
|
import net.runelite.api.GameState;
|
||||||
import net.runelite.api.events.GameStateChanged;
|
import net.runelite.api.events.GameStateChanged;
|
||||||
import net.runelite.api.events.ResizeableChanged;
|
|
||||||
import net.runelite.api.widgets.Widget;
|
import net.runelite.api.widgets.Widget;
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.client.config.ConfigGroup;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import net.runelite.client.config.RuneLiteConfig;
|
||||||
import net.runelite.client.events.PluginChanged;
|
import net.runelite.client.events.PluginChanged;
|
||||||
|
import net.runelite.client.input.KeyListener;
|
||||||
|
import net.runelite.client.input.KeyManager;
|
||||||
|
import net.runelite.client.input.MouseListener;
|
||||||
|
import net.runelite.client.input.MouseManager;
|
||||||
import net.runelite.client.plugins.PluginManager;
|
import net.runelite.client.plugins.PluginManager;
|
||||||
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
|
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
|
||||||
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
|
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class OverlayRenderer
|
public class OverlayRenderer extends MouseListener implements KeyListener
|
||||||
{
|
{
|
||||||
private static final int BORDER_LEFT_RESIZABLE = 5;
|
private static final int BORDER_LEFT_RESIZABLE = 5;
|
||||||
private static final int BORDER_TOP_RESIZABLE = 20;
|
private static final int BORDER_TOP_RESIZABLE = 20;
|
||||||
@@ -66,29 +75,56 @@ public class OverlayRenderer
|
|||||||
private static final int BORDER_RIGHT = 2;
|
private static final int BORDER_RIGHT = 2;
|
||||||
private static final int BORDER_BOTTOM = 2;
|
private static final int BORDER_BOTTOM = 2;
|
||||||
private static final int PADDING = 2;
|
private static final int PADDING = 2;
|
||||||
|
private static final Dimension SNAP_CORNER_SIZE = new Dimension(80, 80);
|
||||||
|
private static final Color SNAP_CORNER_COLOR = new Color(0, 255, 255, 50);
|
||||||
|
private static final Color SNAP_CORNER_ACTIVE_COLOR = new Color(0, 255, 0, 100);
|
||||||
|
private static final Color MOVING_OVERLAY_COLOR = new Color(255, 255, 0, 100);
|
||||||
|
private static final Color MOVING_OVERLAY_ACTIVE_COLOR = new Color(255, 255, 0, 200);
|
||||||
|
private static final String OVERLAY_CONFIG_PREFERRED_LOCATION = "_preferredLocation";
|
||||||
|
private static final String OVERLAY_CONFIG_PREFERRED_POSITION = "_preferredPosition";
|
||||||
|
|
||||||
|
private final PluginManager pluginManager;
|
||||||
|
private final Provider<Client> clientProvider;
|
||||||
|
private final InfoBoxOverlay infoBoxOverlay;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
private final TooltipOverlay tooltipOverlay;
|
||||||
|
private final List<Overlay> allOverlays = new CopyOnWriteArrayList<>();
|
||||||
|
private final List<Overlay> overlaysAboveScene = new CopyOnWriteArrayList<>(),
|
||||||
|
overlaysUnderWidgets = new CopyOnWriteArrayList<>(),
|
||||||
|
overlaysAboveWidgets = new CopyOnWriteArrayList<>(),
|
||||||
|
overlaysOnTop = new CopyOnWriteArrayList<>();
|
||||||
|
private final ConcurrentLinkedQueue<Consumer<BufferedImage>> screenshotRequests = new ConcurrentLinkedQueue<>();
|
||||||
|
private final String runeliteGroupName = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).keyName();
|
||||||
|
|
||||||
|
// Overlay movement variables
|
||||||
|
private final Point overlayOffset = new Point();
|
||||||
|
private final Point mousePosition = new Point();
|
||||||
|
private Overlay movedOverlay;
|
||||||
|
private boolean inOverlayDraggingMode;
|
||||||
|
|
||||||
|
// Overlay state validation
|
||||||
|
private Rectangle viewportBounds;
|
||||||
|
private boolean chatboxHidden;
|
||||||
|
private boolean isResizeable;
|
||||||
|
private OverlayBounds snapCorners;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PluginManager pluginManager;
|
private OverlayRenderer(
|
||||||
|
final Provider<Client> clientProvider,
|
||||||
@Inject
|
final PluginManager pluginManager,
|
||||||
Provider<Client> clientProvider;
|
final MouseManager mouseManager,
|
||||||
|
final KeyManager keyManager,
|
||||||
@Inject
|
final TooltipOverlay tooltipOverlay,
|
||||||
InfoBoxOverlay infoBoxOverlay;
|
final InfoBoxOverlay infoBoxOverlay,
|
||||||
|
final ConfigManager configManager)
|
||||||
@Inject
|
|
||||||
TooltipOverlay tooltipOverlay;
|
|
||||||
|
|
||||||
private final List<Overlay> overlays = new CopyOnWriteArrayList<>();
|
|
||||||
private BufferedImage surface;
|
|
||||||
private Graphics2D surfaceGraphics;
|
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<Consumer<BufferedImage>> screenshotRequests = new ConcurrentLinkedQueue<>();
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onResizableChanged(ResizeableChanged event)
|
|
||||||
{
|
{
|
||||||
updateSurface();
|
this.clientProvider = clientProvider;
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
|
this.tooltipOverlay = tooltipOverlay;
|
||||||
|
this.infoBoxOverlay = infoBoxOverlay;
|
||||||
|
this.configManager = configManager;
|
||||||
|
keyManager.registerKeyListener(this);
|
||||||
|
mouseManager.registerMouseListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -101,32 +137,101 @@ public class OverlayRenderer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getGameState().equals(GameState.LOGIN_SCREEN) || event.getGameState().equals(GameState.LOGGED_IN))
|
if (event.getGameState().equals(GameState.LOGGED_IN))
|
||||||
{
|
{
|
||||||
refreshPlugins();
|
rebuildOverlays();
|
||||||
updateSurface();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onPluginChanged(PluginChanged event)
|
public void onPluginChanged(PluginChanged event)
|
||||||
{
|
{
|
||||||
refreshPlugins();
|
rebuildOverlays();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshPlugins()
|
private List<Overlay> getOverlaysForLayer(OverlayLayer layer)
|
||||||
{
|
{
|
||||||
overlays.clear();
|
switch (layer)
|
||||||
overlays.addAll(Stream
|
{
|
||||||
|
case ABOVE_SCENE:
|
||||||
|
return overlaysAboveScene;
|
||||||
|
case UNDER_WIDGETS:
|
||||||
|
return overlaysUnderWidgets;
|
||||||
|
case ABOVE_WIDGETS:
|
||||||
|
return overlaysAboveWidgets;
|
||||||
|
case ALWAYS_ON_TOP:
|
||||||
|
return overlaysOnTop;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildOverlays()
|
||||||
|
{
|
||||||
|
List<Overlay> overlays = Stream
|
||||||
.concat(
|
.concat(
|
||||||
pluginManager.getPlugins()
|
pluginManager.getPlugins()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(plugin -> pluginManager.isPluginEnabled(plugin))
|
.filter(pluginManager::isPluginEnabled)
|
||||||
.flatMap(plugin -> plugin.getOverlays().stream()),
|
.flatMap(plugin -> plugin.getOverlays().stream()),
|
||||||
Stream.of(infoBoxOverlay, tooltipOverlay))
|
Stream.of(infoBoxOverlay, tooltipOverlay))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
sortOverlays(overlays);
|
sortOverlays(overlays);
|
||||||
|
|
||||||
|
allOverlays.clear();
|
||||||
|
allOverlays.addAll(overlays);
|
||||||
|
|
||||||
|
final Client client = clientProvider.get();
|
||||||
|
|
||||||
|
for (final Overlay overlay : overlays)
|
||||||
|
{
|
||||||
|
final Point location = loadOverlayLocation(overlay);
|
||||||
|
|
||||||
|
if (location != null
|
||||||
|
&& client.getCanvas() != null
|
||||||
|
&& !client.getCanvas().contains(location))
|
||||||
|
{
|
||||||
|
overlay.setPreferredLocation(null);
|
||||||
|
saveOverlayLocation(overlay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overlay.setPreferredLocation(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
final OverlayPosition position = loadOverlayPosition(overlay);
|
||||||
|
overlay.setPreferredPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuildOverlayLayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildOverlayLayers()
|
||||||
|
{
|
||||||
|
overlaysAboveScene.clear();
|
||||||
|
overlaysUnderWidgets.clear();
|
||||||
|
overlaysAboveWidgets.clear();
|
||||||
|
overlaysOnTop.clear();
|
||||||
|
|
||||||
|
for (final Overlay overlay : allOverlays)
|
||||||
|
{
|
||||||
|
OverlayLayer layer = overlay.getLayer();
|
||||||
|
|
||||||
|
if (overlay.getPreferredLocation() != null && overlay.getPreferredPosition() == null)
|
||||||
|
{
|
||||||
|
// When UNDER_WIDGET overlays are in preferred locations, move to
|
||||||
|
// ABOVE_WIDGETS so that it can draw over interfaces
|
||||||
|
if (layer == OverlayLayer.UNDER_WIDGETS)
|
||||||
|
{
|
||||||
|
layer = OverlayLayer.ABOVE_WIDGETS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Overlay> overlayLayer = getOverlaysForLayer(layer);
|
||||||
|
overlayLayer.add(overlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sortOverlays(List<Overlay> overlays)
|
static void sortOverlays(List<Overlay> overlays)
|
||||||
@@ -151,89 +256,54 @@ public class OverlayRenderer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSurface()
|
public void render(Graphics2D graphics, final OverlayLayer layer)
|
||||||
{
|
{
|
||||||
final Client client = clientProvider.get();
|
final Client client = clientProvider.get();
|
||||||
|
List<Overlay> overlays = getOverlaysForLayer(layer);
|
||||||
|
|
||||||
if (client == null)
|
if (client == null
|
||||||
|
|| overlays.isEmpty()
|
||||||
|
|| client.getViewportWidget() == null
|
||||||
|
|| client.getGameState() != GameState.LOGGED_IN
|
||||||
|
|| client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Dimension size = client.getCanvas().getSize();
|
if (shouldInvalidateOverlays())
|
||||||
final BufferedImage temp = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
|
|
||||||
final Graphics2D subGraphics = temp.createGraphics();
|
|
||||||
subGraphics.setBackground(new Color(0, 0, 0, 0));
|
|
||||||
OverlayUtil.setGraphicProperties(subGraphics);
|
|
||||||
|
|
||||||
surface = temp;
|
|
||||||
|
|
||||||
if (surfaceGraphics != null)
|
|
||||||
{
|
{
|
||||||
surfaceGraphics.dispose();
|
snapCorners = buildSnapCorners();
|
||||||
}
|
}
|
||||||
|
|
||||||
surfaceGraphics = subGraphics;
|
// Create copy of snap corners because overlays will modify them
|
||||||
}
|
OverlayBounds snapCorners = new OverlayBounds(this.snapCorners);
|
||||||
|
|
||||||
public void render(Graphics2D graphics, OverlayLayer layer)
|
|
||||||
{
|
|
||||||
final Client client = clientProvider.get();
|
|
||||||
|
|
||||||
if (client == null || surface == null || overlays.isEmpty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.getGameState() != GameState.LOGGED_IN)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN) != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean isResizeable = client.isResized();
|
|
||||||
final Widget viewport = client.getViewportWidget();
|
|
||||||
final Rectangle bounds = viewport != null
|
|
||||||
? new Rectangle(viewport.getBounds())
|
|
||||||
: new Rectangle(0, 0, surface.getWidth(), surface.getHeight());
|
|
||||||
|
|
||||||
final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX_MESSAGES);
|
|
||||||
final Rectangle chatboxBounds = chatbox != null
|
|
||||||
? chatbox.getBounds() : new Rectangle(0, bounds.height, 519, 165);
|
|
||||||
|
|
||||||
OverlayUtil.setGraphicProperties(graphics);
|
OverlayUtil.setGraphicProperties(graphics);
|
||||||
final Point topLeftPoint = new Point();
|
|
||||||
topLeftPoint.move(
|
|
||||||
isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED,
|
|
||||||
isResizeable ? BORDER_TOP_RESIZABLE : BORDER_TOP_FIXED);
|
|
||||||
final Point topRightPoint = new Point();
|
|
||||||
topRightPoint.move(bounds.x + bounds.width - BORDER_RIGHT, BORDER_TOP_FIXED);
|
|
||||||
final Point bottomLeftPoint = new Point();
|
|
||||||
bottomLeftPoint.move(isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED, bounds.y + bounds.height - BORDER_BOTTOM);
|
|
||||||
final Point bottomRightPoint = new Point();
|
|
||||||
bottomRightPoint.move(bounds.x + bounds.width - BORDER_RIGHT, bounds.y + bounds.height - BORDER_BOTTOM);
|
|
||||||
final Point rightChatboxPoint = new Point();
|
|
||||||
rightChatboxPoint.move(bounds.x + chatboxBounds.width - BORDER_RIGHT, bounds.y + bounds.height - BORDER_BOTTOM);
|
|
||||||
|
|
||||||
//check to see if Chatbox is minimized
|
// Draw snap corners
|
||||||
if (chatbox != null && isResizeable && chatbox.isHidden())
|
if (layer == OverlayLayer.UNDER_WIDGETS && movedOverlay != null)
|
||||||
{
|
{
|
||||||
rightChatboxPoint.y += chatboxBounds.height;
|
final OverlayBounds translatedSnapCorners = translateSnapCorners(snapCorners);
|
||||||
bottomLeftPoint.y += chatboxBounds.height;
|
final Color previous = graphics.getColor();
|
||||||
|
|
||||||
|
for (final Rectangle corner : translatedSnapCorners.getBounds())
|
||||||
|
{
|
||||||
|
graphics.setColor(corner.contains(mousePosition) ? SNAP_CORNER_ACTIVE_COLOR : SNAP_CORNER_COLOR);
|
||||||
|
graphics.fill(corner);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphics.setColor(previous);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Overlay overlay : overlays)
|
for (Overlay overlay : overlays)
|
||||||
{
|
{
|
||||||
if (overlay.getLayer() != layer)
|
OverlayPosition overlayPosition = overlay.getPosition();
|
||||||
|
|
||||||
|
if (overlay.getPreferredPosition() != null)
|
||||||
{
|
{
|
||||||
continue;
|
overlayPosition = overlay.getPreferredPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayPosition overlayPosition = overlay.getPosition();
|
|
||||||
if (overlayPosition == OverlayPosition.ABOVE_CHATBOX_RIGHT && !client.isResized())
|
if (overlayPosition == OverlayPosition.ABOVE_CHATBOX_RIGHT && !client.isResized())
|
||||||
{
|
{
|
||||||
// On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as
|
// On fixed mode, ABOVE_CHATBOX_RIGHT is in the same location as
|
||||||
@@ -241,25 +311,6 @@ public class OverlayRenderer
|
|||||||
// drawing over each other.
|
// drawing over each other.
|
||||||
overlayPosition = OverlayPosition.BOTTOM_RIGHT;
|
overlayPosition = OverlayPosition.BOTTOM_RIGHT;
|
||||||
}
|
}
|
||||||
final Point subPosition = new Point();
|
|
||||||
switch (overlayPosition)
|
|
||||||
{
|
|
||||||
case BOTTOM_LEFT:
|
|
||||||
subPosition.setLocation(bottomLeftPoint);
|
|
||||||
break;
|
|
||||||
case BOTTOM_RIGHT:
|
|
||||||
subPosition.setLocation(bottomRightPoint);
|
|
||||||
break;
|
|
||||||
case TOP_LEFT:
|
|
||||||
subPosition.setLocation(topLeftPoint);
|
|
||||||
break;
|
|
||||||
case TOP_RIGHT:
|
|
||||||
subPosition.setLocation(topRightPoint);
|
|
||||||
break;
|
|
||||||
case ABOVE_CHATBOX_RIGHT:
|
|
||||||
subPosition.setLocation(rightChatboxPoint);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP)
|
if (overlayPosition == OverlayPosition.DYNAMIC || overlayPosition == OverlayPosition.TOOLTIP)
|
||||||
{
|
{
|
||||||
@@ -267,48 +318,313 @@ public class OverlayRenderer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
final Dimension dimension = MoreObjects.firstNonNull(safeRender(overlay, surfaceGraphics, subPosition), new Dimension());
|
final Point location = overlay.getBounds().getLocation();
|
||||||
if (dimension.width == 0 && dimension.height == 0)
|
final Dimension dimension = overlay.getBounds().getSize();
|
||||||
|
|
||||||
|
// If the final position is not modified, layout it
|
||||||
|
if (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null)
|
||||||
|
{
|
||||||
|
final Rectangle snapCorner = snapCorners.forPosition(overlayPosition);
|
||||||
|
final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension);
|
||||||
|
location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y);
|
||||||
|
final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING);
|
||||||
|
snapCorner.translate(padding.x, padding.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
location.setLocation(overlay.getPreferredLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
final Dimension overlayDimension = MoreObjects.firstNonNull(
|
||||||
|
safeRender(overlay, graphics, location),
|
||||||
|
new Dimension());
|
||||||
|
|
||||||
|
overlay.setBounds(new Rectangle(location, overlayDimension));
|
||||||
|
|
||||||
|
if (overlayDimension.width == 0 && overlayDimension.height == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final BufferedImage clippedImage = surface.getSubimage(0, 0, dimension.width, dimension.height);
|
if (inOverlayDraggingMode)
|
||||||
|
|
||||||
switch (overlayPosition)
|
|
||||||
{
|
{
|
||||||
case BOTTOM_LEFT:
|
final Color previous = graphics.getColor();
|
||||||
bottomLeftPoint.x += dimension.width + (dimension.width == 0 ? 0 : PADDING);
|
graphics.setColor(movedOverlay == overlay ? MOVING_OVERLAY_ACTIVE_COLOR : MOVING_OVERLAY_COLOR);
|
||||||
break;
|
graphics.drawRect(location.x, location.y, dimension.width - 1, dimension.height - 1);
|
||||||
case BOTTOM_RIGHT:
|
graphics.setColor(previous);
|
||||||
bottomRightPoint.x -= dimension.width + (dimension.width == 0 ? 0 : PADDING);
|
}
|
||||||
break;
|
}
|
||||||
case TOP_LEFT:
|
}
|
||||||
topLeftPoint.y += dimension.height + (dimension.height == 0 ? 0 : PADDING);
|
}
|
||||||
break;
|
|
||||||
case TOP_RIGHT:
|
@Override
|
||||||
topRightPoint.y += dimension.height + (dimension.height == 0 ? 0 : PADDING);
|
public MouseEvent mousePressed(MouseEvent mouseEvent)
|
||||||
break;
|
{
|
||||||
case ABOVE_CHATBOX_RIGHT:
|
if (!inOverlayDraggingMode)
|
||||||
rightChatboxPoint.y -= dimension.height + (dimension.height == 0 ? 0 : PADDING);
|
{
|
||||||
break;
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Point mousePoint = mouseEvent.getPoint();
|
||||||
|
mousePosition.setLocation(mousePoint);
|
||||||
|
|
||||||
|
for (Overlay overlay : allOverlays)
|
||||||
|
{
|
||||||
|
if (overlay.getBounds().contains(mousePoint))
|
||||||
|
{
|
||||||
|
if (SwingUtilities.isRightMouseButton(mouseEvent))
|
||||||
|
{
|
||||||
|
overlay.setPreferredLocation(null);
|
||||||
|
overlay.setPreferredPosition(null);
|
||||||
|
rebuildOverlayLayers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mousePoint.translate(-overlay.getBounds().x, -overlay.getBounds().y);
|
||||||
|
overlayOffset.setLocation(mousePoint);
|
||||||
|
movedOverlay = overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Point transformed = OverlayUtil.transformPosition(overlayPosition, dimension);
|
mouseEvent.consume();
|
||||||
graphics.drawImage(clippedImage, subPosition.x + transformed.x, subPosition.y + transformed.y, null);
|
break;
|
||||||
surfaceGraphics.clearRect(0, 0, (int) dimension.getWidth(), (int) dimension.getHeight());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MouseEvent mouseDragged(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
if (!inOverlayDraggingMode)
|
||||||
|
{
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Client client = clientProvider.get();
|
||||||
|
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Point mousePoint = mouseEvent.getPoint();
|
||||||
|
mousePosition.setLocation(mousePoint);
|
||||||
|
final Rectangle canvasRect = new Rectangle(client.getRealDimensions());
|
||||||
|
|
||||||
|
if (!canvasRect.contains(mousePoint))
|
||||||
|
{
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movedOverlay != null)
|
||||||
|
{
|
||||||
|
mousePoint.translate(-overlayOffset.x, -overlayOffset.y);
|
||||||
|
movedOverlay.setPreferredPosition(null);
|
||||||
|
movedOverlay.setPreferredLocation(mousePoint);
|
||||||
|
rebuildOverlayLayers();
|
||||||
|
mouseEvent.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MouseEvent mouseReleased(MouseEvent mouseEvent)
|
||||||
|
{
|
||||||
|
if (movedOverlay != null)
|
||||||
|
{
|
||||||
|
mousePosition.setLocation(-1, -1);
|
||||||
|
final OverlayBounds snapCorners = translateSnapCorners(buildSnapCorners());
|
||||||
|
|
||||||
|
for (Rectangle snapCorner : snapCorners.getBounds())
|
||||||
|
{
|
||||||
|
if (snapCorner.contains(mouseEvent.getPoint()))
|
||||||
|
{
|
||||||
|
OverlayPosition position = snapCorners.fromBounds(snapCorner);
|
||||||
|
if (position == movedOverlay.getPosition())
|
||||||
|
{
|
||||||
|
// overlay moves back to default position
|
||||||
|
position = null;
|
||||||
|
}
|
||||||
|
movedOverlay.setPreferredPosition(position);
|
||||||
|
movedOverlay.setPreferredLocation(null); // from dragging
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveOverlayPosition(movedOverlay);
|
||||||
|
saveOverlayLocation(movedOverlay);
|
||||||
|
rebuildOverlayLayers();
|
||||||
|
movedOverlay = null;
|
||||||
|
mouseEvent.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mouseEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyTyped(KeyEvent e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyEvent e)
|
||||||
|
{
|
||||||
|
if (e.isAltDown())
|
||||||
|
{
|
||||||
|
inOverlayDraggingMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyReleased(KeyEvent e)
|
||||||
|
{
|
||||||
|
if (!e.isAltDown())
|
||||||
|
{
|
||||||
|
inOverlayDraggingMode = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dimension safeRender(RenderableEntity entity, Graphics2D graphics, Point point)
|
private Dimension safeRender(RenderableEntity entity, Graphics2D graphics, Point point)
|
||||||
{
|
{
|
||||||
final Graphics2D subGraphics = (Graphics2D) graphics.create();
|
final Graphics2D subGraphics = (Graphics2D) graphics.create();
|
||||||
|
subGraphics.translate(point.x, point.y);
|
||||||
final Dimension dimension = entity.render(subGraphics, point);
|
final Dimension dimension = entity.render(subGraphics, point);
|
||||||
subGraphics.dispose();
|
subGraphics.dispose();
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldInvalidateOverlays()
|
||||||
|
{
|
||||||
|
final Client client = clientProvider.get();
|
||||||
|
final Widget widget = client.getWidget(WidgetInfo.CHATBOX_MESSAGES);
|
||||||
|
final boolean resizeableChanged = isResizeable != client.isResized();
|
||||||
|
|
||||||
|
if (resizeableChanged)
|
||||||
|
{
|
||||||
|
isResizeable = client.isResized();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean chatboxHiddenChanged = chatboxHidden != (widget != null && widget.isHidden());
|
||||||
|
|
||||||
|
if (chatboxHiddenChanged)
|
||||||
|
{
|
||||||
|
chatboxHidden = widget != null && widget.isHidden();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean viewportChanged = !client.getViewportWidget().getBounds().equals(viewportBounds);
|
||||||
|
|
||||||
|
if (viewportChanged)
|
||||||
|
{
|
||||||
|
viewportBounds = client.getViewportWidget().getBounds();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OverlayBounds buildSnapCorners()
|
||||||
|
{
|
||||||
|
final Client client = clientProvider.get();
|
||||||
|
|
||||||
|
final Rectangle bounds = viewportBounds != null
|
||||||
|
? viewportBounds
|
||||||
|
: new Rectangle(0, 0, client.getCanvas().getWidth(), client.getCanvas().getHeight());
|
||||||
|
|
||||||
|
final Widget chatbox = client.getWidget(WidgetInfo.CHATBOX_MESSAGES);
|
||||||
|
final Rectangle chatboxBounds = chatbox != null
|
||||||
|
? chatbox.getBounds() : new Rectangle(0, bounds.height, 519, 165);
|
||||||
|
|
||||||
|
final Point topLeftPoint = new Point(
|
||||||
|
isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED,
|
||||||
|
isResizeable ? BORDER_TOP_RESIZABLE : BORDER_TOP_FIXED);
|
||||||
|
final Point topRightPoint = new Point(bounds.x + bounds.width - BORDER_RIGHT, BORDER_TOP_FIXED);
|
||||||
|
final Point bottomLeftPoint = new Point(isResizeable ? BORDER_LEFT_RESIZABLE : BORDER_LEFT_FIXED, bounds.y + bounds.height - BORDER_BOTTOM);
|
||||||
|
final Point bottomRightPoint = new Point(bounds.x + bounds.width - BORDER_RIGHT, bounds.y + bounds.height - BORDER_BOTTOM);
|
||||||
|
final Point rightChatboxPoint = new Point(bounds.x + chatboxBounds.width - BORDER_RIGHT, bounds.y + bounds.height - BORDER_BOTTOM);
|
||||||
|
|
||||||
|
// Check to see if chat box is minimized
|
||||||
|
if (chatbox != null && isResizeable && chatboxHidden)
|
||||||
|
{
|
||||||
|
rightChatboxPoint.y += chatboxBounds.height;
|
||||||
|
bottomLeftPoint.y += chatboxBounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OverlayBounds(
|
||||||
|
new Rectangle(topLeftPoint, SNAP_CORNER_SIZE),
|
||||||
|
new Rectangle(topRightPoint, SNAP_CORNER_SIZE),
|
||||||
|
new Rectangle(bottomLeftPoint, SNAP_CORNER_SIZE),
|
||||||
|
new Rectangle(bottomRightPoint, SNAP_CORNER_SIZE),
|
||||||
|
new Rectangle(rightChatboxPoint, SNAP_CORNER_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private OverlayBounds translateSnapCorners(OverlayBounds snapCorners)
|
||||||
|
{
|
||||||
|
return new OverlayBounds(
|
||||||
|
snapCorners.getTopLeft(),
|
||||||
|
translate(snapCorners.getTopRight(), -SNAP_CORNER_SIZE.width, 0),
|
||||||
|
translate(snapCorners.getBottomLeft(), 0, -SNAP_CORNER_SIZE.height),
|
||||||
|
translate(snapCorners.getBottomRight(), -SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height),
|
||||||
|
translate(snapCorners.getAboveChatboxRight(), -SNAP_CORNER_SIZE.width, -SNAP_CORNER_SIZE.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Rectangle translate(Rectangle rectangle, int dx, int dy)
|
||||||
|
{
|
||||||
|
rectangle.translate(dx, dy);
|
||||||
|
return rectangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveOverlayLocation(final Overlay overlay)
|
||||||
|
{
|
||||||
|
final String key = overlay.getClass().getSimpleName() + OVERLAY_CONFIG_PREFERRED_LOCATION;
|
||||||
|
if (overlay.getPreferredLocation() != null)
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(
|
||||||
|
runeliteGroupName,
|
||||||
|
key,
|
||||||
|
overlay.getPreferredLocation());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configManager.unsetConfiguration(
|
||||||
|
runeliteGroupName,
|
||||||
|
key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveOverlayPosition(final Overlay overlay)
|
||||||
|
{
|
||||||
|
final String key = overlay.getClass().getSimpleName() + OVERLAY_CONFIG_PREFERRED_POSITION;
|
||||||
|
if (overlay.getPreferredPosition() != null)
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(
|
||||||
|
runeliteGroupName,
|
||||||
|
key,
|
||||||
|
overlay.getPreferredPosition());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configManager.unsetConfiguration(
|
||||||
|
runeliteGroupName,
|
||||||
|
key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point loadOverlayLocation(final Overlay overlay)
|
||||||
|
{
|
||||||
|
final String key = overlay.getClass().getSimpleName() + OVERLAY_CONFIG_PREFERRED_LOCATION;
|
||||||
|
return configManager.getConfiguration(runeliteGroupName, key, Point.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OverlayPosition loadOverlayPosition(final Overlay overlay)
|
||||||
|
{
|
||||||
|
final String locationKey = overlay.getClass().getSimpleName() + OVERLAY_CONFIG_PREFERRED_POSITION;
|
||||||
|
return configManager.getConfiguration(runeliteGroupName, locationKey, OverlayPosition.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void provideScreenshot(BufferedImage image)
|
public void provideScreenshot(BufferedImage image)
|
||||||
{
|
{
|
||||||
Consumer<BufferedImage> consumer;
|
Consumer<BufferedImage> consumer;
|
||||||
|
|||||||
@@ -137,6 +137,35 @@ public class OverlayUtil
|
|||||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static java.awt.Point padPosition(OverlayPosition position, Dimension dimension, final int padding)
|
||||||
|
{
|
||||||
|
final java.awt.Point result = new java.awt.Point();
|
||||||
|
|
||||||
|
switch (position)
|
||||||
|
{
|
||||||
|
case DYNAMIC:
|
||||||
|
case TOOLTIP:
|
||||||
|
break;
|
||||||
|
case BOTTOM_LEFT:
|
||||||
|
result.x += dimension.width + (dimension.width == 0 ? 0 : padding);
|
||||||
|
break;
|
||||||
|
case BOTTOM_RIGHT:
|
||||||
|
result.x -= dimension.width + (dimension.width == 0 ? 0 : padding);
|
||||||
|
break;
|
||||||
|
case TOP_LEFT:
|
||||||
|
result.y += dimension.height + (dimension.height == 0 ? 0 : padding);
|
||||||
|
break;
|
||||||
|
case TOP_RIGHT:
|
||||||
|
result.y += dimension.height + (dimension.height == 0 ? 0 : padding);
|
||||||
|
break;
|
||||||
|
case ABOVE_CHATBOX_RIGHT:
|
||||||
|
result.y -= dimension.height + (dimension.height == 0 ? 0 : padding);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static java.awt.Point transformPosition(OverlayPosition position, Dimension dimension)
|
public static java.awt.Point transformPosition(OverlayPosition position, Dimension dimension)
|
||||||
{
|
{
|
||||||
final java.awt.Point result = new java.awt.Point();
|
final java.awt.Point result = new java.awt.Point();
|
||||||
@@ -144,6 +173,7 @@ public class OverlayUtil
|
|||||||
switch (position)
|
switch (position)
|
||||||
{
|
{
|
||||||
case DYNAMIC:
|
case DYNAMIC:
|
||||||
|
case TOOLTIP:
|
||||||
case TOP_LEFT:
|
case TOP_LEFT:
|
||||||
break;
|
break;
|
||||||
case BOTTOM_LEFT:
|
case BOTTOM_LEFT:
|
||||||
|
|||||||
@@ -85,6 +85,18 @@ public abstract class StretchedFixedModeMixin implements RSClient
|
|||||||
cachedStretchedDimensions = null;
|
cachedStretchedDimensions = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Override
|
||||||
|
public Dimension getRealDimensions()
|
||||||
|
{
|
||||||
|
if (isStretchedEnabled() && !isResized())
|
||||||
|
{
|
||||||
|
return Constants.GAME_FIXED_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCanvas().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Override
|
@Override
|
||||||
public Dimension getStretchedDimensions()
|
public Dimension getStretchedDimensions()
|
||||||
|
|||||||
Reference in New Issue
Block a user