mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 04:38:00 +00:00
Add counters to mobile Forge and adjust desktop counters
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1174,7 +1174,6 @@ forge-gui-desktop/src/main/java/forge/view/arcane/util/CardPanelMouseListener.ja
|
||||
forge-gui-desktop/src/main/java/forge/view/arcane/util/OutlinedLabel.java -text
|
||||
forge-gui-desktop/src/main/java/forge/view/arcane/util/package-info.java -text
|
||||
forge-gui-desktop/src/main/java/forge/view/package-info.java -text
|
||||
forge-gui-desktop/src/main/resources/Roboto-Bold.ttf -text
|
||||
forge-gui-desktop/src/test/java/forge/BoosterDraft1Test.java -text
|
||||
forge-gui-desktop/src/test/java/forge/BoosterDraftTest.java -text
|
||||
forge-gui-desktop/src/test/java/forge/CardRankerTest.java -text
|
||||
@@ -19084,6 +19083,7 @@ forge-gui/res/editions/Worldwake.txt -text
|
||||
forge-gui/res/editions/Zendikar[!!-~]Expeditions.txt -text
|
||||
forge-gui/res/editions/Zendikar.txt -text
|
||||
forge-gui/res/effects/lightning.gif -text
|
||||
forge-gui/res/fonts/Roboto-Bold.ttf -text
|
||||
forge-gui/res/howto.txt svneol=native#text/plain
|
||||
forge-gui/res/languages/en-US.properties -text
|
||||
forge-gui/res/licenses/java-yield-license.txt svneol=native#text/plain
|
||||
|
||||
@@ -195,6 +195,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
initializeColorIdentityCombobox();
|
||||
initializeAutoYieldModeComboBox();
|
||||
initializeCounterDisplayTypeComboBox();
|
||||
initializeCounterDisplayLocationComboBox();
|
||||
initializePlayerNameButton();
|
||||
}
|
||||
|
||||
@@ -360,6 +361,25 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
|
||||
}
|
||||
|
||||
private void initializeCounterDisplayLocationComboBox() {
|
||||
|
||||
final String[] elements = new String[ForgeConstants.CounterDisplayLocation.values().length];
|
||||
|
||||
ForgeConstants.CounterDisplayLocation[] values = ForgeConstants.CounterDisplayLocation.values();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
elements[i] = values[i].getName();
|
||||
}
|
||||
|
||||
final FPref userSetting = FPref.UI_CARD_COUNTER_DISPLAY_LOCATION;
|
||||
final FComboBoxPanel<String> panel = this.view.getCounterDisplayLocationComboBoxPanel();
|
||||
|
||||
final FComboBox<String> comboBox = createComboBox(elements, userSetting);
|
||||
final String selectedItem = this.prefs.getPref(userSetting);
|
||||
|
||||
panel.setComboBox(comboBox, selectedItem);
|
||||
|
||||
}
|
||||
|
||||
private <E> FComboBox<E> createComboBox(final E[] items, final ForgePreferences.FPref setting) {
|
||||
final FComboBox<E> comboBox = new FComboBox<>(items);
|
||||
addComboBoxListener(comboBox, setting);
|
||||
|
||||
@@ -103,6 +103,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
private final FComboBoxPanel<String> cbpDisplayCurrentCardColors = new FComboBoxPanel<>("Show Detailed Card Color:");
|
||||
private final FComboBoxPanel<String> cbpAutoYieldMode = new FComboBoxPanel<>("Auto-Yield:");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayType = new FComboBoxPanel<>("Counter Display Type:");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayLocation = new FComboBoxPanel<>("Counter Display Location:");
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -280,6 +281,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
pnlPrefs.add(cbpCounterDisplayType, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Selects the style of the in-game counter display for cards. Text-based is a new tab-like display on the cards. Image-based is the old counter image. Hybrid displays both at once."), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpCounterDisplayLocation, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Determines where to position the text-based counters on the card: close to the top or close to the bottom."), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpDisplayCurrentCardColors, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Displays the breakdown of the current color of cards in the card detail information panel."), descriptionConstraints);
|
||||
|
||||
@@ -593,6 +597,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
return cbpCounterDisplayType;
|
||||
}
|
||||
|
||||
public FComboBoxPanel<String> getCounterDisplayLocationComboBoxPanel() {
|
||||
return cbpCounterDisplayLocation;
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JCheckBox} */
|
||||
public JCheckBox getCbEnforceDeckLegality() {
|
||||
return cbEnforceDeckLegality;
|
||||
|
||||
@@ -29,6 +29,7 @@ import forge.game.card.CounterType;
|
||||
import forge.gui.CardContainer;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgeConstants.CounterDisplayType;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.CMatchUI;
|
||||
@@ -45,6 +46,7 @@ import java.awt.font.TextAttribute;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -99,7 +101,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
|
||||
try {
|
||||
|
||||
Font roboto = Font.createFont(Font.TRUETYPE_FONT, CardPanel.class.getClassLoader().getResourceAsStream("Roboto-Bold.ttf"));
|
||||
Font roboto = Font.createFont(Font.TRUETYPE_FONT, Paths.get(ForgeConstants.COMMON_FONTS_DIR, "Roboto-Bold.ttf").toFile());
|
||||
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
ge.registerFont(roboto);
|
||||
@@ -108,7 +110,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
|
||||
attributes.put(TextAttribute.FAMILY, "Roboto Bold");
|
||||
attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
|
||||
attributes.put(TextAttribute.SIZE, 10);
|
||||
attributes.put(TextAttribute.SIZE, 11);
|
||||
attributes.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
|
||||
|
||||
smallCounterFont = Font.getFont(attributes);
|
||||
@@ -437,7 +439,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
}
|
||||
|
||||
|
||||
if (card.getCounters() != null) {
|
||||
if (card.getCounters() != null && !card.getCounters().isEmpty()) {
|
||||
|
||||
switch (CounterDisplayType.from(FModel.getPreferences().getPref(FPref.UI_CARD_COUNTER_DISPLAY_TYPE))) {
|
||||
case OLD_WHEN_SMALL:
|
||||
@@ -517,7 +519,13 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
final int numberOfCounters = counterEntry.getValue();
|
||||
final int counterBoxRealWidth = counterBoxBaseWidth + largeFontMetrics.stringWidth(String.valueOf(numberOfCounters));
|
||||
|
||||
final int counterYOffset = cardYOffset + spaceFromTopOfCard - counterBoxHeight + currentCounter++ * (counterBoxHeight + counterBoxSpacing);
|
||||
final int counterYOffset;
|
||||
|
||||
if (ForgeConstants.CounterDisplayLocation.from(FModel.getPreferences().getPref(FPref.UI_CARD_COUNTER_DISPLAY_LOCATION)) == ForgeConstants.CounterDisplayLocation.TOP) {
|
||||
counterYOffset = cardYOffset + spaceFromTopOfCard - counterBoxHeight + currentCounter++ * (counterBoxHeight + counterBoxSpacing);
|
||||
} else {
|
||||
counterYOffset = cardYOffset + cardHeight - spaceFromTopOfCard / 2 - counterBoxHeight + currentCounter++ * (counterBoxHeight + counterBoxSpacing);
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
g.setColor(new Color(0, 0, 0, 255));
|
||||
@@ -537,7 +545,8 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
}
|
||||
|
||||
Rectangle nameBounds = counterArea.getBounds();
|
||||
nameBounds.x += 12;
|
||||
nameBounds.x += 8;
|
||||
nameBounds.y -= 1;
|
||||
nameBounds.width = 43;
|
||||
drawVerticallyCenteredString(g, counter.getCounterOnCardDisplayName(), nameBounds, smallCounterFont, smallFontMetrics);
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
package forge;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
@@ -17,13 +15,14 @@ import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
|
||||
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.toolbox.FDisplayObject;
|
||||
import forge.util.Utils;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class Graphics {
|
||||
private static final int GL_BLEND = GL20.GL_BLEND;
|
||||
private static final int GL_LINE_SMOOTH = 2848; //create constant here since not in GL20
|
||||
@@ -62,6 +61,10 @@ public class Graphics {
|
||||
shapeRenderer.dispose();
|
||||
}
|
||||
|
||||
public SpriteBatch getBatch() {
|
||||
return batch;
|
||||
}
|
||||
|
||||
public boolean startClip() {
|
||||
return startClip(0, 0, bounds.width, bounds.height);
|
||||
}
|
||||
@@ -667,11 +670,11 @@ public class Graphics {
|
||||
drawText(text, skinFont, textColor, x, y, w, h, wrap, horzAlignment, centerVertically);
|
||||
}
|
||||
|
||||
private float adjustX(float x) {
|
||||
public float adjustX(float x) {
|
||||
return x + bounds.x;
|
||||
}
|
||||
|
||||
private float adjustY(float y, float height) {
|
||||
public float adjustY(float y, float height) {
|
||||
return regionHeight - y - bounds.y - height; //flip y-axis
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
package forge.assets;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
@@ -20,12 +16,15 @@ import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FSkinFont {
|
||||
private static final int MIN_FONT_SIZE = 8;
|
||||
private static final int MAX_FONT_SIZE = 72;
|
||||
@@ -127,8 +126,7 @@ public class FSkinFont {
|
||||
font.setColor(color);
|
||||
if (wrap) {
|
||||
font.drawWrapped(batch, text, x, y, w, horzAlignment);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
font.drawMultiLine(batch, text, x, y, w, horzAlignment);
|
||||
}
|
||||
}
|
||||
@@ -152,8 +150,7 @@ public class FSkinFont {
|
||||
if (scale != 1) { //re-use font inside range if possible
|
||||
if (fontSize > MAX_FONT_SIZE) {
|
||||
font = _get(MAX_FONT_SIZE).font;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
font = _get(MIN_FONT_SIZE).font;
|
||||
}
|
||||
return;
|
||||
@@ -169,9 +166,7 @@ public class FSkinFont {
|
||||
font = new BitmapFont(data, (TextureRegion)null, true);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
generateFont(FSkin.getSkinFile(TTF_FILE), fontName, fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,46 @@
|
||||
package forge.card;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
|
||||
import com.badlogic.gdx.graphics.g2d.PixmapPacker;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
|
||||
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import forge.FThreads;
|
||||
import forge.Graphics;
|
||||
import forge.StaticData;
|
||||
import forge.assets.FImageComplex;
|
||||
import forge.assets.FRotatedImage;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.assets.FTextureRegionImage;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.assets.*;
|
||||
import forge.card.CardDetailUtil.DetailColors;
|
||||
import forge.card.CardZoom.ActivateHandler;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CardView.CardStateView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgeConstants.CounterDisplayType;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.MatchController;
|
||||
import forge.toolbox.FList;
|
||||
import forge.util.Utils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CardRenderer {
|
||||
public enum CardStackPosition {
|
||||
@@ -53,6 +60,16 @@ public class CardRenderer {
|
||||
private static final float BORDER_THICKNESS = Utils.scale(1);
|
||||
public static final float PADDING_MULTIPLIER = 0.021f;
|
||||
|
||||
private static BitmapFont counterFont;
|
||||
private static final Color counterBackgroundColor = new Color(0f, 0f, 0f, 0.9f);
|
||||
private static final Map<CounterType, Color> counterColorCache = new HashMap<>();
|
||||
|
||||
static {
|
||||
if (counterFont == null) {
|
||||
generateFontForCounters();
|
||||
}
|
||||
}
|
||||
|
||||
private static Color fromDetailColor(DetailColors detailColor) {
|
||||
return FSkinColor.fromRGB(detailColor.r, detailColor.g, detailColor.b);
|
||||
}
|
||||
@@ -88,10 +105,12 @@ public class CardRenderer {
|
||||
CardType type = pc.getRules().getType();
|
||||
return getCardArt(pc.getImageKey(false), pc.getRules().getSplitType() == CardSplitType.Split, type.isPlane() || type.isPhenomenon(),pc.getRules().getOracleText().contains("Aftermath"));
|
||||
}
|
||||
|
||||
public static FImageComplex getCardArt(CardView card) {
|
||||
CardTypeView type = card.getCurrentState().getType();
|
||||
return getCardArt(card.getCurrentState().getImageKey(), card.isSplitCard(), type.isPlane() || type.isPhenomenon(),card.getText().contains("Aftermath"));
|
||||
}
|
||||
|
||||
public static FImageComplex getCardArt(String imageKey, boolean isSplitCard, boolean isHorizontalCard, boolean isAftermathCard) {
|
||||
FImageComplex cardArt = cardArtCache.get(imageKey);
|
||||
if (cardArt == null) {
|
||||
@@ -181,8 +200,6 @@ public class CardRenderer {
|
||||
return cardArt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, CardView card, int count, String suffix, float x, float y, float w, float h, boolean compactMode) {
|
||||
final CardStateView state = card.getCurrentState();
|
||||
if (card.getId() > 0) {
|
||||
@@ -201,6 +218,7 @@ public class CardRenderer {
|
||||
g.drawText(name, font, foreColor, x, y, w, h, false, HAlignment.CENTER, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, IPaperCard pc, int count, String suffix, float x, float y, float w, float h, boolean compactMode) {
|
||||
final CardView card = CardView.getCardForUi(pc);
|
||||
final CardStateView state = card.getCurrentState();
|
||||
@@ -208,6 +226,7 @@ public class CardRenderer {
|
||||
pc.getRarity(), state.getPower(), state.getToughness(),
|
||||
state.getLoyalty(), count, suffix, x, y, w, h, compactMode);
|
||||
}
|
||||
|
||||
public static void drawCardListItem(Graphics g, FSkinFont font, FSkinColor foreColor, FImageComplex cardArt, CardView card, String set, CardRarity rarity, int power, int toughness, int loyalty, int count, String suffix, float x, float y, float w, float h, boolean compactMode) {
|
||||
float cardArtHeight = h + 2 * FList.PADDING;
|
||||
float cardArtWidth = cardArtHeight * CARD_ART_RATIO;
|
||||
@@ -295,6 +314,7 @@ public class CardRenderer {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean paperCardListItemTap(List<?> cards, int selectedIndex, ActivateHandler activateHandler, float x, float y, int count, boolean compactMode) {
|
||||
float cardArtHeight = getCardListItemHeight(compactMode);
|
||||
float cardArtWidth = cardArtHeight * CARD_ART_RATIO;
|
||||
@@ -337,6 +357,7 @@ public class CardRenderer {
|
||||
g.fillRect(Color.BLACK, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawCard(Graphics g, CardView card, float x, float y, float w, float h, CardStackPosition pos) {
|
||||
Texture image = ImageCache.getImage(card);
|
||||
if (image != null) {
|
||||
@@ -406,36 +427,28 @@ public class CardRenderer {
|
||||
g.drawOutlinedText(String.valueOf(card.getId()), idFont, Color.WHITE, Color.BLACK, x + padding, y + h - idHeight - padding, w, h, false, HAlignment.LEFT, false);
|
||||
}
|
||||
|
||||
int number = 0;
|
||||
if (card.getCounters() != null) {
|
||||
for (final Integer i : card.getCounters().values()) {
|
||||
number += i.intValue();
|
||||
}
|
||||
if (card.getCounters() != null && !card.getCounters().isEmpty()) {
|
||||
|
||||
switch (CounterDisplayType.from(FModel.getPreferences().getPref(FPref.UI_CARD_COUNTER_DISPLAY_TYPE))) {
|
||||
case OLD_WHEN_SMALL:
|
||||
case TEXT:
|
||||
drawCounterTabs(card, g, x, y, w, h);
|
||||
break;
|
||||
case IMAGE:
|
||||
drawCounterImage(card, g, x, y, w, h);
|
||||
break;
|
||||
case HYBRID:
|
||||
drawCounterImage(card, g, x, y, w, h);
|
||||
drawCounterTabs(card, g, x, y, w, h);
|
||||
break;
|
||||
}
|
||||
|
||||
final int counters = number;
|
||||
|
||||
float countersSize = w / 2;
|
||||
final float xCounters = x - countersSize / 2;
|
||||
final float yCounters = y + h * 2 / 3 - countersSize;
|
||||
|
||||
if (counters == 1) {
|
||||
CardFaceSymbols.drawSymbol("counters1", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters == 2) {
|
||||
CardFaceSymbols.drawSymbol("counters2", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters == 3) {
|
||||
CardFaceSymbols.drawSymbol("counters3", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters > 3) {
|
||||
CardFaceSymbols.drawSymbol("countersMulti", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
|
||||
float otherSymbolsSize = w / 2;
|
||||
final float combatXSymbols = (x + (w / 4)) - otherSymbolsSize / 2;
|
||||
final float stateXSymbols = (x + (w / 2)) - otherSymbolsSize / 2;
|
||||
final float ySymbols = (y + h) - (h / 8) - otherSymbolsSize / 2;
|
||||
float otherSymbolsSize = w / 3.5f;
|
||||
final float combatXSymbols = (x + (w / 4)) - otherSymbolsSize / 2 - 10;
|
||||
final float stateXSymbols = (x + (w / 2)) - otherSymbolsSize / 2 - 10;
|
||||
final float ySymbols = (y + h) - (h / 12) - otherSymbolsSize / 2;
|
||||
|
||||
if (card.isAttacking()) {
|
||||
CardFaceSymbols.drawSymbol("attack", g, combatXSymbols, ySymbols, otherSymbolsSize, otherSymbolsSize);
|
||||
@@ -462,6 +475,111 @@ public class CardRenderer {
|
||||
//only needed if on top since otherwise P/T will be hidden
|
||||
drawPtBox(g, card, details, color, x, y, w, h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void drawCounterTabs(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
|
||||
float otherSymbolsSize = w / 3.5f;
|
||||
final float ySymbols = (h / 12) - otherSymbolsSize / 2;
|
||||
|
||||
final float counterBoxHeight = 20;
|
||||
final float counterBoxBaseWidth = 50;
|
||||
final float counterBoxSpacing = -4;
|
||||
|
||||
final float spaceFromTopOfCard = y + h - counterBoxHeight - counterBoxSpacing - otherSymbolsSize + ySymbols;
|
||||
|
||||
int currentCounter = 0;
|
||||
|
||||
if (CounterDisplayType.from(FModel.getPreferences().getPref(FPref.UI_CARD_COUNTER_DISPLAY_TYPE)) == CounterDisplayType.OLD_WHEN_SMALL) {
|
||||
|
||||
int maxCounters = 0;
|
||||
for (Integer numberOfCounters : card.getCounters().values()) {
|
||||
maxCounters = Math.max(maxCounters, numberOfCounters);
|
||||
}
|
||||
|
||||
if (counterBoxBaseWidth + counterFont.getBounds(String.valueOf(maxCounters)).width > w) {
|
||||
drawCounterImage(card, g, x, y, w, h);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (Map.Entry<CounterType, Integer> counterEntry : card.getCounters().entrySet()) {
|
||||
|
||||
final CounterType counter = counterEntry.getKey();
|
||||
final int numberOfCounters = counterEntry.getValue();
|
||||
final float counterBoxRealWidth = counterBoxBaseWidth + counterFont.getBounds(String.valueOf(numberOfCounters)).width + 4;
|
||||
|
||||
final float counterYOffset = spaceFromTopOfCard - (currentCounter++ * (counterBoxHeight + counterBoxSpacing));
|
||||
|
||||
g.fillRect(counterBackgroundColor, x - 2, counterYOffset, counterBoxRealWidth, counterBoxHeight);
|
||||
|
||||
if (!counterColorCache.containsKey(counter)) {
|
||||
counterColorCache.put(counter, new Color(counter.getRed() / 255.0f, counter.getGreen() / 255.0f, counter.getBlue() / 255.0f, 1.0f));
|
||||
}
|
||||
|
||||
Color counterColor = counterColorCache.get(counter);
|
||||
|
||||
drawText(g, counter.getCounterOnCardDisplayName(), counterFont, counterColor, x + 2, counterYOffset, counterBoxRealWidth, counterBoxHeight, HAlignment.LEFT);
|
||||
drawText(g, String.valueOf(numberOfCounters), counterFont, counterColor, x + counterBoxBaseWidth - 3f, counterYOffset, counterBoxRealWidth, counterBoxHeight, HAlignment.LEFT);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final int GL_BLEND = GL20.GL_BLEND;
|
||||
|
||||
private static void drawText(Graphics g, String text, BitmapFont font, Color color, float x, float y, float w, float h, HAlignment horizontalAlignment) {
|
||||
|
||||
if (color.a < 1) { //enable blending so alpha colored shapes work properly
|
||||
Gdx.gl.glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
TextBounds textBounds = font.getMultiLineBounds(text);
|
||||
|
||||
float textHeight = textBounds.height;
|
||||
if (h > textHeight) {
|
||||
y += (h - textHeight) / 2;
|
||||
}
|
||||
|
||||
font.setColor(color);
|
||||
font.drawMultiLine(g.getBatch(), text, g.adjustX(x), g.adjustY(y, 0), w, horizontalAlignment);
|
||||
|
||||
if (color.a < 1) {
|
||||
Gdx.gl.glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void drawCounterImage(final CardView card, final Graphics g, final float x, final float y, final float w, final float h) {
|
||||
|
||||
int number = 0;
|
||||
if (card.getCounters() != null) {
|
||||
for (final Integer i : card.getCounters().values()) {
|
||||
number += i;
|
||||
}
|
||||
}
|
||||
|
||||
final int counters = number;
|
||||
|
||||
float countersSize = w / 2;
|
||||
final float xCounters = x - countersSize / 2;
|
||||
final float yCounters = y + h * 2 / 3 - countersSize;
|
||||
|
||||
if (counters == 1) {
|
||||
CardFaceSymbols.drawSymbol("counters1", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters == 2) {
|
||||
CardFaceSymbols.drawSymbol("counters2", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters == 3) {
|
||||
CardFaceSymbols.drawSymbol("counters3", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
else if (counters > 3) {
|
||||
CardFaceSymbols.drawSymbol("countersMulti", g, xCounters, yCounters, countersSize, countersSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void drawPtBox(Graphics g, CardView card, CardStateView details, Color color, float x, float y, float w, float h) {
|
||||
@@ -564,4 +682,66 @@ public class CardRenderer {
|
||||
private static boolean showCardIdOverlay(CardView card) {
|
||||
return card.getId() > 0 && isShowingOverlays(card) && isPreferenceEnabled(FPref.UI_OVERLAY_CARD_ID);
|
||||
}
|
||||
|
||||
//TODO Make FSkinFont accept more than one kind of font and merge this with it
|
||||
private static void generateFontForCounters() {
|
||||
|
||||
FileHandle ttfFile = Gdx.files.absolute(ForgeConstants.COMMON_FONTS_DIR).child("Roboto-Bold.ttf");
|
||||
final int fontSize = 11;
|
||||
|
||||
if (!ttfFile.exists()) { return; }
|
||||
|
||||
final FreeTypeFontGenerator generator = new FreeTypeFontGenerator(ttfFile);
|
||||
|
||||
//approximate optimal page size
|
||||
int pageSize = 128;
|
||||
|
||||
//only generate images for characters that could be used by Forge
|
||||
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\"!?'.,;:()[]{}<>|/@\\^$-%+=#_&*\u2014\u2022";
|
||||
|
||||
final PixmapPacker packer = new PixmapPacker(pageSize, pageSize, Pixmap.Format.RGBA8888, 2, false);
|
||||
final FreeTypeFontParameter parameter = new FreeTypeFontParameter();
|
||||
parameter.characters = chars;
|
||||
parameter.size = fontSize;
|
||||
parameter.packer = packer;
|
||||
final FreeTypeFontGenerator.FreeTypeBitmapFontData fontData = generator.generateData(parameter);
|
||||
final Array<PixmapPacker.Page> pages = packer.getPages();
|
||||
|
||||
//finish generating font on UI thread
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TextureRegion[] textureRegions = new TextureRegion[pages.size];
|
||||
for (int i = 0; i < pages.size; i++) {
|
||||
PixmapPacker.Page p = pages.get(i);
|
||||
Texture texture = new Texture(new PixmapTextureData(p.getPixmap(), p.getPixmap().getFormat(), false, false)) {
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
getTextureData().consumePixmap().dispose();
|
||||
}
|
||||
};
|
||||
texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||
textureRegions[i] = new TextureRegion(texture);
|
||||
}
|
||||
|
||||
counterFont = new BitmapFont(fontData, textureRegions, true);
|
||||
|
||||
//create .fnt and .png files for font
|
||||
FileHandle pixmapDir = Gdx.files.absolute(ForgeConstants.FONTS_DIR);
|
||||
if (pixmapDir != null) {
|
||||
FileHandle fontFile = pixmapDir.child("Roboto-Bold.fnt");
|
||||
BitmapFontWriter.setOutputFormat(BitmapFontWriter.OutputFormat.Text);
|
||||
|
||||
String[] pageRefs = BitmapFontWriter.writePixmaps(packer.getPages(), pixmapDir, "Roboto-Bold");
|
||||
BitmapFontWriter.writeFont(counterFont.getData(), pageRefs, fontFile, new BitmapFontWriter.FontInfo("Roboto-Bold", fontSize), 1, 1);
|
||||
}
|
||||
|
||||
generator.dispose();
|
||||
packer.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -219,6 +219,14 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
||||
ForgeConstants.DISP_CURRENT_COLORS_ALWAYS}),
|
||||
4);
|
||||
|
||||
lstSettings.addItem(new CustomSelectSetting(FPref.UI_CARD_COUNTER_DISPLAY_TYPE,
|
||||
"Counter Display Type",
|
||||
"Selects the style of the in-game counter display for cards. Text-based is a new tab-like display on the cards. Image-based is the old counter image. Hybrid displays both at once.",
|
||||
new String[]{
|
||||
ForgeConstants.CounterDisplayType.TEXT.getName(), ForgeConstants.CounterDisplayType.IMAGE.getName(),
|
||||
ForgeConstants.CounterDisplayType.HYBRID.getName(), ForgeConstants.CounterDisplayType.OLD_WHEN_SMALL.getName()}),
|
||||
4);
|
||||
|
||||
//Card Overlays
|
||||
lstSettings.addItem(new BooleanSetting(FPref.UI_SHOW_CARD_OVERLAYS,
|
||||
"Show Card Overlays",
|
||||
|
||||
@@ -81,6 +81,7 @@ public final class ForgeConstants {
|
||||
public static final String CONQUEST_PLANES_DIR = CONQUEST_DIR + "planes" + PATH_SEPARATOR;
|
||||
|
||||
public static final String SKINS_DIR = RES_DIR + "skins" + PATH_SEPARATOR;
|
||||
public static final String COMMON_FONTS_DIR = RES_DIR + "fonts" + PATH_SEPARATOR;
|
||||
public static final String DEFAULT_SKINS_DIR = SKINS_DIR + "default" + PATH_SEPARATOR;
|
||||
//don't associate these skin files with a directory since skin directory will be determined later
|
||||
public static final String SPRITE_ICONS_FILE = "sprite_icons.png";
|
||||
@@ -203,6 +204,31 @@ public final class ForgeConstants {
|
||||
public static final String AUTO_YIELD_PER_CARD = "Per Card (Each Game)";
|
||||
public static final String AUTO_YIELD_PER_ABILITY = "Per Ability (Each Match)";
|
||||
|
||||
public enum CounterDisplayLocation {
|
||||
|
||||
TOP("Top of Card"), BOTTOM("Bottom of Card");
|
||||
|
||||
private String name;
|
||||
|
||||
CounterDisplayLocation(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static CounterDisplayLocation from(final String name) {
|
||||
for (CounterDisplayLocation counterDisplayLocation : values()) {
|
||||
if (counterDisplayLocation.name.equals(name)) {
|
||||
return counterDisplayLocation;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Counter display location '" + name + "' not found.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum CounterDisplayType {
|
||||
|
||||
/** Use only the new tab-like counter display */
|
||||
|
||||
@@ -92,6 +92,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
UI_AUTO_YIELD_MODE (ForgeConstants.AUTO_YIELD_PER_ABILITY),
|
||||
UI_SHOW_STORM_COUNT_IN_PROMPT ("false"),
|
||||
UI_CARD_COUNTER_DISPLAY_TYPE(ForgeConstants.CounterDisplayType.TEXT.getName()),
|
||||
UI_CARD_COUNTER_DISPLAY_LOCATION(ForgeConstants.CounterDisplayLocation.TOP.getName()),
|
||||
|
||||
UI_FOR_TOUCHSCREN("false"),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user