diff --git a/forge-gui-mobile/src/forge/CachedCardImage.java b/forge-gui-mobile/src/forge/CachedCardImage.java index d10b1dea577..29ad190f341 100644 --- a/forge-gui-mobile/src/forge/CachedCardImage.java +++ b/forge-gui-mobile/src/forge/CachedCardImage.java @@ -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); } } diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 4f3bf3c0acd..cde6160e492 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -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 BorderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); - if(BorderlessCardlistkeys.isEmpty()) + List borderlessCardlistkeys = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); + if(borderlessCardlistkeys.isEmpty()) return; List 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(); diff --git a/forge-gui-mobile/src/forge/assets/FSkin.java b/forge-gui-mobile/src/forge/assets/FSkin.java index ae9c6971bc8..9f716df533a 100644 --- a/forge-gui-mobile/src/forge/assets/FSkin.java +++ b/forge-gui-mobile/src/forge/assets/FSkin.java @@ -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(); diff --git a/forge-gui-mobile/src/forge/assets/ImageCache.java b/forge-gui-mobile/src/forge/assets/ImageCache.java index e8c17306b0f..83ca1991956 100644 --- a/forge-gui-mobile/src/forge/assets/ImageCache.java +++ b/forge-gui-mobile/src/forge/assets/ImageCache.java @@ -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 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); diff --git a/forge-gui-mobile/src/forge/deck/FDeckChooser.java b/forge-gui-mobile/src/forge/deck/FDeckChooser.java index ccbe174bc3b..36378199774 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckChooser.java +++ b/forge-gui-mobile/src/forge/deck/FDeckChooser.java @@ -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*/ } }); } diff --git a/forge-gui-mobile/src/forge/deck/FDeckViewer.java b/forge-gui-mobile/src/forge/deck/FDeckViewer.java index c363cec6ebd..51e838b8b96 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckViewer.java +++ b/forge-gui-mobile/src/forge/deck/FDeckViewer.java @@ -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); diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 529df5cde9e..32abd93cbe5 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -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) { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 6e0d269c725..ec7bf10906a 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -445,7 +445,6 @@ public class MatchController extends AbstractGuiGame { @Override public void afterGameEnd() { Forge.back(); - ImageCache.disposeTexture(); //view = null; } diff --git a/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java b/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java index 2c0d0e8e413..9efa454a3d5 100644 --- a/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java +++ b/forge-gui-mobile/src/forge/screens/match/winlose/ControlWinLose.java @@ -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(); } } diff --git a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java index 5cee692ef29..81b113fb80d 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java @@ -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)); } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java index 5e2a0bc3344..902bd7eafe7 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java @@ -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)); } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java index c1e22b1aab5..7d8e2507154 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java @@ -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())); } diff --git a/forge-gui-mobile/src/forge/toolbox/FButton.java b/forge-gui-mobile/src/forge/toolbox/FButton.java index 33b64b7b4fc..63139276219 100644 --- a/forge-gui-mobile/src/forge/toolbox/FButton.java +++ b/forge-gui-mobile/src/forge/toolbox/FButton.java @@ -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; }