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.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
@@ -46,8 +44,6 @@ import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@Slf4j
class BoostsOverlay extends Overlay
{
private final BufferedImage[] imgCache = new BufferedImage[Skill.values().length - 1];
@Getter
private final BoostIndicator[] indicators = new BoostIndicator[Skill.values().length - 1];
@@ -58,6 +54,9 @@ class BoostsOverlay extends Overlay
@Inject
private BoostsPlugin plugin;
@Inject
private SkillIconManager iconManager;
private PanelComponent panelComponent;
@Inject
@@ -100,7 +99,7 @@ class BoostsOverlay extends Overlay
{
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;
infoBoxManager.addInfoBox(indicator);
}
@@ -146,29 +145,4 @@ class BoostsOverlay extends Overlay
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.inject.Binder;
import com.google.inject.Provides;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -37,7 +36,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.AccessLevel;
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> ROCK_OBSTACLES = Sets.newHashSet(ROCKFALL, ROCKFALL_26680);
@Getter
private BufferedImage mineIcon;
@Inject
private MotherlodeOverlay overlay;
@@ -113,12 +108,6 @@ public class MotherlodePlugin extends Plugin
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()
{
return session;

View File

@@ -29,13 +29,16 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.Skill;
import net.runelite.api.WallObject;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
@@ -49,14 +52,18 @@ class MotherlodeRocksOverlay extends Overlay
private final MotherlodePlugin plugin;
private final MotherlodeConfig config;
private final BufferedImage miningIcon;
@Inject
MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config)
MotherlodeRocksOverlay(Client client, MotherlodePlugin plugin, MotherlodeConfig config, SkillIconManager iconManager)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.plugin = plugin;
this.config = config;
miningIcon = iconManager.getSkillImage(Skill.MINING);
}
@Override
@@ -98,11 +105,11 @@ class MotherlodeRocksOverlay extends Overlay
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)
{
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.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Experience;
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.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
@@ -56,6 +54,9 @@ public class XpGlobesOverlay extends Overlay
private final XpGlobesPlugin plugin;
private final XpGlobesConfig config;
@Inject
private SkillIconManager iconManager;
private static final int DEFAULT_CIRCLE_WIDTH = 40;
private static final int DEFAULT_CIRCLE_HEIGHT = 40;
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 final BufferedImage[] imgCache = new BufferedImage[Skill.values().length - 1];
private static final int TOOLTIP_RECT_SIZE_X = 150;
@Inject
@@ -171,7 +170,7 @@ public class XpGlobesOverlay extends Overlay
private void drawSkillImage(Graphics2D graphics, XpGlobe xpGlobe, int x, int y)
{
BufferedImage skillImage = getSkillImage(xpGlobe);
BufferedImage skillImage = iconManager.getSkillImage(xpGlobe.getSkill());
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)
{
Point mouse = client.getMouseCanvasPosition();

View File

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

View File

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