Rethink overlay rendering stuff

This commit is contained in:
Adam
2016-04-24 10:29:39 -04:00
parent 5bbdec9a76
commit 271752873f
16 changed files with 318 additions and 208 deletions

View File

@@ -6,7 +6,7 @@ import joptsimple.OptionSet;
import net.runelite.api.Client;
import net.runelite.client.plugins.PluginManager;
import net.runelite.client.ui.ClientUI;
import net.runelite.client.ui.OverlayRenderer;
import net.runelite.client.ui.overlay.OverlayRenderer;
public class RuneLite

View File

@@ -1,8 +1,8 @@
package net.runelite.client.plugins;
import net.runelite.client.ui.Overlay;
import net.runelite.client.ui.overlay.Overlay;
public abstract class Plugin
{
public abstract Overlay drawOverlay();
public abstract Overlay getOverlay();
}

View File

@@ -3,6 +3,7 @@ package net.runelite.client.plugins;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.runelite.client.plugins.boosts.Boosts;
import net.runelite.client.plugins.opponentinfo.OpponentInfo;
public class PluginManager
@@ -11,6 +12,7 @@ public class PluginManager
public void loadAll()
{
plugins.add(new Boosts());
plugins.add(new OpponentInfo());
}

View File

@@ -0,0 +1,15 @@
package net.runelite.client.plugins.boosts;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.Overlay;
public class Boosts extends Plugin
{
private final Overlay overlay = new BoostsOverlay();
@Override
public Overlay getOverlay()
{
return overlay;
}
}

View File

@@ -0,0 +1,81 @@
package net.runelite.client.plugins.boosts;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import net.runelite.api.Client;
import net.runelite.api.Skill;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
class BoostsOverlay extends Overlay
{
private static final int WIDTH = 140;
private static final Color BACKGROUND = new Color(Color.gray.getRed(), Color.gray.getGreen(), Color.gray.getBlue(), 127);
private static final Skill[] SHOW = new Skill[] { Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE, Skill.RANGED, Skill.MAGIC };
private static final int TOP_BORDER = 2;
private static final int LEFT_BORDER = 2;
private static final int RIGHT_BORDER = 2;
private static final int SEPARATOR = 2;
BoostsOverlay()
{
super(OverlayPosition.TOP_LEFT, OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
Client client = RuneLite.getClient();
FontMetrics metrics = graphics.getFontMetrics();
int[] boostedSkills = client.getBoostedSkillLevels(),
baseSkills = client.getRealSkillLevels();
int height = TOP_BORDER;
for (Skill skill : SHOW)
{
int boosted = boostedSkills[skill.ordinal()],
base = baseSkills[skill.ordinal()];
if (boosted == base)
continue;
height += metrics.getHeight() + SEPARATOR;
}
if (height == TOP_BORDER)
return null;
graphics.setColor(BACKGROUND);
graphics.fillRect(0, 0, WIDTH, height);
int y = TOP_BORDER;
for (Skill skill : SHOW)
{
int boosted = boostedSkills[skill.ordinal()],
base = baseSkills[skill.ordinal()];
if (boosted == base)
continue;
graphics.setColor(Color.white);
graphics.drawString(skill.getName(), LEFT_BORDER, y + metrics.getHeight());
String str = boosted + "/" + base;
graphics.drawString(str, WIDTH - RIGHT_BORDER - metrics.stringWidth(str), y + metrics.getHeight());
y += metrics.getHeight() + SEPARATOR;
}
return new Dimension(WIDTH, height);
}
}

View File

@@ -1,105 +1,15 @@
package net.runelite.client.plugins.opponentinfo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.client.RuneLite;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.Overlay;
import net.runelite.client.ui.OverlayPosition;
import net.runelite.client.ui.OverlayPriority;
import net.runelite.client.ui.overlay.Overlay;
public class OpponentInfo extends Plugin
{
private static final int WIDTH = 140;
private static final int HEIGHT = 75;
private static final int TOP_BORDER = 2;
private static final int BOTTOM_BORDER = 2;
private static final int BAR_WIDTH = 124;
private static final int BAR_HEIGHT = 20;
private static final Color BACKGROUND = new Color(Color.gray.getRed(), Color.gray.getGreen(), Color.gray.getBlue(), 127);
private static final Color HP_GREEN = new Color(0, 146, 54, 230);
private static final Color HP_RED = new Color(102, 15, 16, 230);
private final BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
private final Overlay overlay = new Overlay(image, OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
private Actor getOpponent()
{
Client client = RuneLite.getClient();
Player player = client.getLocalPlayer();
if (player == null)
return null;
return player.getInteracting();
}
private final Overlay overlay = new OpponentInfoOverlay();
@Override
public Overlay drawOverlay()
public Overlay getOverlay()
{
Actor opponent = getOpponent();
if (opponent == null)
return null;
int cur = opponent.getHealth();
int max = opponent.getMaxHealth();
Graphics g = image.getGraphics();
FontMetrics fm = g.getFontMetrics();
int height = TOP_BORDER
+ fm.getHeight(); // opponent name
if (max > 0)
height += 1 // between name and hp bar
+ BAR_HEIGHT; // bar
height += BOTTOM_BORDER;
g.setColor(BACKGROUND);
g.fillRect(0, 0, image.getWidth(), height);
String str = opponent.getName();
int x = (image.getWidth() - fm.stringWidth(str)) / 2;
g.setColor(Color.white);
g.drawString(str, x, fm.getHeight() + TOP_BORDER);
// hp bar
if (max > 0)
{
float percent = (float) cur / (float) max;
if (percent > 100f)
percent = 100f;
int barWidth = (int) (percent * (float) BAR_WIDTH);
int barY = TOP_BORDER + fm.getHeight() + 1;
g.setColor(HP_GREEN);
g.fillRect((WIDTH - BAR_WIDTH) / 2, barY, barWidth, BAR_HEIGHT);
g.setColor(HP_RED);
g.fillRect(((WIDTH - BAR_WIDTH) / 2) + barWidth, barY, BAR_WIDTH - barWidth, BAR_HEIGHT);
str = cur + " / " + max;
x = (image.getWidth() - fm.stringWidth(str)) / 2;
g.setColor(Color.white);
g.drawString(str, x, barY + fm.getHeight());
}
g.dispose();
overlay.setDimension(new Dimension(height, image.getWidth()));
return overlay;
}
}

View File

@@ -0,0 +1,99 @@
package net.runelite.client.plugins.opponentinfo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
class OpponentInfoOverlay extends Overlay
{
private static final int WIDTH = 140;
private static final int TOP_BORDER = 2;
private static final int BOTTOM_BORDER = 2;
private static final int BAR_WIDTH = 124;
private static final int BAR_HEIGHT = 20;
private static final Color BACKGROUND = new Color(Color.gray.getRed(), Color.gray.getGreen(), Color.gray.getBlue(), 127);
private static final Color HP_GREEN = new Color(0, 146, 54, 230);
private static final Color HP_RED = new Color(102, 15, 16, 230);
OpponentInfoOverlay()
{
super(OverlayPosition.TOP_LEFT, OverlayPriority.HIGH);
}
private Actor getOpponent()
{
Client client = RuneLite.getClient();
Player player = client.getLocalPlayer();
if (player == null)
return null;
return player.getInteracting();
}
@Override
public Dimension render(Graphics2D graphics)
{
Actor opponent = getOpponent();
if (opponent == null)
return null;
int cur = opponent.getHealth();
int max = opponent.getMaxHealth();
FontMetrics fm = graphics.getFontMetrics();
int height = TOP_BORDER
+ fm.getHeight(); // opponent name
if (max > 0)
height += 1 // between name and hp bar
+ BAR_HEIGHT; // bar
height += BOTTOM_BORDER;
graphics.setColor(BACKGROUND);
graphics.fillRect(0, 0, WIDTH, height);
String str = opponent.getName();
int x = (WIDTH - fm.stringWidth(str)) / 2;
graphics.setColor(Color.white);
graphics.drawString(str, x, fm.getHeight() + TOP_BORDER);
// hp bar
if (max > 0)
{
float percent = (float) cur / (float) max;
if (percent > 100f)
percent = 100f;
int barWidth = (int) (percent * (float) BAR_WIDTH);
int barY = TOP_BORDER + fm.getHeight() + 1;
graphics.setColor(HP_GREEN);
graphics.fillRect((WIDTH - BAR_WIDTH) / 2, barY, barWidth, BAR_HEIGHT);
graphics.setColor(HP_RED);
graphics.fillRect(((WIDTH - BAR_WIDTH) / 2) + barWidth, barY, BAR_WIDTH - barWidth, BAR_HEIGHT);
str = cur + " / " + max;
x = (WIDTH - fm.stringWidth(str)) / 2;
graphics.setColor(Color.white);
graphics.drawString(str, x, barY + fm.getHeight());
}
return new Dimension(WIDTH, height);
}
}

View File

@@ -1,59 +0,0 @@
package net.runelite.client.ui;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
public class Overlay
{
private BufferedImage image; // image to draw
private Dimension dimension; // dimension of visable overlay
private OverlayPosition position; // where to draw it
private OverlayPriority priority; // if multiple overlays exist in the same position, who wins
public Overlay(BufferedImage image, OverlayPosition position, OverlayPriority priority)
{
this.image = image;
this.position = position;
this.priority = priority;
}
public BufferedImage getImage()
{
return image;
}
public void setImage(BufferedImage image)
{
this.image = image;
}
public Dimension getDimension()
{
return dimension;
}
public void setDimension(Dimension dimension)
{
this.dimension = dimension;
}
public OverlayPosition getPosition()
{
return position;
}
public void setPosition(OverlayPosition position)
{
this.position = position;
}
public OverlayPriority getPriority()
{
return priority;
}
public void setPriority(OverlayPriority priority)
{
this.priority = priority;
}
}

View File

@@ -1,6 +0,0 @@
package net.runelite.client.ui;
public enum OverlayPosition
{
TOP_LEFT;
}

View File

@@ -1,40 +0,0 @@
package net.runelite.client.ui;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import net.runelite.client.RuneLite;
import net.runelite.client.plugins.Plugin;
public class OverlayRenderer
{
private static final int TOP_LEFT_BORDER_TOP = 25;
private static final int TOP_LEFT_BORDER_LEFT = 10;
private static final int TOP_LEFT_PADDING = 10;
public void render(Graphics graphics)
{
List<Overlay> overlays = new ArrayList<>();
for (Plugin plugin : RuneLite.getRunelite().getPluginManager().getPlugins())
{
Overlay overlay = plugin.drawOverlay();
if (overlay != null)
overlays.add(overlay);
}
Overlay[] topLeft = overlays.stream().filter(o -> o.getPosition() == OverlayPosition.TOP_LEFT).sorted((o1, o2) -> o1.getPriority().compareTo(o2.getPriority())).toArray(s -> new Overlay[s]);
int y = TOP_LEFT_BORDER_TOP;
for (Overlay overlay : topLeft)
{
BufferedImage image = overlay.getImage();
Dimension dimension = overlay.getDimension();
graphics.drawImage(image, TOP_LEFT_BORDER_LEFT, y, null);
y += dimension.getHeight() + TOP_LEFT_PADDING;
}
}
}

View File

@@ -0,0 +1,38 @@
package net.runelite.client.ui.overlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
public abstract class Overlay
{
private OverlayPosition position; // where to draw it
private OverlayPriority priority; // if multiple overlays exist in the same position, who wins
public Overlay(OverlayPosition position, OverlayPriority priority)
{
this.position = position;
this.priority = priority;
}
public OverlayPosition getPosition()
{
return position;
}
public void setPosition(OverlayPosition position)
{
this.position = position;
}
public OverlayPriority getPriority()
{
return priority;
}
public void setPriority(OverlayPriority priority)
{
this.priority = priority;
}
public abstract Dimension render(Graphics2D graphics);
}

View File

@@ -0,0 +1,6 @@
package net.runelite.client.ui.overlay;
public enum OverlayPosition
{
TOP_LEFT;
}

View File

@@ -1,4 +1,4 @@
package net.runelite.client.ui;
package net.runelite.client.ui.overlay;
public enum OverlayPriority
{

View File

@@ -0,0 +1,23 @@
package net.runelite.client.ui.overlay;
import java.awt.image.BufferedImage;
import net.runelite.client.RuneLite;
import net.runelite.client.plugins.Plugin;
public class OverlayRenderer
{
public void render(BufferedImage clientBuffer)
{
TopDownRenderer td = new TopDownRenderer();
for (Plugin plugin : RuneLite.getRunelite().getPluginManager().getPlugins())
{
Overlay overlay = plugin.getOverlay();
if (overlay.getPosition() == OverlayPosition.TOP_LEFT)
td.add(overlay);
}
td.render(clientBuffer);
}
}

View File

@@ -0,0 +1,40 @@
package net.runelite.client.ui.overlay;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
public class TopDownRenderer
{
private static final int BORDER_TOP = 25;
private static final int BORDER_LEFT = 10;
private static final int PADDING = 10;
private final List<Overlay> overlays = new ArrayList<>();
public void add(Overlay overlay)
{
overlays.add(overlay);
}
public void render(BufferedImage clientBuffer)
{
overlays.sort((o1, o2) -> o2.getPriority().compareTo(o1.getPriority()));
int y = BORDER_TOP;
for (Overlay overlay : overlays)
{
BufferedImage image = clientBuffer.getSubimage(BORDER_LEFT, y, clientBuffer.getWidth() - BORDER_LEFT, clientBuffer.getHeight() - y);//(int) dimension.getWidth(), (int) dimension.getHeight());
Graphics2D graphics = image.createGraphics();
Dimension dimension = overlay.render(graphics);
graphics.dispose();
if (dimension == null)
continue;
y += dimension.getHeight() + PADDING;
}
}
}

View File

@@ -4,28 +4,29 @@ import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import net.runelite.client.RuneLite;
import net.runelite.client.ui.OverlayRenderer;
import net.runelite.client.ui.overlay.OverlayRenderer;
public class RSCanvasCallback
{
private final BufferedImage clientBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB);
private final BufferedImage gameBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB);
private final BufferedImage clientBuffer = new BufferedImage(765, 503, BufferedImage.TYPE_INT_RGB);
private final BufferedImage gameBuffer = new BufferedImage(765, 503, BufferedImage.TYPE_INT_RGB);
public Graphics getGraphics(Canvas canvas, Graphics superGraphics)
{
Graphics clientGraphics = clientBuffer.getGraphics();
clientGraphics.drawImage(gameBuffer, 0, 0, null);
clientGraphics.dispose();
RuneLite runelite = RuneLite.getRunelite();
if (runelite != null)
{
OverlayRenderer renderer = runelite.getRenderer();
if (renderer != null)
renderer.render(clientGraphics);
{
renderer.render(clientBuffer);
}
}
clientGraphics.dispose();
superGraphics.drawImage(clientBuffer, 0, 0, null);
return gameBuffer.getGraphics();