From 6fb600e6fbbe2a9a882424941d691c79df1870d2 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 27 Oct 2024 08:52:58 +0800 Subject: [PATCH 1/4] refactor mobile ImageCache, ImageView, FChoiceList removed method to generate borderless card since we used shader as default method Texture, TextureRegion and other LibGDX objects that are disposable should be nonstatic show Morph image on FChoiceList --- .../main/java/forge/game/keyword/Keyword.java | 4 + .../src/forge/CachedCardImage.java | 6 +- forge-gui-mobile/src/forge/Forge.java | 12 +- forge-gui-mobile/src/forge/Graphics.java | 4 +- forge-gui-mobile/src/forge/GuiMobile.java | 14 +- .../forge/adventure/scene/RewardScene.java | 4 +- .../forge/adventure/scene/SettingsScene.java | 3 +- .../src/forge/adventure/util/RewardActor.java | 34 +- forge-gui-mobile/src/forge/assets/Assets.java | 24 +- .../src/forge/assets/ImageCache.java | 269 ++++++-------- .../src/forge/card/CardAvatarImage.java | 2 +- .../src/forge/card/CardImage.java | 12 +- .../src/forge/card/CardImageRenderer.java | 34 +- .../src/forge/card/CardRenderer.java | 61 ++-- .../src/forge/deck/FDeckChooser.java | 2 +- .../src/forge/deck/FDeckViewer.java | 2 +- .../forge/itemmanager/SpellShopManager.java | 4 +- .../forge/itemmanager/views/ImageView.java | 336 +++++++++++------- .../screens/constructed/LobbyScreen.java | 2 +- .../forge/screens/match/MatchController.java | 4 +- .../ConquestCommandersScreen.java | 2 +- .../planarconquest/ConquestRewardDialog.java | 2 +- .../forge/screens/quest/QuestDecksScreen.java | 2 +- .../forge/screens/quest/QuestEventPanel.java | 2 +- .../screens/quest/QuestTournamentsScreen.java | 2 +- .../forge/screens/settings/SettingsPage.java | 5 +- .../src/forge/toolbox/FChoiceList.java | 144 ++++++-- 27 files changed, 534 insertions(+), 458 deletions(-) diff --git a/forge-game/src/main/java/forge/game/keyword/Keyword.java b/forge-game/src/main/java/forge/game/keyword/Keyword.java index 38d34a76797..85e40819642 100644 --- a/forge-game/src/main/java/forge/game/keyword/Keyword.java +++ b/forge-game/src/main/java/forge/game/keyword/Keyword.java @@ -328,6 +328,10 @@ public static Set setValueOf(String value) { return result; } + public String getReminderText() { + return reminderText; + } + public boolean isMultipleRedundant() { return isMultipleRedundant; } diff --git a/forge-gui-mobile/src/forge/CachedCardImage.java b/forge-gui-mobile/src/forge/CachedCardImage.java index 51ae26f81cc..33b26696341 100644 --- a/forge-gui-mobile/src/forge/CachedCardImage.java +++ b/forge-gui-mobile/src/forge/CachedCardImage.java @@ -29,17 +29,17 @@ public CachedCardImage(String key) { } public void fetch() { - if (!ImageCache.imageKeyFileExists(key)) { + if (!ImageCache.getInstance().imageKeyFileExists(key)) { fetcher.fetchImage(key, this); } } public Texture getImage() { - return ImageCache.getImage(key, true); + return ImageCache.getInstance().getImage(key, true); } public Texture getImage(String mykey) { - return ImageCache.getImage(mykey, true); + return ImageCache.getInstance().getImage(mykey, true); } public abstract void onImageFetched(); diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 73502b18914..e313ce36b4d 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -302,7 +302,7 @@ private void preloadExtendedArt() { filteredkeys.add(cardname); } if (!filteredkeys.isEmpty()) - ImageCache.preloadCache(filteredkeys); + ImageCache.getInstance().preloadCache(filteredkeys); } private void preloadBoosterDrafts() { @@ -759,7 +759,7 @@ public static void clearCurrentScreen() { public static void switchToClassic() { setTransitionScreen(new TransitionScreen(() -> { - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); isMobileAdventureMode = false; GuiBase.setIsAdventureMode(false); setCursor(FSkin.getCursor().get(0), "0"); @@ -773,7 +773,7 @@ public static void switchToClassic() { public static void switchToAdventure() { setTransitionScreen(new TransitionScreen(() -> { - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); clearCurrentScreen(); clearTransitionScreen(); openAdventure(); @@ -842,17 +842,17 @@ private static void setCurrentScreen(FScreen screen0) { BugReporter.reportException(ex); } finally { if (dispose) - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); } } @Override public void render() { if (showFPS) - frameRate.update(ImageCache.counter, getAssets().manager().getMemoryInMegabytes()); + getFrameRate().update(ImageCache.getInstance().counter, getAssets().manager().getMemoryInMegabytes()); try { - ImageCache.allowSingleLoad(); + ImageCache.getInstance().allowSingleLoad(); ForgeAnimation.advanceAll(); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear the screen. diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index bc6b01fe8ec..bb5f7303693 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -916,7 +916,7 @@ public void drawCardRoundRect(Texture image, TextureRegion damage_overlay, float batch.end(); shaderRoundedRect.bind(); shaderRoundedRect.setUniformf("u_resolution", image.getWidth(), image.getHeight()); - shaderRoundedRect.setUniformf("edge_radius", (image.getHeight() / image.getWidth()) * ImageCache.getRadius(image)); + shaderRoundedRect.setUniformf("edge_radius", (float)(image.getHeight() / image.getWidth()) * ImageCache.getInstance().getRadius(image)); shaderRoundedRect.setUniformf("u_gray", drawGray ? 0.8f : 0f); batch.setShader(shaderRoundedRect); batch.begin(); @@ -936,7 +936,7 @@ public void drawCardRoundRect(Texture image, float x, float y, float w, float h, batch.end(); shaderRoundedRect.bind(); shaderRoundedRect.setUniformf("u_resolution", image.getWidth(), image.getHeight()); - shaderRoundedRect.setUniformf("edge_radius", (image.getHeight() / image.getWidth()) * ImageCache.getRadius(image)); + shaderRoundedRect.setUniformf("edge_radius", (float)(image.getHeight() / image.getWidth()) * ImageCache.getInstance().getRadius(image)); shaderRoundedRect.setUniformf("u_gray", 0f); batch.setShader(shaderRoundedRect); batch.begin(); diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java index 1191fc360ba..8856d133db8 100644 --- a/forge-gui-mobile/src/forge/GuiMobile.java +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -35,8 +35,8 @@ public class GuiMobile implements IGuiBase { private final String assetsDir; - private ImageFetcher imageFetcher = new LibGDXImageFetcher(); - private List integerChoices = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + private final ImageFetcher imageFetcher = new LibGDXImageFetcher(); + private final List integerChoices = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); public GuiMobile(final String assetsDir0) { assetsDir = assetsDir0; @@ -44,7 +44,7 @@ public GuiMobile(final String assetsDir0) { @Override public boolean isRunningOnDesktop() { - return Gdx.app==null ? true : Gdx.app.getType() == ApplicationType.Desktop; + return Gdx.app == null || Gdx.app.getType() == ApplicationType.Desktop; } @Override @@ -136,11 +136,11 @@ protected void draw(final Graphics g, final float w, final float h) { if (FileUtil.doesFileExist(overlayFilename)) { try { final Texture overlay = Forge.getAssets().getTexture(Gdx.files.absolute(overlayFilename)); - g.drawImage(overlay, (background.getWidth() - overlay.getWidth()) / 2, (background.getHeight() - overlay.getHeight()) / 2, overlay.getWidth(), overlay.getHeight()); - } catch (final Exception e) { + g.drawImage(overlay, (background.getWidth() - overlay.getWidth()) / 2f, (background.getHeight() - overlay.getHeight()) / 2f, overlay.getWidth(), overlay.getHeight()); + } catch (Exception ignored) { } } else if (paperCard != null) { - Texture cardImage = ImageCache.getImage(paperCard.getCardImageKey(), false); + Texture cardImage = ImageCache.getInstance().getImage(paperCard.getCardImageKey(), false); if (cardImage != null) g.drawCardRoundRect(cardImage, null, (background.getWidth() - cardImageWidth) / 2, (background.getHeight() - cardImageHeight) / 3.8f, cardImageWidth, cardImageHeight, false, false); } @@ -306,7 +306,7 @@ public void startAltSoundSystem(final String filename, final boolean isSynchroni @Override public void clearImageCache() { - ImageCache.clear(); + ImageCache.getInstance().clear(); ImageKeys.clearMissingCards(); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java index 278e59faeba..f85a12c833b 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java @@ -133,7 +133,7 @@ public void quitScene() { } } //save RAM - ImageCache.unloadCardTextures(true); + ImageCache.getInstance().unloadCardTextures(true); Forge.advFreezePlayerControls = false; if (this.collectionPool != null) { this.collectionPool.clear(); @@ -196,7 +196,7 @@ void clearGenerated() { @Override public void act(float delta) { stage.act(delta); - ImageCache.allowSingleLoad(); + ImageCache.getInstance().allowSingleLoad(); if (doneClicked) { if (type == Type.Loot || type == Type.QuestReward) { flipCountDown -= Gdx.graphics.getDeltaTime(); diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index bdf07bbecd4..cac9022c05a 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -264,8 +264,7 @@ public void changed(ChangeEvent event, Actor actor) { FModel.getPreferences().save(); Forge.enableUIMask = FModel.getPreferences().getPref(ForgePreferences.FPref.UI_ENABLE_BORDER_MASKING); } - ImageCache.clearGeneratedCards(); - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); return null; }); addLabel(Forge.getLocalizer().getMessage("lblBorderMaskOption")); diff --git a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java index 579e2ee6da2..72f7c21702d 100644 --- a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java +++ b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java @@ -113,7 +113,7 @@ public Reward getReward() { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); String imageKey = reward.getCard().getImageKey(false); PaperCard card = ImageUtil.getPaperCardFromImageKey(imageKey); imageKey = card.getCardImageKey(); @@ -169,7 +169,7 @@ public void onImageFetched() { T.dispose(); if (alternate && Talt != null) Talt.dispose(); - ImageCache.updateSynqCount(imageFile, count); + ImageCache.getInstance().updateSynqCount(imageFile, count); if (Forge.getCurrentScene() instanceof RewardScene) RewardScene.instance().reactivateInputs(); else if (Forge.getCurrentScene() instanceof UIScene) { @@ -202,7 +202,7 @@ public void clicked(InputEvent event, float x, float y) { }); } hasbackface = reward.getCard().hasBackFace(); - if (ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) { + if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false)) && !Forge.enableUIMask.equals("Art")) { int count = 0; PaperCard card = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(false)); File frontFace = ImageKeys.getImageFile(card.getCardImageKey()); @@ -227,10 +227,10 @@ public void clicked(InputEvent event, float x, float y) { } else { loaded = false; } - ImageCache.updateSynqCount(frontFace, count); + ImageCache.getInstance().updateSynqCount(frontFace, count); //preload card back for performance if (hasbackface) { - if (ImageCache.imageKeyFileExists(reward.getCard().getImageKey(true))) { + if (ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(true))) { PaperCard cardBack = ImageUtil.getPaperCardFromImageKey(reward.getCard().getImageKey(true)); File backFace = ImageKeys.getImageFile(cardBack.getCardAltImageKey()); if (backFace != null) { @@ -242,7 +242,7 @@ public void clicked(InputEvent event, float x, float y) { back = Forge.getAssets().manager().get(backFace.getPath(), Texture.class, false); } if (back != null) { - ImageCache.updateSynqCount(backFace, 1); + ImageCache.getInstance().updateSynqCount(backFace, 1); generateBackFace(reward, back); } else { generateBackFace(reward, getRenderedBackface(reward)); @@ -273,7 +273,7 @@ public void clicked(InputEvent event, float x, float y) { } else { loaded = false; } - ImageCache.updateSynqCount(lookup, count); + ImageCache.getInstance().updateSynqCount(lookup, count); } catch (Exception e) { System.err.println("Failed to load image: " + lookup.getPath()); loaded = false; @@ -290,7 +290,7 @@ public void clicked(InputEvent event, float x, float y) { Forge.getAssets().manager().load(file.getPath(), Texture.class, Forge.getAssets().getTextureFilter()); Forge.getAssets().manager().finishLoadingAsset(file.getPath()); } - ImageCache.updateSynqCount(file, 1); + ImageCache.getInstance().updateSynqCount(file, 1); } } catch (Exception e) { } @@ -298,11 +298,11 @@ public void clicked(InputEvent event, float x, float y) { T = renderPlaceholder(new Graphics(), reward.getCard(), false); //Now we can render the card. setCardImage(T); loaded = false; - if (!ImageCache.imageKeyFileExists(reward.getCard().getImageKey(false))) + if (!ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(false))) fetcher.fetchImage(reward.getCard().getImageKey(false), this); if (hasbackface) { - if (!ImageCache.imageKeyFileExists(reward.getCard().getImageKey(true))) { - fetcher.fetchImage(reward.getCard().getImageKey(true), null); + if (!ImageCache.getInstance().imageKeyFileExists(reward.getCard().getImageKey(true))) { + fetcher.fetchImage(reward.getCard().getImageKey(true), () -> System.out.println("Backface fetched: " + reward.getCard().getImageKey(true))); } } } @@ -349,7 +349,7 @@ public void clicked(InputEvent event, float x, float y) { } boolean isBooster = false; Sprite item; - Texture t = ImageCache.getImage(imageKey, false, true); + Texture t = ImageCache.getInstance().getImage(imageKey, false, true); if (t != null) { item = new Sprite(new TextureRegion(t)); isBooster = true; @@ -461,7 +461,7 @@ private void switchTooltip() { holdTooltip.tooltip_actor.swapActor(holdTooltip.tooltip_actor.cImage, holdTooltip.tooltip_actor.altcImage); } } else { - Texture alt = ImageCache.getImage(reward.getCard().getImageKey(true), false); + Texture alt = ImageCache.getInstance().getImage(reward.getCard().getImageKey(true), false); if (hover) { if (alternate) { if (alt != null) { @@ -480,7 +480,7 @@ private void switchTooltip() { } private TextureRegionDrawable processDrawable(Texture texture) { - TextureRegionDrawable drawable = new TextureRegionDrawable(ImageCache.croppedBorderImage(texture)); + TextureRegionDrawable drawable = new TextureRegionDrawable(ImageCache.getInstance().croppedBorderImage(texture)); float origW = texture.getWidth(); float origH = texture.getHeight(); float boundW = Scene.getIntendedWidth() * 0.95f; @@ -887,7 +887,7 @@ private void drawCard(Batch batch, Texture image, float x, float width) { batch.begin(); } else { if (!sold) - batch.draw(ImageCache.croppedBorderImage(image), x, -getHeight() / 2, width, getHeight()); + batch.draw(ImageCache.getInstance().croppedBorderImage(image), x, -getHeight() / 2, width, getHeight()); else { batch.end(); shaderGrayscale.bind(); @@ -896,7 +896,7 @@ private void drawCard(Batch batch, Texture image, float x, float width) { batch.setShader(shaderGrayscale); batch.begin(); //draw gray - batch.draw(ImageCache.croppedBorderImage(image), x, -getHeight() / 2, width, getHeight()); + batch.draw(ImageCache.getInstance().croppedBorderImage(image), x, -getHeight() / 2, width, getHeight()); //reset batch.end(); batch.setShader(null); @@ -1119,7 +1119,7 @@ public void draw(Batch batch, float parentAlpha) { batch.end(); shaderRoundRect.bind(); shaderRoundRect.setUniformf("u_resolution", t.getWidth(), t.getHeight()); - shaderRoundRect.setUniformf("edge_radius", ((float) (t.getHeight() / t.getWidth())) * ImageCache.getRadius(t)); + shaderRoundRect.setUniformf("edge_radius", ((float) (t.getHeight() / t.getWidth())) * ImageCache.getInstance().getRadius(t)); shaderRoundRect.setUniformf("u_gray", sold ? 0.8f : 0f); batch.setShader(shaderRoundRect); batch.begin(); diff --git a/forge-gui-mobile/src/forge/assets/Assets.java b/forge-gui-mobile/src/forge/assets/Assets.java index 863a408902d..680c025846c 100644 --- a/forge-gui-mobile/src/forge/assets/Assets.java +++ b/forge-gui-mobile/src/forge/assets/Assets.java @@ -45,13 +45,12 @@ public class Assets implements Disposable { private HashMap deckbox; private HashMap cursor; private ObjectMap counterFonts; - private ObjectMap generatedCards; private ObjectMap fallback_skins; private ObjectMap tmxMap; private Texture defaultImage, dummy; private TextureParameter textureParameter; private ObjectMap textrafonts; - private int cGen = 0, cGenVal = 0, cFB = 0, cFBVal = 0, cTM = 0, cTMVal = 0, cSF = 0, cSFVal = 0, cCF = 0, cCFVal = 0, aDF = 0, cDFVal = 0; + private int cFB = 0, cFBVal = 0, cTM = 0, cTMVal = 0, cSF = 0, cSFVal = 0, cCF = 0, cCFVal = 0; public Assets() { String titleFilename = Forge.isLandscapeMode() ? "title_bg_lq.png" : "title_bg_lq_portrait.png"; @@ -81,11 +80,6 @@ public void dispose() { bitmapFont.dispose(); counterFonts.clear(); } - if (generatedCards != null) { - for (Texture texture : generatedCards.values()) - texture.dispose(); - generatedCards.clear(); - } if (fallback_skins != null) { for (Texture texture : fallback_skins.values()) texture.dispose(); @@ -207,12 +201,6 @@ public ObjectMap counterFonts() { return counterFonts; } - public ObjectMap generatedCards() { - if (generatedCards == null) - generatedCards = new ObjectMap<>(); - return generatedCards; - } - public ObjectMap fallback_skins() { if (fallback_skins == null) fallback_skins = new ObjectMap() { @@ -445,7 +433,7 @@ private int calculateTextureSize(AssetManager assetManager, String fileName, Cla memoryPerFile.put(fileName, calcTextureDataSize(textureSize, textureData.getFormat())); return memoryPerFile.values().stream().mapToInt(Integer::intValue).sum() + calcFonts() + calcCounterFonts() - + calculateObjectMaps(generatedCards()) + calculateObjectMaps(fallback_skins()) + calculateObjectMaps(tmxMap()); + + calculateObjectMaps(fallback_skins()) + calculateObjectMaps(tmxMap()); } @SuppressWarnings("unchecked") @@ -454,12 +442,6 @@ private int calculateObjectMaps(ObjectMap objectMap) { return 0; if (objectMap == null || objectMap.isEmpty()) return 0; - if (objectMap == generatedCards) { - if (cGen == objectMap.size) - return cGenVal; - else - cGen = objectMap.size; - } if (objectMap == tmxMap) { if (cTM == objectMap.size) return cTMVal; @@ -480,8 +462,6 @@ private int calculateObjectMaps(ObjectMap objectMap) { textureSize = textureSize + (textureSize / 3); sum += calcTextureDataSize(textureSize, textureData.getFormat()); } - if (objectMap == generatedCards) - cGenVal = sum; if (objectMap == tmxMap) cTMVal = sum; if (objectMap == fallback_skins) diff --git a/forge-gui-mobile/src/forge/assets/ImageCache.java b/forge-gui-mobile/src/forge/assets/ImageCache.java index f04c221d552..3ecc0e9ccb8 100644 --- a/forge-gui-mobile/src/forge/assets/ImageCache.java +++ b/forge-gui-mobile/src/forge/assets/ImageCache.java @@ -18,22 +18,17 @@ package forge.assets; import java.io.File; -import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Queue; import java.util.Set; -import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.TextureData; -import com.badlogic.gdx.graphics.glutils.PixmapTextureData; import com.google.common.collect.EvictingQueue; import com.google.common.collect.Queues; import com.google.common.collect.Sets; import forge.deck.DeckProxy; -import forge.gui.FThreads; import forge.gui.GuiBase; import forge.util.FileUtil; import forge.util.TextUtil; @@ -42,7 +37,6 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; @@ -75,15 +69,35 @@ * @version $Id: ImageCache.java 24769 2014-02-09 13:56:04Z Hellfish $ */ public class ImageCache { - private static final HashSet missingIconKeys = new HashSet<>(); - private static List borderlessCardlistKey = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); - public static int counter = 0; - static int maxCardCapacity = 300; //default card capacity - static EvictingQueue q; - static Set cardsLoaded; - static Queue syncQ; - - public static void initCache(int capacity) { + private static ImageCache imageCache; + private HashSet _missingIconKeys; + private HashSet missingIconKeys() { + HashSet result = _missingIconKeys; + if (result == null) { + synchronized (this) { + result = _missingIconKeys; + if (result == null) { + result = new HashSet<>(); + _missingIconKeys = result; + } + } + } + return _missingIconKeys; + } + private final List borderlessCardlistKey = FileUtil.readFile(ForgeConstants.BORDERLESS_CARD_LIST_FILE); + public int counter = 0; + private int maxCardCapacity = 300; //default card capacity + private EvictingQueue q; + private Set cardsLoaded; + private Queue syncQ; + public static ImageCache getInstance() { + if (imageCache == null) { + imageCache = new ImageCache(); + imageCache.initCache(Forge.cacheSize); + } + return imageCache; + } + private void initCache(int capacity) { //override maxCardCapacity maxCardCapacity = capacity; //init q @@ -95,48 +109,57 @@ public static void initCache(int capacity) { cardsLoaded = new HashSet<>(cl); } - private static Set getCardsLoaded() { + private Set getCardsLoaded() { if (cardsLoaded == null) { cardsLoaded = new HashSet<>(400); } return cardsLoaded; } - private static EvictingQueue getQ() { + private EvictingQueue getQ() { if (q == null) { q = EvictingQueue.create(400); } return q; } - private static Queue getSyncQ() { + private Queue getSyncQ() { if (syncQ == null) syncQ = Queues.synchronizedQueue(getQ()); return syncQ; } - public static Texture getDefaultImage() { + public Texture getDefaultImage() { return Forge.getAssets().getDefaultImage(); } - private static final HashMap imageRecord = new HashMap<>(1024); - private static boolean imageLoaded, delayLoadRequested; + private HashMap _imageRecord; + private HashMap imageRecord() { + HashMap result = _imageRecord; + if (result == null) { + synchronized (this) { + result = _imageRecord; + if (result == null) { + result = new HashMap<>(maxCardCapacity + (maxCardCapacity / 3)); + _imageRecord = result; + } + } + } + return _imageRecord; + } + private boolean imageLoaded, delayLoadRequested; - public static void allowSingleLoad() { + public void allowSingleLoad() { imageLoaded = false; //reset at the beginning of each render delayLoadRequested = false; } - public static void clear() { - missingIconKeys.clear(); + public void clear() { + missingIconKeys().clear(); ImageKeys.clearMissingCards(); } - public static void clearGeneratedCards() { - Forge.getAssets().generatedCards().clear(); - } - - public static void disposeTextures() { + public void disposeTextures() { CardRenderer.clearcardArtCache(); //unload all cardsLoaded try { @@ -153,7 +176,7 @@ public static void disposeTextures() { /** * Update counter for use with adventure mode since it uses direct loading for assetmanager for loot and shops */ - public static void updateSynqCount(File file, int count) { + public void updateSynqCount(File file, int count) { if (file == null) return; getSyncQ().add(file.getPath()); @@ -161,7 +184,7 @@ public static void updateSynqCount(File file, int count) { counter += count; } - public static Texture getImage(InventoryItem ii) { + public Texture getImage(InventoryItem ii) { boolean useDefault = ii instanceof DeckProxy; String imageKey = ii.getImageKey(false); if (imageKey != null) { @@ -175,11 +198,11 @@ public static Texture getImage(InventoryItem ii) { * 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) { + public FImage getIcon(IHasIcon ihi) { String imageKey = ihi.getIconImageKey(); final Texture icon; - if (missingIconKeys.contains(imageKey) || (icon = getImage(ihi.getIconImageKey(), false, true)) == null) { - missingIconKeys.add(imageKey); + if (missingIconKeys().contains(imageKey) || (icon = getImage(ihi.getIconImageKey(), false, true)) == null) { + missingIconKeys().add(imageKey); return FSkinImage.UNKNOWN; } return new FTextureImage(icon); @@ -188,7 +211,7 @@ public static FImage getIcon(IHasIcon ihi) { /** * checks the card image exists from the disk. */ - public static boolean imageKeyFileExists(String imageKey) { + public boolean imageKeyFileExists(String imageKey) { if (StringUtils.isEmpty(imageKey)) return false; @@ -197,7 +220,7 @@ public static boolean imageKeyFileExists(String imageKey) { final String prefix = imageKey.substring(0, 2); - PaperCard paperCard = null; + PaperCard paperCard; if (prefix.equals(ImageKeys.CARD_PREFIX)) { try { paperCard = ImageUtil.getPaperCardFromImageKey(imageKey); @@ -216,9 +239,8 @@ public static boolean imageKeyFileExists(String imageKey) { } } 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; + File tokenFile = new File(ForgeConstants.CACHE_TOKEN_PICS_DIR, tokenfilename); + return tokenFile.exists(); } return true; @@ -232,11 +254,11 @@ public static boolean imageKeyFileExists(String imageKey) { * the image from file (slower) and then add it to the cache for fast future access. *

*/ - public static Texture getImage(String imageKey, boolean useDefaultIfNotFound) { + public Texture getImage(String imageKey, boolean useDefaultIfNotFound) { return getImage(imageKey, useDefaultIfNotFound, false); } - public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, boolean others) { + public Texture getImage(String imageKey, boolean useDefaultIfNotFound, boolean others) { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES)) return null; @@ -264,7 +286,7 @@ public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, bo File imageFile = ImageKeys.getImageFile(imageKey); if (useDefaultIfNotFound) { // Load from file and add to cache if not found in cache initially. - image = getAsset(imageKey, imageFile, others); + image = getAsset(imageFile); if (image != null) { return image; @@ -295,25 +317,23 @@ public static Texture getImage(String imageKey, boolean useDefaultIfNotFound, bo /*fix not loading image file since we intentionally not to update the cache in order for the image fetcher to update automatically after the card image/s are downloaded*/ imageLoaded = false; - if (image != null && imageRecord.get(image.toString()) == null) - imageRecord.put(image.toString(), new ImageRecord(Color.valueOf("#171717").toString(), false, getRadius(image))); //black border + if (image != null && imageRecord().get(image.toString()) == null) + imageRecord().put(image.toString(), new ImageRecord(Color.valueOf("#171717").toString(), false, getRadius(image))); //black border } } return image; } - static Texture getAsset(String imageKey, File file, boolean others) { + private Texture getAsset(File file) { if (file == null) return null; - /*if (!others && Forge.enableUIMask.equals("Full") && isBorderless(imageKey)) - return Forge.getAssets().generatedCards().get(imageKey);*/ return Forge.getAssets().manager().get(file.getPath(), Texture.class, false); } - static Texture loadAsset(String imageKey, File file, boolean others) { + private Texture loadAsset(String imageKey, File file, boolean others) { if (file == null) return null; - Texture check = getAsset(imageKey, file, others); + Texture check = getAsset(file); if (check != null) return check; if (!others) { @@ -352,17 +372,13 @@ else if (setCode.equals("MED") || setCode.equals("ME2") || setCode.equals("ME3") radius = 22; updateImageRecord(cardTexture.toString(), borderless ? Color.valueOf("#171717").toString() : isCloserToWhite(getpixelColor(cardTexture)).getLeft(), - borderless ? false : isCloserToWhite(getpixelColor(cardTexture)).getRight(), radius); - //if borderless, generate new texture from the asset and store - /*if (borderless) { - Forge.getAssets().generatedCards().put(imageKey, generateTexture(new FileHandle(file), cardTexture, Forge.isTextureFilteringEnabled())); - }*/ + !borderless && isCloserToWhite(getpixelColor(cardTexture)).getRight(), radius); } return cardTexture; } } - public static void unloadCardTextures(boolean removeAll) { + public void unloadCardTextures(boolean removeAll) { if (removeAll) { try { for (String asset : Forge.getAssets().manager().getAssetNames()) { @@ -374,11 +390,8 @@ public static void unloadCardTextures(boolean removeAll) { getCardsLoaded().clear(); counter = 0; CardRenderer.clearcardArtCache(); - } catch (Exception e) { - //e.printStackTrace(); - } finally { - return; - } + } catch (Exception ignored) {} + return; } if (getCardsLoaded().size() <= maxCardCapacity) return; @@ -397,12 +410,10 @@ public static void unloadCardTextures(boolean removeAll) { //clear cachedArt since this is dependant to the loaded texture CardRenderer.clearcardArtCache(); ((Forge) Gdx.app.getApplicationListener()).needsUpdate = true; - } catch (ConcurrentModificationException e) { - //e.printstacktrace - } + } catch (Exception ignored) {} } - public static void preloadCache(Iterable keys) { + public void preloadCache(Iterable keys) { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES)) return; for (String imageKey : keys) { @@ -411,7 +422,7 @@ public static void preloadCache(Iterable keys) { } } - public static void preloadCache(Deck deck) { + public void preloadCache(Deck deck) { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_CARD_IMAGES)) return; if (deck == null || !Forge.enablePreloadExtendedArt) @@ -419,12 +430,12 @@ public static void preloadCache(Deck deck) { if (deck.getAllCardsInASinglePool().toFlatList().size() <= 100) { for (PaperCard p : deck.getAllCardsInASinglePool().toFlatList()) { if (getImage(p.getImageKey(false), false) == null) - System.err.println("could not load card image:" + p.toString()); + System.err.println("could not load card image:" + p); } } } - public static TextureRegion croppedBorderImage(Texture image) { + public TextureRegion croppedBorderImage(Texture image) { if (!image.toString().contains(".fullborder.")) return new TextureRegion(image); float rscale = 0.96f; @@ -435,17 +446,17 @@ public static TextureRegion croppedBorderImage(Texture image) { return new TextureRegion(image, rx, ry, rw, rh); } - public static Color borderColor(Texture t) { + public Color borderColor(Texture t) { if (t == null) return Color.valueOf("#171717"); try { - return Color.valueOf(imageRecord.get(t.toString()).colorValue); + return Color.valueOf(imageRecord().get(t.toString()).colorValue); } catch (Exception e) { return Color.valueOf("#171717"); } } - public static int getFSkinBorders(CardView c) { + public int getFSkinBorders(CardView c) { if (c == null) return 0; @@ -456,16 +467,14 @@ public static int getFSkinBorders(CardView c) { return 1; return 0; } - - /*public static boolean isBorderlessCardArt(Texture t) { - return isBorderless(t); - }*/ - public static void updateImageRecord(String textureString, String colorValue, Boolean isClosertoWhite, int radius) { - imageRecord.put(textureString, new ImageRecord(colorValue, isClosertoWhite, radius)); + public void updateImageRecord(String textureString, String colorValue, Boolean isClosertoWhite, int radius) { + imageRecord().put(textureString, new ImageRecord(colorValue, isClosertoWhite, radius)); } - public static int getRadius(Texture t) { - ImageRecord record = imageRecord.get(t.toString()); + public int getRadius(Texture t) { + if (t == null) + return 20; + ImageRecord record = imageRecord().get(t.toString()); if (record == null) return 20; Integer i = record.cardRadius; @@ -474,8 +483,8 @@ public static int getRadius(Texture t) { return i; } - public static FImage getBorder(String textureString) { - ImageRecord record = imageRecord.get(textureString); + public FImage getBorder(String textureString) { + ImageRecord record = imageRecord().get(textureString); if (record == null) return FSkinImage.IMG_BORDER_BLACK; Boolean border = record.isCloserToWhite; @@ -484,17 +493,17 @@ public static FImage getBorder(String textureString) { return border ? FSkinImage.IMG_BORDER_WHITE : FSkinImage.IMG_BORDER_BLACK; } - public static FImage getBorderImage(String textureString, boolean canshow) { + public FImage getBorderImage(String textureString, boolean canshow) { if (!canshow) return FSkinImage.IMG_BORDER_BLACK; return getBorder(textureString); } - public static FImage getBorderImage(String textureString) { + public FImage getBorderImage(String textureString) { return getBorder(textureString); } - public static Color getTint(CardView c, Texture t) { + public Color getTint(CardView c, Texture t) { if (c == null) return borderColor(t); if (c.isFaceDown()) @@ -507,85 +516,22 @@ public static Color getTint(CardView c, Texture t) { return Color.valueOf("#A0A6A4"); } else if (state.getColors().isMonoColor()) { if (state.getColors().hasBlack()) - return Color.valueOf("#48494a"); + return Color.valueOf("#263238"); else if (state.getColors().hasBlue()) - return Color.valueOf("#62b5f8"); + return Color.valueOf("#03a9f4"); else if (state.getColors().hasRed()) - return Color.valueOf("#f6532d"); + return Color.valueOf("#f44336"); else if (state.getColors().hasGreen()) - return Color.valueOf("#66cb35"); + return Color.valueOf("#4caf50 "); else if (state.getColors().hasWhite()) - return Color.valueOf("#EEEBE1"); + return Color.valueOf("#f4f3e9"); } else if (state.getColors().isMulticolor()) - return Color.valueOf("#F9E084"); + return Color.valueOf("#F8DB55"); return borderColor(t); } - public static Texture generateTexture(FileHandle fh, Texture cardTexture, boolean textureFilter) { - if (cardTexture == null || fh == null) - return cardTexture; - final Texture[] placeholder = new Texture[1]; - FThreads.invokeInEdtNowOrLater(() -> { - Pixmap pImage = new Pixmap(fh); - int w = pImage.getWidth(); - int h = pImage.getHeight(); - int radius = (h - w) / 8; - Pixmap pMask = createRoundedRectangle(w, h, radius, Color.RED); - drawPixelstoMask(pImage, pMask); - TextureData textureData = new PixmapTextureData( - pMask, //pixmap to use - Format.RGBA4444, - textureFilter, //use mipmaps - false, true); - placeholder[0] = new Texture(textureData); - if (textureFilter) - placeholder[0].setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear); - pImage.dispose(); - pMask.dispose(); - }); - return placeholder[0]; - } - - public static Pixmap createRoundedRectangle(int width, int height, int cornerRadius, Color color) { - Pixmap pixmap = new Pixmap(width, height, Format.RGBA4444); - Pixmap ret = new Pixmap(width, height, Format.RGBA4444); - pixmap.setColor(color); - //round corners - pixmap.fillCircle(cornerRadius, cornerRadius, cornerRadius); - pixmap.fillCircle(width - cornerRadius - 1, cornerRadius, cornerRadius); - pixmap.fillCircle(cornerRadius, height - cornerRadius - 1, cornerRadius); - pixmap.fillCircle(width - cornerRadius - 1, height - cornerRadius - 1, cornerRadius); - //two rectangle parts - pixmap.fillRectangle(cornerRadius, 0, width - cornerRadius * 2, height); - pixmap.fillRectangle(0, cornerRadius, width, height - cornerRadius * 2); - //draw rounded rectangle - ret.setColor(color); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - if (pixmap.getPixel(x, y) != 0) ret.drawPixel(x, y); - } - } - pixmap.dispose(); - return ret; - } - - public static void drawPixelstoMask(Pixmap pixmap, Pixmap mask) { - int pixmapWidth = mask.getWidth(); - int pixmapHeight = mask.getHeight(); - Color pixelColor = new Color(); - for (int x = 0; x < pixmapWidth; x++) { - for (int y = 0; y < pixmapHeight; y++) { - if (mask.getPixel(x, y) != 0) { - Color.rgba8888ToColor(pixelColor, pixmap.getPixel(x, y)); - mask.setColor(pixelColor); - mask.drawPixel(x, y); - } - } - } - } - - public static boolean isBorderless(String imagekey) { + public boolean isBorderless(String imagekey) { if (borderlessCardlistKey.isEmpty()) return false; if (imagekey.length() > 7) { @@ -595,16 +541,7 @@ public static boolean isBorderless(String imagekey) { return borderlessCardlistKey.contains(TextUtil.fastReplace(imagekey, ".full", ".fullborder")); } - public static boolean isBorderless(Texture t) { - if (borderlessCardlistKey.isEmpty()) - return false; - //generated texture/pixmap? - if (t.toString().contains("com.badlogic.gdx.graphics.Texture@")) - return true; - return borderlessCardlistKey.stream().anyMatch(key -> t.toString().contains(key)); - } - - public static String getpixelColor(Texture i) { + public String getpixelColor(Texture i) { if (!i.getTextureData().isPrepared()) { i.getTextureData().prepare(); //prepare texture } @@ -616,8 +553,8 @@ public static String getpixelColor(Texture i) { return color.toString(); } - public static Pair isCloserToWhite(String c) { - if (c == null || c == "") + public Pair isCloserToWhite(String c) { + if (c == null || "".equals(c)) return Pair.of(Color.valueOf("#171717").toString(), false); int c_r = Integer.parseInt(c.substring(0, 2), 16); int c_g = Integer.parseInt(c.substring(2, 4), 16); @@ -626,7 +563,7 @@ public static Pair isCloserToWhite(String c) { return Pair.of(c, brightness > 155); } - static class ImageRecord { + private static class ImageRecord { String colorValue; Boolean isCloserToWhite; Integer cardRadius; diff --git a/forge-gui-mobile/src/forge/card/CardAvatarImage.java b/forge-gui-mobile/src/forge/card/CardAvatarImage.java index e2b9c8c6340..4d48fc31fb9 100644 --- a/forge-gui-mobile/src/forge/card/CardAvatarImage.java +++ b/forge-gui-mobile/src/forge/card/CardAvatarImage.java @@ -26,7 +26,7 @@ public float getHeight() { if (image != null) { return image.getHeight(); } - return ImageCache.getDefaultImage().getHeight() * CardRenderer.CARD_ART_HEIGHT_PERCENTAGE; + return ImageCache.getInstance().getDefaultImage().getHeight() * CardRenderer.CARD_ART_HEIGHT_PERCENTAGE; } @Override diff --git a/forge-gui-mobile/src/forge/card/CardImage.java b/forge-gui-mobile/src/forge/card/CardImage.java index 8194622929b..a72dfd4e022 100644 --- a/forge-gui-mobile/src/forge/card/CardImage.java +++ b/forge-gui-mobile/src/forge/card/CardImage.java @@ -24,7 +24,7 @@ public float getWidth() { if (image != null) { return image.getWidth(); } - return ImageCache.getDefaultImage().getWidth(); + return ImageCache.getInstance().getDefaultImage().getWidth(); } @Override @@ -35,7 +35,7 @@ public float getHeight() { @Override public void draw(Graphics g, float x, float y, float w, float h) { if (image == null) { //attempt to retrieve card image if needed - image = ImageCache.getImage(card); + image = ImageCache.getInstance().getImage(card); if (image == null) { if (!Forge.enableUIMask.equals("Off")) //render this if mask is still loading CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top, Forge.enableUIMask.equals("Art"), true); @@ -44,7 +44,7 @@ public void draw(Graphics g, float x, float y, float w, float h) { } } - if (image == ImageCache.getDefaultImage() || Forge.enableUIMask.equals("Art")) { + if (image == ImageCache.getInstance().getDefaultImage() || Forge.enableUIMask.equals("Art")) { CardImageRenderer.drawCardImage(g, CardView.getCardForUi(card), false, x, y, w, h, CardStackPosition.Top, true, true); } else { if (Forge.enableUIMask.equals("Full")) { @@ -52,11 +52,11 @@ public void draw(Graphics g, float x, float y, float w, float h) { g.drawCardRoundRect(image, null, x, y, w, h, false, false); else { float radius = (h - w) / 8; - g.drawborderImage(ImageCache.borderColor(image), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.2f, y + radius / 2, w * 0.96f, h * 0.96f); + g.drawborderImage(ImageCache.getInstance().borderColor(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.2f, y + radius / 2, w * 0.96f, h * 0.96f); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawImage(ImageCache.croppedBorderImage(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h); } else g.drawImage(image, x, y, w, h); } diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 542b9bd2323..8cce60377c2 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -342,7 +342,7 @@ private static void drawArt(CardView cv, Graphics g, float x, float y, float w, } if (cv == null) { if (isFaceDown) { - Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), false); + Texture cardBack = ImageCache.getInstance().getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), false); if (cardBack != null) { g.drawImage(cardBack, x, y, w, h); return; @@ -775,7 +775,7 @@ public CachedCardImageRenderer(String key) { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); } } public static void drawZoom(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h, float dispW, float dispH, boolean isCurrentCard) { @@ -793,7 +793,7 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea return; } - if (image == ImageCache.getDefaultImage() || Forge.enableUIMask.equals("Art")) { //support drawing card image manually if card image not found + if (image == ImageCache.getInstance().getDefaultImage() || Forge.enableUIMask.equals("Art")) { //support drawing card image manually if card image not found drawCardImage(g, card, altState, x, y, w, h, CardStackPosition.Top, true, true); } else { float radius = (h - w) / 8; @@ -818,10 +818,10 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea g.drawCardRoundRect(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); else { g.drawRotatedImage(FSkin.getBorders().get(0), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, -90); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); } else g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, -90); } else if (rotateSplit && isCurrentCard && card.isSplitCard() && canshow && !card.isFaceDown()) { @@ -830,11 +830,11 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea if (image.toString().contains(".fullborder.")) g.drawCardRoundRect(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); else { - g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getInstance().getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, isAftermath ? 90 : -90); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); } else g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); } else { @@ -846,11 +846,11 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea if (image.toString().contains(".fullborder.")) g.drawCardRoundRect(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); else { - g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(FSkin.getBorders().get(ImageCache.getInstance().getFSkinBorders(card)), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x + radius / 2 - minusxy, new_y + radius / 2 - minusxy, new_w * croppedArea, new_h * croppedArea, (new_x + radius / 2 - minusxy) + (new_w * croppedArea) / 2, (new_y + radius / 2 - minusxy) + (new_h * croppedArea) / 2, isAftermath ? 90 : -90); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawRotatedImage(ImageCache.croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); } else g.drawRotatedImage(image, new_x, new_y, new_w, new_h, new_x + new_w / 2, new_y + new_h / 2, isAftermath ? 90 : -90); } else { @@ -858,11 +858,11 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea if (image.toString().contains(".fullborder.")) g.drawCardRoundRect(image, null, x, y, w, h, false, false); else { - g.drawImage(ImageCache.getBorderImage(image.toString()), ImageCache.borderColor(image), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); + g.drawImage(ImageCache.getInstance().getBorderImage(image.toString()), ImageCache.getInstance().borderColor(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawImage(ImageCache.croppedBorderImage(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h); } else { g.drawImage(image, x, y, w, h); } @@ -875,11 +875,11 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea if (image.toString().contains(".fullborder.")) g.drawCardRoundRect(image, null, x, y, w, h, false, false); else { - g.drawImage(ImageCache.getBorderImage(image.toString()), ImageCache.borderColor(image), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); + g.drawImage(ImageCache.getInstance().getBorderImage(image.toString()), ImageCache.getInstance().borderColor(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); } } else if (Forge.enableUIMask.equals("Crop") && canshow) { - g.drawImage(ImageCache.croppedBorderImage(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h); } else { if (canshow) g.drawImage(image, x, y, w, h); diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index a2af6855121..de9d6855088 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -90,7 +90,7 @@ public RendererCachedCardImage(String key, boolean clearArtCache) { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); if (clearcardArtCache) { clearcardArtCache(); } @@ -126,9 +126,7 @@ private static float calcSymbolSize(FSkinProp skinProp) { for (int fontSize = 8; fontSize <= 22; fontSize++) { generateFontForCounters(fontSize); } - } catch (Exception e) { - e.printStackTrace(); - } + } catch (Exception ignored) {} } private static Color fromDetailColor(DetailColors detailColor) { @@ -243,7 +241,7 @@ public static FImageComplex getCardArt(String imageKey, boolean isSplitCard, boo if (cardArt == null) { Texture image = new RendererCachedCardImage(imageKey, true).getImage(); if (image != null) { - if (image == ImageCache.getDefaultImage()) { + if (image == ImageCache.getInstance().getDefaultImage()) { cardArt = CardImageRenderer.forgeArt; } else { float x, y; @@ -344,12 +342,12 @@ public static FImageComplex getAftermathSecondCardArt(final String imageKey) { Texture image = new CachedCardImage(imageKey) { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); Forge.getAssets().cardArtCache().remove("Aftermath_second_" + imageKey); } }.getImage(); if (image != null) { - if (image == ImageCache.getDefaultImage()) { + if (image == ImageCache.getInstance().getDefaultImage()) { cardArt = CardImageRenderer.forgeArt; } else { float x, y; @@ -377,12 +375,12 @@ public static FImageComplex getAlternateCardArt(final String imageKey, boolean i Texture image = new CachedCardImage(imageKey) { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); Forge.getAssets().cardArtCache().remove("Alternate_" + imageKey); } }.getImage(); if (image != null) { - if (image == ImageCache.getDefaultImage()) { + if (image == ImageCache.getInstance().getDefaultImage()) { cardArt = CardImageRenderer.forgeArt; } else { float x, y; @@ -430,13 +428,13 @@ public static FImageComplex getMeldCardParts(final String imageKey, boolean bott Texture image = new CachedCardImage(imageKey) { @Override public void onImageFetched() { - ImageCache.clear(); + ImageCache.getInstance().clear(); Forge.getAssets().cardArtCache().remove("Meld_primary_" + imageKey); Forge.getAssets().cardArtCache().remove("Meld_secondary_" + imageKey); } }.getImage(); if (image != null) { - if (image == ImageCache.getDefaultImage()) { + if (image == ImageCache.getInstance().getDefaultImage()) { cardArt = CardImageRenderer.forgeArt; } else { float x = 0; @@ -607,7 +605,7 @@ public static void drawCard(Graphics g, IPaperCard pc, float x, float y, float w minusxy = 0.135f * radius; } if (image != null) { - if (image == ImageCache.getDefaultImage() || Forge.enableUIMask.equals("Art")) { + if (image == ImageCache.getInstance().getDefaultImage() || Forge.enableUIMask.equals("Art")) { CardImageRenderer.drawCardImage(g, CardView.getCardForUi(pc), false, x, y, w, h, pos, true, true); } else { if (Forge.enableUIMask.equals("Full")) { @@ -615,11 +613,11 @@ public static void drawCard(Graphics g, IPaperCard pc, float x, float y, float w g.drawCardRoundRect(image, null, x, y, w, h, false, false); else { //tint the border - g.drawImage(ImageCache.getBorderImage(image.toString()), ImageCache.borderColor(image), x, y, w, h); - g.drawImage(ImageCache.croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); + g.drawImage(ImageCache.getInstance().getBorderImage(image.toString()), ImageCache.getInstance().borderColor(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawImage(ImageCache.croppedBorderImage(image), x, y, w, h); + g.drawImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h); } else g.drawImage(image, x, y, w, h); } @@ -653,17 +651,14 @@ public static void drawCard(Graphics g, CardView card, float x, float y, float w croppedArea = 0.975f; minusxy = 0.135f * radius; } - float oldAlpha = g.getfloatAlphaComposite(); - if (card.isPhasedOut() && !magnify) - g.setAlphaComposite(0.2f); if (image != null) { - if (image == ImageCache.getDefaultImage() || Forge.enableUIMask.equals("Art")) { + if (image == ImageCache.getInstance().getDefaultImage() || Forge.enableUIMask.equals("Art")) { CardImageRenderer.drawCardImage(g, card, showAltState, x, y, w, h, pos, true, false, isChoiceList, !showCardIdOverlay(card)); } else if (showsleeves) { if (!card.isForeTold()) - g.drawCardImage(sleeves, crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardImage(sleeves, crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); else - g.drawCardImage(image, crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardImage(image, crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); } else { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_PLANE_OR_PHENOMENON) && (card.getCurrentState().isPhenomenon() || card.getCurrentState().isPlane() || (card.getCurrentState().isBattle() && !showAltState) || (card.getAlternateState() != null && card.getAlternateState().isBattle() && showAltState)) && rotate) { @@ -672,28 +667,28 @@ public static void drawCard(Graphics g, CardView card, float x, float y, float w g.drawCardRoundRect(image, x, y, w, h, x + w / 2, y + h / 2, -90); else { g.drawRotatedImage(FSkin.getBorders().get(0), x, y, w, h, x + w / 2, y + h / 2, -90); - g.drawRotatedImage(ImageCache.croppedBorderImage(image), x + radius / 2.3f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea, (x + radius / 2.3f - minusxy) + (w * croppedArea) / 2, (y + radius / 2 - minusxy) + (h * croppedArea) / 2, -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), x + radius / 2.3f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea, (x + radius / 2.3f - minusxy) + (w * croppedArea) / 2, (y + radius / 2 - minusxy) + (h * croppedArea) / 2, -90); } } else if (Forge.enableUIMask.equals("Crop")) { - g.drawRotatedImage(ImageCache.croppedBorderImage(image), x, y, w, h, x + w / 2, y + h / 2, -90); + g.drawRotatedImage(ImageCache.getInstance().croppedBorderImage(image), x, y, w, h, x + w / 2, y + h / 2, -90); } else g.drawRotatedImage(image, x, y, w, h, x + w / 2, y + h / 2, -90); } else { if (Forge.enableUIMask.equals("Full") && canshow) { if (image.toString().contains(".fullborder.")) - g.drawCardRoundRect(image, crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardRoundRect(image, crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); else { - boolean t = (card.getCurrentState().getOriginalColors() != card.getCurrentState().getColors()) || card.getCurrentState().hasChangeColors(); - g.drawBorderImage(ImageCache.getBorderImage(image.toString(), canshow), ImageCache.borderColor(image), ImageCache.getTint(card, image), x, y, w, h, t); //tint check for changed colors - g.drawCardImage(ImageCache.croppedBorderImage(image), crack_overlay, x + radius / 2.4f-minusxy, y + radius / 2-minusxy, w * croppedArea, h * croppedArea, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + //boolean t = (card.getCurrentState().getOriginalColors() != card.getCurrentState().getColors()) || card.getCurrentState().hasChangeColors(); + g.drawBorderImage(ImageCache.getInstance().getBorderImage(image.toString(), canshow), ImageCache.getInstance().borderColor(image), ImageCache.getInstance().getTint(card, image), x, y, w, h, false); //tint check for changed colors + g.drawCardImage(ImageCache.getInstance().croppedBorderImage(image), crack_overlay, x + radius / 2.4f - minusxy, y + radius / 2 - minusxy, w * croppedArea, h * croppedArea, drawGray(card), magnify ? false : card.getDamage() > 0); } } else if (Forge.enableUIMask.equals("Crop") && canshow) { - g.drawCardImage(ImageCache.croppedBorderImage(image), crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardImage(ImageCache.getInstance().croppedBorderImage(image), crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); } else { if (canshow) - g.drawCardImage(image, crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardImage(image, crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); else // draw card back sleeves - g.drawCardImage(sleeves, crack_overlay, x, y, w, h, card.wasDestroyed(), magnify ? false : card.getDamage() > 0); + g.drawCardImage(sleeves, crack_overlay, x, y, w, h, drawGray(card), magnify ? false : card.getDamage() > 0); } } } @@ -705,6 +700,12 @@ public static void drawCard(Graphics g, CardView card, float x, float y, float w g.setAlphaComposite(oldAlpha); } + private static boolean drawGray(CardView c) { + if (c == null) + return false; + return c.wasDestroyed() || c.isPhasedOut(); + } + public static void drawCardWithOverlays(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) { drawCardWithOverlays(g, card, x, y, w, h, pos, false, false, false); } diff --git a/forge-gui-mobile/src/forge/deck/FDeckChooser.java b/forge-gui-mobile/src/forge/deck/FDeckChooser.java index e8dea4006b7..d7f6cc3f0e3 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckChooser.java +++ b/forge-gui-mobile/src/forge/deck/FDeckChooser.java @@ -532,7 +532,7 @@ private void editDeck(DeckProxy deck) { } needRefreshOnActivate = true; /*preload deck to cache*/ - ImageCache.preloadCache(deck.getDeck()); + ImageCache.getInstance().preloadCache(deck.getDeck()); Forge.openScreen(new FDeckEditor(editorType, deck, true)); } diff --git a/forge-gui-mobile/src/forge/deck/FDeckViewer.java b/forge-gui-mobile/src/forge/deck/FDeckViewer.java index 650f8471f1e..006b0eaa375 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckViewer.java +++ b/forge-gui-mobile/src/forge/deck/FDeckViewer.java @@ -111,7 +111,7 @@ public static void show(final Deck deck0, boolean noPreload, boolean showRanking if (!noPreload){ /*preload deck to cache*/ - ImageCache.preloadCache(deck0); + ImageCache.getInstance().preloadCache(deck0); } deckViewer = new FDeckViewer(deck0, showRanking); diff --git a/forge-gui-mobile/src/forge/itemmanager/SpellShopManager.java b/forge-gui-mobile/src/forge/itemmanager/SpellShopManager.java index 6202cff5591..8b65fcb660e 100644 --- a/forge-gui-mobile/src/forge/itemmanager/SpellShopManager.java +++ b/forge-gui-mobile/src/forge/itemmanager/SpellShopManager.java @@ -68,8 +68,8 @@ public void drawValue(Graphics g, Entry value, FSkinFont CardRenderer.drawCardListItem(g, font, foreColor, (PaperCard)value.getKey(), value.getValue(), getItemSuffix(value), x, y, w, h, compactModeHandler.isCompactMode()); } else { - g.drawText(value.getValue().toString() + " " + value.getKey().toString(), font, foreColor, x + cardArtWidth, y, w - cardArtWidth, h, false, Align.left, true); - Texture image = ImageCache.getImage(value.getKey()); + g.drawText(value.getValue() + " " + value.getKey().toString(), font, foreColor, x + cardArtWidth, y, w - cardArtWidth, h, false, Align.left, true); + Texture image = ImageCache.getInstance().getImage(value.getKey()); if (image != null) { float imageRatio = (float)image.getWidth() / (float)image.getHeight(); float imageHeight = totalHeight; diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java index 34f4f5b57a3..500c77245df 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java @@ -2,7 +2,6 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Align; @@ -27,6 +26,7 @@ import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.toolbox.*; +import forge.util.ImageFetcher; import forge.util.ImageUtil; import forge.util.TextUtil; import forge.util.Utils; @@ -63,7 +63,20 @@ private static FSkinColor getGroupHeaderLineColor() { private static final int MIN_COLUMN_COUNT = Forge.isLandscapeMode() ? 2 : 1; private static final int MAX_COLUMN_COUNT = 10; - private final List selectedIndices = new ArrayList<>(); + private List _selectedIndices; + private List selectedIndices() { + List result = _selectedIndices; + if (result == null) { + synchronized (this) { + result = _selectedIndices; + if (result == null) { + result = new ArrayList<>(); + _selectedIndices = result; + } + } + } + return _selectedIndices; + } private int columnCount = 4; private float scrollHeight = 0; private ColumnDef pileBy = null; @@ -71,8 +84,34 @@ private static FSkinColor getGroupHeaderLineColor() { private ItemInfo focalItem; private boolean updatingLayout; private float totalZoomAmount; - private final List orderedItems = new ArrayList<>(); - private final List groups = new ArrayList<>(); + private List _orderedItems; + private List orderedItems() { + List result = _orderedItems; + if (result == null) { + synchronized (this) { + result = _orderedItems; + if (result == null) { + result = new ArrayList<>(); + _orderedItems = result; + } + } + } + return _orderedItems; + } + private List _groups; + private List groups() { + List result = _groups; + if (result == null) { + synchronized (this) { + result = _groups; + if (result == null) { + result = new ArrayList<>(); + _groups = result; + } + } + } + return _groups; + } private class ExpandCollapseButton extends FLabel { private boolean isAllCollapsed; @@ -85,7 +124,7 @@ private ExpandCollapseButton() { } boolean collapsed = !isAllCollapsed; - for (Group group : groups) { + for (Group group : groups()) { group.isCollapsed = collapsed; } @@ -97,7 +136,7 @@ private ExpandCollapseButton() { private void updateIsAllCollapsed() { boolean isAllCollapsed0 = true; - for (Group group : groups) { + for (Group group : groups()) { if (!group.isCollapsed) { isAllCollapsed0 = false; break; @@ -172,7 +211,7 @@ public ImageView(ItemManager itemManager0, ItemManagerModel model0) { getPnlOptions().add(cbPileByOptions); Group group = new Group(""); //add default group - groups.add(group); + groups().add(group); getScroller().add(group); } @@ -203,26 +242,26 @@ private void setGroupBy(GroupDef groupBy0, boolean forSetup) { cbGroupByOptions.setSelectedItem(groupBy); } - groups.clear(); + groups().clear(); if (groupBy == null) { - groups.add(new Group("")); + groups().add(new Group("")); btnExpandCollapseAll.updateIsAllCollapsed(); } else { for (String groupName : groupBy.getGroups()) { - groups.add(new Group(groupName)); + groups().add(new Group(groupName)); } //collapse all groups by default if all previous groups were collapsed if (btnExpandCollapseAll.isAllCollapsed) { - for (Group group : groups) { + for (Group group : groups()) { group.isCollapsed = true; } } } getScroller().clear(); - for (Group group : groups) { + for (Group group : groups()) { getScroller().add(group); } @@ -313,7 +352,7 @@ private ItemInfo getFocalItem() { //if not item hovered, use first fully visible item as focal point final float visibleTop = getScrollValue(); - for (Group group : groups) { + for (Group group : groups()) { if (group.getBottom() < visibleTop) { continue; } @@ -328,10 +367,10 @@ private ItemInfo getFocalItem() { } } } - if (orderedItems.isEmpty()) { + if (orderedItems().isEmpty()) { return null; } - return orderedItems.get(0); + return orderedItems().get(0); } @Override @@ -341,42 +380,49 @@ protected void onResize(float visibleWidth, float visibleHeight) { @Override protected void onRefresh() { - Group otherItems = groupBy == null ? groups.get(0) : null; + Group otherItems = groupBy == null ? groups().get(0) : null; - for (Group group : groups) { + for (Group group : groups()) { group.items.clear(); } clearSelection(); - for (Entry itemEntry : model.getOrderedList()) { - T item = itemEntry.getKey(); - int qty = itemEntry.getValue(); - int groupIndex = groupBy == null ? -1 : groupBy.getItemGroupIndex(item); - - Group group; - if (groupIndex >= 0) { - group = groups.get(groupIndex); - } else { - if (otherItems == null) { - //reuse existing Other group if possible - if (groups.size() > groupBy.getGroups().length) { - otherItems = groups.get(groups.size() - 1); - } else { - otherItems = new Group(Forge.getLocalizer().getMessage("lblOther")); - otherItems.isCollapsed = btnExpandCollapseAll.isAllCollapsed; - groups.add(otherItems); + if (model.getOrderedList() != null) { + for (Entry itemEntry : model.getOrderedList()) { + T item = itemEntry.getKey(); + int qty = itemEntry.getValue(); + int groupIndex = groupBy == null ? -1 : groupBy.getItemGroupIndex(item); + + Group group; + if (groupIndex >= 0) { + if (groupIndex >= groups().size()) + group = groups().get(groups().size() - 1); + else + group = groups().get(groupIndex); + } else { + if (otherItems == null) { + //reuse existing Other group if possible + if (groups().size() > groupBy.getGroups().length) { + otherItems = groups().get(groups().size() - 1); + } else { + otherItems = new Group(Forge.getLocalizer().getMessage("lblOther")); + otherItems.isCollapsed = btnExpandCollapseAll.isAllCollapsed; + groups().add(otherItems); + } } + group = otherItems; } - group = otherItems; - } - for (int i = 0; i < qty; i++) { - group.add(new ItemInfo(item, group)); + for (int i = 0; i < qty; i++) { + group.add(new ItemInfo(item, group)); + } } } - if (otherItems == null && groups.size() > groupBy.getGroups().length) { - groups.remove(groups.size() - 1); //remove Other group if empty + if (otherItems == null && groups().size() > groupBy.getGroups().length) { + int index = groups().size() - 1; + if (index < groups().size() && index >= 0) + groups().remove(index); //remove Other group if empty btnExpandCollapseAll.updateIsAllCollapsed(); } @@ -414,7 +460,7 @@ private void updateLayout(boolean forRefresh) { float itemAreaWidth = getScroller().getWidth(); float groupWidth = itemAreaWidth - 2 * groupX; - float gap = (MAX_COLUMN_COUNT - columnCount) / 2 + Utils.scale(2); //more items per row == less gap between them + float gap = (MAX_COLUMN_COUNT - columnCount) / 2f + Utils.scale(2); //more items per row == less gap between them float itemWidth = (groupWidth + gap) / columnCount - gap; if (pileBy != null) { //if showing piles, make smaller so part of the next card is visible so it's obvious if scrolling is needed @@ -424,8 +470,8 @@ private void updateLayout(boolean forRefresh) { float dx = itemWidth + gap; float dy = pileBy == null ? itemHeight + gap : itemHeight * PILE_SPACING_Y; - for (int i = 0; i < groups.size(); i++) { - Group group = groups.get(i); + for (int i = 0; i < groups().size(); i++) { + Group group = groups().get(i); if (forRefresh && pileBy != null) { //refresh piles if needed //use TreeMap to build pile set so iterating below sorts on key @@ -518,8 +564,8 @@ private void updateLayout(boolean forRefresh) { if (forRefresh) { //refresh ordered items if needed int index = 0; - orderedItems.clear(); - for (Group group : groups) { + orderedItems().clear(); + for (Group group : groups()) { if (group.isCollapsed || group.items.isEmpty()) { continue; } @@ -527,7 +573,7 @@ private void updateLayout(boolean forRefresh) { for (Pile pile : group.piles) { for (ItemInfo itemInfo : pile.items) { itemInfo.index = index++; - orderedItems.add(itemInfo); + orderedItems().add(itemInfo); } } } @@ -546,7 +592,10 @@ protected boolean tap(float x, float y, int count) { ItemInfo item = getItemAtPoint(x, y); if (count == 1) { selectItem(item); - itemManager.showMenu(false); + if (item != null) + itemManager.showMenu(false, item.getLeft(), item.getWidth()); + else + itemManager.showMenu(false); } else if (count == 2) { if (item != null && item.selected) { if (!(item.getKey() instanceof DeckProxy)) @@ -574,11 +623,11 @@ protected boolean zoom(float x, float y, float amount) { private ItemInfo getItemAtPoint(float x, float y) { //check selected items first since they appear on top - for (int i = selectedIndices.size() - 1; i >= 0; i--) { - int currentIndex = selectedIndices.get(i); - if (currentIndex < 0 || orderedItems.size() <= currentIndex) + for (int i = selectedIndices().size() - 1; i >= 0; i--) { + int currentIndex = selectedIndices().get(i); + if (currentIndex < 0 || orderedItems().size() <= currentIndex) continue; - ItemInfo item = orderedItems.get(currentIndex); + ItemInfo item = orderedItems().get(currentIndex); float relX = x + item.group.getScrollLeft() - item.group.getLeft(); float relY = y + getScrollValue(); if (item.contains(relX, relY)) { @@ -586,8 +635,8 @@ private ItemInfo getItemAtPoint(float x, float y) { } } - for (int i = groups.size() - 1; i >= 0; i--) { - Group group = groups.get(i); + for (int i = groups().size() - 1; i >= 0; i--) { + Group group = groups().get(i); if (!group.isCollapsed) { for (int j = group.piles.size() - 1; j >= 0; j--) { float relX = x + group.getScrollLeft() - group.getLeft(); @@ -610,14 +659,14 @@ private ItemInfo getItemAtPoint(float x, float y) { @Override public T getItemAtIndex(int index) { if (index >= 0 && index < getCount()) { - return orderedItems.get(index).item; + return orderedItems().get(index).item; } return null; } @Override public int getIndexOfItem(T item) { - for (Group group : groups) { + for (Group group : groups()) { for (ItemInfo itemInfo : group.items) { if (itemInfo.item == item) { //if group containing item is collapsed, expand it so the item can be selected and has a valid index @@ -636,22 +685,22 @@ public int getIndexOfItem(T item) { @Override public int getSelectedIndex() { - return selectedIndices.isEmpty() ? -1 : selectedIndices.get(0); + return selectedIndices().isEmpty() ? -1 : selectedIndices().get(0); } @Override public Iterable getSelectedIndices() { - return selectedIndices; + return selectedIndices(); } @Override public int getCount() { - return orderedItems.size(); + return orderedItems().size(); } @Override public int getSelectionCount() { - return selectedIndices.size(); + return selectedIndices().size(); } @Override @@ -679,7 +728,7 @@ public String getCaption() { @Override public void selectAll() { clearSelection(); - IntStream.range(0, getCount()).forEach(selectedIndices::add); + IntStream.range(0, getCount()).forEach(selectedIndices()::add); updateSelection(); onSelectionChange(); } @@ -687,7 +736,7 @@ public void selectAll() { @Override protected void onSetSelectedIndex(int index) { clearSelection(); - selectedIndices.add(index); + selectedIndices().add(index); updateSelection(); } @@ -695,24 +744,24 @@ protected void onSetSelectedIndex(int index) { protected void onSetSelectedIndices(Iterable indices) { clearSelection(); for (Integer index : indices) { - selectedIndices.add(index); + selectedIndices().add(index); } updateSelection(); } private void clearSelection() { int count = getCount(); - for (Integer i : selectedIndices) { + for (Integer i : selectedIndices()) { if (i < count) { - orderedItems.get(i).selected = false; + orderedItems().get(i).selected = false; } } - selectedIndices.clear(); + selectedIndices().clear(); } private void updateSelection() { - for (Integer i : selectedIndices) { - orderedItems.get(i).selected = true; + for (Integer i : selectedIndices()) { + orderedItems().get(i).selected = true; } } @@ -728,9 +777,9 @@ private boolean selectItem(ItemInfo item) { } if (item.selected) { //unselect item if already selected - if (selectedIndices.size() > minSelections) { + if (selectedIndices().size() > minSelections) { item.selected = false; - selectedIndices.remove((Object) item.index); + selectedIndices().remove((Object) item.index); onSelectionChange(); item.group.scrollIntoView(item); } @@ -739,8 +788,8 @@ private boolean selectItem(ItemInfo item) { if (maxSelections <= 1 || (!KeyInputAdapter.isCtrlKeyDown() && !KeyInputAdapter.isShiftKeyDown())) { clearSelection(); } - if (selectedIndices.size() < maxSelections) { - selectedIndices.add(0, item.index); + if (selectedIndices().size() < maxSelections) { + selectedIndices().add(0, item.index); item.selected = true; onSelectionChange(); item.group.scrollIntoView(item); @@ -751,29 +800,29 @@ private boolean selectItem(ItemInfo item) { @Override public void scrollSelectionIntoView() { - if (selectedIndices.isEmpty()) { + if (selectedIndices().isEmpty()) { return; } - int index = selectedIndices.get(0); - if (index < 0 || orderedItems.size() <= index) { + int index = selectedIndices().get(0); + if (index < 0 || orderedItems().size() <= index) { return; } - ItemInfo itemInfo = orderedItems.get(index); + ItemInfo itemInfo = orderedItems().get(index); getScroller().scrollIntoView(itemInfo); } @Override public Rectangle getSelectionBounds() { - if (selectedIndices.isEmpty()) { + if (selectedIndices().isEmpty()) { return new Rectangle(); } - int index = selectedIndices.get(0); - if (index < 0 || orderedItems.size() <= index) { + int index = selectedIndices().get(0); + if (index < 0 || orderedItems().size() <= index) { return new Rectangle(); } - ItemInfo itemInfo = orderedItems.get(index); + ItemInfo itemInfo = orderedItems().get(index); Vector2 relPos = itemInfo.group.getChildRelativePosition(itemInfo); return new Rectangle(itemInfo.group.screenPos.x + relPos.x - SEL_BORDER_SIZE + itemInfo.group.getLeft(), itemInfo.group.screenPos.y + relPos.y - SEL_BORDER_SIZE, @@ -782,21 +831,21 @@ public Rectangle getSelectionBounds() { @Override public void zoomSelected() { - if (selectedIndices.isEmpty()) { + if (selectedIndices().isEmpty()) { return; } - int index = selectedIndices.get(0); - if (index < 0 || orderedItems.size() <= index) { + int index = selectedIndices().get(0); + if (index < 0 || orderedItems().size() <= index) { return; } - ItemInfo itemInfo = orderedItems.get(index); + ItemInfo itemInfo = orderedItems().get(index); if (itemInfo != null) { if (itemInfo.getKey() instanceof CardThemedDeckGenerator || itemInfo.getKey() instanceof CommanderDeckGenerator || itemInfo.getKey() instanceof ArchetypeDeckGenerator || itemInfo.getKey() instanceof DeckProxy) { FDeckViewer.show(((DeckProxy) itemInfo.getKey()).getDeck()); } - CardZoom.show(orderedItems, orderedItems.indexOf(itemInfo), itemManager); + CardZoom.show(orderedItems(), orderedItems().indexOf(itemInfo), itemManager); } } @@ -873,6 +922,8 @@ public void draw(Graphics g) { final float visibleTop = getScrollValue(); final float visibleBottom = visibleTop + getScroller().getHeight(); for (ItemInfo itemInfo : items) { + if (itemInfo == null) + continue; if (itemInfo.getBottom() < visibleTop) { continue; } @@ -924,7 +975,7 @@ public boolean longPress(float x, float y) { FDeckViewer.show(((DeckProxy) item.getKey()).getDeck()); return true; } - CardZoom.show(orderedItems, orderedItems.indexOf(item), itemManager); + CardZoom.show(orderedItems(), orderedItems().indexOf(item), itemManager); return true; } return false; @@ -968,18 +1019,43 @@ public void draw(Graphics g) { } } - private class ItemInfo extends FDisplayObject implements Entry { + private class ItemInfo extends FDisplayObject implements Entry, ImageFetcher.Callback { private final T item; private Integer cardPrice; private final Group group; - private int index; + private int index, draftRank; + private FSkinImage draftRankImage = FSkinImage.DRAFTRANK_D; private CardStackPosition pos; - private boolean selected; + private boolean selected, deckSelectMode, showRanking; private final float IMAGE_SIZE = CardRenderer.MANA_SYMBOL_SIZE; + private DeckProxy deckProxy = null; + private FImageComplex deckCover = null; + private Texture dpImg = null; + //private TextureRegion tr; private ItemInfo(T item0, Group group0) { item = item0; group = group0; + if (item instanceof DeckProxy) { + deckSelectMode = true; + deckProxy = (DeckProxy) item; + } + if (item instanceof PaperCard) { + showRanking = itemManager.getShowRanking() && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_OVERLAY_DRAFT_RANKING); + if (showRanking) { + double score = CardRanker.getRawScore((PaperCard) item); + draftRank = score <= 0 ? 0 : score > 99 ? 99 : (int) Math.round(CardRanker.getRawScore((PaperCard) item)); + if (draftRank >= 90) { + draftRankImage = FSkinImage.DRAFTRANK_S; + } else if (draftRank >= 80) { + draftRankImage = FSkinImage.DRAFTRANK_A; + } else if (draftRank >= 60) { + draftRankImage = FSkinImage.DRAFTRANK_B; + } else if (draftRank >= 25) { + draftRankImage = FSkinImage.DRAFTRANK_C; + } + } + } } @Override @@ -1019,11 +1095,8 @@ public void draw(Graphics g) { final float y = getTop() - group.getTop() - getScrollValue(); final float w = getWidth(); final float h = getHeight(); - Texture dpImg = null; - boolean deckSelectMode = false; - if (item instanceof DeckProxy) { - dpImg = ImageCache.getImage(item); - deckSelectMode = true; + if (deckSelectMode) { + dpImg = ImageCache.getInstance().getImage(item); } if (selected) { if (!deckSelectMode) { @@ -1040,25 +1113,12 @@ public void draw(Graphics g) { if (item instanceof PaperCard) { CardRenderer.drawCard(g, (PaperCard) item, x, y, w, h, pos); - if (itemManager.getShowRanking() && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_OVERLAY_DRAFT_RANKING)) { - double score = CardRanker.getRawScore((PaperCard) item); - int draftRank = score <= 0 ? 0 : score > 99 ? 99 : (int) Math.round(CardRanker.getRawScore((PaperCard) item)); + if (showRanking) { float rankSize = w / 2; float y2 = y + (rankSize - (rankSize * 0.1f)); float x2 = x + rankSize / 2; - if (draftRank >= 90) { - g.drawImage(FSkinImage.DRAFTRANK_S, x2, y2 + 1, rankSize, rankSize); - } else if (draftRank >= 80 && draftRank <= 89) { - g.drawImage(FSkinImage.DRAFTRANK_A, x2, y2 + 1, rankSize, rankSize); - } else if (draftRank >= 60 && draftRank <= 79) { - g.drawImage(FSkinImage.DRAFTRANK_B, x2, y2 + 1, rankSize, rankSize); - } else if (draftRank >= 25 && draftRank <= 59) { - g.drawImage(FSkinImage.DRAFTRANK_C, x2, y2 + 1, rankSize, rankSize); - } else { - g.drawImage(FSkinImage.DRAFTRANK_D, x2, y2 + 1, rankSize, rankSize); - } - String value = String.valueOf(draftRank); - g.drawText(value, FSkinFont.forHeight(rankSize / 4), Color.WHITE, x, y, w, h, true, Align.center, true); + g.drawImage(draftRankImage, x2, y2 + 1, rankSize, rankSize); + g.drawText(String.valueOf(draftRank), FSkinFont.forHeight(rankSize / 4), Color.WHITE, x, y, w, h, true, Align.center, true); } if (Forge.isMobileAdventureMode) { @@ -1077,8 +1137,7 @@ public void draw(Graphics g) { } else if (item instanceof ConquestCommander) { CardRenderer.drawCard(g, ((ConquestCommander) item).getCard(), x, y, w, h, pos); } else if (deckSelectMode) { - DeckProxy dp = ((DeckProxy) item); - ColorSet deckColor = dp.getColor(); + ColorSet deckColor = deckProxy.getColor(); float scale = 0.75f; if (dpImg != null) {//generated decks have missing info... @@ -1093,15 +1152,18 @@ public void draw(Graphics g) { PaperCard paperCard = null; String imageKey = item.getImageKey(false); if (imageKey != null) { - if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) + if (imageKey.startsWith(ImageKeys.CARD_PREFIX)) { paperCard = ImageUtil.getPaperCardFromImageKey(imageKey); + CardRenderer.getCardArt(paperCard); + } } if (paperCard != null && Forge.enableUIMask.equals("Art")) { CardImageRenderer.drawCardImage(g, CardView.getCardForUi(paperCard), false, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale, CardStackPosition.Top, true, false, false, true); } else { - TextureRegion tr = ImageCache.croppedBorderImage(dpImg); - g.drawImage(tr, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); + //tr = ImageCache.getInstance().croppedBorderImage(dpImg); + g.drawImage(dpImg, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); + //g.drawImage(tr, x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); } //draw plastic effect overlay. g.drawImage(Forge.getAssets().getTexture(getDefaultSkinFile("cover.png")), x + (w - w * scale) / 2, y + (h - h * scale) / 1.5f, w * scale, h * scale); @@ -1111,19 +1173,15 @@ public void draw(Graphics g) { //labelname g.drawText(item.getName(), GROUP_HEADER_FONT, Color.WHITE, x + PADDING, y + PADDING * 2, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false); } else { - if (!dp.isGeneratedDeck()) { - if (dp.getDeck().isEmpty()) { + if (!deckProxy.isGeneratedDeck()) { + if (deckProxy.getDeck().isEmpty()) { g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y - (h * 0.25f), w, h, Color.RED, selected); } else { - //If deck has Commander, use it as cardArt reference - PaperCard paperCard = dp.getDeck().getCommanders().isEmpty() ? dp.getHighestCMCCard() : dp.getDeck().getCommanders().get(0); - FImageComplex cardArt = CardRenderer.getCardArt(paperCard); - //draw the deckbox - if (cardArt == null) { - //draw generic box if null or still loading - g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y - (h * 0.25f), w, h, Color.GREEN, selected); + deckCover = CardRenderer.getCardArt(deckProxy.getDeck().getCommanders().isEmpty() ? deckProxy.getHighestCMCCard() : deckProxy.getDeck().getCommanders().get(0)); + if (deckCover != null) { + g.drawDeckBox(deckCover, scale, FSkin.getDeckbox().get(1), FSkin.getDeckbox().get(2), x, y, w, h, Color.GREEN, selected); } else { - g.drawDeckBox(cardArt, scale, FSkin.getDeckbox().get(1), FSkin.getDeckbox().get(2), x, y, w, h, Color.GREEN, selected); + g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y - (h * 0.25f), w, h, Color.GREEN, selected); } } } else { @@ -1158,16 +1216,16 @@ else if (columnCount == 1) } //vertical mana icons CardFaceSymbols.drawColorSet(g, deckColor, x + (w - symbolSize), y + (h / 8), symbolSize, true); - if (!dp.isGeneratedDeck()) { - if (dp.getDeck().isEmpty()) { + if (!deckProxy.isGeneratedDeck()) { + if (deckProxy.getDeck().isEmpty()) { g.drawImage(Forge.hdbuttons ? FSkinImage.HDYIELD : FSkinImage.WARNING, x, y, symbolSize, symbolSize); } else { if (Forge.hdbuttons) - g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.HDSTAR_FILLED : FSkinImage.HDSTAR_OUTLINE, x, y, symbolSize, symbolSize); + g.drawImage(DeckPreferences.getPrefs(deckProxy).getStarCount() > 0 ? FSkinImage.HDSTAR_FILLED : FSkinImage.HDSTAR_OUTLINE, x, y, symbolSize, symbolSize); else - g.drawImage(DeckPreferences.getPrefs(dp).getStarCount() > 0 ? FSkinImage.STAR_FILLED : FSkinImage.STAR_OUTLINE, x, y, symbolSize, symbolSize); + g.drawImage(DeckPreferences.getPrefs(deckProxy).getStarCount() > 0 ? FSkinImage.STAR_FILLED : FSkinImage.STAR_OUTLINE, x, y, symbolSize, symbolSize); //AI Icon - g.drawImage(dp.getAI().inMainDeck == 0 ? FSkinImage.AI_ACTIVE : FSkinImage.AI_INACTIVE, x, y + symbolSize, symbolSize, symbolSize); + g.drawImage(deckProxy.getAI().inMainDeck == 0 ? FSkinImage.AI_ACTIVE : FSkinImage.AI_INACTIVE, x, y + symbolSize, symbolSize, symbolSize); } } } @@ -1178,14 +1236,32 @@ else if (columnCount == 1) g.drawText(deckname, GROUP_HEADER_FONT, Color.WHITE, x + PADDING, y + (h / 10) + PADDING, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, true); } } else { - Texture img = ImageCache.getImage(item); + Texture img = ImageCache.getInstance().getImage(item); if (img != null) { g.drawImage(img, x, y, w, h); } else { + if (img == null && item instanceof InventoryItem) { + String key = item.getImageKey(false); + if (key.startsWith(ImageKeys.PRECON_PREFIX) || key.startsWith(ImageKeys.FATPACK_PREFIX) + || key.startsWith(ImageKeys.BOOSTERBOX_PREFIX) || key.startsWith(ImageKeys.BOOSTER_PREFIX) || key.startsWith(ImageKeys.TOURNAMENTPACK_PREFIX)) { + CardView cv = new CardView(-1, null, item.getName(), null, item.getImageKey(false)); + CardImageRenderer.drawCardImage(g, cv, false, x, y, w, h, CardStackPosition.Top, false, false); + return; + } + } g.fillRect(Color.BLACK, x, y, w, h); g.drawText(item.getName(), GROUP_HEADER_FONT, Color.WHITE, x + PADDING, y + PADDING, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false); } } } + + @Override + public void onImageFetched() { + if (deckSelectMode) { + if (dpImg == ImageCache.getInstance().getDefaultImage()) { + dpImg = ImageCache.getInstance().getImage(item); + } + } + } } } diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 58cc3c0008f..e7db61405a1 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -672,7 +672,7 @@ public void update(final boolean fullUpdate) { if (Forge.gameInProgress) { /*preload deck to cache*/ if(slot.getType() == LobbySlotType.LOCAL) - ImageCache.preloadCache(decks[i]); + ImageCache.getInstance().preloadCache(decks[i]); } Gdx.graphics.requestRendering(); } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index f1af40a93b2..fef9b242624 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -544,7 +544,7 @@ public void afterGameEnd() { super.afterGameEnd(); Forge.back(true); if (Forge.disposeTextures) - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); //view = null; } @@ -722,7 +722,7 @@ public void setCard(final CardView card) { @Override public void setPlayerAvatar(final LobbyPlayer player, final IHasIcon ihi) { - Forge.getAssets().avatarImages().put(player.getName(), ImageCache.getIcon(ihi)); + Forge.getAssets().avatarImages().put(player.getName(), ImageCache.getInstance().getIcon(ihi)); } @Override diff --git a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java index d2fa2f62667..e74c01d3a4c 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestCommandersScreen.java @@ -65,7 +65,7 @@ public ConquestCommandersScreen() { final ConquestCommander commander = lstCommanders.getSelectedItem(); if (commander != null) { /*preload deck to cache*/ - ImageCache.preloadCache(commander.getDeck()); + ImageCache.getInstance().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/planarconquest/ConquestRewardDialog.java b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java index 5e63deabb7d..d276b24b34f 100644 --- a/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java +++ b/forge-gui-mobile/src/forge/screens/planarconquest/ConquestRewardDialog.java @@ -349,7 +349,7 @@ public void draw(Graphics g) { CardRenderer.drawCard(g, reward.getCard(), (w - flipWidth) / 2, 0, flipWidth, h, CardStackPosition.Top); } else { - Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), true); + Texture cardBack = ImageCache.getInstance().getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), true); if (cardBack != null) { float flipWidth = w * (halfDuration - progress) / halfDuration; g.drawImage(cardBack, (w - flipWidth) / 2, 0, flipWidth, h); diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java index 1dd2f3ffde2..3a76efdd479 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestDecksScreen.java @@ -119,7 +119,7 @@ private void editSelectedDeck() { if (deck == null) { return; } /*preload deck to cache*/ - ImageCache.preloadCache(deck.getDeck()); + ImageCache.getInstance().preloadCache(deck.getDeck()); needRefreshOnActivate = true; Forge.openScreen(new QuestDeckEditor(deck, commanderMode)); diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestEventPanel.java b/forge-gui-mobile/src/forge/screens/quest/QuestEventPanel.java index e48d51fbaf9..2a3b3e7d50d 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestEventPanel.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestEventPanel.java @@ -48,7 +48,7 @@ class QuestEventPanel extends FDisplayObject { if (event.getFullTitle().startsWith("Random Opponent")) { image = FSkinImage.UNKNOWN; } else { - image = event.hasImage() ? ImageCache.getIcon(e0) : null; + image = event.hasImage() ? ImageCache.getInstance().getIcon(e0) : null; } container = container0; diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java index 7eee1297e12..9686bc469c9 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestTournamentsScreen.java @@ -213,7 +213,7 @@ public void editDeck(boolean isExistingDeck) { Deck deck = getDeck(); if (deck != null) { /*preload deck to cache*/ - ImageCache.preloadCache(deck); + ImageCache.getInstance().preloadCache(deck); if (isExistingDeck) { Forge.openScreen(new QuestDraftDeckEditor(deck.getName())); } diff --git a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java index 405cc8125aa..9ecfec087b2 100644 --- a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java @@ -477,7 +477,7 @@ public void run(Boolean result) { @Override public void select() { super.select(); - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); } }, 4); @@ -580,8 +580,7 @@ public void select() { public void valueChanged(String newValue) { super.valueChanged(newValue); Forge.enableUIMask = FModel.getPreferences().getPref(FPref.UI_ENABLE_BORDER_MASKING); - ImageCache.clearGeneratedCards(); - ImageCache.disposeTextures(); + ImageCache.getInstance().disposeTextures(); } }, 4); lstSettings.addItem(new BooleanSetting(FPref.UI_ENABLE_PRELOAD_EXTENDED_ART, diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index 69234662def..310510ca523 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -6,14 +6,17 @@ import java.util.Collections; import java.util.List; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.utils.Align; import forge.Forge; import forge.Graphics; +import forge.ImageKeys; import forge.assets.FSkin; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinFont; +import forge.assets.ImageCache; import forge.assets.TextRenderer; import forge.card.CardFaceSymbols; import forge.card.CardRenderer; @@ -24,6 +27,7 @@ import forge.card.mana.ManaCostParser; import forge.game.card.CardView; import forge.game.card.IHasCardView; +import forge.game.keyword.Keyword; import forge.game.player.PlayerView; import forge.item.InventoryItem; import forge.item.PaperCard; @@ -40,23 +44,29 @@ import forge.util.Utils; public class FChoiceList extends FList implements ActivateHandler { + private String MORPH_KEY = Keyword.MORPH.getReminderText().split("\\. ")[0]; public static FSkinColor getItemColor() { if (Forge.isMobileAdventureMode) return FSkinColor.get(Colors.ADV_CLR_ZEBRA); return FSkinColor.get(Colors.CLR_ZEBRA); } + public static FSkinColor getAltItemColor() { return getItemColor().getContrastColor(-20); } + public static FSkinColor getSelColor() { if (Forge.isMobileAdventureMode) return FSkinColor.get(Colors.ADV_CLR_ACTIVE); return FSkinColor.get(Colors.CLR_ACTIVE); } + public static FSkinColor getBorderColor() { return FList.getForeColor(); } + public static final float DEFAULT_ITEM_HEIGHT = Utils.AVG_FINGER_HEIGHT * 0.75f; + private boolean hasCardView = false; protected final int minChoices, maxChoices; private final CompactModeHandler compactModeHandler = new CompactModeHandler(); @@ -65,15 +75,18 @@ public static FSkinColor getBorderColor() { public FChoiceList(Iterable items) { this(items, null); } + protected FChoiceList(Iterable items, T typeItem) { this(items, 0, 1, typeItem); if (getCount() > 0) { addSelectedIndex(0); //select first item by default } } + public FChoiceList(Iterable items, int minChoices0, int maxChoices0) { this(items, minChoices0, maxChoices0, null); } + protected FChoiceList(Iterable items, int minChoices0, int maxChoices0, T typeItem) { super(items); minChoices = minChoices0; @@ -84,23 +97,23 @@ protected FChoiceList(Iterable items, int minChoices0, int maxChoic final ItemRenderer renderer; if (item instanceof PaperCard) { renderer = new PaperCardItemRenderer(); - } - else if (item instanceof CardView) { + } else if (item instanceof CardView) { renderer = new CardItemRenderer(); - } - else if (item instanceof IHasCardView) { + } else if (item instanceof IHasCardView) { renderer = new IHasCardViewItemRenderer(); - } - else if (item instanceof PlayerView) { + } else if (item instanceof PlayerView) { renderer = new PlayerItemRenderer(); - } - else if (item instanceof Integer || item == FilterOperator.EQUALS) { //allow numeric operators to be selected horizontally + } else if (item instanceof Integer || item == FilterOperator.EQUALS) { //allow numeric operators to be selected horizontally renderer = new NumberRenderer(); - } - else if (item instanceof IHasSkinProp) { + } else if (item instanceof IHasSkinProp) { renderer = new IHasSkinPropRenderer(); - } - else { + } else { + for (Object t : items) { + if (t instanceof CardView) { + hasCardView = true; + break; + } + } renderer = new DefaultItemRenderer(); } setListItemRenderer(new ListItemRenderer() { @@ -130,14 +143,12 @@ public boolean tap(Integer index, T value, float x, float y, int count) { selectedIndices.remove(index); onSelectionChange(); } - } - else if (selectedIndices.size() < maxChoices) { + } else if (selectedIndices.size() < maxChoices) { selectedIndices.add(index); Collections.sort(selectedIndices); //ensure selected indices are sorted onSelectionChange(); } - } - else if (maxChoices > 0) { + } else if (maxChoices > 0) { selectedIndices.clear(); selectedIndices.add(index); onSelectionChange(); @@ -318,9 +329,13 @@ protected boolean drawLineSeparators() { protected abstract class ItemRenderer { public abstract FSkinFont getDefaultFont(); + public abstract float getItemHeight(); + public abstract boolean tap(Integer index, T value, float x, float y, int count); + public abstract boolean longPress(Integer index, T value, float x, float y); + public abstract void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h); public boolean layoutHorizontal() { @@ -331,14 +346,20 @@ public AdvancedSearchFilter getAdvancedSearchFilter(Lis return null; //allow overriding to support advanced search } } + protected class DefaultItemRenderer extends ItemRenderer { @Override public FSkinFont getDefaultFont() { + if (hasCardView) + return FSkinFont.get(14); return FSkinFont.get(12); } @Override public float getItemHeight() { + if (hasCardView) { + return CardRenderer.getCardListItemHeight(compactModeHandler.isCompactMode()); + } if (allowDefaultItemWrap()) { return DEFAULT_ITEM_HEIGHT * 1.5f; //provide more height for wrapping } @@ -347,11 +368,17 @@ public float getItemHeight() { @Override public boolean tap(Integer index, T value, float x, float y, int count) { + if (value instanceof CardView) + return CardRenderer.cardListItemTap(items, index, FChoiceList.this, x, y, count, compactModeHandler.isCompactMode()); return false; } @Override public boolean longPress(Integer index, T value, float x, float y) { + if (value instanceof CardView) { + CardZoom.show(items, index, FChoiceList.this); + return true; + } return false; } @@ -375,6 +402,7 @@ else if (value != null && value.toString().contains(" {")) { } } } + protected class NumberRenderer extends DefaultItemRenderer { @Override public FSkinFont getDefaultFont() { @@ -402,13 +430,16 @@ public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, g.drawText(getChoiceText(value), font, foreColor, x, y, w, h, false, Align.center, true); } } + //simple check for cardview needed on some special renderer for cards - private boolean showAlternate(CardView cardView, String value){ - if(cardView == null) + private boolean showAlternate(CardView cardView, String value) { + if (cardView == null) + return false; + if (cardView.isFaceDown()) return false; boolean showAlt = false; - if(cardView.hasAlternateState()){ - if(cardView.hasBackSide()) + if (cardView.hasAlternateState()) { + if (cardView.hasBackSide()) showAlt = value.contains(cardView.getBackSideName()) || cardView.getAlternateState().getAbilityText().contains(value); else if (cardView.isAdventureCard()) showAlt = value.equals(cardView.getAlternateState().getAbilityText()); @@ -422,6 +453,7 @@ else if (cardView.isSplitCard()) { } return showAlt; } + //special renderer for cards protected class PaperCardItemRenderer extends ItemRenderer { @Override @@ -447,7 +479,7 @@ public boolean longPress(Integer index, T value, float x, float y) { @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - CardRenderer.drawCardListItem(g, font, foreColor, (PaperCard)value, 0, null, x, y, w, h, compactModeHandler.isCompactMode()); + CardRenderer.drawCardListItem(g, font, foreColor, (PaperCard) value, 0, null, x, y, w, h, compactModeHandler.isCompactMode()); } @Override @@ -474,6 +506,7 @@ protected void addDefaultFilters() { return CardManager.createAdvancedSearchFilter(manager); } } + //special renderer for cards protected class CardItemRenderer extends ItemRenderer { @Override @@ -499,9 +532,10 @@ public boolean longPress(Integer index, T value, float x, float y) { @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - CardRenderer.drawCardListItem(g, font, foreColor, (CardView)value, 0, null, x, y, w, h, compactModeHandler.isCompactMode()); + CardRenderer.drawCardListItem(g, font, foreColor, (CardView) value, 0, null, x, y, w, h, compactModeHandler.isCompactMode()); } } + //special renderer for SpellAbilities protected class IHasCardViewItemRenderer extends ItemRenderer { private final TextRenderer textRenderer = new TextRenderer(true); @@ -519,8 +553,19 @@ public float getItemHeight() { @Override public boolean tap(Integer index, T value, float x, float y, int count) { if (x <= VStack.CARD_WIDTH + 2 * FList.PADDING) { - CardView cv = ((IHasCardView)value).getCardView(); - CardZoom.show(cv, showAlternate(cv, value.toString())); + try { + if (value != null && value.toString().contains(MORPH_KEY)) { + Texture morph = ImageCache.getInstance().getImage(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE), false); + if (morph != null) { + CardZoom.show(morph); + return true; + } + } + CardView cv = ((IHasCardView) value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); + } catch (Exception ignored) { + //fixme: java.lang.ClassCastException for cards like Subtlety which should be cancelable instead... + } return true; } return false; @@ -528,8 +573,19 @@ public boolean tap(Integer index, T value, float x, float y, int count) { @Override public boolean longPress(Integer index, T value, float x, float y) { - CardView cv = ((IHasCardView)value).getCardView(); - CardZoom.show(cv, showAlternate(cv, value.toString())); + try { + if (value != null && value.toString().contains(MORPH_KEY)) { + Texture morph = ImageCache.getInstance().getImage(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE), false); + if (morph != null) { + CardZoom.show(morph); + return true; + } + } + CardView cv = ((IHasCardView) value).getCardView(); + CardZoom.show(cv, showAlternate(cv, value.toString())); + } catch (Exception ignored) { + //fixme: java.lang.ClassCastException for cards like Subtlety which should be cancelable instead... + } return true; } @@ -538,11 +594,27 @@ public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, //should fix NPE ie Thief of Sanity, Gonti... etc try { CardView cv = ((IHasCardView) value).getCardView(); - if (cv != null) { - boolean showAlternate = showAlternate(cv, value.toString()); - CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); + if (value != null && value.toString().contains(MORPH_KEY)) { + Texture morph = ImageCache.getInstance().getImage(ImageKeys.getTokenKey(ImageKeys.MORPH_IMAGE), false); + if (morph != null) { + g.drawImage(morph, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT); + } else if (cv != null) { + boolean showAlternate = showAlternate(cv, value.toString()); + if (!cv.isFaceDown()) + CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); + else + CardRenderer.drawCard(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true, false); + } + } else { + if (cv != null) { + boolean showAlternate = showAlternate(cv, value.toString()); + if (!cv.isFaceDown()) + CardRenderer.drawCardWithOverlays(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true); + else + CardRenderer.drawCard(g, cv, x, y, VStack.CARD_WIDTH, VStack.CARD_HEIGHT, CardStackPosition.Top, false, showAlternate, true, false); + } } - } catch (Exception e) { + } catch (Exception ignored) { //fixme: java.lang.ClassCastException for cards like Subtlety which should be cancelable instead... } @@ -552,6 +624,7 @@ public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, textRenderer.drawText(g, value.toString(), font, foreColor, x, y, w, h, y, h, true, Align.left, true); } } + protected class PlayerItemRenderer extends ItemRenderer { @Override public FSkinFont getDefaultFont() { @@ -565,29 +638,36 @@ public float getItemHeight() { @Override public boolean tap(Integer index, T value, float x, float y, int count) { + if (value instanceof CardView) + return CardRenderer.cardListItemTap(items, index, FChoiceList.this, x, y, count, compactModeHandler.isCompactMode()); return false; } @Override public boolean longPress(Integer index, T value, float x, float y) { + if (value instanceof CardView) { + CardZoom.show(items, index, FChoiceList.this); + return true; + } return false; } @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - PlayerView player = (PlayerView)value; + PlayerView player = (PlayerView) value; g.drawImage(MatchController.getPlayerAvatar(player), x - FList.PADDING, y - FList.PADDING, VAvatar.WIDTH, VAvatar.HEIGHT); x += VAvatar.WIDTH; w -= VAvatar.WIDTH; g.drawText(player.getName() + " (" + player.getLife() + ")", font, foreColor, x, y, w, h, false, Align.left, true); } } + protected class IHasSkinPropRenderer extends DefaultItemRenderer { private final TextRenderer textRenderer = new TextRenderer(true); @Override public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) { - FSkinProp skinProp = ((IHasSkinProp)value).getSkinProp(); + FSkinProp skinProp = ((IHasSkinProp) value).getSkinProp(); if (skinProp != null) { float iconSize = h * 0.8f; float offset = (h - iconSize) / 2; From 720ac7f8ca971803bd55554c019501b514b57625 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 27 Oct 2024 09:38:53 +0800 Subject: [PATCH 2/4] fix uncommited changes --- forge-gui-mobile/src/forge/Forge.java | 2 +- .../src/forge/card/CardImageRenderer.java | 2 +- .../src/forge/card/CardRenderer.java | 1 - .../src/forge/itemmanager/ItemManager.java | 83 +++++++++++-------- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index e313ce36b4d..2b95a5b53d4 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -849,7 +849,7 @@ private static void setCurrentScreen(FScreen screen0) { @Override public void render() { if (showFPS) - getFrameRate().update(ImageCache.getInstance().counter, getAssets().manager().getMemoryInMegabytes()); + frameRate.update(ImageCache.getInstance().counter, getAssets().manager().getMemoryInMegabytes()); try { ImageCache.getInstance().allowSingleLoad(); diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 8cce60377c2..e0771825003 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -888,7 +888,7 @@ public static void drawZoom(Graphics g, CardView card, GameView gameView, boolea } } } - CardRenderer.drawFoilEffect(g, card, x, y, w, h, isCurrentCard && canshow && image != ImageCache.getDefaultImage()); + CardRenderer.drawFoilEffect(g, card, x, y, w, h, isCurrentCard && canshow && image != ImageCache.getInstance().getDefaultImage()); } public static void drawDetails(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h) { diff --git a/forge-gui-mobile/src/forge/card/CardRenderer.java b/forge-gui-mobile/src/forge/card/CardRenderer.java index de9d6855088..000d0391dff 100644 --- a/forge-gui-mobile/src/forge/card/CardRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardRenderer.java @@ -697,7 +697,6 @@ public static void drawCard(Graphics g, CardView card, float x, float y, float w //if card has invalid or no texture due to sudden changes in ImageCache, draw CardImageRenderer instead and wait for it to refresh automatically CardImageRenderer.drawCardImage(g, card, showAltState, x, y, w, h, pos, true, false, isChoiceList, !showCardIdOverlay(card)); } - g.setAlphaComposite(oldAlpha); } private static boolean drawGray(CardView c) { diff --git a/forge-gui-mobile/src/forge/itemmanager/ItemManager.java b/forge-gui-mobile/src/forge/itemmanager/ItemManager.java index d1bfa7b27ad..60418090a24 100644 --- a/forge-gui-mobile/src/forge/itemmanager/ItemManager.java +++ b/forge-gui-mobile/src/forge/itemmanager/ItemManager.java @@ -59,6 +59,8 @@ public abstract class ItemManager extends FContainer implements IItemManager, ActivateHandler { + private ItemManager instance; + private float itemLeft = 0f, itemWidth = 0f; private ItemPool pool; protected final ItemManagerModel model; private Predicate filterPredicate = null; @@ -104,6 +106,7 @@ public abstract class ItemManager extends FContainer im * @param wantUnique0 whether this table should display only one item with the same name */ protected ItemManager(final Class genericType0, final boolean wantUnique0) { + instance = this; genericType = genericType0; wantUnique = wantUnique0; model = new ItemManagerModel<>(genericType0); @@ -874,7 +877,11 @@ public void setContextMenuBuilder(ContextMenuBuilder contextMenuBuilder0) { } public void showMenu(boolean delay) { + showMenu(delay, 0f, 0f); + } + public void showMenu(boolean delay, float left, float width) { if (contextMenuBuilder != null && getSelectionCount() > 0) { + itemLeft = left; itemWidth = width; if (contextMenu == null) { contextMenu = new ContextMenu(); } @@ -944,45 +951,55 @@ protected void updateSizeAndPosition() { float w = paneSize.getWidth(); float h = paneSize.getHeight(); - Rectangle bounds = currentView.getSelectionBounds(); - - //try displaying right of selection if possible - float x = bounds.x + bounds.width; - float y = bounds.y; - if (x + w > screenWidth) { - //try displaying left of selection if possible - x = bounds.x - w; - if (x < 0) { - //display below selection if no room left or right of selection - x = bounds.x; - if (w < bounds.width) { - //center below item if needed - x += (bounds.width - w) / 2; - } - if (x + w > screenWidth) { - x = screenWidth - w; + try { + Rectangle bounds = currentView.getSelectionBounds(); + + //try displaying right of selection if possible + float x = bounds.x + bounds.width; + float y = bounds.y; + if (x + w > screenWidth) { + //try displaying left of selection if possible + x = bounds.x - w; + if (x < 0) { + //display below selection if no room left or right of selection + x = bounds.x; + if (w < bounds.width) { + //center below item if needed + x += (bounds.width - w) / 2; + } + if (x + w > screenWidth) { + x = screenWidth - w; + } + y += bounds.height; } - y += bounds.height; - } - } - if (y + h > screenHeight) { - if (y == bounds.y) { - //if displaying to left or right, move up if not enough room - y = screenHeight - h; } - else { - //if displaying below selection and not enough room, display above selection - y -= bounds.height + h; + if (y + h > screenHeight) { + if (y == bounds.y) { + //if displaying to left or right, move up if not enough room + y = screenHeight - h; + } + else { + //if displaying below selection and not enough room, display above selection + y -= bounds.height + h; + } + if (y < 0) { + y = 0; + if (h > bounds.y) { + h = bounds.y; //cut off menu if not enough room above or below selection + } + } } - if (y < 0) { - y = 0; - if (h > bounds.y) { - h = bounds.y; //cut off menu if not enough room above or below selection + if (Forge.isLandscapeMode() && getSelectedItem() instanceof InventoryItem) { + if (instance instanceof SpellShopManager) { + if (instance.currentView == imageView) { + x = instance.itemLeft + instance.itemWidth/2 - this.getWidth()/2; + } } } + setBounds(Math.round(x), Math.round(y), Math.round(w), Math.round(h)); + } catch (Exception ignored) { + //FIXME: IndexOutOfBoundsException on Rectangle bounds = currentView.getSelectionBounds(); } - - setBounds(Math.round(x), Math.round(y), Math.round(w), Math.round(h)); } } From 9bde2075759c7819e07a4869671b2c2f9f0727a3 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 27 Oct 2024 11:39:28 +0800 Subject: [PATCH 3/4] add settings for snapshot notification, removed obsolote java 8 check --- .../src/main/java/forge/control/FControl.java | 25 ++-- .../home/settings/CSubmenuPreferences.java | 9 +- .../home/settings/VSubmenuPreferences.java | 17 ++- .../main/java/forge/view/FTitleBarBase.java | 15 ++- .../src/main/java/forge/view/FView.java | 121 ------------------ .../src/forge/toolbox/FChoiceList.java | 2 +- forge-gui/res/languages/de-DE.properties | 4 +- forge-gui/res/languages/en-US.properties | 4 +- forge-gui/res/languages/es-ES.properties | 4 +- forge-gui/res/languages/fr-FR.properties | 4 +- forge-gui/res/languages/it-IT.properties | 4 +- forge-gui/res/languages/ja-JP.properties | 4 +- forge-gui/res/languages/pt-BR.properties | 4 +- forge-gui/res/languages/zh-CN.properties | 4 +- .../properties/ForgePreferences.java | 5 +- 15 files changed, 67 insertions(+), 159 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/control/FControl.java b/forge-gui-desktop/src/main/java/forge/control/FControl.java index 620fcbdc08b..3a3d5156a4c 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -62,6 +62,7 @@ import forge.screens.deckeditor.CDeckEditorUI; import forge.toolbox.FOptionPane; import forge.toolbox.FSkin; +import forge.util.BuildInfo; import forge.util.FileUtil; import forge.util.Localizer; import forge.util.RestartUtil; @@ -86,7 +87,8 @@ public enum FControl implements KeyEventDispatcher { private boolean altKeyLastDown; private CloseAction closeAction; private final List currentMatches = Lists.newArrayList(); - private String snapsVersion = ""; + private String snapsVersion = "", currentVersion = ""; + private boolean isSnapshot; public enum CloseAction { NONE, @@ -214,19 +216,22 @@ public boolean exitForge() { /** After view and model have been initialized, control can start.*/ public void initialize() { + final ForgePreferences prefs = FModel.getPreferences(); + currentVersion = BuildInfo.getVersionString(); + isSnapshot = currentVersion.contains("SNAPSHOT"); //get version string try { - URL url = new URL("https://downloads.cardforge.org/dailysnapshots/version.txt"); - snapsVersion = FileUtil.readFileToString(url); + if (isSnapshot && prefs.getPrefBoolean(FPref.CHECK_SNAPSHOT_AT_STARTUP)) { + URL url = new URL("https://downloads.cardforge.org/dailysnapshots/version.txt"); + snapsVersion = FileUtil.readFileToString(url); + } - } catch (Exception e) {} + } catch (Exception ignored) {} // Preloads skin components (using progress bar). FSkin.loadFull(true); display = FView.SINGLETON_INSTANCE.getLpnDocument(); - final ForgePreferences prefs = FModel.getPreferences(); - //set ExperimentalNetworkOption from preference boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT); GuiBase.enablePropertyConfig(propertyConfig); @@ -275,9 +280,11 @@ public void componentMoved(final ComponentEvent e) { FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(localizer.getMessage("lblOpeningMainWindow")); SwingUtilities.invokeLater(() -> Singletons.getView().initialize()); } - public String compareVersion(String currentVersion) { - if (currentVersion.isEmpty() || snapsVersion.isEmpty() - || !currentVersion.contains("SNAPSHOT") || currentVersion.equalsIgnoreCase(snapsVersion)) + public boolean isSnapshot() { + return isSnapshot; + } + public String getSnapshotNotification() { + if (!isSnapshot || snapsVersion.isEmpty() || currentVersion.equalsIgnoreCase(snapsVersion)) return ""; return "NEW SNAPSHOT AVAILABLE!!!"; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 1efcd550dbc..efe4a9ba1b2 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -137,6 +137,7 @@ public void initialize() { lstControls.add(Pair.of(view.getCbTimedTargOverlay(), FPref.UI_TIMED_TARGETING_OVERLAY_UPDATES)); lstControls.add(Pair.of(view.getCbCompactMainMenu(), FPref.UI_COMPACT_MAIN_MENU)); lstControls.add(Pair.of(view.getCbUseSentry(), FPref.USE_SENTRY)); + lstControls.add(Pair.of(view.getCbCheckSnapshot(), FPref.CHECK_SNAPSHOT_AT_STARTUP)); lstControls.add(Pair.of(view.getCbPromptFreeBlocks(), FPref.MATCHPREF_PROMPT_FREE_BLOCKS)); lstControls.add(Pair.of(view.getCbPauseWhileMinimized(), FPref.UI_PAUSE_WHILE_MINIMIZED)); lstControls.add(Pair.of(view.getCbWorkshopSyntax(), FPref.DEV_WORKSHOP_SYNTAX)); @@ -192,14 +193,12 @@ public void initialize() { view.getBtnTokenPreviewer().setCommand((UiCommand) CSubmenuPreferences.this::openTokenPreviewer); - view.getBtnResetJavaFutureCompatibilityWarnings().setCommand((UiCommand) () -> { - prefs.setPref(FPref.DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING, false); + view.getBtnContentDirectoryUI().setCommand((UiCommand) CSubmenuPreferences.this::openContentDirectory); + view.getCbCheckSnapshot().addItemListener(e -> { + Singletons.getView().getNavigationBar().setUpdaterVisibility(); prefs.save(); - FOptionPane.showMessageDialog(localizer.getMessage("CompatibilityWarningsReEnabled")); }); - view.getBtnContentDirectoryUI().setCommand((UiCommand) CSubmenuPreferences.this::openContentDirectory); - initializeGameLogVerbosityComboBox(); initializeCloseActionComboBox(); initializeDefaultFontSizeComboBox(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index 485abc426cd..10d4afab6fb 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -1,5 +1,6 @@ package forge.screens.home.settings; +import forge.control.FControl; import forge.control.FControl.CloseAction; import forge.control.KeyboardShortcuts; import forge.control.KeyboardShortcuts.Shortcut; @@ -55,7 +56,6 @@ public enum VSubmenuPreferences implements IVSubmenu { private final FLabel btnDeleteWorkshopUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnDeleteWorkshopUI")).build(); private final FLabel btnUserProfileUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnUserProfileUI")).build(); private final FLabel btnContentDirectoryUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnContentDirectoryUI")).build(); - private final FLabel btnResetJavaFutureCompatibilityWarnings = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnResetJavaFutureCompatibilityWarnings")).build(); private final FLabel btnClearImageCache = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnClearImageCache")).build(); private final FLabel btnTokenPreviewer = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnTokenPreviewer")).build(); @@ -112,6 +112,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final JCheckBox cbShowStormCount = new OptionsCheckBox(localizer.getMessage("cbShowStormCount")); private final JCheckBox cbRemindOnPriority = new OptionsCheckBox(localizer.getMessage("cbRemindOnPriority")); private final JCheckBox cbUseSentry = new OptionsCheckBox(localizer.getMessage("cbUseSentry")); + private final JCheckBox cbCheckSnapshot = new OptionsCheckBox(localizer.getMessage("cbSnapshotUpdate")); private final JCheckBox cbEnableUnknownCards = new OptionsCheckBox(localizer.getMessage("lblEnableUnknownCards")); private final JCheckBox cbEnableNonLegalCards = new OptionsCheckBox(localizer.getMessage("lblEnableNonLegalCards")); private final JCheckBox cbAllowCustomCardsDeckConformance = new OptionsCheckBox(localizer.getMessage("lblAllowCustomCardsInDecks")); @@ -193,7 +194,10 @@ public enum VSubmenuPreferences implements IVSubmenu { pnlPrefs.add(cbUseSentry, titleConstraints); pnlPrefs.add(new NoteLabel(localizer.getMessage("nlUseSentry")), descriptionConstraints); - pnlPrefs.add(btnResetJavaFutureCompatibilityWarnings, "w 300px!, h 30px!, gap 27px 0 0 20px, span 2 1"); + if (FControl.instance.isSnapshot()) { + pnlPrefs.add(cbCheckSnapshot, titleConstraints); + pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSnapshotUpdate")), descriptionConstraints); + } // Gameplay Options pnlPrefs.add(new SectionLabel(localizer.getMessage("GamePlay")), sectionConstraints); @@ -625,6 +629,11 @@ public final JCheckBox getCbUseSentry() { return cbUseSentry; } + /** @return {@link javax.swing.JCheckBox} */ + public final JCheckBox getCbCheckSnapshot() { + return cbCheckSnapshot; + } + /** @return {@link javax.swing.JCheckBox} */ public final JCheckBox getCbRemoveSmall() { return cbRemoveSmall; @@ -985,10 +994,6 @@ public final FLabel getBtnDeleteWorkshopUI() { public final FLabel getBtnClearImageCache() { return btnClearImageCache; } public final FLabel getBtnTokenPreviewer() { return btnTokenPreviewer; } - public final FLabel getBtnResetJavaFutureCompatibilityWarnings() { - return btnResetJavaFutureCompatibilityWarnings; - } - /* (non-Javadoc) * @see forge.gui.framework.IVDoc#getDocumentID() */ diff --git a/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java b/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java index 65457a699fb..de5446c9037 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java +++ b/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java @@ -25,7 +25,6 @@ import forge.toolbox.FSkin.SkinColor; import forge.toolbox.FSkin.SkinnedLabel; import forge.toolbox.FSkin.SkinnedMenuBar; -import forge.util.BuildInfo; import forge.util.Localizer; import forge.util.RSSReader; @@ -95,7 +94,10 @@ protected void addControls() { public abstract void setTitle(String title); public abstract void setIconImage(Image image); - + public void setUpdaterVisibility() { + if (btnUpdateShortcut != null) + btnUpdateShortcut.updateVisibility(); + } public void updateButtons() { boolean fullScreen = owner.isFullScreen(); btnLockTitleBar.setVisible(fullScreen); @@ -424,11 +426,11 @@ public void paintComponent(Graphics g) { public class UpdaterButton extends TitleBarButton { final int MARQUEE_SPEED_DIV = 15; final int REPAINT_WITHIN_MS = 25; - final String displayText = FControl.instance.compareVersion(BuildInfo.getVersionString()); - private UpdaterButton() { + final String displayText = FControl.instance.getSnapshotNotification(); + public UpdaterButton() { setToolTipText(Localizer.getInstance().getMessage("btnCheckForUpdates")); setPreferredSize(new Dimension(160, 25)); - setEnabled(!displayText.isEmpty()); + updateVisibility(); } @Override protected void onClick() { @@ -450,5 +452,8 @@ public void paintComponent(Graphics g) { g2d.drawString(displayText, 0, 17); repaint(REPAINT_WITHIN_MS); } + private void updateVisibility() { + setVisible(!isVisible()); + } } } diff --git a/forge-gui-desktop/src/main/java/forge/view/FView.java b/forge-gui-desktop/src/main/java/forge/view/FView.java index 9c81454c646..843d78aa3e2 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FView.java +++ b/forge-gui-desktop/src/main/java/forge/view/FView.java @@ -2,14 +2,10 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Desktop; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; import java.io.File; -import java.net.URI; import java.util.ArrayList; import java.util.Deque; import java.util.HashSet; @@ -21,15 +17,10 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; -import javax.swing.JTextPane; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; -import javax.swing.text.BadLocationException; -import javax.swing.text.Style; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; import org.apache.commons.lang3.StringUtils; @@ -38,7 +29,6 @@ import forge.Singletons; import forge.gui.ImportDialog; import forge.gui.SOverlayUtils; -import forge.gui.UiCommand; import forge.gui.framework.DragCell; import forge.gui.framework.EDocID; import forge.gui.framework.FScreen; @@ -47,9 +37,7 @@ import forge.gui.framework.SLayoutConstants; import forge.gui.framework.SLayoutIO; import forge.localinstance.properties.ForgeConstants; -import forge.localinstance.properties.ForgePreferences; import forge.localinstance.skin.FSkinProp; -import forge.model.FModel; import forge.screens.bazaar.VBazaarUI; import forge.screens.deckeditor.VDeckEditorUI; import forge.screens.home.VHomeUI; @@ -59,7 +47,6 @@ import forge.toolbox.FAbsolutePositioner; import forge.toolbox.FButton; import forge.toolbox.FLabel; -import forge.toolbox.FOptionPane; import forge.toolbox.FOverlay; import forge.toolbox.FPanel; import forge.toolbox.FProgressBar; @@ -67,7 +54,6 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLayeredPane; import forge.util.BuildInfo; -import forge.util.RuntimeVersion; import net.miginfocom.swing.MigLayout; public enum FView { @@ -250,113 +236,6 @@ public void initialize() { } } - RuntimeVersion javaVersion = RuntimeVersion.of(System.getProperty("java.version")); - - if (javaVersion.getMajor() < 9 && javaVersion.getMinor() < 8 && !FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING)) { - - JPanel updateWarningOverlay = FOverlay.SINGLETON_INSTANCE.getPanel(); - updateWarningOverlay.setLayout(new GridBagLayout()); - - FPanel updateWarningContentPanel = new FPanel(new MigLayout("insets 20, wrap 3")); - - JTextPane textPane = new JTextPane(); - StyledDocument text = textPane.getStyledDocument(); - - Style normalStyle = text.addStyle("normal", null); - Style boldStyle = text.addStyle("bold", null); - - StyleConstants.setBold(normalStyle, false); - StyleConstants.setBold(boldStyle, true); - - try { - text.insertString(text.getLength(), "The next version of Forge will require ", normalStyle); - text.insertString(text.getLength(), "Java 1.8", boldStyle); - text.insertString(text.getLength(), " and will ", normalStyle); - text.insertString(text.getLength(), "no longer run", boldStyle); - text.insertString(text.getLength(), " on Java 1.7. You appear to be running Forge with version ", normalStyle); - text.insertString(text.getLength(), javaVersion.toString(), boldStyle); - text.insertString(text.getLength(), ".\n\nPlease upgrade to the latest version of Java if you plan to update Forge in the future.", normalStyle); - } catch (BadLocationException e) { - e.printStackTrace(); - } - - textPane.setEditable(false); - textPane.setOpaque(false); - textPane.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT).getColor()); - textPane.setBorder(null); - textPane.setFont(FSkin.getRelativeFont(14).getBaseFont()); - - final FLabel btnRemindMeLater = new FLabel.Builder().text("Remind Me Later").hoverable().opaque().build(); - final FLabel btnDoNotRemindMe = new FLabel.Builder().text("Don't Remind Me Again").hoverable().opaque().build(); - final FLabel btnDownloadLatestJava = new FLabel.Builder().text("Download Latest Java").hoverable().opaque().build(); - - String buttonConstraints = "w 200px!, h 30px!"; - updateWarningContentPanel.add(textPane, "w 600px!, h 100px!, span 3 1"); - updateWarningContentPanel.add(btnRemindMeLater, buttonConstraints); - updateWarningContentPanel.add(btnDoNotRemindMe, buttonConstraints + ", gap 10px 10px 0 0"); - - final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; - if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) { - updateWarningContentPanel.add(btnDownloadLatestJava, buttonConstraints); - } - - GridBagConstraints constraints = new GridBagConstraints(); - constraints.weightx = constraints.weighty = 1; - - updateWarningOverlay.add(updateWarningContentPanel, constraints); - - btnRemindMeLater.setCommand(new UiCommand() { - /** - * - */ - private static final long serialVersionUID = 1L; - - @Override - public void run() { - SOverlayUtils.hideOverlay(); - } - }); - - btnDoNotRemindMe.setCommand(new UiCommand() { - /** - * - */ - private static final long serialVersionUID = 1L; - - @Override - public void run() { - if (FOptionPane.showConfirmDialog("Are you sure? You can re-enable this warning in Forge's general preferences.")) { - FModel.getPreferences().setPref(ForgePreferences.FPref.DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING, true); - FModel.getPreferences().save(); - SOverlayUtils.hideOverlay(); - } - } - }); - - btnDownloadLatestJava.setCommand(new UiCommand() { - /** - * - */ - private static final long serialVersionUID = 1L; - - @Override - public void run() { - try { - assert desktop != null; - desktop.browse(new URI("http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html")); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - SwingUtilities.invokeLater(() -> { - SOverlayUtils.showOverlay(); - SwingUtilities.invokeLater(btnRemindMeLater::requestFocusInWindow); - }); - - } - //start background music SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS); diff --git a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java index 310510ca523..f487c5b0dcc 100644 --- a/forge-gui-mobile/src/forge/toolbox/FChoiceList.java +++ b/forge-gui-mobile/src/forge/toolbox/FChoiceList.java @@ -44,7 +44,7 @@ import forge.util.Utils; public class FChoiceList extends FList implements ActivateHandler { - private String MORPH_KEY = Keyword.MORPH.getReminderText().split("\\. ")[0]; + private final String MORPH_KEY = Keyword.MORPH.getReminderText().split("\\. ")[0]; public static FSkinColor getItemColor() { if (Forge.isMobileAdventureMode) return FSkinColor.get(Colors.ADV_CLR_ZEBRA); diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 7be69997848..42452727b63 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -3439,4 +3439,6 @@ lblTake=Nehmen lblRefund=Erstattung lblForgeUpdateMessage=Das Update wurde hier heruntergeladen: {0}.\nForge wird nun beendet und führt den Updater aus. lblRelease=Freigeben -lblSnapshot=Schnappschuss \ No newline at end of file +lblSnapshot=Schnappschuss +cbSnapshotUpdate=Überprüfen Sie Snapshot-Updates beim Start. +nlSnapshotUpdate=Wenn diese Option aktiviert ist, werden Snapshot-Updates beim Start automatisch überprüft und die Benachrichtigung in der Titelleiste angezeigt. \ No newline at end of file diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 8fff4005151..71ac0e73045 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -3172,4 +3172,6 @@ lblTake=Take lblRefund=Refund lblForgeUpdateMessage=Update has been downloaded here: {0}.\nForge will now exit and run the updater. lblRelease=Release -lblSnapshot=Snapshot \ No newline at end of file +lblSnapshot=Snapshot +cbSnapshotUpdate=Check snapshot updates on startup. +nlSnapshotUpdate=When enabled, automatically check snapshot updates on startup and displays the notification on the title bar. \ No newline at end of file diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 102bbc1daaa..27aa763977f 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -3453,4 +3453,6 @@ lblTake=Llevar lblRefund=Reembolso lblForgeUpdateMessage=La actualización se descargó aquí: {0}.\nForge ahora saldrá y ejecutará el actualizador. lblRelease=Liberar -lblSnapshot=Instantánea \ No newline at end of file +lblSnapshot=Instantánea +cbSnapshotUpdate=Verifique las actualizaciones de instantáneas al inicio. +nlSnapshotUpdate=Cuando está habilitado, verifica automáticamente las actualizaciones de instantáneas al inicio y muestra la notificación en la barra de título. \ No newline at end of file diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 67d2ecd1d7a..4449dfa0486 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -3447,4 +3447,6 @@ lblTake=Prendre lblRefund=Remboursement lblForgeUpdateMessage=La mise à jour a été téléchargée ici: {0}.\nForge va maintenant quitter et exécuter le programme de mise à jour. lblRelease=Libérer -lblSnapshot=Instantané \ No newline at end of file +lblSnapshot=Instantané +cbSnapshotUpdate=Vérifiez les mises à jour des instantanés au démarrage. +nlSnapshotUpdate=Lorsqu'il est activé, vérifie automatiquement les mises à jour des instantanés au démarrage et affiche la notification sur la barre de titre. \ No newline at end of file diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 73947da262b..5c413d912e4 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -3445,4 +3445,6 @@ lblTake=Prendere lblRefund=Rimborso lblForgeUpdateMessage=L'aggiornamento è stato scaricato qui: {0}.\nForge ora uscirà ed eseguirà l'aggiornamento. lblRelease=Pubblicazione -lblSnapshot=Istantanea \ No newline at end of file +lblSnapshot=Istantanea +cbSnapshotUpdate=Controlla gli aggiornamenti delle istantanee all'avvio. +nlSnapshotUpdate=Se abilitato, controlla automaticamente gli aggiornamenti delle istantanee all'avvio e visualizza la notifica sulla barra del titolo. \ No newline at end of file diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index bf0e2bb66c6..bda6324926b 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -3441,4 +3441,6 @@ lblTake=取る lblRefund=返金 lblForgeUpdateMessage=アップデートはここにダウンロードされました: {0}。\nForge が終了し、アップデーターが実行されます。 lblRelease=リリース -lblSnapshot=スナップショット \ No newline at end of file +lblSnapshot=スナップショット +cbSnapshotUpdate=起動時にスナップショットの更新を確認します。 +nlSnapshotUpdate=有効にすると、起動時にスナップショットの更新が自動的にチェックされ、タイトル バーに通知が表示されます。 \ No newline at end of file diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index a6413fe876c..ca4f5423007 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -3531,4 +3531,6 @@ lblTake=Pegar lblRefund=Reembolso lblForgeUpdateMessage=A atualização foi baixada aqui: {0}.\nO Forge agora sairá e executará o atualizador. lblRelease=Liberar -lblSnapshot=Instantâneo \ No newline at end of file +lblSnapshot=Instantâneo +cbSnapshotUpdate=Verifique as atualizações de instantâneos na inicialização. +nlSnapshotUpdate=Quando ativado, verifica automaticamente as atualizações do snapshot na inicialização e exibe a notificação na barra de título. \ No newline at end of file diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 5a5fb9d4c95..44159ee3ab0 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -3432,4 +3432,6 @@ lblTake=拿 lblRefund=退款 lblForgeUpdateMessage=更新已在此处下载:{0}。\nForge 现在将退出并运行更新程序。 lblRelease=发布 -lblSnapshot=快照 \ No newline at end of file +lblSnapshot=快照 +cbSnapshotUpdate=启动时检查快照更新。 +nlSnapshotUpdate=启用后,启动时自动检查快照更新并在标题栏上显示通知。 \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java index c398fa71096..6ada470ae44 100644 --- a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java @@ -182,12 +182,9 @@ public enum FPref { UI_LANGUAGE("en-US"), - /** This is used to disable the future version compatibility warning dialog for Java 8. */ - //TODO This should be removed after the update that requires Java 8. - DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"), - AUTO_UPDATE("none"), USE_SENTRY("false"), // this controls whether automated bug reporting is done or not + CHECK_SNAPSHOT_AT_STARTUP("true"), MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game MATCHPREF_PROMPT_FREE_BLOCKS("false"), From 89bc9c126f563400842f1948bf69807b74cc509f Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 27 Oct 2024 13:00:39 +0800 Subject: [PATCH 4/4] update snapshot notification message --- .../src/main/java/forge/control/FControl.java | 33 ++++++++++--------- .../main/java/forge/view/FTitleBarBase.java | 7 ++-- forge-gui/res/languages/de-DE.properties | 1 + forge-gui/res/languages/en-US.properties | 1 + forge-gui/res/languages/es-ES.properties | 1 + forge-gui/res/languages/fr-FR.properties | 1 + forge-gui/res/languages/it-IT.properties | 1 + forge-gui/res/languages/ja-JP.properties | 1 + forge-gui/res/languages/pt-BR.properties | 1 + forge-gui/res/languages/zh-CN.properties | 1 + 10 files changed, 30 insertions(+), 18 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/control/FControl.java b/forge-gui-desktop/src/main/java/forge/control/FControl.java index 3a3d5156a4c..fbd7d496816 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -89,6 +89,7 @@ public enum FControl implements KeyEventDispatcher { private final List currentMatches = Lists.newArrayList(); private String snapsVersion = "", currentVersion = ""; private boolean isSnapshot; + private Localizer localizer; public enum CloseAction { NONE, @@ -96,6 +97,12 @@ public enum CloseAction { EXIT_FORGE } + public Localizer getLocalizer() { + if (localizer == null) + localizer = Localizer.getInstance(); + return localizer; + } + private boolean hasCurrentMatches() { cleanMatches(); return !currentMatches.isEmpty(); @@ -128,16 +135,15 @@ private void cleanMatches() { * instantiated separately by each screen's top level view class. */ FControl() { - final Localizer localizer = Localizer.getInstance(); Singletons.getView().getFrame().addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent e) { switch (closeAction) { case NONE: //prompt user for close action if not previously specified - final List options = ImmutableList.of(localizer.getMessage("lblCloseScreen"), localizer.getMessage("lblExitForge"), localizer.getMessage("lblCancel")); + final List options = ImmutableList.of(getLocalizer().getMessage("lblCloseScreen"), getLocalizer().getMessage("lblExitForge"), getLocalizer().getMessage("lblCancel")); final int reply = FOptionPane.showOptionDialog( - localizer.getMessage("txCloseAction1") + "\n\n" + localizer.getMessage("txCloseAction2"), - localizer.getMessage("titCloseAction"), + getLocalizer().getMessage("txCloseAction1") + "\n\n" + getLocalizer().getMessage("txCloseAction2"), + getLocalizer().getMessage("titCloseAction"), FOptionPane.INFORMATION_ICON, options, 2); @@ -180,14 +186,13 @@ public void setCloseAction(final CloseAction closeAction0) { } public boolean canExitForge(final boolean forRestart) { - final Localizer localizer = Localizer.getInstance(); - final String action = (forRestart ? localizer.getMessage("lblRestart") : localizer.getMessage("lblExit")); - String userPrompt =(forRestart ? localizer.getMessage("lblAreYouSureYouWishRestartForge") : localizer.getMessage("lblAreYouSureYouWishExitForge")); + final String action = (forRestart ? getLocalizer().getMessage("lblRestart") : getLocalizer().getMessage("lblExit")); + String userPrompt =(forRestart ? getLocalizer().getMessage("lblAreYouSureYouWishRestartForge") : getLocalizer().getMessage("lblAreYouSureYouWishExitForge")); final boolean hasCurrentMatches = hasCurrentMatches(); if (hasCurrentMatches) { - userPrompt = localizer.getMessage("lblOneOrMoreGamesActive") + ". " + userPrompt; + userPrompt = getLocalizer().getMessage("lblOneOrMoreGamesActive") + ". " + userPrompt; } - if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, localizer.getMessage("lblCancel"), !hasCurrentMatches)) { //default Yes if no game active + if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, getLocalizer().getMessage("lblCancel"), !hasCurrentMatches)) { //default Yes if no game active return false; } return CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true); @@ -238,8 +243,7 @@ public void initialize() { closeAction = CloseAction.valueOf(prefs.getPref(FPref.UI_CLOSE_ACTION)); - final Localizer localizer = Localizer.getInstance(); - FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(localizer.getMessage("lblLoadingQuest")); + FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(getLocalizer().getMessage("lblLoadingQuest")); // Preload quest data if present final File dirQuests = new File(ForgeConstants.QUEST_SAVE_DIR); final String questname = FModel.getQuestPreferences().getPref(QPref.CURRENT_QUEST); @@ -277,7 +281,7 @@ public void componentMoved(final ComponentEvent e) { FView.SINGLETON_INSTANCE.getLpnDocument().addComponentListener(SResizingUtil.getWindowResizeListener()); setGlobalKeyboardHandler(); - FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(localizer.getMessage("lblOpeningMainWindow")); + FView.SINGLETON_INSTANCE.setSplashProgessBarMessage(getLocalizer().getMessage("lblOpeningMainWindow")); SwingUtilities.invokeLater(() -> Singletons.getView().initialize()); } public boolean isSnapshot() { @@ -286,7 +290,7 @@ public boolean isSnapshot() { public String getSnapshotNotification() { if (!isSnapshot || snapsVersion.isEmpty() || currentVersion.equalsIgnoreCase(snapsVersion)) return ""; - return "NEW SNAPSHOT AVAILABLE!!!"; + return getLocalizer().getMessage("lblNewSnapshotVersion", snapsVersion); } private void setGlobalKeyboardHandler() { @@ -339,8 +343,7 @@ public boolean setCurrentScreen(final FScreen screen, final boolean previousScre try { SLayoutIO.loadLayout(null); } catch (final InvalidLayoutFileException ex) { - final Localizer localizer = Localizer.getInstance(); - SOptionPane.showMessageDialog(String.format(localizer.getMessage("lblerrLoadingLayoutFile"), screen.getTabCaption()), "Warning!"); + SOptionPane.showMessageDialog(String.format(getLocalizer().getMessage("lblerrLoadingLayoutFile"), screen.getTabCaption()), "Warning!"); if (screen.deleteLayoutFile()) { SLayoutIO.loadLayout(null); //try again } diff --git a/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java b/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java index de5446c9037..efae38f2f95 100644 --- a/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java +++ b/forge-gui-desktop/src/main/java/forge/view/FTitleBarBase.java @@ -424,8 +424,9 @@ public void paintComponent(Graphics g) { } } public class UpdaterButton extends TitleBarButton { - final int MARQUEE_SPEED_DIV = 15; - final int REPAINT_WITHIN_MS = 25; + final int MARQUEE_SPEED_DIV = 50; + final int REPAINT_WITHIN_MS = 50; + final int wMod = 60; final String displayText = FControl.instance.getSnapshotNotification(); public UpdaterButton() { setToolTipText(Localizer.getInstance().getMessage("btnCheckForUpdates")); @@ -442,7 +443,7 @@ protected void onClick() { } @Override public void paintComponent(Graphics g) { - g.translate((int)((System.currentTimeMillis() / MARQUEE_SPEED_DIV) % (getWidth() * 2)) - getWidth(), 0); + g.translate(-((int)((System.currentTimeMillis() / MARQUEE_SPEED_DIV) % ((getWidth() + wMod) * 2)) - (getWidth() + wMod)), 0); super.paintComponent(g); int thickness = 2; Graphics2D g2d = (Graphics2D) g; diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 42452727b63..d0e59c3ad83 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -3440,5 +3440,6 @@ lblRefund=Erstattung lblForgeUpdateMessage=Das Update wurde hier heruntergeladen: {0}.\nForge wird nun beendet und führt den Updater aus. lblRelease=Freigeben lblSnapshot=Schnappschuss +lblNewSnapshotVersion=NEU FORGE-{0}! cbSnapshotUpdate=Überprüfen Sie Snapshot-Updates beim Start. nlSnapshotUpdate=Wenn diese Option aktiviert ist, werden Snapshot-Updates beim Start automatisch überprüft und die Benachrichtigung in der Titelleiste angezeigt. \ No newline at end of file diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 71ac0e73045..2976acc4c85 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -3173,5 +3173,6 @@ lblRefund=Refund lblForgeUpdateMessage=Update has been downloaded here: {0}.\nForge will now exit and run the updater. lblRelease=Release lblSnapshot=Snapshot +lblNewSnapshotVersion=NEW FORGE-{0}! cbSnapshotUpdate=Check snapshot updates on startup. nlSnapshotUpdate=When enabled, automatically check snapshot updates on startup and displays the notification on the title bar. \ No newline at end of file diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 27aa763977f..709599f586e 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -3454,5 +3454,6 @@ lblRefund=Reembolso lblForgeUpdateMessage=La actualización se descargó aquí: {0}.\nForge ahora saldrá y ejecutará el actualizador. lblRelease=Liberar lblSnapshot=Instantánea +lblNewSnapshotVersion=NUEVO FORGE-{0}! cbSnapshotUpdate=Verifique las actualizaciones de instantáneas al inicio. nlSnapshotUpdate=Cuando está habilitado, verifica automáticamente las actualizaciones de instantáneas al inicio y muestra la notificación en la barra de título. \ No newline at end of file diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 4449dfa0486..665c8a3433b 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -3448,5 +3448,6 @@ lblRefund=Remboursement lblForgeUpdateMessage=La mise à jour a été téléchargée ici: {0}.\nForge va maintenant quitter et exécuter le programme de mise à jour. lblRelease=Libérer lblSnapshot=Instantané +lblNewSnapshotVersion=NOUVEAU FORGE–{0}! cbSnapshotUpdate=Vérifiez les mises à jour des instantanés au démarrage. nlSnapshotUpdate=Lorsqu'il est activé, vérifie automatiquement les mises à jour des instantanés au démarrage et affiche la notification sur la barre de titre. \ No newline at end of file diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 5c413d912e4..23d0b728b7f 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -3446,5 +3446,6 @@ lblRefund=Rimborso lblForgeUpdateMessage=L'aggiornamento è stato scaricato qui: {0}.\nForge ora uscirà ed eseguirà l'aggiornamento. lblRelease=Pubblicazione lblSnapshot=Istantanea +lblNewSnapshotVersion=NUOVO FORGE-{0}! cbSnapshotUpdate=Controlla gli aggiornamenti delle istantanee all'avvio. nlSnapshotUpdate=Se abilitato, controlla automaticamente gli aggiornamenti delle istantanee all'avvio e visualizza la notifica sulla barra del titolo. \ No newline at end of file diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index bda6324926b..6920b588e0e 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -3442,5 +3442,6 @@ lblRefund=返金 lblForgeUpdateMessage=アップデートはここにダウンロードされました: {0}。\nForge が終了し、アップデーターが実行されます。 lblRelease=リリース lblSnapshot=スナップショット +lblNewSnapshotVersion=新しい FORGE-{0}! cbSnapshotUpdate=起動時にスナップショットの更新を確認します。 nlSnapshotUpdate=有効にすると、起動時にスナップショットの更新が自動的にチェックされ、タイトル バーに通知が表示されます。 \ No newline at end of file diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index ca4f5423007..ee91a34fb19 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -3532,5 +3532,6 @@ lblRefund=Reembolso lblForgeUpdateMessage=A atualização foi baixada aqui: {0}.\nO Forge agora sairá e executará o atualizador. lblRelease=Liberar lblSnapshot=Instantâneo +lblNewSnapshotVersion=NOVO FORGE-{0}! cbSnapshotUpdate=Verifique as atualizações de instantâneos na inicialização. nlSnapshotUpdate=Quando ativado, verifica automaticamente as atualizações do snapshot na inicialização e exibe a notificação na barra de título. \ No newline at end of file diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 44159ee3ab0..1affbd7a025 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -3433,5 +3433,6 @@ lblRefund=退款 lblForgeUpdateMessage=更新已在此处下载:{0}。\nForge 现在将退出并运行更新程序。 lblRelease=发布 lblSnapshot=快照 +lblNewSnapshotVersion=新 FORGE-{0}! cbSnapshotUpdate=启动时检查快照更新。 nlSnapshotUpdate=启用后,启动时自动检查快照更新并在标题栏上显示通知。 \ No newline at end of file