mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-14 09:48:02 +00:00
refactor libgdx static objects to be disposed
-fixes memory leaks since these objects are not properly disposed by the GC -Textures, BitmapFonts and others should be disposed manually if not loaded in the assetmanager
This commit is contained in:
@@ -55,7 +55,6 @@ import java.io.File;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -104,8 +103,7 @@ public class Forge implements ApplicationListener {
|
||||
public static boolean enablePreloadExtendedArt = false;
|
||||
public static boolean isTabletDevice = false;
|
||||
public static String locale = "en-US";
|
||||
public Assets cardAssets;
|
||||
public Assets otherAssets;
|
||||
public Assets assets;
|
||||
public static boolean hdbuttons = false;
|
||||
public static boolean hdstart = false;
|
||||
public static boolean isPortraitMode = false;
|
||||
@@ -166,8 +164,7 @@ public class Forge implements ApplicationListener {
|
||||
// don't allow to read and process
|
||||
ForgeConstants.SPRITE_CARDBG_FILE = "";
|
||||
}
|
||||
cardAssets = new Assets();
|
||||
otherAssets = new Assets();
|
||||
assets = new Assets();
|
||||
graphics = new Graphics();
|
||||
splashScreen = new SplashScreen();
|
||||
frameRate = new FrameRate();
|
||||
@@ -954,8 +951,7 @@ public class Forge implements ApplicationListener {
|
||||
currentScreen.onClose(null);
|
||||
currentScreen = null;
|
||||
}
|
||||
cardAssets.dispose();
|
||||
otherAssets.dispose();
|
||||
assets.dispose();
|
||||
Dscreens.clear();
|
||||
graphics.dispose();
|
||||
SoundSystem.instance.dispose();
|
||||
@@ -967,11 +963,8 @@ public class Forge implements ApplicationListener {
|
||||
/** Retrieve assets.
|
||||
* @param other if set to true returns otherAssets otherwise returns cardAssets
|
||||
*/
|
||||
public static Assets getAssets(boolean other) {
|
||||
if (other)
|
||||
return ((Forge)Gdx.app.getApplicationListener()).otherAssets;
|
||||
else
|
||||
return ((Forge)Gdx.app.getApplicationListener()).cardAssets;
|
||||
public static Assets getAssets() {
|
||||
return ((Forge)Gdx.app.getApplicationListener()).assets;
|
||||
}
|
||||
public static boolean switchScene(Scene newScene) {
|
||||
if (currentScene != null) {
|
||||
|
||||
@@ -120,11 +120,11 @@ public class Config {
|
||||
|
||||
public TextureAtlas getAtlas(String spriteAtlas) {
|
||||
String fileName = getFile(spriteAtlas).path();
|
||||
if (!Forge.getAssets(true).manager.contains(fileName, TextureAtlas.class)) {
|
||||
Forge.getAssets(true).manager.load(fileName, TextureAtlas.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(fileName);
|
||||
if (!Forge.getAssets().others.contains(fileName, TextureAtlas.class)) {
|
||||
Forge.getAssets().others.load(fileName, TextureAtlas.class);
|
||||
Forge.getAssets().others.finishLoadingAsset(fileName);
|
||||
}
|
||||
return Forge.getAssets(true).manager.get(fileName);
|
||||
return Forge.getAssets().others.get(fileName);
|
||||
}
|
||||
public SettingData getSettingData()
|
||||
{
|
||||
|
||||
@@ -2,12 +2,28 @@ package forge.assets;
|
||||
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.assets.loaders.resolvers.AbsoluteFileHandleResolver;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Assets implements Disposable {
|
||||
public AssetManager manager = new AssetManager(new AbsoluteFileHandleResolver());
|
||||
public AssetManager cards = new AssetManager(new AbsoluteFileHandleResolver());
|
||||
public AssetManager others = new AssetManager(new AbsoluteFileHandleResolver());
|
||||
public HashMap<Integer, FSkinFont> fonts = new HashMap<>();
|
||||
public ObjectMap<Integer, BitmapFont> counterFonts = new ObjectMap<>();
|
||||
public ObjectMap<String, Texture> generatedCards = new ObjectMap<>(512);
|
||||
@Override
|
||||
public void dispose() {
|
||||
manager.dispose();
|
||||
cards.dispose();
|
||||
others.dispose();
|
||||
for (BitmapFont bitmapFont : counterFonts.values())
|
||||
bitmapFont.dispose();
|
||||
for (Texture texture : generatedCards.values())
|
||||
texture.dispose();
|
||||
for (FSkinFont fSkinFont : fonts.values())
|
||||
fSkinFont.font.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class FSkin {
|
||||
* the skin name
|
||||
*/
|
||||
public static void loadLight(String skinName, final SplashScreen splashScreen) {
|
||||
AssetManager manager = Forge.getAssets(true).manager;
|
||||
AssetManager manager = Forge.getAssets().others;
|
||||
preferredName = skinName.toLowerCase().replace(' ', '_');
|
||||
|
||||
//reset hd buttons/icons
|
||||
@@ -236,7 +236,7 @@ public class FSkin {
|
||||
parameter.magFilter = Texture.TextureFilter.Linear;
|
||||
}
|
||||
|
||||
AssetManager manager = Forge.getAssets(true).manager;
|
||||
AssetManager manager = Forge.getAssets().others;
|
||||
|
||||
// Grab and test various sprite files.
|
||||
final FileHandle f1 = getDefaultSkinFile(SourceFile.ICONS.getFilename());
|
||||
|
||||
@@ -3,7 +3,6 @@ package forge.assets;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
@@ -39,7 +38,6 @@ public class FSkinFont {
|
||||
private static final int MAX_FONT_SIZE_MANY_GLYPHS = 36;
|
||||
|
||||
private static final String TTF_FILE = "font1.ttf";
|
||||
private static final HashMap<Integer, FSkinFont> fonts = new HashMap<>();
|
||||
|
||||
private static final String commonCharacterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"
|
||||
+ "nopqrstuvwxyz1234567890\"!?'.,;:()[]{}<>|/@\\^$-%+=#_&*\u2014"
|
||||
@@ -58,10 +56,10 @@ public class FSkinFont {
|
||||
return _get((int)Utils.scale(unscaledSize));
|
||||
}
|
||||
public static FSkinFont _get(final int scaledSize) {
|
||||
FSkinFont skinFont = fonts.get(scaledSize);
|
||||
FSkinFont skinFont = Forge.getAssets().fonts.get(scaledSize);
|
||||
if (skinFont == null) {
|
||||
skinFont = new FSkinFont(scaledSize);
|
||||
fonts.put(scaledSize, skinFont);
|
||||
Forge.getAssets().fonts.put(scaledSize, skinFont);
|
||||
}
|
||||
return skinFont;
|
||||
}
|
||||
@@ -97,14 +95,14 @@ public class FSkinFont {
|
||||
}
|
||||
|
||||
public static void updateAll() {
|
||||
for (FSkinFont skinFont : fonts.values()) {
|
||||
for (FSkinFont skinFont : Forge.getAssets().fonts.values()) {
|
||||
skinFont.updateFont();
|
||||
}
|
||||
}
|
||||
|
||||
private final int fontSize;
|
||||
private final float scale;
|
||||
private BitmapFont font;
|
||||
BitmapFont font;
|
||||
|
||||
private FSkinFont(int fontSize0) {
|
||||
if (fontSize0 > MAX_FONT_SIZE) {
|
||||
@@ -400,16 +398,13 @@ public class FSkinFont {
|
||||
if (fontFile != null && fontFile.exists()) {
|
||||
final BitmapFontData data = new BitmapFontData(fontFile, false);
|
||||
String finalFontName = fontName;
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() { //font must be initialized on UI thread
|
||||
try {
|
||||
font = new BitmapFont(data, (TextureRegion) null, true);
|
||||
found[0] = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
found[0] = false;
|
||||
}
|
||||
FThreads.invokeInEdtNowOrLater(() -> { //font must be initialized on UI thread
|
||||
try {
|
||||
font = new BitmapFont(data, (TextureRegion) null, true);
|
||||
found[0] = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
found[0] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,9 +131,9 @@ public enum FSkinTexture implements FImage {
|
||||
if (preferredFile.path().contains("fallback_skin")) {
|
||||
texture = new Texture(preferredFile);
|
||||
} else {
|
||||
Forge.getAssets(true).manager.load(preferredFile.path(), Texture.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(preferredFile.path());
|
||||
texture = Forge.getAssets(true).manager.get(preferredFile.path(), Texture.class);
|
||||
Forge.getAssets().others.load(preferredFile.path(), Texture.class);
|
||||
Forge.getAssets().others.finishLoadingAsset(preferredFile.path());
|
||||
texture = Forge.getAssets().others.get(preferredFile.path(), Texture.class);
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
@@ -155,9 +155,9 @@ public enum FSkinTexture implements FImage {
|
||||
if (defaultFile.path().contains("fallback_skin")) {
|
||||
texture = new Texture(defaultFile);
|
||||
} else {
|
||||
Forge.getAssets(true).manager.load(defaultFile.path(), Texture.class);
|
||||
Forge.getAssets(true).manager.finishLoadingAsset(defaultFile.path());
|
||||
texture = Forge.getAssets(true).manager.get(defaultFile.path(), Texture.class);
|
||||
Forge.getAssets().others.load(defaultFile.path(), Texture.class);
|
||||
Forge.getAssets().others.finishLoadingAsset(defaultFile.path());
|
||||
texture = Forge.getAssets().others.get(defaultFile.path(), Texture.class);
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
|
||||
@@ -97,7 +97,6 @@ public class ImageCache {
|
||||
public static FImage BlackBorder = FSkinImage.IMG_BORDER_BLACK;
|
||||
public static FImage WhiteBorder = FSkinImage.IMG_BORDER_WHITE;
|
||||
private static final ObjectMap<String, Pair<String, Boolean>> imageBorder = new ObjectMap<>(1024);
|
||||
private static final ObjectMap<String, Texture> generatedCards = new ObjectMap<>(512);
|
||||
|
||||
private static boolean imageLoaded, delayLoadRequested;
|
||||
public static void allowSingleLoad() {
|
||||
@@ -121,11 +120,11 @@ public class ImageCache {
|
||||
ImageKeys.clearMissingCards();
|
||||
}
|
||||
public static void clearGeneratedCards() {
|
||||
generatedCards.clear();
|
||||
Forge.getAssets().generatedCards.clear();
|
||||
}
|
||||
public static void disposeTextures(){
|
||||
CardRenderer.clearcardArtCache();
|
||||
Forge.getAssets(false).manager.clear();
|
||||
Forge.getAssets().cards.clear();
|
||||
}
|
||||
|
||||
public static Texture getImage(InventoryItem ii) {
|
||||
@@ -134,7 +133,9 @@ public class ImageCache {
|
||||
if(imageKey.startsWith(ImageKeys.CARD_PREFIX) || imageKey.startsWith(ImageKeys.TOKEN_PREFIX))
|
||||
return getImage(ii.getImageKey(false), true, false);
|
||||
}
|
||||
return getImage(ii.getImageKey(false), true, true);
|
||||
boolean useDefaultNotFound = imageKey != null && !(imageKey.startsWith(ImageKeys.PRECON_PREFIX) || imageKey.startsWith(ImageKeys.FATPACK_PREFIX)
|
||||
|| imageKey.startsWith(ImageKeys.BOOSTERBOX_PREFIX) || imageKey.startsWith(ImageKeys.BOOSTER_PREFIX) || imageKey.startsWith(ImageKeys.TOURNAMENTPACK_PREFIX));
|
||||
return getImage(ii.getImageKey(false), useDefaultNotFound, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,33 +266,40 @@ public class ImageCache {
|
||||
if (file == null)
|
||||
return null;
|
||||
if (!otherCache && Forge.enableUIMask.equals("Full") && isBorderless(imageKey))
|
||||
return generatedCards.get(imageKey);
|
||||
return Forge.getAssets(otherCache).manager.get(file.getPath(), Texture.class, false);
|
||||
return Forge.getAssets().generatedCards.get(imageKey);
|
||||
if (otherCache)
|
||||
return Forge.getAssets().others.get(file.getPath(), Texture.class, false);
|
||||
return Forge.getAssets().cards.get(file.getPath(), Texture.class, false);
|
||||
}
|
||||
static Texture loadAsset(String imageKey, File file, boolean otherCache) {
|
||||
if (file == null)
|
||||
return null;
|
||||
syncQ.add(file.getPath());
|
||||
if (!otherCache && Forge.getAssets(false).manager.getLoadedAssets() > maxCardCapacity) {
|
||||
unloadCardTextures(Forge.getAssets(false).manager);
|
||||
if (!otherCache && Forge.getAssets().cards.getLoadedAssets() > maxCardCapacity) {
|
||||
unloadCardTextures(Forge.getAssets().cards);
|
||||
return null;
|
||||
}
|
||||
String fileName = file.getPath();
|
||||
//load to assetmanager
|
||||
Forge.getAssets(otherCache).manager.load(fileName, Texture.class, Forge.isTextureFilteringEnabled() ? filtered : defaultParameter);
|
||||
Forge.getAssets(otherCache).manager.finishLoadingAsset(fileName);
|
||||
if (otherCache) {
|
||||
Forge.getAssets().others.load(fileName, Texture.class, Forge.isTextureFilteringEnabled() ? filtered : defaultParameter);
|
||||
Forge.getAssets().others.finishLoadingAsset(fileName);
|
||||
} else {
|
||||
Forge.getAssets().cards.load(fileName, Texture.class, Forge.isTextureFilteringEnabled() ? filtered : defaultParameter);
|
||||
Forge.getAssets().cards.finishLoadingAsset(fileName);
|
||||
}
|
||||
//return loaded assets
|
||||
if (otherCache) {
|
||||
return Forge.getAssets(true).manager.get(fileName, Texture.class, false);
|
||||
return Forge.getAssets().others.get(fileName, Texture.class, false);
|
||||
} else {
|
||||
Texture t = Forge.getAssets(false).manager.get(fileName, Texture.class, false);
|
||||
Texture t = Forge.getAssets().cards.get(fileName, Texture.class, false);
|
||||
//if full bordermasking is enabled, update the border color
|
||||
if (Forge.enableUIMask.equals("Full")) {
|
||||
boolean borderless = isBorderless(imageKey);
|
||||
updateBorders(t.toString(), borderless ? Pair.of(Color.valueOf("#171717").toString(), false): isCloserToWhite(getpixelColor(t)));
|
||||
//if borderless, generate new texture from the asset and store
|
||||
if (borderless) {
|
||||
generatedCards.put(imageKey, generateTexture(new FileHandle(file), t, Forge.isTextureFilteringEnabled()));
|
||||
Forge.getAssets().generatedCards.put(imageKey, generateTexture(new FileHandle(file), t, Forge.isTextureFilteringEnabled()));
|
||||
}
|
||||
}
|
||||
return t;
|
||||
|
||||
@@ -104,8 +104,6 @@ public class CardRenderer {
|
||||
private static final float BORDER_THICKNESS = Utils.scale(1);
|
||||
public static final float PADDING_MULTIPLIER = 0.021f;
|
||||
public static final float CROP_MULTIPLIER = 0.96f;
|
||||
|
||||
private static Map<Integer, BitmapFont> counterFonts = new HashMap<>();
|
||||
private static final Color counterBackgroundColor = new Color(0f, 0f, 0f, 0.9f);
|
||||
private static final Map<CounterType, Color> counterColorCache = new HashMap<>();
|
||||
private static final GlyphLayout layout = new GlyphLayout();
|
||||
@@ -1101,7 +1099,7 @@ public class CardRenderer {
|
||||
private static void drawCounterTabs(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
|
||||
int fontSize = Math.max(11, Math.min(22, (int) (h * 0.08)));
|
||||
BitmapFont font = counterFonts.get(fontSize);
|
||||
BitmapFont font = Forge.getAssets().counterFonts.get(fontSize);
|
||||
|
||||
final float additionalXOffset = 3f * ((fontSize - 11) / 11f);
|
||||
final float variableWidth = ((fontSize - 11) / 11f) * 44f;
|
||||
@@ -1218,7 +1216,7 @@ public class CardRenderer {
|
||||
private static void drawMarkersTabs(final List<String> markers, final Graphics g, final float x, final float y, final float w, final float h, boolean larger) {
|
||||
|
||||
int fontSize = larger ? Math.max(9, Math.min(22, (int) (h * 0.08))) : Math.max(8, Math.min(22, (int) (h * 0.05)));
|
||||
BitmapFont font = counterFonts.get(fontSize);
|
||||
BitmapFont font = Forge.getAssets().counterFonts.get(fontSize);
|
||||
|
||||
final float additionalXOffset = 3f * ((fontSize - 8) / 8f);
|
||||
|
||||
@@ -1410,7 +1408,7 @@ public class CardRenderer {
|
||||
textureRegions.add(new TextureRegion(texture));
|
||||
}
|
||||
|
||||
counterFonts.put(fontSize, new BitmapFont(fontData, textureRegions, true));
|
||||
Forge.getAssets().counterFonts.put(fontSize, new BitmapFont(fontData, textureRegions, true));
|
||||
|
||||
generator.dispose();
|
||||
packer.dispose();
|
||||
|
||||
Reference in New Issue
Block a user