Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions src/main/java/net/rptools/lib/image/ImageUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@
import net.rptools.lib.MathUtil;
import net.rptools.maptool.client.AppConstants;
import net.rptools.maptool.client.AppPreferences;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.model.*;
import net.rptools.maptool.util.ImageManager;
import net.rptools.parser.ParserException;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -521,39 +518,6 @@ public static double getIsoFigureScaleFactor(Token token, Rectangle2D footprintB
footprintBounds.getHeight() * 2 / token.getHeight());
}

/**
* Checks to see if token has an image table and references that if the token has a facing
* otherwise uses basic image
*
* @param token the token to get the image from.
* @return BufferedImage
*/
public static BufferedImage getTokenImage(Token token, ImageObserver... observers) {
BufferedImage image = null;
// Get the basic image
if (token.getHasImageTable() && token.hasFacing() && token.getImageTableName() != null) {
LookupTable lookupTable =
MapTool.getCampaign().getLookupTableMap().get(token.getImageTableName());
if (lookupTable != null) {
try {
LookupTable.LookupEntry result =
lookupTable.getLookup(Integer.toString(token.getFacing()));
if (result != null) {
image = ImageManager.getImage(result.getImageId(), observers);
}
} catch (ParserException p) {
// do nothing
}
}
}

if (image == null) {
// Adds zr as observer so we can repaint once the image is ready. Fixes #1700.
image = ImageManager.getImage(token.getImageAssetId(), observers);
}
return image;
}

public static BufferedImage flipIsometric(BufferedImage image, boolean toRhombus) {
BufferedImage workImage;
boolean isSquished =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import javax.swing.*;
import net.rptools.lib.CodeTimer;
import net.rptools.lib.MD5Key;
import net.rptools.lib.image.ImageUtil;
import net.rptools.maptool.client.*;
import net.rptools.maptool.client.functions.TokenMoveFunctions;
import net.rptools.maptool.client.swing.ImageLabel;
Expand Down Expand Up @@ -1794,7 +1793,8 @@ protected void renderTokens(

timer.start("token-list-1b");
// get token image, using image table if present
BufferedImage image = ImageUtil.getTokenImage(token, this);
MD5Key tokenImageId = token.getTokenImageAssetId();
BufferedImage image = ImageManager.getImage(tokenImageId, this);
timer.stop("token-list-1b");

timer.start("token-list-5a");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,9 @@
package net.rptools.maptool.client.ui.zone.renderer.tokenRender;

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.*;
import net.rptools.lib.CodeTimer;
import net.rptools.lib.MD5Key;
import net.rptools.lib.image.ImageUtil;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.ui.zone.ZoneViewModel.TokenPosition;
import net.rptools.maptool.client.ui.zone.renderer.RenderHelper;
import net.rptools.maptool.model.*;
Expand All @@ -36,8 +28,6 @@

public class TokenRenderer {
private static final Logger log = LogManager.getLogger(TokenRenderer.class);
private static final Map<String, Map<Integer, BufferedImage>> imageTableMap =
Collections.synchronizedMap(new HashMap<>());

private final RenderHelper renderHelper;
private final Zone zone;
Expand All @@ -51,50 +41,27 @@ public void renderToken(Token token, TokenPosition position, Graphics2D g2d, flo
var timer = CodeTimer.get();
timer.increment("TokenRenderer-renderToken");
timer.start("TokenRenderer-renderToken");

timer.start("TokenRenderer-loadImageTable");
if (token.getHasImageTable() && !imageTableMap.containsKey(token.getImageTableName())) {
(new CacheTableImagesWorker(token.getImageTableName())).execute();
}
timer.stop("TokenRenderer-loadImageTable");

timer.start("TokenRenderer-paintTokenImage");
renderHelper.render(
g2d, worldG -> paintTokenImage(worldG, position, extraOpacity * token.getTokenOpacity()));
timer.stop("TokenRenderer-paintTokenImage");
timer.stop("TokenRenderer-renderToken");
}

/**
* Checks to see if token has an image table and references that if the token has a facing
* otherwise uses basic image
*
* @param token the token to get the image from.
* @return The token's current image based on its facing.
*/
private BufferedImage getRenderImage(Token token) {
var timer = CodeTimer.get();
timer.start("TokenRenderer-getRenderImage");
BufferedImage bi = ImageManager.BROKEN_IMAGE;
if (token.getHasImageTable() && imageTableMap.containsKey(token.getImageTableName())) {
Map<Integer, BufferedImage> imageTable = imageTableMap.get(token.getImageTableName());
int max = imageTable.keySet().stream().max(Integer::compareTo).orElse(Integer.MAX_VALUE);
if (max != Integer.MAX_VALUE) {
int useValue = (360 + token.getFacingInDegrees()) % max;
bi =
imageTable.get(
imageTable.keySet().stream()
.sorted()
.filter(integer -> integer >= useValue)
.toList()
.getFirst());
}
} else {
bi = ImageUtil.getTokenImage(token, renderHelper.getImageObserver());
}
timer.stop("TokenRenderer-getRenderImage");
return bi;
// get token image, using image table if present
MD5Key tokenImageId = token.getTokenImageAssetId();
return ImageManager.getImage(tokenImageId, renderHelper.getImageObserver());
}

private void paintTokenImage(Graphics2D g2d, TokenPosition position, float opacity) {
var token = position.token();
var renderImage = getRenderImage(token);
if (renderImage == null) {
return;
}

var imageTransform =
TokenUtil.getRenderTransform(
Expand All @@ -110,48 +77,4 @@ private void paintTokenImage(Graphics2D g2d, TokenPosition position, float opaci
g2d.drawImage(renderImage, imageTransform, renderHelper.getImageObserver());
g2d.setStroke(new BasicStroke(1f));
}

private static Map<Integer, BufferedImage> cacheImageTable(String tableName) {
LookupTable lookupTable = MapTool.getCampaign().getLookupTableMap().get(tableName);
if (lookupTable != null) {
BufferedImage broken = ImageManager.BROKEN_IMAGE;
Map<Integer, BufferedImage> tmp = new HashMap<>();
List<LookupTable.LookupEntry> entries = lookupTable.getEntryList();
for (LookupTable.LookupEntry entry : entries) {
MD5Key asset = entry.getImageId();
if (asset != null) {
BufferedImage bi = ImageManager.getImageAndWait(asset);
if (!bi.equals(broken)) {
tmp.put(entry.getMax(), bi);
}
}
}
if (!tmp.isEmpty()) {
return tmp;
}
}
return null;
}

private static class CacheTableImagesWorker
extends SwingWorker<Map<Integer, BufferedImage>, String> {
String tableName;

public CacheTableImagesWorker(String tableName) {
this.tableName = tableName;
}

@Override
public Map<Integer, BufferedImage> doInBackground() {
return cacheImageTable(tableName);
}

@Override
protected void done() {
try {
imageTableMap.put(tableName, get());
} catch (Exception ignore) {
}
}
}
}
49 changes: 40 additions & 9 deletions src/main/java/net/rptools/maptool/model/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -1133,22 +1133,53 @@ public MD5Key getImageAssetId() {
return assetId;
}

public MD5Key getTokenImageAssetId() {
if (!getHasImageTable() || !hasFacing() || getImageTableName() == null)
return getImageAssetId();
/**
* Looks up the token's facing in the token's image table.
*
* <p>If the token does not have an image table, or does not have its facing set, or otherwise
* cannot find an image ID from the lookup table, this method return {@code null}.
*
* @return The image ID from the image table, or {@code null} if none can be found.
*/
private @Nullable MD5Key lookupImageTableByFacing() {
if (!getHasImageTable() || !hasFacing() || getImageTableName() == null) {
return null;
}

LookupTable lookupTable = MapTool.getCampaign().getLookupTableMap().get(getImageTableName());
if (lookupTable == null) return getImageAssetId();
if (lookupTable == null) {
return null;
}

LookupTable.LookupEntry result;
try {
LookupTable.LookupEntry result = lookupTable.getLookup(String.valueOf(getFacing()));
if (result != null) return result.getImageId();

result = lookupTable.getLookup(String.valueOf(getFacing()));
} catch (ParserException p) {
/* do nothing */
return null;
}
if (result == null) {
return null;
}

MD5Key imageId = result.getImageId();
if (imageId == null) {
return null;
}

return imageId;
}

return getImageAssetId();
/**
* Looks up the token's facing in the token's image table.
*
* <p>If the token does not have an image table, or does not have its facing set, or otherwise
* cannot find an image ID from the lookup table, this method returns same result as {@link
* #getImageAssetId()}.
*
* @return The image ID from the image table.
*/
public MD5Key getTokenImageAssetId() {
return Objects.requireNonNullElseGet(lookupImageTableByFacing(), this::getImageAssetId);
}

/**
Expand Down
Loading