Improve handling of rendering card image from scratch

This commit is contained in:
drdev
2014-07-27 22:15:14 +00:00
parent 390b5eb315
commit c03bbca0fc
6 changed files with 100 additions and 62 deletions

View File

@@ -6,9 +6,12 @@ import com.badlogic.gdx.graphics.glutils.FrameBuffer;
//Special graphics object for rendering to a texture //Special graphics object for rendering to a texture
public class TextureRenderer extends Graphics { public class TextureRenderer extends Graphics {
private final float width, height;
private final FrameBuffer frameBuffer; private final FrameBuffer frameBuffer;
public TextureRenderer(float width, float height) { public TextureRenderer(float width0, float height0) {
width = width0;
height = height0;
frameBuffer = new FrameBuffer(Format.RGB565, (int)width, (int)height, false); frameBuffer = new FrameBuffer(Format.RGB565, (int)width, (int)height, false);
frameBuffer.begin(); frameBuffer.begin();
begin(width, height); begin(width, height);
@@ -16,12 +19,19 @@ public class TextureRenderer extends Graphics {
public Texture finish() { public Texture finish() {
end(); end();
frameBuffer.end();
Texture texture = frameBuffer.getColorBufferTexture(); //draw buffered texture to another frame buffer to flip it to the proper orientation
FrameBuffer fb = new FrameBuffer(Format.RGB565, (int)width, (int)height, false);
fb.begin();
begin(width, height);
drawImage(frameBuffer.getColorBufferTexture(), 0, 0, width, height);
//frameBuffer.dispose(); //avoid holding on to the first frame buffer
end();
fb.end();
Texture texture = fb.getColorBufferTexture();
dispose(); //dispose after generating texture dispose(); //dispose after generating texture
frameBuffer.dispose();
return texture; return texture;
} }
} }

View File

@@ -25,7 +25,6 @@ import com.google.common.cache.LoadingCache;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException; import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import forge.ImageKeys; import forge.ImageKeys;
import forge.card.CardImageRenderer;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.player.IHasIcon; import forge.game.player.IHasIcon;
import forge.item.InventoryItem; import forge.item.InventoryItem;
@@ -64,11 +63,9 @@ public class ImageCache {
Texture defImage = null; Texture defImage = null;
try { try {
defImage = new Texture(Gdx.files.absolute(ForgeConstants.NO_CARD_FILE)); defImage = new Texture(Gdx.files.absolute(ForgeConstants.NO_CARD_FILE));
} } catch (Exception ex) {
catch (Exception ex) {
System.err.println("could not load default card image"); System.err.println("could not load default card image");
} } finally {
finally {
defaultImage = (null == defImage) ? new Texture(10, 10, Format.RGBA8888) : defImage; defaultImage = (null == defImage) ? new Texture(10, 10, Format.RGBA8888) : defImage;
} }
} }
@@ -79,34 +76,20 @@ public class ImageCache {
} }
public static Texture getImage(Card card) { public static Texture getImage(Card card) {
final String key;
if (!FControl.mayShowCard(card) || card.isFaceDown()) { if (!FControl.mayShowCard(card) || card.isFaceDown()) {
return getImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true); key = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE;
} }
return getOrCreateImage(card); else {
} key = card.getImageKey();
public static Texture getOrCreateImage(Card card) {
String imageKey = card.getImageKey();
Texture image = getImage(imageKey, false);
if (image == null) {
image = CardImageRenderer.createCardImage(card, cache, imageKey);
} }
return image; return getImage(key, true);
} }
public static Texture getImage(PaperCard pc) { public static Texture getImage(PaperCard pc) {
String imageKey = ImageKeys.getImageKey(pc, false); return getImage(ImageKeys.getImageKey(pc, false), true);
Texture image = getImage(imageKey, false);
if (image == null) {
image = CardImageRenderer.createCardImage(pc, cache, imageKey);
}
return image;
} }
public static Texture getImage(InventoryItem ii) { public static Texture getImage(InventoryItem ii) {
if (ii instanceof PaperCard) {
return getImage((PaperCard)ii);
}
return getImage(ImageKeys.getImageKey(ii, false), true); return getImage(ImageKeys.getImageKey(ii, false), true);
} }
@@ -152,7 +135,7 @@ public class ImageCache {
// Load from file and add to cache if not found in cache initially. // Load from file and add to cache if not found in cache initially.
Texture image; Texture image;
try { try {
image = cache.get(imageKey); image = ImageCache.cache.get(imageKey);
} }
catch (final ExecutionException ex) { catch (final ExecutionException ex) {
if (!(ex.getCause() instanceof NullPointerException)) { if (!(ex.getCause() instanceof NullPointerException)) {

View File

@@ -1,11 +1,17 @@
package forge.assets; package forge.assets;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.PixmapIO;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import forge.Forge; import forge.Forge;
import forge.ImageKeys; import forge.ImageKeys;
import forge.card.CardImageRenderer;
import forge.game.card.Card;
import forge.item.PaperCard;
import forge.model.FModel;
import forge.properties.ForgeConstants; import forge.properties.ForgeConstants;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -25,9 +31,11 @@ final class ImageLoader extends CacheLoader<String, Texture> {
final String path; final String path;
final String filename; final String filename;
boolean isCard = false;
if (key.startsWith(ImageKeys.TOKEN_PREFIX)) { if (key.startsWith(ImageKeys.TOKEN_PREFIX)) {
filename = key.substring(ImageKeys.TOKEN_PREFIX.length()); filename = key.substring(ImageKeys.TOKEN_PREFIX.length());
path = ForgeConstants.CACHE_TOKEN_PICS_DIR; path = ForgeConstants.CACHE_TOKEN_PICS_DIR;
isCard = true;
} }
else if (key.startsWith(ImageKeys.ICON_PREFIX)) { else if (key.startsWith(ImageKeys.ICON_PREFIX)) {
filename = key.substring(ImageKeys.ICON_PREFIX.length()); filename = key.substring(ImageKeys.ICON_PREFIX.length());
@@ -52,35 +60,70 @@ final class ImageLoader extends CacheLoader<String, Texture> {
else { else {
filename = key; filename = key;
path = ForgeConstants.CACHE_CARD_PICS_DIR; path = ForgeConstants.CACHE_CARD_PICS_DIR;
isCard = true;
} }
Texture ret = findFile(key, path, filename); Texture ret = findFile(key, path, filename);
if (ret != null) { return ret; }
// some S00 cards are really part of 6ED // some S00 cards are really part of 6ED
if (null == ret ) { String s2kAlias = ImageUtil.getSetFolder("S00");
String s2kAlias = ImageUtil.getSetFolder("S00"); if (filename.startsWith(s2kAlias)) {
if ( filename.startsWith(s2kAlias) ) { ret = findFile(key, path, filename.replace(s2kAlias, ImageUtil.getSetFolder("6ED")));
ret = findFile(key, path, filename.replace(s2kAlias, ImageUtil.getSetFolder("6ED"))); if (ret != null) { return ret; }
}
} }
// try without set prefix // try without set prefix
String setlessFilename = null; String setCode;
if (null == ret && filename.contains("/")) { String setlessFilename;
setlessFilename = filename.substring(filename.indexOf('/') + 1); int idx = filename.indexOf('/');
if (idx != -1) {
setCode = filename.substring(0, idx);
setlessFilename = filename.substring(idx + 1);
ret = findFile(key, path, setlessFilename); ret = findFile(key, path, setlessFilename);
if (ret != null) { return ret; }
// try lowering the art index to the minimum for regular cards // try lowering the art index to the minimum for regular cards
if (null == ret && setlessFilename.contains(".full")) { if (setlessFilename.contains(".full")) {
ret = findFile(key, path, setlessFilename.replaceAll("[0-9]*[.]full", "1.full")); ret = findFile(key, path, setlessFilename.replaceAll("[0-9]*[.]full", "1.full"));
if (ret != null) { return ret; }
}
}
else {
setCode = null;
setlessFilename = filename;
}
if (isCard) { //if image is for card, attempt to create image for it
int artIndex = 0;
String cardName = setlessFilename;
idx = cardName.indexOf('.');
if (idx != -1) {
int dotIdx = idx;
//trim art index
while (idx > 0 && Character.isDigit(cardName.charAt(idx - 1))) {
idx--;
}
if (dotIdx > idx) {
artIndex = Integer.parseInt(cardName.substring(dotIdx, idx));
}
cardName = cardName.substring(0, idx);
}
PaperCard pc = FModel.getMagicDb().getCommonCards().getCard(cardName, setCode, artIndex);
if (pc == null) {
pc = FModel.getMagicDb().getVariantCards().getCard(cardName, setCode, artIndex);
}
if (pc != null) {
ret = CardImageRenderer.createCardImage(Card.getCardForUi(pc));
if (ret != null) {
//PixmapIO.writePNG(Gdx.files.absolute(path + filename + ".png"), ret.);
return ret;
}
} }
} }
if (null == ret) { System.out.println("File not found, no image created: " + key);
System.out.println("File not found, no image created: " + key); return null;
}
return ret;
} }
private static Texture findFile(String key, String path, String filename) { private static Texture findFile(String key, String path, String filename) {

View File

@@ -7,7 +7,6 @@ import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
import com.google.common.cache.LoadingCache;
import forge.TextureRenderer; import forge.TextureRenderer;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
@@ -16,7 +15,6 @@ import forge.assets.TextRenderer;
import forge.card.CardDetailUtil.DetailColors; import forge.card.CardDetailUtil.DetailColors;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.card.Card; import forge.game.card.Card;
import forge.item.IPaperCard;
public class CardImageRenderer { public class CardImageRenderer {
private static final float IMAGE_WIDTH = 360; private static final float IMAGE_WIDTH = 360;
@@ -28,10 +26,7 @@ public class CardImageRenderer {
private static final FSkinFont TEXT_FONT = FSkinFont.forHeight(MANA_SYMBOL_SIZE * 0.95f); private static final FSkinFont TEXT_FONT = FSkinFont.forHeight(MANA_SYMBOL_SIZE * 0.95f);
private static final FSkinFont PT_FONT = NAME_FONT; private static final FSkinFont PT_FONT = NAME_FONT;
public static Texture createCardImage(IPaperCard pc, LoadingCache<String, Texture> cache, String imageKey) { public static Texture createCardImage(Card card) {
return createCardImage(Card.getCardForUi(pc), cache, imageKey);
}
public static Texture createCardImage(Card card, LoadingCache<String, Texture> cache, String imageKey) {
float w = IMAGE_WIDTH; float w = IMAGE_WIDTH;
float h = IMAGE_HEIGHT; float h = IMAGE_HEIGHT;
@@ -90,9 +85,7 @@ public class CardImageRenderer {
Color ptColor2 = color2 == null ? null : FSkinColor.tintColor(Color.WHITE, color2, CardRenderer.PT_BOX_TINT); Color ptColor2 = color2 == null ? null : FSkinColor.tintColor(Color.WHITE, color2, CardRenderer.PT_BOX_TINT);
drawPtBox(renderer, card, idForeColor, ptColor1, ptColor2, x, y, w, ptBoxHeight); drawPtBox(renderer, card, idForeColor, ptColor1, ptColor2, x, y, w, ptBoxHeight);
Texture image = renderer.finish(); return renderer.finish();
cache.put(imageKey, image);
return image;
} }
private static void drawHeader(TextureRenderer renderer, Card card, boolean canShow, Color color1, Color color2, float x, float y, float w, float h) { private static void drawHeader(TextureRenderer renderer, Card card, boolean canShow, Color color1, Color color2, float x, float y, float w, float h) {

View File

@@ -57,13 +57,14 @@ public class CardRenderer {
float w = width - 2 * FDialog.INSETS; float w = width - 2 * FDialog.INSETS;
float h = height - 2 * FDialog.INSETS; float h = height - 2 * FDialog.INSETS;
final Texture image; final String key;
if (FControl.mayShowCard(card) || FDialog.isDialogOpen()) { //support showing if card revealed in dialog if (FControl.mayShowCard(card) || FDialog.isDialogOpen()) { //support showing if card revealed in dialog
image = ImageCache.getOrCreateImage(card); key = card.getImageKey();
} }
else { //only show card back if can't show card else { //only show card back if can't show card
image = ImageCache.getImage(ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE, true); key = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE;
} }
Texture image = ImageCache.getImage(key, true);
if (image == null || image == ImageCache.defaultImage) { return false; } //don't support drawing zoom for null or default textures if (image == null || image == ImageCache.defaultImage) { return false; } //don't support drawing zoom for null or default textures
float imageWidth = image.getWidth(); float imageWidth = image.getWidth();

View File

@@ -1,6 +1,7 @@
package forge.toolbox; package forge.toolbox;
import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import forge.Forge; import forge.Forge;
@@ -8,8 +9,8 @@ import forge.Graphics;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.assets.FImage; import forge.assets.FImage;
import forge.assets.FSkinImage; import forge.assets.FSkinImage;
import forge.assets.ImageCache;
import forge.assets.ImageUtil; import forge.assets.ImageUtil;
import forge.card.CardRenderer;
import forge.card.CardZoom; import forge.card.CardZoom;
import forge.game.card.Card; import forge.game.card.Card;
import forge.screens.match.views.VPrompt; import forge.screens.match.views.VPrompt;
@@ -104,8 +105,15 @@ public class FOptionPane extends FDialog {
} }
@Override @Override
public void draw(Graphics g) { public void draw(Graphics g) {
float cardWidth = getHeight() / FCardPanel.ASPECT_RATIO; float h = getHeight();
CardRenderer.drawCardWithOverlays(g, card, (getWidth() - cardWidth) / 2, 0, cardWidth, getHeight()); float w = h / FCardPanel.ASPECT_RATIO;
float x = (getWidth() - w) / 2;
float y = 0;
Texture image = ImageCache.getImage(card);
if (image != null) {
g.drawImage(image, x, y, w, h);
}
} }
}; };
cardDisplay.setHeight(Utils.SCREEN_HEIGHT / 2); cardDisplay.setHeight(Utils.SCREEN_HEIGHT / 2);