mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 10:18:01 +00:00
Various fixes for Mobile
Optimize ImageFetcher and ImageCache on fetching and disposing textures. Fix Quest Tournament crash when using a theme without sprite avatars. Fix NPE on HDButtons.
This commit is contained in:
@@ -27,8 +27,7 @@ public abstract class CachedCardImage implements ImageFetcher.Callback {
|
||||
}
|
||||
|
||||
public void fetch() {
|
||||
Texture image = ImageCache.getImage(key, false);
|
||||
if (image == null) {
|
||||
if (!ImageCache.imageKeyFileExists(key)) {
|
||||
fetcher.fetchImage(key, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class Forge implements ApplicationListener {
|
||||
public static boolean hdbuttons = false;
|
||||
public static boolean hdstart = false;
|
||||
public static boolean isPortraitMode = false;
|
||||
public static boolean gameInProgress = false;
|
||||
|
||||
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation) {
|
||||
if (GuiBase.getInterface() == null) {
|
||||
@@ -159,12 +160,12 @@ public class Forge implements ApplicationListener {
|
||||
private void preloadExtendedArt() {
|
||||
if (!enablePreloadExtendedArt)
|
||||
return;
|
||||
List<String> BorderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE);
|
||||
if(BorderlessCardlistkeys.isEmpty())
|
||||
List<String> borderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE);
|
||||
if(borderlessCardlistkeys.isEmpty())
|
||||
return;
|
||||
List<String> filteredkeys = new ArrayList<>();
|
||||
for (String cardname : BorderlessCardlistkeys){
|
||||
File image = new File(ForgeConstants.CACHE_CARD_PICS_DIR+"/"+cardname+".jpg");
|
||||
for (String cardname : borderlessCardlistkeys){
|
||||
File image = new File(ForgeConstants.CACHE_CARD_PICS_DIR+ForgeConstants.PATH_SEPARATOR+cardname+".jpg");
|
||||
if (image.exists())
|
||||
filteredkeys.add(cardname);
|
||||
}
|
||||
@@ -393,18 +394,14 @@ public class Forge implements ApplicationListener {
|
||||
}
|
||||
|
||||
private static void setCurrentScreen(FScreen screen0) {
|
||||
String toNewScreen = screen0 != null ? screen0.toString() : "";
|
||||
String previousScreen = currentScreen != null ? currentScreen.toString() : "";
|
||||
|
||||
gameInProgress = toNewScreen.toLowerCase().contains("match") || previousScreen.toLowerCase().contains("match");
|
||||
|
||||
try {
|
||||
endKeyInput(); //end key input before switching screens
|
||||
ForgeAnimation.endAll(); //end all active animations before switching screens
|
||||
try {
|
||||
ImageCache.disposeTexture();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// FIXME: This isn't supposed to be necessary, but disposeTexture crashes e.g. in Quest Tournaments on mobile, needs proper fixing.
|
||||
System.err.println("Warning: caught an exception while trying to call ImageCache.disposeTexture() in setCurrentScreen.");
|
||||
}
|
||||
|
||||
currentScreen = screen0;
|
||||
currentScreen.setSize(screenWidth, screenHeight);
|
||||
currentScreen.onActivate();
|
||||
|
||||
@@ -275,6 +275,20 @@ public class FSkin {
|
||||
}
|
||||
}
|
||||
pxPreferredAvatars.dispose();
|
||||
} else if (!FSkin.preferredName.isEmpty()){
|
||||
//workaround bug crash fix if missing sprite avatar on preferred theme for quest tournament...
|
||||
//i really don't know why it needs to populate the avatars twice.... needs investigation
|
||||
final int pw = pxDefaultAvatars.getWidth();
|
||||
final int ph = pxDefaultAvatars.getHeight();
|
||||
|
||||
for (int j = 0; j < ph; j += 100) {
|
||||
for (int i = 0; i < pw; i += 100) {
|
||||
if (i == 0 && j == 0) { continue; }
|
||||
pxTest = new Color(pxDefaultAvatars.getPixel(i + 50, j + 50));
|
||||
if (pxTest.a == 0) { continue; }
|
||||
FSkin.avatars.put(counter++, new TextureRegion(txDefaultAvatars, i, j, 100, 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int aw = pxDefaultAvatars.getWidth();
|
||||
|
||||
@@ -30,20 +30,23 @@ import com.google.common.cache.RemovalNotification;
|
||||
import forge.ImageKeys;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRenderer;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.IHasIcon;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.ImageUtil;
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -73,6 +76,7 @@ public class ImageCache {
|
||||
if(removalNotification.wasEvicted()||removalNotification.getCause() == RemovalCause.EXPIRED) {
|
||||
removalNotification.getValue().dispose();
|
||||
}
|
||||
CardRenderer.clearcardArtCache();
|
||||
}
|
||||
})
|
||||
.build(new ImageLoader());
|
||||
@@ -104,15 +108,6 @@ public class ImageCache {
|
||||
missingIconKeys.clear();
|
||||
}
|
||||
|
||||
public static void disposeTexture(){
|
||||
for (Texture t: cache.asMap().values()) {
|
||||
if (!t.toString().contains("pics/icons")) //fixes quest avatars black texture. todo: filter textures that are safe to dispose...
|
||||
t.dispose();
|
||||
}
|
||||
CardRenderer.clearcardArtCache();
|
||||
clear();
|
||||
}
|
||||
|
||||
public static Texture getImage(InventoryItem ii) {
|
||||
return getImage(ii.getImageKey(false), true);
|
||||
}
|
||||
@@ -131,6 +126,39 @@ public class ImageCache {
|
||||
return new FTextureImage(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks the card image exists from the disk.
|
||||
*/
|
||||
public static boolean imageKeyFileExists(String imageKey) {
|
||||
if (StringUtils.isEmpty(imageKey))
|
||||
return false;
|
||||
|
||||
if (imageKey.length() < 2)
|
||||
return false;
|
||||
|
||||
final String prefix = imageKey.substring(0, 2);
|
||||
|
||||
if (prefix.equals(ImageKeys.CARD_PREFIX)) {
|
||||
PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(imageKey);
|
||||
if (paperCard == null)
|
||||
return false;
|
||||
|
||||
final boolean backFace = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
||||
final String cardfilename = ImageUtil.getImageKey(paperCard, backFace, true);
|
||||
if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + cardfilename + ".jpg").exists())
|
||||
if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + cardfilename + ".png").exists())
|
||||
if (!new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + TextUtil.fastReplace(cardfilename,".full", ".fullborder") + ".jpg").exists())
|
||||
return false;
|
||||
} else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) {
|
||||
final String tokenfilename = imageKey.substring(2) + ".jpg";
|
||||
|
||||
if (!new File(ForgeConstants.CACHE_TOKEN_PICS_DIR, tokenfilename).exists())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -191,12 +219,20 @@ public class ImageCache {
|
||||
return image;
|
||||
}
|
||||
public static void preloadCache(Iterable<String> keys) {
|
||||
try {
|
||||
cache.getAll(keys);
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
for (String imageKey : keys){
|
||||
if(getImage(imageKey, false) == null)
|
||||
System.err.println("could not load card image:"+imageKey);
|
||||
}
|
||||
}
|
||||
public static void preloadCache(Deck deck) {
|
||||
if(deck == null)
|
||||
return;
|
||||
for (PaperCard p : deck.getAllCardsInASinglePool().toFlatList()) {
|
||||
if (getImage(p.getImageKey(false),false) == null)
|
||||
System.err.println("could not load card image:"+p.toString());
|
||||
}
|
||||
|
||||
}
|
||||
public static TextureRegion croppedBorderImage(Texture image) {
|
||||
if (!image.toString().contains(".fullborder."))
|
||||
return new TextureRegion(image);
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.deck;
|
||||
import forge.FThreads;
|
||||
import forge.Forge;
|
||||
import forge.GuiBase;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.deck.FDeckEditor.EditorType;
|
||||
import forge.deck.io.DeckPreferences;
|
||||
import forge.error.BugReporter;
|
||||
@@ -472,6 +473,8 @@ public class FDeckChooser extends FScreen {
|
||||
break;
|
||||
}
|
||||
needRefreshOnActivate = true;
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(deck.getDeck());
|
||||
Forge.openScreen(new FDeckEditor(editorType, deck, true));
|
||||
}
|
||||
|
||||
@@ -1147,7 +1150,7 @@ public class FDeckChooser extends FScreen {
|
||||
});
|
||||
}
|
||||
});
|
||||
chooser.show(null, true);
|
||||
chooser.show(null, false); /*setting selectMax to true will select all available option*/
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import forge.assets.FImage;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.assets.FTextureRegionImage;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.CardManager;
|
||||
import forge.itemmanager.ItemManagerConfig;
|
||||
@@ -112,6 +113,9 @@ public class FDeckViewer extends FScreen {
|
||||
public static void show(final Deck deck0) {
|
||||
if (deck0 == null) { return; }
|
||||
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(deck0);
|
||||
|
||||
deckViewer = new FDeckViewer(deck0);
|
||||
deckViewer.setRotate180(MatchController.getView() != null && MatchController.getView().isTopHumanPlayerActive());
|
||||
Forge.openScreen(deckViewer);
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
@@ -625,6 +626,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView {
|
||||
if (isNewPanel) {
|
||||
panel.setVisible(true);
|
||||
}
|
||||
if (Forge.gameInProgress) {
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(decks[i]);
|
||||
}
|
||||
Gdx.graphics.requestRendering();
|
||||
}
|
||||
else if (hasPanel) {
|
||||
|
||||
@@ -445,7 +445,6 @@ public class MatchController extends AbstractGuiGame {
|
||||
@Override
|
||||
public void afterGameEnd() {
|
||||
Forge.back();
|
||||
ImageCache.disposeTexture();
|
||||
//view = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package forge.screens.match.winlose;
|
||||
|
||||
import forge.Forge;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.game.GameView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.screens.match.MatchController;
|
||||
@@ -85,7 +84,6 @@ public class ControlWinLose {
|
||||
view.hide();
|
||||
if(humancount == 0) {
|
||||
Forge.back();
|
||||
ImageCache.disposeTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import forge.Graphics;
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.card.CardFaceSymbols;
|
||||
import forge.card.CardRenderer;
|
||||
import forge.card.ColorSet;
|
||||
@@ -76,6 +77,8 @@ public class ConquestCommandersScreen extends FScreen {
|
||||
public void handleEvent(FEvent e) {
|
||||
final ConquestCommander commander = lstCommanders.getSelectedItem();
|
||||
if (commander != null) {
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(commander.getDeck());
|
||||
preventRefreshOnActivate = true; //refresh not needed since deck changes won't affect commander display
|
||||
Forge.openScreen(new ConquestDeckEditor(commander));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Align;
|
||||
import forge.FThreads;
|
||||
import forge.Forge;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.deck.FDeckChooser;
|
||||
@@ -152,6 +153,9 @@ public class QuestDecksScreen extends FScreen {
|
||||
final DeckProxy deck = lstDecks.getSelectedItem();
|
||||
if (deck == null) { return; }
|
||||
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(deck.getDeck());
|
||||
|
||||
needRefreshOnActivate = true;
|
||||
Forge.openScreen(new QuestDeckEditor(deck));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import forge.GuiBase;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckGroup;
|
||||
@@ -241,6 +242,8 @@ public class QuestTournamentsScreen extends QuestLaunchScreen implements IQuestT
|
||||
public void editDeck(boolean isExistingDeck) {
|
||||
Deck deck = getDeck();
|
||||
if (deck != null) {
|
||||
/*preload deck to cache*/
|
||||
ImageCache.preloadCache(deck);
|
||||
if (isExistingDeck) {
|
||||
Forge.openScreen(new QuestDraftDeckEditor(deck.getName()));
|
||||
}
|
||||
|
||||
@@ -60,16 +60,9 @@ public class FButton extends FDisplayObject implements IButton {
|
||||
}
|
||||
|
||||
private void resetImg() {
|
||||
if (hdbuttonskin())
|
||||
{
|
||||
imgL = FSkinImage.HDBTN_UP_LEFT;
|
||||
imgM = FSkinImage.HDBTN_UP_CENTER;
|
||||
imgR = FSkinImage.HDBTN_UP_RIGHT;
|
||||
} else {
|
||||
imgL = FSkinImage.BTN_UP_LEFT;
|
||||
imgM = FSkinImage.BTN_UP_CENTER;
|
||||
imgR = FSkinImage.BTN_UP_RIGHT;
|
||||
}
|
||||
imgL = (hdbuttonskin() && FSkinImage.HDBTN_UP_LEFT != null) ? FSkinImage.HDBTN_UP_LEFT : FSkinImage.BTN_UP_LEFT;
|
||||
imgM = (hdbuttonskin() && FSkinImage.HDBTN_UP_CENTER != null) ? FSkinImage.HDBTN_UP_CENTER : FSkinImage.BTN_UP_CENTER;
|
||||
imgR = (hdbuttonskin() && FSkinImage.HDBTN_UP_RIGHT != null) ? FSkinImage.HDBTN_UP_RIGHT : FSkinImage.BTN_UP_RIGHT;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
@@ -95,16 +88,9 @@ public class FButton extends FDisplayObject implements IButton {
|
||||
resetImg();
|
||||
}
|
||||
else {
|
||||
if (hdbuttonskin())
|
||||
{
|
||||
imgL = FSkinImage.HDBTN_DISABLED_LEFT;
|
||||
imgM = FSkinImage.HDBTN_DISABLED_CENTER;
|
||||
imgR = FSkinImage.HDBTN_DISABLED_RIGHT;
|
||||
} else {
|
||||
imgL = FSkinImage.BTN_DISABLED_LEFT;
|
||||
imgM = FSkinImage.BTN_DISABLED_CENTER;
|
||||
imgR = FSkinImage.BTN_DISABLED_RIGHT;
|
||||
}
|
||||
imgL = (hdbuttonskin() && FSkinImage.HDBTN_UP_LEFT != null) ? FSkinImage.HDBTN_UP_LEFT : FSkinImage.BTN_UP_LEFT;
|
||||
imgM = (hdbuttonskin() && FSkinImage.HDBTN_UP_CENTER != null) ? FSkinImage.HDBTN_UP_CENTER : FSkinImage.BTN_UP_CENTER;
|
||||
imgR = (hdbuttonskin() && FSkinImage.HDBTN_UP_RIGHT != null) ? FSkinImage.HDBTN_UP_RIGHT : FSkinImage.BTN_UP_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,31 +107,17 @@ public class FButton extends FDisplayObject implements IButton {
|
||||
toggled = b0;
|
||||
|
||||
if (toggled) {
|
||||
if (hdbuttonskin())
|
||||
{
|
||||
imgL = FSkinImage.HDBTN_TOGGLE_LEFT;
|
||||
imgM = FSkinImage.HDBTN_TOGGLE_CENTER;
|
||||
imgR = FSkinImage.HDBTN_TOGGLE_RIGHT;
|
||||
} else {
|
||||
imgL = FSkinImage.BTN_TOGGLE_LEFT;
|
||||
imgM = FSkinImage.BTN_TOGGLE_CENTER;
|
||||
imgR = FSkinImage.BTN_TOGGLE_RIGHT;
|
||||
}
|
||||
imgL = (hdbuttonskin() && FSkinImage.HDBTN_UP_LEFT != null) ? FSkinImage.HDBTN_UP_LEFT : FSkinImage.BTN_UP_LEFT;
|
||||
imgM = (hdbuttonskin() && FSkinImage.HDBTN_UP_CENTER != null) ? FSkinImage.HDBTN_UP_CENTER : FSkinImage.BTN_UP_CENTER;
|
||||
imgR = (hdbuttonskin() && FSkinImage.HDBTN_UP_RIGHT != null) ? FSkinImage.HDBTN_UP_RIGHT : FSkinImage.BTN_UP_RIGHT;
|
||||
}
|
||||
else if (isEnabled()) {
|
||||
resetImg();
|
||||
}
|
||||
else {
|
||||
if (hdbuttonskin())
|
||||
{
|
||||
imgL = FSkinImage.HDBTN_DISABLED_LEFT;
|
||||
imgM = FSkinImage.HDBTN_DISABLED_CENTER;
|
||||
imgR = FSkinImage.HDBTN_DISABLED_RIGHT;
|
||||
} else {
|
||||
imgL = FSkinImage.BTN_DISABLED_LEFT;
|
||||
imgM = FSkinImage.BTN_DISABLED_CENTER;
|
||||
imgR = FSkinImage.BTN_DISABLED_RIGHT;
|
||||
}
|
||||
imgL = (hdbuttonskin() && FSkinImage.HDBTN_UP_LEFT != null) ? FSkinImage.HDBTN_UP_LEFT : FSkinImage.BTN_UP_LEFT;
|
||||
imgM = (hdbuttonskin() && FSkinImage.HDBTN_UP_CENTER != null) ? FSkinImage.HDBTN_UP_CENTER : FSkinImage.BTN_UP_CENTER;
|
||||
imgR = (hdbuttonskin() && FSkinImage.HDBTN_UP_RIGHT != null) ? FSkinImage.HDBTN_UP_RIGHT : FSkinImage.BTN_UP_RIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,16 +143,9 @@ public class FButton extends FDisplayObject implements IButton {
|
||||
public final boolean press(float x, float y) {
|
||||
if (isToggled()) { return true; }
|
||||
|
||||
if (hdbuttonskin())
|
||||
{
|
||||
imgL = FSkinImage.HDBTN_DOWN_LEFT;
|
||||
imgM = FSkinImage.HDBTN_DOWN_CENTER;
|
||||
imgR = FSkinImage.HDBTN_DOWN_RIGHT;
|
||||
} else {
|
||||
imgL = FSkinImage.BTN_DOWN_LEFT;
|
||||
imgM = FSkinImage.BTN_DOWN_CENTER;
|
||||
imgR = FSkinImage.BTN_DOWN_RIGHT;
|
||||
}
|
||||
imgL = (hdbuttonskin() && FSkinImage.HDBTN_UP_LEFT != null) ? FSkinImage.HDBTN_UP_LEFT : FSkinImage.BTN_UP_LEFT;
|
||||
imgM = (hdbuttonskin() && FSkinImage.HDBTN_UP_CENTER != null) ? FSkinImage.HDBTN_UP_CENTER : FSkinImage.BTN_UP_CENTER;
|
||||
imgR = (hdbuttonskin() && FSkinImage.HDBTN_UP_RIGHT != null) ? FSkinImage.HDBTN_UP_RIGHT : FSkinImage.BTN_UP_RIGHT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user