Skip to content

Commit

Permalink
Merge pull request #4192 from cwisniew/feature-addon-images-for-token…
Browse files Browse the repository at this point in the history
…-macros

Add ability to set Token Images, Portraits, and Handouts from addon assets (include copy/create token)
  • Loading branch information
cwisniew authored Jul 3, 2023
2 parents b024db5 + d9a43e4 commit 3334e03
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.rptools.maptool.model.TokenFootprint;
import net.rptools.maptool.model.Zone;
import net.rptools.maptool.model.ZonePoint;
import net.rptools.maptool.util.AssetResolver;
import net.rptools.maptool.util.FunctionUtil;
import net.rptools.parser.Parser;
import net.rptools.parser.ParserException;
Expand Down Expand Up @@ -119,6 +120,10 @@ private String createToken(MapToolVariableResolver resolver, JsonObject vals)
throw new ParserException(I18N.getText("macro.function.tokenCopyDelete.noImage"));
}
String tokenImage = vals.get("tokenImage").getAsString();
var asset = new AssetResolver().getAssetKey(tokenImage);
if (asset.isPresent()) {
tokenImage = asset.get().toString();
}

Zone zone = MapTool.getFrame().getCurrentZoneRenderer().getZone();
List<Token> allTokens = zone.getTokens();
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/net/rptools/maptool/client/functions/TokenImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@
import java.awt.Image;
import java.math.BigDecimal;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.rptools.lib.MD5Key;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.ui.zone.ZoneRenderer;
import net.rptools.maptool.language.I18N;
import net.rptools.maptool.model.Asset;
import net.rptools.maptool.model.AssetManager;
import net.rptools.maptool.model.Token;
import net.rptools.maptool.util.AssetResolver;
import net.rptools.maptool.util.FunctionUtil;
import net.rptools.maptool.util.ImageManager;
import net.rptools.parser.Parser;
Expand All @@ -39,8 +38,6 @@ public class TokenImage extends AbstractFunction {
/** Singleton instance. */
private static final TokenImage instance = new TokenImage();

private static final Pattern assetRE = Pattern.compile("asset://([^-]+)");

enum imageType {
TOKEN_IMAGE(0),
TOKEN_PORTRAIT(1),
Expand Down Expand Up @@ -260,23 +257,26 @@ private String typeOf(Object ob) {
* @throws ParserException if assetName not found or assetName doesn't
*/
public static MD5Key getMD5Key(String assetName, String functionName) throws ParserException {
Matcher m = assetRE.matcher(assetName);

String assetId;
if (m.matches()) {
assetId = m.group(1);
} else if (assetName.toLowerCase().startsWith("image:")) {
String assetId = null;
if (assetName.toLowerCase().startsWith("image:")) {
Token imageToken = findImageToken(assetName, functionName);
if (imageToken == null) {
throw new ParserException(
I18N.getText("macro.function.general.unknownToken", functionName, assetName));
}
assetId = imageToken.getImageAssetId().toString();
} else {
var assetKey = new AssetResolver().getAssetKey(assetName);
if (assetKey.isPresent()) {
assetId = assetKey.get().toString();
}
}
if (assetId == null) {
throw new ParserException(
I18N.getText("macro.function.general.argumentTypeInvalid", functionName, 1, assetName));
} else {
return new MD5Key(assetId);
}
return new MD5Key(assetId);
}

private static void setImage(Token token, String assetName) throws ParserException {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/net/rptools/maptool/model/library/Library.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import net.rptools.lib.MD5Key;
import net.rptools.maptool.client.MapToolMacroContext;
import net.rptools.maptool.model.Asset;
import net.rptools.maptool.model.Token;
Expand Down Expand Up @@ -48,6 +49,23 @@ public interface Library {
*/
CompletableFuture<Boolean> locationExists(URL location) throws IOException;

/**
* Checks to see if the specified location is an Asset.
*
* @param location the location to check.
* @return {@code true} if the location is an asset, otherwise {@code false}.
*/
CompletableFuture<Boolean> isAsset(URL location);

/**
* Returns the asset at the specified location. This will only return a value if {@link
* #isAsset(URL)} returns {@code true}.
*
* @param location the location to get the asset for.
* @return the asset at the specified location.
*/
CompletableFuture<Optional<MD5Key>> getAssetKey(URL location);

/**
* Reads the location as a string.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,20 @@ public CompletableFuture<Boolean> locationExists(URL location) throws IOExceptio
}
}

@Override
public CompletableFuture<Boolean> isAsset(URL location) {
return CompletableFuture.completedFuture(getURILocation(location) != null);
}

@Override
public CompletableFuture<Optional<MD5Key>> getAssetKey(URL location) {
var AssetInfo = getURILocation(location);
if (AssetInfo == null) {
return CompletableFuture.completedFuture(Optional.empty());
}
return CompletableFuture.completedFuture(Optional.of(AssetInfo.getValue0()));
}

@Override
public CompletableFuture<String> readAsString(URL location) throws IOException {
if (allowsUriAccess) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import net.rptools.lib.MD5Key;
import net.rptools.maptool.client.AppConstants;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.MapToolMacroContext;
Expand Down Expand Up @@ -109,6 +110,16 @@ public CompletableFuture<Boolean> locationExists(URL location) throws IOExceptio
return CompletableFuture.completedFuture(resourcesMap.containsKey(key));
}

@Override
public CompletableFuture<Boolean> isAsset(URL location) {
return CompletableFuture.completedFuture(false);
}

@Override
public CompletableFuture<Optional<MD5Key>> getAssetKey(URL location) {
return CompletableFuture.completedFuture(Optional.empty());
}

@Override
public CompletableFuture<String> readAsString(URL location) throws IOException {
var path = location.getPath().replaceFirst("^/", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream;
import net.rptools.lib.MD5Key;
import net.rptools.maptool.client.MapTool;
import net.rptools.maptool.client.MapToolMacroContext;
import net.rptools.maptool.language.I18N;
Expand Down Expand Up @@ -182,6 +183,16 @@ public CompletableFuture<Boolean> locationExists(URL location) throws IOExceptio
});
}

@Override
public CompletableFuture<Boolean> isAsset(URL location) {
return CompletableFuture.completedFuture(Boolean.FALSE);
}

@Override
public CompletableFuture<Optional<MD5Key>> getAssetKey(URL location) {
return CompletableFuture.completedFuture(Optional.empty());
}

@Override
public CompletableFuture<String> readAsString(URL location) throws IOException {
final var loc = Location.getLocation(location);
Expand Down
90 changes: 90 additions & 0 deletions src/main/java/net/rptools/maptool/util/AssetResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* This software Copyright by the RPTools.net development team, and
* licensed under the Affero GPL Version 3 or, at your option, any later
* version.
*
* MapTool Source Code is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public
* License * along with this source Code. If not, please visit
* <http://www.gnu.org/licenses/> and specifically the Affero license
* text at <http://www.gnu.org/licenses/agpl.html>.
*/
package net.rptools.maptool.util;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import net.rptools.lib.MD5Key;
import net.rptools.maptool.model.library.Library;
import net.rptools.maptool.model.library.LibraryManager;

/**
* Utility Class to aid in resolving asset keys for images. It will resolve the asset key for the
* following: lib:// URI asset:// URI image:token MD5 hash (as String)
*/
public class AssetResolver {

/**
* Returns the asset key for the specified URL.
*
* @param url the URL to get the asset key for.
* @return the MD5key of the asset at the specified URL.
*/
public Optional<MD5Key> getAssetKey(URL url) {
Optional<Library> lib = null;
try {
lib = new LibraryManager().getLibrary(url).get();
if (lib.isPresent()) {
var asset = lib.get().getAssetKey(url).get();
if (asset.isPresent()) {
String key = asset.get().toString();
return Optional.of(new MD5Key(key));
}
}
} catch (InterruptedException | ExecutionException e) {
return Optional.empty();
}
return Optional.empty();
}

/**
* Returns the asset key for the specified location. Locations can be: lib:// URI asset:// URI
* image:token MD5 hash (as String)
*
* @param location the location to get the asset key for.
* @return the MD5key of the asset at the specified location.
*/
public Optional<MD5Key> getAssetKey(String location) {
if (location.startsWith("asset://")) {
return getAssetKey(location.substring(8));
} else if (location.toLowerCase().startsWith("lib:")) {
try {
return getAssetKey(new URI(location));
} catch (URISyntaxException e) {
return Optional.empty();
}
} else {
return Optional.of(new MD5Key(location));
}
}

/**
* Returns the asset key for the specified URI.
*
* @param uri the URI to get the asset key for.
* @return the MD5key of the asset at the specified URI.
*/
public Optional<MD5Key> getAssetKey(URI uri) {
try {
return getAssetKey(uri.toURL());
} catch (MalformedURLException e) {
return Optional.empty();
}
}
}

0 comments on commit 3334e03

Please sign in to comment.