package greenfoot.gui;
import greenfoot.Actor;
import greenfoot.ActorVisitor;
import greenfoot.GreenfootImage;
import greenfoot.ImageVisitor;
import greenfoot.World;
import greenfoot.WorldVisitor;
import greenfoot.core.TextLabel;
import greenfoot.util.GreenfootUtil;
import threadchecker.OnThread;
import threadchecker.Tag;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
| A class which handles the rendering of a World into a BufferedImage, including
| handling the currently-dragging actor (if any).
|
@OnThread(Tag.Simulation)
public class WorldRenderer
{
private static final Color BACKGROUND = Color.WHITE;
| The actor being dragged. Null if no dragging.
|
private Actor dragActor;
| The current location where the object is dragged - in pixel coordinates relative to this canvas.
|
private Point dragLocation;
| Image used when dragging new actors on the world. Includes the drop shadow.
|
private BufferedImage dragImage;
@OnThread(Tag.Any)
public WorldRenderer()
{
}
| Render the currently held world into the given image. It is assumed
| that the image size matches the current world size.
|
| @param drawWorld The world to draw (may be null, in which case a blank image is drawn)
| @param worldImage The image to draw onto, which is assumed to be
| of the right size for the world (or desired blank size
| if drawWorld is null)
|
public void renderWorld(World drawWorld, BufferedImage worldImage)
{
Graphics2D g2 = (Graphics2D)worldImage.getGraphics();
if (drawWorld == null)
{
g2.setColor(BACKGROUND);
g2.fillRect(0, 0, worldImage.getWidth(), worldImage.getHeight());
}
else
{
paintBackground(g2, drawWorld, worldImage.getWidth(), worldImage.getHeight());
paintObjects(g2, drawWorld);
paintDraggedObject(g2, drawWorld);
WorldVisitor.paintDebug(drawWorld, g2);
paintWorldText(g2, drawWorld);
}
}
| Paints all the objects.
|
| Must be synchronized on the World.lock.
|
private void paintObjects(Graphics2D g, World drawWorld)
{
if (drawWorld == null)
return;
Set<Actor> objects = WorldVisitor.getObjectsListInPaintOrder(drawWorld);
int paintSeq = 0;
for (Iterator<Actor> iter = objects.iterator(); iter.hasNext();) {
Actor thing = iter.next();
int cellSize = WorldVisitor.getCellSize(drawWorld);
GreenfootImage image = ActorVisitor.getDisplayImage(thing);
if (image != null) {
ActorVisitor.setLastPaintSeqNum(thing, paintSeq++);
double halfWidth = image.getWidth() / 2.;
double halfHeight = image.getHeight() / 2.;
AffineTransform oldTx = null;
try {
int ax = ActorVisitor.getX(thing);
int ay = ActorVisitor.getY(thing);
double xCenter = ax * cellSize + cellSize / 2.;
int paintX = (int) Math.floor(xCenter - halfWidth);
double yCenter = ay * cellSize + cellSize / 2.;
int paintY = (int) Math.floor(yCenter - halfHeight);
int rotation = ActorVisitor.getRotation(thing);
if (rotation != 0) {
oldTx = g.getTransform();
g.rotate(Math.toRadians(rotation), xCenter, yCenter);
}
ImageVisitor.drawImage(image, g, paintX, paintY, null, true);
}
catch (IllegalStateException e) {
}
if (oldTx != null) {
g.setTransform(oldTx);
}
}
}
}
| Paint the world background. This takes tiling into account: the
| world image is painted either once or tiled onto this component.
|
private void paintBackground(Graphics2D g, World drawWorld, int width, int height)
{
if (drawWorld != null) {
GreenfootImage backgroundImage = WorldVisitor.getBackgroundImage(drawWorld);
if (backgroundImage != null) {
ImageVisitor.drawImage(backgroundImage, g, 0, 0, null, true);
}
else {
Color oldColor = g.getColor();
g.setColor(BACKGROUND);
g.fillRect(0, 0, width, height);
g.setColor(oldColor);
}
}
}
| Paint text labels that have been placed on the world using World.showText(...).
| @param g The graphics context to draw on
| @param drawWorld The world
|
private void paintWorldText(Graphics2D g, World drawWorld)
{
List<TextLabel> labels = WorldVisitor.getTextLabels(drawWorld);
if (labels.isEmpty()) {
return;
}
Font origFont = g.getFont();
Color orig = g.getColor();
Object origAntiAliasing = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
int cellsize = WorldVisitor.getCellSize(drawWorld);
for (TextLabel label : labels) {
label.draw(g, cellsize);
}
g.setFont(origFont);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, origAntiAliasing);
g.setColor(orig);
}
| If an object is being dragged, paint it.
|
private void paintDraggedObject(Graphics g, World drawWorld)
{
if (dragImage != null) {
int x = (int) dragLocation.getX();
int y = (int) dragLocation.getY();
int xCell = WorldVisitor.toCellFloor(drawWorld, x);
int yCell = WorldVisitor.toCellFloor(drawWorld, y);
int cellSize = WorldVisitor.getCellSize(drawWorld);
x = (int) ((xCell + 0.5) * cellSize - dragImage.getWidth()/2);
y = (int) ((yCell + 0.5) * cellSize - dragImage.getHeight()/2);
g.drawImage(dragImage, x, y, null);
}
}
}
top,
use,
map,
class WorldRenderer
. WorldRenderer
. renderWorld
. paintObjects
. paintBackground
. paintWorldText
. paintDraggedObject
200 neLoCode
+ 19 LoComm