use of games.strategy.triplea.ui.screen.Tile in project triplea by triplea-game.
the class MapPanel method updateUndrawnTiles.
/**
* If we have nothing left undrawn, draw the tiles within preDrawMargin of us, optionally
* forcing the tiles to remain in memory.
*/
private void updateUndrawnTiles(final List<Tile> undrawnTiles, final int preDrawMargin, final boolean forceInMemory) {
// that way when we scroll slowly we wont notice a glitch
if (undrawnTiles.isEmpty()) {
final Rectangle2D extendedBounds = new Rectangle2D.Double(Math.max(model.getX() - preDrawMargin, 0), Math.max(model.getY() - preDrawMargin, 0), getScaledWidth() + (2 * preDrawMargin), getScaledHeight() + (2 * preDrawMargin));
final List<Tile> tileList = tileManager.getTiles(extendedBounds);
for (final Tile tile : tileList) {
if (tile.isDirty()) {
undrawnTiles.add(tile);
} else if (forceInMemory) {
images.add(tile);
}
}
}
}
use of games.strategy.triplea.ui.screen.Tile in project triplea by triplea-game.
the class MapPanel method paint.
@Override
public void paint(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g;
super.paint(g2d);
g2d.clip(new Rectangle2D.Double(0, 0, (getImageWidth() * scale), (getImageHeight() * scale)));
int x = model.getX();
int y = model.getY();
final List<Tile> images = new ArrayList<>();
final List<Tile> undrawnTiles = new ArrayList<>();
final Stopwatch stopWatch = new Stopwatch(Logger.getLogger(MapPanel.class.getName()), Level.FINER, "Paint");
// make sure we use the same data for the entire paint
final GameData data = gameData;
// if the map fits on screen, dont draw any overlap
final boolean fitAxisX = !mapWidthFitsOnScreen() && uiContext.getMapData().scrollWrapX();
final boolean fitAxisY = !mapHeightFitsOnScreen() && uiContext.getMapData().scrollWrapY();
if (fitAxisX || fitAxisY) {
if (fitAxisX && x + (int) getScaledWidth() > model.getMaxWidth()) {
x -= model.getMaxWidth();
}
if (fitAxisY && y + (int) getScaledHeight() > model.getMaxHeight()) {
y -= model.getMaxHeight();
}
// handle wrapping off the screen
if (fitAxisX && x < 0) {
if (fitAxisY && y < 0) {
final Rectangle2D.Double leftUpperBounds = new Rectangle2D.Double(model.getMaxWidth() + x, model.getMaxHeight() + y, -x, -y);
drawTiles(g2d, images, data, leftUpperBounds, undrawnTiles);
}
final Rectangle2D.Double leftBounds = new Rectangle2D.Double(model.getMaxWidth() + x, y, -x, getScaledHeight());
drawTiles(g2d, images, data, leftBounds, undrawnTiles);
}
if (fitAxisY && y < 0) {
final Rectangle2D.Double upperBounds = new Rectangle2D.Double(x, model.getMaxHeight() + y, getScaledWidth(), -y);
drawTiles(g2d, images, data, upperBounds, undrawnTiles);
}
}
// handle non overlap
final Rectangle2D.Double mainBounds = new Rectangle2D.Double(x, y, getScaledWidth(), getScaledHeight());
drawTiles(g2d, images, data, mainBounds, undrawnTiles);
if (routeDescription != null && mouseShadowImage != null && routeDescription.getEnd() != null) {
final AffineTransform t = new AffineTransform();
t.translate(scale * normalizeX(routeDescription.getEnd().getX() - getXOffset()), scale * normalizeY(routeDescription.getEnd().getY() - getYOffset()));
t.translate(mouseShadowImage.getWidth() / -2, mouseShadowImage.getHeight() / -2);
t.scale(scale, scale);
g2d.drawImage(mouseShadowImage, t, this);
}
if (routeDescription != null) {
routeDrawer.drawRoute(g2d, routeDescription, movementLeftForCurrentUnits, movementFuelCost, uiContext.getResourceImageFactory());
}
// used to keep strong references to what is on the screen so it wont be garbage collected
// other references to the images are weak references
this.images.clear();
this.images.addAll(images);
if (highlightedUnits != null) {
for (final Entry<Territory, List<Unit>> entry : highlightedUnits.entrySet()) {
final Set<UnitCategory> categories = UnitSeperator.categorize(entry.getValue());
for (final UnitCategory category : categories) {
final List<Unit> territoryUnitsOfSameCategory = category.getUnits();
if (territoryUnitsOfSameCategory.isEmpty()) {
continue;
}
final Rectangle r = tileManager.getUnitRect(territoryUnitsOfSameCategory, gameData);
if (r == null) {
continue;
}
final Optional<Image> image = uiContext.getUnitImageFactory().getHighlightImage(category.getType(), category.getOwner(), category.hasDamageOrBombingUnitDamage(), category.getDisabled());
if (image.isPresent()) {
final AffineTransform t = new AffineTransform();
t.translate(normalizeX(r.getX() - getXOffset()) * scale, normalizeY(r.getY() - getYOffset()) * scale);
t.scale(scale, scale);
g2d.drawImage(image.get(), t, this);
}
}
}
}
// draw the tiles nearest us first
// then draw farther away
updateUndrawnTiles(undrawnTiles, 30, true);
updateUndrawnTiles(undrawnTiles, 257, true);
// when we are this far away, dont force the tiles to stay in memroy
updateUndrawnTiles(undrawnTiles, 513, false);
updateUndrawnTiles(undrawnTiles, 767, false);
clearPendingDrawOperations();
undrawnTiles.forEach(tile -> pendingDrawOperations.add(Tuple.of(tile, data)));
stopWatch.done();
}
use of games.strategy.triplea.ui.screen.Tile in project triplea by triplea-game.
the class MapPanel method drawMapImage.
/**
* Draws an image of the complete map to the specified graphics context.
*
* <p>
* This method is useful for capturing screenshots. This method can be called from a thread other than the EDT.
* </p>
*
* @param g The graphics context on which to draw the map; must not be {@code null}.
*/
public void drawMapImage(final Graphics g) {
final Graphics2D g2d = (Graphics2D) checkNotNull(g);
// make sure we use the same data for the entire print
final GameData gameData = this.gameData;
gameData.acquireReadLock();
try {
final Rectangle2D.Double bounds = new Rectangle2D.Double(0, 0, getImageWidth(), getImageHeight());
final Collection<Tile> tileList = tileManager.getTiles(bounds);
for (final Tile tile : tileList) {
tile.acquireLock();
try {
final Image img = tile.getImage(gameData, uiContext.getMapData());
if (img != null) {
final AffineTransform t = new AffineTransform();
t.translate((tile.getBounds().x - bounds.getX()) * scale, (tile.getBounds().y - bounds.getY()) * scale);
g2d.drawImage(img, t, this);
}
} finally {
tile.releaseLock();
}
}
} finally {
gameData.releaseReadLock();
}
}
use of games.strategy.triplea.ui.screen.Tile in project triplea by triplea-game.
the class MapPanel method drawTiles.
private void drawTiles(final Graphics2D g, final List<Tile> images, final GameData data, Rectangle2D.Double bounds, final List<Tile> undrawn) {
final List<Tile> tileList = tileManager.getTiles(bounds);
bounds = new Rectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getHeight(), bounds.getWidth());
for (final Tile tile : tileList) {
final Image img;
tile.acquireLock();
try {
if (tile.isDirty()) {
// take what we can get to avoid screen flicker
undrawn.add(tile);
img = tile.getRawImage();
} else {
img = tile.getImage(data, uiContext.getMapData());
images.add(tile);
}
if (img != null) {
final AffineTransform t = new AffineTransform();
t.translate(scale * (tile.getBounds().x - bounds.getX()), scale * (tile.getBounds().y - bounds.getY()));
g.drawImage(img, t, this);
}
} finally {
tile.releaseLock();
}
}
}
Aggregations