mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
171 lines
6.1 KiB
Java
171 lines
6.1 KiB
Java
/*
|
|
* Forge: Play Magic: the Gathering.
|
|
* Copyright (C) 2011 Forge Team
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package forge.assets;
|
|
|
|
import com.badlogic.gdx.Gdx;
|
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
|
import com.badlogic.gdx.graphics.Texture;
|
|
import forge.ImageKeys;
|
|
import forge.game.player.IHasIcon;
|
|
import forge.item.InventoryItem;
|
|
import forge.properties.ForgeConstants;
|
|
import forge.util.ImageUtil;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.cache2k.Cache;
|
|
import org.cache2k.Cache2kBuilder;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
/**
|
|
* This class stores ALL card images in a cache with soft values. this means
|
|
* that the images may be collected when they are not needed any more, but will
|
|
* be kept as long as possible.
|
|
* <p/>
|
|
* The keys are the following:
|
|
* <ul>
|
|
* <li>Keys start with the file name, extension is skipped</li>
|
|
* <li>The key without suffix belongs to the unmodified image from the file</li>
|
|
* </ul>
|
|
*
|
|
* @author Forge
|
|
* @version $Id: ImageCache.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
*/
|
|
public class ImageCache {
|
|
// short prefixes to save memory
|
|
|
|
private static final Set<String> missingIconKeys = new HashSet<>();
|
|
private static final Cache<String, Texture> cache = new Cache2kBuilder<String, Texture>() {}
|
|
.name("cache")
|
|
.entryCapacity(500)
|
|
.expireAfterWrite(15, TimeUnit.MINUTES)
|
|
.refreshAhead(true)
|
|
.permitNullValues(true)
|
|
.loader(new ImageLoader())
|
|
.build();
|
|
public static final Texture defaultImage;
|
|
|
|
private static boolean imageLoaded, delayLoadRequested;
|
|
public static void allowSingleLoad() {
|
|
imageLoaded = false; //reset at the beginning of each render
|
|
delayLoadRequested = false;
|
|
}
|
|
|
|
static {
|
|
Texture defImage = null;
|
|
try {
|
|
defImage = new Texture(Gdx.files.absolute(ForgeConstants.NO_CARD_FILE));
|
|
} catch (Exception ex) {
|
|
System.err.println("could not load default card image");
|
|
} finally {
|
|
defaultImage = (null == defImage) ? new Texture(10, 10, Format.RGBA8888) : defImage;
|
|
}
|
|
}
|
|
|
|
public static void clear() {
|
|
cache.clear();
|
|
missingIconKeys.clear();
|
|
}
|
|
|
|
public static Texture getImage(InventoryItem ii) {
|
|
return getImage(ii.getImageKey(false), true, false);
|
|
}
|
|
|
|
public static Texture getImage(InventoryItem ii, Boolean mask) {
|
|
return getImage(ii.getImageKey(false), true, mask);
|
|
}
|
|
|
|
/**
|
|
* retrieve an icon from the cache. returns the current skin's ICO_UNKNOWN if the icon image is not found
|
|
* in the cache and cannot be loaded from disk.
|
|
*/
|
|
public static FImage getIcon(IHasIcon ihi) {
|
|
String imageKey = ihi.getIconImageKey();
|
|
final Texture icon;
|
|
if (missingIconKeys.contains(imageKey) || (icon = getImage(ihi.getIconImageKey(), false)) == null) {
|
|
missingIconKeys.add(imageKey);
|
|
return FSkinImage.UNKNOWN;
|
|
}
|
|
return new FTextureImage(icon);
|
|
}
|
|
|
|
/**
|
|
* This requests the original unscaled image from the cache for the given key.
|
|
* If the image does not exist then it can return a default image if desired.
|
|
* <p>
|
|
* If the requested image is not present in the cache then it attempts to load
|
|
* the image from file (slower) and then add it to the cache for fast future access.
|
|
* </p>
|
|
*/
|
|
public static Texture getImage(String imageKey, boolean useDefaultIfNotFound) {
|
|
return getImage(imageKey, useDefaultIfNotFound, false);
|
|
}
|
|
public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, boolean maskCard) {
|
|
if (StringUtils.isEmpty(imageKey)) {
|
|
return null;
|
|
}
|
|
|
|
boolean altState = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
|
if (altState) {
|
|
imageKey = imageKey.substring(0, imageKey.length() - ImageKeys.BACKFACE_POSTFIX.length());
|
|
}
|
|
if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) {
|
|
imageKey = ImageUtil.getImageKey(ImageUtil.getPaperCardFromImageKey(imageKey), altState, true);
|
|
if (StringUtils.isBlank(imageKey)) {
|
|
return defaultImage;
|
|
}
|
|
}
|
|
|
|
Texture image;
|
|
if (useDefaultIfNotFound) {
|
|
// Load from file and add to cache if not found in cache initially.
|
|
if (maskCard)//if we add pixmap modification here, it will slow performance so we do this on the image loader lol :)...
|
|
imageKey += "#drawroundcorner#";
|
|
image = cache.get(imageKey);
|
|
|
|
if (image != null) { return image; }
|
|
|
|
if (imageLoaded) { //prevent loading more than one image each render for performance
|
|
if (!delayLoadRequested) {
|
|
//ensure images continue to load even if no input is being received
|
|
delayLoadRequested = true;
|
|
Gdx.graphics.requestRendering();
|
|
}
|
|
return null;
|
|
}
|
|
imageLoaded = true;
|
|
}
|
|
|
|
try { image = cache.get(imageKey); }
|
|
catch (final Exception ex) {
|
|
image = null;
|
|
}
|
|
|
|
// No image file exists for the given key so optionally associate with
|
|
// a default "not available" image and add to cache for given key.
|
|
if (image == null) {
|
|
if (useDefaultIfNotFound) {
|
|
image = defaultImage;
|
|
cache.put(imageKey, defaultImage);
|
|
}
|
|
}
|
|
return image;
|
|
}
|
|
}
|