From eb7ebddec389866d72400f0984603a3ef4cd7c2e Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Tue, 29 Jan 2019 16:27:15 -0800 Subject: [PATCH] player indicators: Add name position configuration This allows players to select from a number of positions where they would like highlighted player's names to be drawn relative to the player's model. Closes runelite/runelite#878 --- .../PlayerIndicatorsConfig.java | 10 +- .../PlayerIndicatorsOverlay.java | 94 ++++++++++++++----- .../playerindicators/PlayerNameLocation.java | 45 +++++++++ 3 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerNameLocation.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java index c40d4a9020..6b032bc8ee 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsConfig.java @@ -155,13 +155,13 @@ public interface PlayerIndicatorsConfig extends Config @ConfigItem( position = 11, - keyName = "drawOverheadPlayerNames", - name = "Draw names above players", - description = "Configures whether or not player names should be drawn above players" + keyName = "playerNamePosition", + name = "Name position", + description = "Configures the position of drawn player names, or if they should be disabled" ) - default boolean drawOverheadPlayerNames() + default PlayerNameLocation playerNamePosition() { - return true; + return PlayerNameLocation.ABOVE_HEAD; } @ConfigItem( diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java index 3795b89f1c..5373fc1eb4 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerIndicatorsOverlay.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, Tomas Slusny + * Copyright (c) 2019, Jordan Atwood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,10 +39,14 @@ import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.OverlayUtil; +import net.runelite.client.util.Text; @Singleton public class PlayerIndicatorsOverlay extends Overlay { + private static final int ACTOR_OVERHEAD_TEXT_MARGIN = 40; + private static final int ACTOR_HORIZONTAL_TEXT_MARGIN = 10; + private final PlayerIndicatorsService playerIndicatorsService; private final PlayerIndicatorsConfig config; private final ClanManager clanManager; @@ -66,39 +71,78 @@ public class PlayerIndicatorsOverlay extends Overlay private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color) { - if (!config.drawOverheadPlayerNames()) + final PlayerNameLocation drawPlayerNamesConfig = config.playerNamePosition(); + if (drawPlayerNamesConfig == PlayerNameLocation.DISABLED) { return; } - String name = actor.getName().replace('\u00A0', ' '); - int offset = actor.getLogicalHeight() + 40; - Point textLocation = actor.getCanvasTextLocation(graphics, name, offset); - - if (textLocation != null) + final int zOffset; + switch (drawPlayerNamesConfig) { - if (config.showClanRanks() && actor.isClanMember()) + case MODEL_CENTER: + case MODEL_RIGHT: + zOffset = actor.getLogicalHeight() / 2; + break; + default: + zOffset = actor.getLogicalHeight() + ACTOR_OVERHEAD_TEXT_MARGIN; + } + + final String name = Text.sanitize(actor.getName()); + Point textLocation = actor.getCanvasTextLocation(graphics, name, zOffset); + + if (drawPlayerNamesConfig == PlayerNameLocation.MODEL_RIGHT) + { + textLocation = actor.getCanvasTextLocation(graphics, "", zOffset); + + if (textLocation == null) { - ClanMemberRank rank = clanManager.getRank(name); - - if (rank != ClanMemberRank.UNRANKED) - { - BufferedImage clanchatImage = clanManager.getClanImage(rank); - - if (clanchatImage != null) - { - int width = clanchatImage.getWidth(); - int textHeight = graphics.getFontMetrics().getHeight() - graphics.getFontMetrics().getMaxDescent(); - Point imageLocation = new Point(textLocation.getX() - width / 2 - 1, textLocation.getY() - textHeight / 2 - clanchatImage.getHeight() / 2); - OverlayUtil.renderImageLocation(graphics, imageLocation, clanchatImage); - - // move text - textLocation = new Point(textLocation.getX() + width / 2, textLocation.getY()); - } - } + return; } - OverlayUtil.renderTextLocation(graphics, textLocation, name, color); + textLocation = new Point(textLocation.getX() + ACTOR_HORIZONTAL_TEXT_MARGIN, textLocation.getY()); } + + if (textLocation == null) + { + return; + } + + if (config.showClanRanks() && actor.isClanMember()) + { + final ClanMemberRank rank = clanManager.getRank(name); + + if (rank != ClanMemberRank.UNRANKED) + { + final BufferedImage clanchatImage = clanManager.getClanImage(rank); + + if (clanchatImage != null) + { + final int clanImageWidth = clanchatImage.getWidth(); + final int clanImageTextMargin; + final int clanImageNegativeMargin; + + if (drawPlayerNamesConfig == PlayerNameLocation.MODEL_RIGHT) + { + clanImageTextMargin = clanImageWidth; + clanImageNegativeMargin = 0; + } + else + { + clanImageTextMargin = clanImageWidth / 2; + clanImageNegativeMargin = clanImageWidth / 2; + } + + final int textHeight = graphics.getFontMetrics().getHeight() - graphics.getFontMetrics().getMaxDescent(); + final Point imageLocation = new Point(textLocation.getX() - clanImageNegativeMargin - 1, textLocation.getY() - textHeight / 2 - clanchatImage.getHeight() / 2); + OverlayUtil.renderImageLocation(graphics, imageLocation, clanchatImage); + + // move text + textLocation = new Point(textLocation.getX() + clanImageTextMargin, textLocation.getY()); + } + } + } + + OverlayUtil.renderTextLocation(graphics, textLocation, name, color); } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerNameLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerNameLocation.java new file mode 100644 index 0000000000..14a4eff208 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/playerindicators/PlayerNameLocation.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019, Jordan Atwood + * 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.plugins.playerindicators; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public enum PlayerNameLocation +{ + + DISABLED("Disabled"), + ABOVE_HEAD("Above head"), + MODEL_CENTER("Center of model"), + MODEL_RIGHT("Right of model"); + + private final String name; + + @Override + public String toString() + { + return name; + } +}