diff --git a/src/main/java/net/rptools/lib/image/ImageUtil.java b/src/main/java/net/rptools/lib/image/ImageUtil.java index 514ea73059..0e87cd1e91 100644 --- a/src/main/java/net/rptools/lib/image/ImageUtil.java +++ b/src/main/java/net/rptools/lib/image/ImageUtil.java @@ -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; @@ -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 = diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/renderer/ZoneRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/renderer/ZoneRenderer.java index c48e311438..56f10b5c05 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/renderer/ZoneRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/renderer/ZoneRenderer.java @@ -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; @@ -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"); diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/renderer/tokenRender/TokenRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/renderer/tokenRender/TokenRenderer.java index f1497a8a98..44c03ecaaf 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/renderer/tokenRender/TokenRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/renderer/tokenRender/TokenRenderer.java @@ -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.*; @@ -36,8 +28,6 @@ public class TokenRenderer { private static final Logger log = LogManager.getLogger(TokenRenderer.class); - private static final Map> imageTableMap = - Collections.synchronizedMap(new HashMap<>()); private final RenderHelper renderHelper; private final Zone zone; @@ -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 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( @@ -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 cacheImageTable(String tableName) { - LookupTable lookupTable = MapTool.getCampaign().getLookupTableMap().get(tableName); - if (lookupTable != null) { - BufferedImage broken = ImageManager.BROKEN_IMAGE; - Map tmp = new HashMap<>(); - List 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, String> { - String tableName; - - public CacheTableImagesWorker(String tableName) { - this.tableName = tableName; - } - - @Override - public Map doInBackground() { - return cacheImageTable(tableName); - } - - @Override - protected void done() { - try { - imageTableMap.put(tableName, get()); - } catch (Exception ignore) { - } - } - } } diff --git a/src/main/java/net/rptools/maptool/model/Token.java b/src/main/java/net/rptools/maptool/model/Token.java index 2f05a997b8..8b1c6f5265 100644 --- a/src/main/java/net/rptools/maptool/model/Token.java +++ b/src/main/java/net/rptools/maptool/model/Token.java @@ -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. + * + *

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. + * + *

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); } /**