runelite-client: add central skill icon cache

This commit is contained in:
Adam
2018-02-03 20:32:02 -05:00
parent d5f56f695e
commit 181c717a05
8 changed files with 112 additions and 95 deletions

View File

@@ -0,0 +1,64 @@
/*
* 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.game;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Skill;
@Singleton
@Slf4j
public class SkillIconManager
{
private final BufferedImage[] imgCache = new BufferedImage[Skill.values().length];
public BufferedImage getSkillImage(Skill skill)
{
int skillIdx = skill.ordinal();
BufferedImage skillImage = null;
if (imgCache[skillIdx] != null)
{
return imgCache[skillIdx];
}
try
{
String skillIconPath = "/skill_icons/" + skill.getName().toLowerCase() + ".png";
log.debug("Loading skill icon from {}", skillIconPath);
skillImage = ImageIO.read(SkillIconManager.class.getResourceAsStream(skillIconPath));
imgCache[skillIdx] = skillImage;
}
catch (IOException e)
{
log.debug("Error Loading skill icons {}", e);
}
return skillImage;
}
}

View File

@@ -28,15 +28,13 @@ import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Skill; import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.OverlayPriority;
@@ -46,8 +44,6 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@Slf4j @Slf4j
class BoostsOverlay extends Overlay class BoostsOverlay extends Overlay
{ {
private final BufferedImage[] imgCache = new BufferedImage[Skill.values().length - 1];
@Getter @Getter
private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1]; private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1];
@@ -58,6 +54,9 @@ class BoostsOverlay extends Overlay
@Inject @Inject
private BoostsPlugin plugin; private BoostsPlugin plugin;
@Inject
private SkillIconManager iconManager;
private PanelComponent panelComponent; private PanelComponent panelComponent;
@Inject @Inject
@@ -100,7 +99,7 @@ class BoostsOverlay extends Overlay
{ {
if (indicators[skill.ordinal()] == null) if (indicators[skill.ordinal()] == null)
{ {
BoostIndicator indicator = new BoostIndicator(skill, getSkillImage(skill), client, config); BoostIndicator indicator = new BoostIndicator(skill, iconManager.getSkillImage(skill), client, config);
indicators[skill.ordinal()] = indicator; indicators[skill.ordinal()] = indicator;
infoBoxManager.addInfoBox(indicator); infoBoxManager.addInfoBox(indicator);
} }
@@ -146,29 +145,4 @@ class BoostsOverlay extends Overlay
return new Color(238, 51, 51); return new Color(238, 51, 51);
} }
private BufferedImage getSkillImage(Skill skill)
{
int skillIdx = skill.ordinal();
BufferedImage skillImage = null;
if (imgCache[skillIdx] != null)
{
return imgCache[skillIdx];
}
try
{
String skillIconPath = "/skill_icons/" + skill.getName().toLowerCase() + ".png";
log.debug("Loading skill icon from {}", skillIconPath);
skillImage = ImageIO.read(BoostsOverlay.class.getResourceAsStream(skillIconPath));
imgCache[skillIdx] = skillImage;
}
catch (IOException e)
{
log.debug("Error Loading skill icons {}", e);
}
return skillImage;
}
} }

View File

@@ -29,7 +29,6 @@ import com.google.common.collect.Sets;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.google.inject.Binder; import com.google.inject.Binder;
import com.google.inject.Provides; import com.google.inject.Provides;
import java.awt.image.BufferedImage;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
@@ -37,7 +36,6 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.imageio.ImageIO;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@@ -73,9 +71,6 @@ public class MotherlodePlugin extends Plugin
private static final Set<Integer> MINE_SPOTS = Sets.newHashSet(ORE_VEIN_26661, ORE_VEIN_26662, ORE_VEIN_26663, ORE_VEIN_26664); private static final Set<Integer> MINE_SPOTS = Sets.newHashSet(ORE_VEIN_26661, ORE_VEIN_26662, ORE_VEIN_26663, ORE_VEIN_26664);
private static final Set<Integer> ROCK_OBSTACLES = Sets.newHashSet(ROCKFALL, ROCKFALL_26680); private static final Set<Integer> ROCK_OBSTACLES = Sets.newHashSet(ROCKFALL, ROCKFALL_26680);
@Getter
private BufferedImage mineIcon;
@Inject @Inject
private MotherlodeOverlay overlay; private MotherlodeOverlay overlay;
@@ -113,12 +108,6 @@ public class MotherlodePlugin extends Plugin
return Arrays.asList(overlay, rocksOverlay, motherlodeSackOverlay); return Arrays.asList(overlay, rocksOverlay, motherlodeSackOverlay);
} }
@Override
protected void startUp() throws Exception
{
mineIcon = ImageIO.read(MotherlodePlugin.class.getResourceAsStream("/skill_icons/mining.png"));
}
public MotherlodeSession getSession() public MotherlodeSession getSession()
{ {
return session; return session;

View File

@@ -29,13 +29,16 @@ import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Polygon; import java.awt.Polygon;
import java.awt.image.BufferedImage;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.GameObject; import net.runelite.api.GameObject;
import net.runelite.api.Perspective; import net.runelite.api.Perspective;
import net.runelite.api.Player; import net.runelite.api.Player;
import net.runelite.api.Point; import net.runelite.api.Point;
import net.runelite.api.Skill;
import net.runelite.api.WallObject; import net.runelite.api.WallObject;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
@@ -49,14 +52,18 @@ class MotherlodeRocksOverlay extends Overlay
private final MotherlodePlugin plugin; private final MotherlodePlugin plugin;
private final MotherlodeConfig config; private final MotherlodeConfig config;
private final BufferedImage miningIcon;
@Inject @Inject
MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config) MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config, SkillIconManager iconManager)
{ {
setPosition(OverlayPosition.DYNAMIC); setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE); setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client; this.client = client;
this.plugin = plugin; this.plugin = plugin;
this.config = config; this.config = config;
miningIcon = iconManager.getSkillImage(Skill.MINING);
} }
@Override @Override
@@ -98,11 +105,11 @@ class MotherlodeRocksOverlay extends Overlay
private void renderVein(Graphics2D graphics, WallObject vein) private void renderVein(Graphics2D graphics, WallObject vein)
{ {
Point canvasLoc = Perspective.getCanvasImageLocation(client, graphics, vein.getLocalLocation(), plugin.getMineIcon(), 150); Point canvasLoc = Perspective.getCanvasImageLocation(client, graphics, vein.getLocalLocation(), miningIcon, 150);
if (canvasLoc != null) if (canvasLoc != null)
{ {
graphics.drawImage(plugin.getMineIcon(), canvasLoc.getX(), canvasLoc.getY(), null); graphics.drawImage(miningIcon, canvasLoc.getX(), canvasLoc.getY(), null);
} }
} }

View File

@@ -32,17 +32,15 @@ import java.awt.Stroke;
import java.awt.geom.Arc2D; import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject; import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Experience; import net.runelite.api.Experience;
import net.runelite.api.Point; import net.runelite.api.Point;
import net.runelite.api.Skill; import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay; import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.OverlayPriority;
@@ -56,6 +54,9 @@ public class XpGlobesOverlay extends Overlay
private final XpGlobesPlugin plugin; private final XpGlobesPlugin plugin;
private final XpGlobesConfig config; private final XpGlobesConfig config;
@Inject
private SkillIconManager iconManager;
private static final int DEFAULT_CIRCLE_WIDTH = 40; private static final int DEFAULT_CIRCLE_WIDTH = 40;
private static final int DEFAULT_CIRCLE_HEIGHT = 40; private static final int DEFAULT_CIRCLE_HEIGHT = 40;
private static final int MINIMUM_STEP_WIDTH = DEFAULT_CIRCLE_WIDTH + 10; private static final int MINIMUM_STEP_WIDTH = DEFAULT_CIRCLE_WIDTH + 10;
@@ -69,8 +70,6 @@ public class XpGlobesOverlay extends Overlay
private static final int DEFAULT_START_Y = 10; private static final int DEFAULT_START_Y = 10;
private final BufferedImage[] imgCache = new BufferedImage[Skill.values().length - 1];
private static final int TOOLTIP_RECT_SIZE_X = 150; private static final int TOOLTIP_RECT_SIZE_X = 150;
@Inject @Inject
@@ -171,7 +170,7 @@ public class XpGlobesOverlay extends Overlay
private void drawSkillImage(Graphics2D graphics, XpGlobe xpGlobe, int x, int y) private void drawSkillImage(Graphics2D graphics, XpGlobe xpGlobe, int x, int y)
{ {
BufferedImage skillImage = getSkillImage(xpGlobe); BufferedImage skillImage = iconManager.getSkillImage(xpGlobe.getSkill());
if (skillImage == null) if (skillImage == null)
{ {
@@ -186,31 +185,6 @@ public class XpGlobesOverlay extends Overlay
); );
} }
private BufferedImage getSkillImage(XpGlobe xpGlobe)
{
int skillIdx = xpGlobe.getSkill().ordinal();
BufferedImage skillImage = null;
if (imgCache[skillIdx] != null)
{
return imgCache[skillIdx];
}
try
{
String skillIconPath = "/skill_icons/" + xpGlobe.getSkillName().toLowerCase() + ".png";
log.debug("Loading skill icon from {}", skillIconPath);
skillImage = ImageIO.read(XpGlobesOverlay.class.getResourceAsStream(skillIconPath));
imgCache[skillIdx] = skillImage;
}
catch (IOException e)
{
log.debug("Error Loading skill icons {}", e);
}
return skillImage;
}
private void drawTooltipIfMouseover(Graphics2D graphics, java.awt.Point parent, XpGlobe mouseOverSkill, Ellipse2D drawnGlobe) private void drawTooltipIfMouseover(Graphics2D graphics, java.awt.Point parent, XpGlobe mouseOverSkill, Ellipse2D drawnGlobe)
{ {
Point mouse = client.getMouseCanvasPosition(); Point mouse = client.getMouseCanvasPosition();

View File

@@ -29,7 +29,6 @@ import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.GridLayout; import java.awt.GridLayout;
import java.io.IOException; import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
@@ -41,13 +40,19 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.client.game.SkillIconManager;
@Slf4j @Slf4j
class XpInfoBox extends JPanel class XpInfoBox extends JPanel
{ {
private static final Color[] PROGRESS_COLORS = new Color[] { Color.RED, Color.YELLOW, Color.GREEN }; private static final Color[] PROGRESS_COLORS = new Color[]
{
Color.RED, Color.YELLOW, Color.GREEN
};
private final Client client;
private final JPanel panel;
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
private final SkillXPInfo xpInfo; private final SkillXPInfo xpInfo;
@@ -56,10 +61,8 @@ class XpInfoBox extends JPanel
private final JLabel xpGained = new JLabel(); private final JLabel xpGained = new JLabel();
private final JLabel actionsHr = new JLabel(); private final JLabel actionsHr = new JLabel();
private final JLabel actions = new JLabel(); private final JLabel actions = new JLabel();
private final Client client;
private final JPanel panel;
XpInfoBox(Client client, JPanel panel, SkillXPInfo xpInfo) throws IOException XpInfoBox(Client client, JPanel panel, SkillXPInfo xpInfo, SkillIconManager iconManager) throws IOException
{ {
this.client = client; this.client = client;
this.panel = panel; this.panel = panel;
@@ -73,8 +76,7 @@ class XpInfoBox extends JPanel
container.setLayout(new BorderLayout(3, 3)); container.setLayout(new BorderLayout(3, 3));
// Create skill/reset icon // Create skill/reset icon
final String skillIcon = "/skill_icons/" + xpInfo.getSkill().getName().toLowerCase() + ".png"; final JButton resetIcon = new JButton(new ImageIcon(iconManager.getSkillImage(xpInfo.getSkill())));
final JButton resetIcon = new JButton(new ImageIcon(ImageIO.read(getClass().getResourceAsStream(skillIcon))));
resetIcon.setToolTipText("Reset " + xpInfo.getSkill().getName() + " tracker"); resetIcon.setToolTipText("Reset " + xpInfo.getSkill().getName() + " tracker");
resetIcon.setPreferredSize(new Dimension(64, 64)); resetIcon.setPreferredSize(new Dimension(64, 64));
resetIcon.addActionListener(e -> reset()); resetIcon.addActionListener(e -> reset());
@@ -143,7 +145,7 @@ class XpInfoBox extends JPanel
final int progress = xpInfo.getSkillProgress(); final int progress = xpInfo.getSkillProgress();
progressBar.setValue(progress); progressBar.setValue(progress);
progressBar.setBackground(interpolateColors(PROGRESS_COLORS, (double)progress / 100d)); progressBar.setBackground(interpolateColors(PROGRESS_COLORS, (double) progress / 100d));
progressBar.setToolTipText("<html>" progressBar.setToolTipText("<html>"
+ XpPanel.formatLine(xpInfo.getXpRemaining(), "xp remaining") + XpPanel.formatLine(xpInfo.getXpRemaining(), "xp remaining")
@@ -158,10 +160,13 @@ class XpInfoBox extends JPanel
}); });
} }
/** /**
* Interpolate between array of colors using Normal (Gaussian) distribution * Interpolate between array of colors using Normal (Gaussian)
* @see <a href="https://en.wikipedia.org/wiki/Normal_distribution}">Normal distribution on Wikipedia</a> * distribution
*
* @see
* <a href="https://en.wikipedia.org/wiki/Normal_distribution}">Normal
* distribution on Wikipedia</a>
* @param colors array of colors * @param colors array of colors
* @param x distribution factor * @param x distribution factor
* @return interpolated color * @return interpolated color
@@ -170,7 +175,7 @@ class XpInfoBox extends JPanel
{ {
double r = 0.0, g = 0.0, b = 0.0; double r = 0.0, g = 0.0, b = 0.0;
double total = 0.0; double total = 0.0;
double step = 1.0 / (double)(colors.length - 1); double step = 1.0 / (double) (colors.length - 1);
double mu = 0.0; double mu = 0.0;
double sigma2 = 0.035; double sigma2 = 0.035;
@@ -192,6 +197,6 @@ class XpInfoBox extends JPanel
b += color.getBlue() * percent / total; b += color.getBlue() * percent / total;
} }
return new Color((int)r, (int)g, (int)b); return new Color((int) r, (int) g, (int) b);
} }
} }

View File

@@ -39,6 +39,7 @@ 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.Skill; import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.PluginPanel;
@Slf4j @Slf4j
@@ -48,8 +49,7 @@ class XpPanel extends PluginPanel
private final JLabel totalXpGained = new JLabel(); private final JLabel totalXpGained = new JLabel();
private final JLabel totalXpHr = new JLabel(); private final JLabel totalXpHr = new JLabel();
XpPanel(Client client, SkillIconManager iconManager)
XpPanel(Client client)
{ {
super(); super();
@@ -90,7 +90,7 @@ class XpPanel extends PluginPanel
break; break;
} }
infoBoxes.put(skill, new XpInfoBox(client, infoBoxPanel, new SkillXPInfo(skill))); infoBoxes.put(skill, new XpInfoBox(client, infoBoxPanel, new SkillXPInfo(skill), iconManager));
} }
} }
catch (IOException e) catch (IOException e)

View File

@@ -39,6 +39,7 @@ import net.runelite.api.Player;
import net.runelite.api.events.ExperienceChanged; import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.ClientUI;
@@ -62,7 +63,10 @@ public class XpTrackerPlugin extends Plugin
private Client client; private Client client;
@Inject @Inject
ScheduledExecutorService executor; private SkillIconManager skillIconManager;
@Inject
private ScheduledExecutorService executor;
private NavigationButton navButton; private NavigationButton navButton;
private XpPanel xpPanel; private XpPanel xpPanel;
@@ -86,7 +90,7 @@ public class XpTrackerPlugin extends Plugin
log.warn("Error looking up worlds list", e); log.warn("Error looking up worlds list", e);
} }
xpPanel = new XpPanel(client); xpPanel = new XpPanel(client, skillIconManager);
navButton = new NavigationButton( navButton = new NavigationButton(
"XP Tracker", "XP Tracker",
ImageIO.read(getClass().getResourceAsStream("xp.png")), ImageIO.read(getClass().getResourceAsStream("xp.png")),