mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Merge remote-tracking branch 'core-developers/master' into translationsfixes
This commit is contained in:
@@ -6,6 +6,7 @@ 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.glutils.ShaderProgram;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
|
||||
import com.badlogic.gdx.math.Matrix4;
|
||||
@@ -37,8 +38,75 @@ public class Graphics {
|
||||
private int failedClipCount;
|
||||
private float alphaComposite = 1;
|
||||
private int transformCount = 0;
|
||||
private String sVertex = "uniform mat4 u_projTrans;\n" +
|
||||
"\n" +
|
||||
"attribute vec4 a_position;\n" +
|
||||
"attribute vec2 a_texCoord0;\n" +
|
||||
"attribute vec4 a_color;\n" +
|
||||
"\n" +
|
||||
"varying vec4 v_color;\n" +
|
||||
"varying vec2 v_texCoord;\n" +
|
||||
"\n" +
|
||||
"uniform vec2 u_viewportInverse;\n" +
|
||||
"\n" +
|
||||
"void main() {\n" +
|
||||
" gl_Position = u_projTrans * a_position;\n" +
|
||||
" v_texCoord = a_texCoord0;\n" +
|
||||
" v_color = a_color;\n" +
|
||||
"}";
|
||||
private String sFragment = "#ifdef GL_ES\n" +
|
||||
"precision mediump float;\n" +
|
||||
"precision mediump int;\n" +
|
||||
"#endif\n" +
|
||||
"\n" +
|
||||
"uniform sampler2D u_texture;\n" +
|
||||
"\n" +
|
||||
"// The inverse of the viewport dimensions along X and Y\n" +
|
||||
"uniform vec2 u_viewportInverse;\n" +
|
||||
"\n" +
|
||||
"// Color of the outline\n" +
|
||||
"uniform vec3 u_color;\n" +
|
||||
"\n" +
|
||||
"// Thickness of the outline\n" +
|
||||
"uniform float u_offset;\n" +
|
||||
"\n" +
|
||||
"// Step to check for neighbors\n" +
|
||||
"uniform float u_step;\n" +
|
||||
"\n" +
|
||||
"varying vec4 v_color;\n" +
|
||||
"varying vec2 v_texCoord;\n" +
|
||||
"\n" +
|
||||
"#define ALPHA_VALUE_BORDER 0.5\n" +
|
||||
"\n" +
|
||||
"void main() {\n" +
|
||||
" vec2 T = v_texCoord.xy;\n" +
|
||||
"\n" +
|
||||
" float alpha = 0.0;\n" +
|
||||
" bool allin = true;\n" +
|
||||
" for( float ix = -u_offset; ix < u_offset; ix += u_step )\n" +
|
||||
" {\n" +
|
||||
" for( float iy = -u_offset; iy < u_offset; iy += u_step )\n" +
|
||||
" {\n" +
|
||||
" float newAlpha = texture2D(u_texture, T + vec2(ix, iy) * u_viewportInverse).a;\n" +
|
||||
" allin = allin && newAlpha > ALPHA_VALUE_BORDER;\n" +
|
||||
" if (newAlpha > ALPHA_VALUE_BORDER && newAlpha >= alpha)\n" +
|
||||
" {\n" +
|
||||
" alpha = newAlpha;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" if (allin)\n" +
|
||||
" {\n" +
|
||||
" alpha = 0.0;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" gl_FragColor = vec4(u_color,alpha);\n" +
|
||||
"}";
|
||||
|
||||
private final ShaderProgram shaderOutline = new ShaderProgram(sVertex, sFragment);
|
||||
|
||||
public Graphics() {
|
||||
ShaderProgram.pedantic = false;
|
||||
}
|
||||
|
||||
public void begin(float regionWidth0, float regionHeight0) {
|
||||
@@ -60,6 +128,7 @@ public class Graphics {
|
||||
public void dispose() {
|
||||
batch.dispose();
|
||||
shapeRenderer.dispose();
|
||||
shaderOutline.dispose();
|
||||
}
|
||||
|
||||
public SpriteBatch getBatch() {
|
||||
@@ -604,6 +673,56 @@ public class Graphics {
|
||||
public void drawImage(TextureRegion image, float x, float y, float w, float h) {
|
||||
batch.draw(image, adjustX(x), adjustY(y, h), w, h);
|
||||
}
|
||||
public void drawImage(TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) {
|
||||
//1st image is the image on top of the shader, 2nd image is for the outline reference for the shader glow...
|
||||
// if the 1st image don't have transparency in the middle (only on the sides, top and bottom, use the 1st image as outline reference...
|
||||
if (!selected) {
|
||||
batch.draw(image, adjustX(x), adjustY(y, h), w, h);
|
||||
} else {
|
||||
batch.end();
|
||||
shaderOutline.begin();
|
||||
shaderOutline.setUniformf("u_viewportInverse", new Vector2(1f / w, 1f / h));
|
||||
shaderOutline.setUniformf("u_offset", 3f);
|
||||
shaderOutline.setUniformf("u_step", Math.min(1f, w / 70f));
|
||||
shaderOutline.setUniformf("u_color", new Vector3(glowColor.r, glowColor.g, glowColor.b));
|
||||
shaderOutline.end();
|
||||
batch.setShader(shaderOutline);
|
||||
batch.begin();
|
||||
//glow
|
||||
batch.draw(glowImageReference, adjustX(x), adjustY(y, h), w, h);
|
||||
batch.end();
|
||||
batch.setShader(null);
|
||||
batch.begin();
|
||||
//img
|
||||
batch.draw(image, adjustX(x), adjustY(y, h), w, h);
|
||||
}
|
||||
}
|
||||
public void drawDeckBox(FImage cardArt, float scale, TextureRegion image, TextureRegion glowImageReference, float x, float y, float w, float h, Color glowColor, boolean selected) {
|
||||
float yBox = y-(h*0.25f);
|
||||
if (!selected) {
|
||||
cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f);
|
||||
batch.draw(image, adjustX(x), adjustY(yBox, h), w, h);
|
||||
} else {
|
||||
batch.end();
|
||||
shaderOutline.begin();
|
||||
shaderOutline.setUniformf("u_viewportInverse", new Vector2(1f / w, 1f / h));
|
||||
shaderOutline.setUniformf("u_offset", 3f);
|
||||
shaderOutline.setUniformf("u_step", Math.min(1f, w / 70f));
|
||||
shaderOutline.setUniformf("u_color", new Vector3(glowColor.r, glowColor.g, glowColor.b));
|
||||
shaderOutline.end();
|
||||
batch.setShader(shaderOutline);
|
||||
batch.begin();
|
||||
//glow
|
||||
batch.draw(glowImageReference, adjustX(x), adjustY(yBox, h), w, h);
|
||||
batch.end();
|
||||
batch.setShader(null);
|
||||
batch.begin();
|
||||
//cardart
|
||||
cardArt.draw(this,x+((w-w*scale)/2), y+((h-h*scale)/3f), w*scale, h*scale/1.85f);
|
||||
//deckbox
|
||||
batch.draw(image, adjustX(x), adjustY(yBox, h), w, h);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawRepeatingImage(Texture image, float x, float y, float w, float h) {
|
||||
if (startClip(x, y, w, h)) { //only render if clip successful, otherwise it will escape bounds
|
||||
|
||||
@@ -30,7 +30,8 @@ public class FSkin {
|
||||
private static final Map<FSkinProp, FSkinImage> images = new HashMap<>(512);
|
||||
private static final Map<Integer, TextureRegion> avatars = new HashMap<>(150);
|
||||
private static final Map<Integer, TextureRegion> sleeves = new HashMap<>(64);
|
||||
private static final Map<Integer, TextureRegion> borders = new HashMap<>(2);
|
||||
private static final Map<Integer, TextureRegion> borders = new HashMap<>();
|
||||
private static final Map<Integer, TextureRegion> deckbox = new HashMap<>();
|
||||
|
||||
private static Array<String> allSkins;
|
||||
private static FileHandle preferredDir;
|
||||
@@ -196,6 +197,7 @@ public class FSkin {
|
||||
final FileHandle f10 = getDefaultSkinFile(ForgeConstants.SPRITE_BORDER_FILE);
|
||||
final FileHandle f11 = getSkinFile(ForgeConstants.SPRITE_BUTTONS_FILE);
|
||||
final FileHandle f12 = getSkinFile(ForgeConstants.SPRITE_START_FILE);
|
||||
final FileHandle f13 = getDefaultSkinFile(ForgeConstants.SPRITE_DECKBOX_FILE);
|
||||
|
||||
try {
|
||||
textures.put(f1.path(), new Texture(f1));
|
||||
@@ -331,10 +333,20 @@ public class FSkin {
|
||||
FSkin.sleeves.put(scount++, new TextureRegion(txDefaultSleeves, i, j, 360, 500));
|
||||
}
|
||||
}
|
||||
|
||||
//borders
|
||||
Texture bordersBW = new Texture(f10);
|
||||
FSkin.borders.put(0, new TextureRegion(bordersBW, 2, 2, 672, 936));
|
||||
FSkin.borders.put(1, new TextureRegion(bordersBW, 676, 2, 672, 936));
|
||||
//deckboxes
|
||||
Texture deckboxes = new Texture(f13, textureFilter);
|
||||
if (textureFilter)
|
||||
deckboxes.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear);
|
||||
//gold bg
|
||||
FSkin.deckbox.put(0, new TextureRegion(deckboxes, 2, 2, 488, 680));
|
||||
//deck box for card art
|
||||
FSkin.deckbox.put(1, new TextureRegion(deckboxes, 492, 2, 488, 680));
|
||||
//generic deck box
|
||||
FSkin.deckbox.put(2, new TextureRegion(deckboxes, 982, 2, 488, 680));
|
||||
|
||||
preferredIcons.dispose();
|
||||
pxDefaultAvatars.dispose();
|
||||
@@ -430,5 +442,9 @@ public class FSkin {
|
||||
return borders;
|
||||
}
|
||||
|
||||
public static Map<Integer, TextureRegion> getDeckbox() {
|
||||
return deckbox;
|
||||
}
|
||||
|
||||
public static boolean isLoaded() { return loaded; }
|
||||
}
|
||||
|
||||
@@ -190,11 +190,17 @@ public class CardFaceSymbols {
|
||||
}
|
||||
|
||||
public static void drawColorSet(Graphics g, ColorSet colorSet, float x, float y, final float imageSize) {
|
||||
drawColorSet(g, colorSet, x, y, imageSize, false);
|
||||
}
|
||||
public static void drawColorSet(Graphics g, ColorSet colorSet, float x, float y, final float imageSize, boolean vertical) {
|
||||
final float dx = imageSize;
|
||||
|
||||
for (final ManaCostShard s : colorSet.getOrderedShards()) {
|
||||
drawSymbol(s.getImageKey(), g, x, y, imageSize, imageSize);
|
||||
x += dx;
|
||||
if (!vertical)
|
||||
x += dx;
|
||||
else
|
||||
y += dx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ public class FDeckChooser extends FScreen {
|
||||
private Callback<Deck> callback;
|
||||
private NetDeckCategory netDeckCategory;
|
||||
private boolean refreshingDeckType;
|
||||
private boolean firstactivation = true;
|
||||
|
||||
private final DeckManager lstDecks;
|
||||
private final FButton btnNewDeck = new FButton(Localizer.getInstance().getMessage("lblNewDeck"));
|
||||
@@ -226,6 +227,11 @@ public class FDeckChooser extends FScreen {
|
||||
|
||||
@Override
|
||||
public void onActivate() {
|
||||
//somehow a loaded deck state from startup don't refresh accordingly for imageview so refresh it on first activation
|
||||
if(firstactivation) {
|
||||
needRefreshOnActivate = true;
|
||||
firstactivation = false;
|
||||
}
|
||||
if (needRefreshOnActivate) {
|
||||
needRefreshOnActivate = false;
|
||||
refreshDecksList(selectedDeckType, true, null);
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
package forge.itemmanager.views;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import forge.Forge;
|
||||
import forge.Forge.KeyInputAdapter;
|
||||
import forge.Graphics;
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FImageComplex;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinColor;
|
||||
import forge.assets.FSkinImage;
|
||||
import forge.assets.FSkinColor.Colors;
|
||||
import forge.assets.FSkinFont;
|
||||
import forge.assets.ImageCache;
|
||||
import forge.card.CardFaceSymbols;
|
||||
import forge.card.CardRenderer;
|
||||
import forge.card.CardRenderer.CardStackPosition;
|
||||
import forge.card.CardZoom;
|
||||
import forge.card.ColorSet;
|
||||
import forge.deck.ArchetypeDeckGenerator;
|
||||
import forge.deck.CardThemedDeckGenerator;
|
||||
import forge.deck.CommanderDeckGenerator;
|
||||
@@ -36,6 +41,7 @@ import forge.toolbox.FEvent.FEventHandler;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -869,7 +875,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
||||
ItemInfo item = getItemAtPoint(x + getLeft(), y + getTop());
|
||||
if (item != null) {
|
||||
if(item.getKey() instanceof CardThemedDeckGenerator || item.getKey() instanceof CommanderDeckGenerator
|
||||
|| item.getKey() instanceof ArchetypeDeckGenerator){
|
||||
|| item.getKey() instanceof ArchetypeDeckGenerator || item.getKey() instanceof DeckProxy){
|
||||
FDeckViewer.show(((DeckProxy)item.getKey()).getDeck());
|
||||
return true;
|
||||
}
|
||||
@@ -922,6 +928,7 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
||||
private int index;
|
||||
private CardStackPosition pos;
|
||||
private boolean selected;
|
||||
private final float IMAGE_SIZE = CardRenderer.MANA_SYMBOL_SIZE;
|
||||
|
||||
private ItemInfo(T item0, Group group0) {
|
||||
item = item0;
|
||||
@@ -954,30 +961,89 @@ public class ImageView<T extends InventoryItem> extends ItemView<T> {
|
||||
final float y = getTop() - group.getTop() - getScrollValue();
|
||||
final float w = getWidth();
|
||||
final float h = getHeight();
|
||||
|
||||
if (selected) { //if round border is enabled, the select highlight is also rounded..
|
||||
if (Forge.enableUIMask) {
|
||||
//fillroundrect has rough/aliased corner
|
||||
g.fillRoundRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE,
|
||||
w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE, (h - w) / 10);
|
||||
//drawroundrect has GL_SMOOTH to `smoothen/faux` the aliased corner
|
||||
g.drawRoundRect(1f, Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE,
|
||||
w + 1.5f * SEL_BORDER_SIZE, h + 1.5f * SEL_BORDER_SIZE, (h - w) / 10);
|
||||
Texture dpImg = null;
|
||||
boolean deckSelectMode = false;
|
||||
if (item instanceof DeckProxy) {
|
||||
dpImg = ImageCache.getImage(item);
|
||||
deckSelectMode = true;
|
||||
}
|
||||
if (selected) {
|
||||
if (!deckSelectMode) {
|
||||
//if round border is enabled, the select highlight is also rounded..
|
||||
if (Forge.enableUIMask) {
|
||||
//fillroundrect has rough/aliased corner
|
||||
g.fillRoundRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE, (h - w) / 10);
|
||||
//drawroundrect has GL_SMOOTH to `smoothen/faux` the aliased corner
|
||||
g.drawRoundRect(1f, Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 1.5f * SEL_BORDER_SIZE, h + 1.5f * SEL_BORDER_SIZE, (h - w) / 10);
|
||||
}
|
||||
else //default rectangle highlight
|
||||
g.fillRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE);
|
||||
}
|
||||
else //default rectangle highlight
|
||||
g.fillRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE,
|
||||
w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE);
|
||||
}
|
||||
|
||||
if (item instanceof PaperCard) {
|
||||
CardRenderer.drawCard(g, (PaperCard)item, x, y, w, h, pos);
|
||||
}
|
||||
else {
|
||||
CardRenderer.drawCard(g, (PaperCard) item, x, y, w, h, pos);
|
||||
} else if (deckSelectMode) {
|
||||
DeckProxy dp = ((DeckProxy) item);
|
||||
ColorSet deckColor = dp.getColor();
|
||||
float scale = 0.75f;
|
||||
|
||||
if (dpImg != null) {//generated decks have missing info...
|
||||
if (Forge.enableUIMask){
|
||||
//commander bg
|
||||
g.drawImage(FSkin.getDeckbox().get(0), FSkin.getDeckbox().get(0), x, y, w, h, Color.GREEN, selected);
|
||||
TextureRegion tr = ImageCache.croppedBorderImage(dpImg);
|
||||
g.drawImage(tr, x+(w-w*scale)/2, y+(h-h*scale)/1.5f, w*scale, h*scale);
|
||||
} else {
|
||||
if (selected)
|
||||
g.fillRect(Color.GREEN, x - SEL_BORDER_SIZE, y - SEL_BORDER_SIZE, w + 2 * SEL_BORDER_SIZE, h + 2 * SEL_BORDER_SIZE);
|
||||
g.drawImage(dpImg, x, y, w, h);
|
||||
}
|
||||
//fake labelname shadow
|
||||
g.drawText(item.getName(), GROUP_HEADER_FONT, Color.BLACK, (x + PADDING)-1f, (y + PADDING*2)+1f, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, false);
|
||||
//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()){
|
||||
FImageComplex cardArt = CardRenderer.getCardArt(dp.getHighestCMCCard().getImageKey(false), false, false, false);
|
||||
//draw the deckbox
|
||||
if (cardArt != null){
|
||||
g.drawDeckBox(cardArt, scale, FSkin.getDeckbox().get(1), FSkin.getDeckbox().get(2), x, y, w, h, Color.GREEN, selected);
|
||||
}
|
||||
} else {
|
||||
//generic box
|
||||
g.drawImage(FSkin.getDeckbox().get(2), FSkin.getDeckbox().get(2), x, y-(h*0.25f), w, h, Color.GREEN, selected);
|
||||
}
|
||||
if (deckColor != null) {
|
||||
//deck color identity
|
||||
float symbolSize = IMAGE_SIZE;
|
||||
if (Forge.isLandscapeMode()) {
|
||||
if (columnCount == 4)
|
||||
symbolSize = IMAGE_SIZE * 1.5f;
|
||||
else if (columnCount == 3)
|
||||
symbolSize = IMAGE_SIZE * 2f;
|
||||
else if (columnCount == 2)
|
||||
symbolSize = IMAGE_SIZE * 3f;
|
||||
else if (columnCount == 1)
|
||||
symbolSize = IMAGE_SIZE * 4f;
|
||||
} else {
|
||||
if (columnCount > 2)
|
||||
symbolSize = IMAGE_SIZE * (0.5f);
|
||||
}
|
||||
//vertical mana icons
|
||||
CardFaceSymbols.drawColorSet(g, deckColor, x +(w-symbolSize), y+(h/8), symbolSize, true);
|
||||
}
|
||||
String deckname = TextUtil.fastReplace(item.getName(),"] #", "]\n#");
|
||||
//deckname fakeshadow
|
||||
g.drawText(deckname, GROUP_HEADER_FONT, Color.BLACK, (x + PADDING)-1f, (y + (h/10) + PADDING)+1f, w - 2 * PADDING, h - 2 * PADDING, true, Align.center, true);
|
||||
//deck name
|
||||
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);
|
||||
if (img != null) {
|
||||
g.drawImage(img, x, y, w, h);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -101,17 +101,22 @@ public class ConquestRewardDialog extends FScrollPane {
|
||||
|
||||
float startX = x;
|
||||
int cardCount = cardRevealers.size();
|
||||
cardRevealers.get(0).setBounds(x, y, cardWidth, cardHeight);
|
||||
for (int i = 1; i < cardCount; i++) {
|
||||
if (i % columnCount == 0) {
|
||||
x = startX;
|
||||
y += cardHeight + PADDING;
|
||||
try {
|
||||
cardRevealers.get(0).setBounds(x, y, cardWidth, cardHeight);
|
||||
for (int i = 1; i < cardCount; i++) {
|
||||
if (i % columnCount == 0) {
|
||||
x = startX;
|
||||
y += cardHeight + PADDING;
|
||||
}
|
||||
else {
|
||||
x += cardWidth + PADDING;
|
||||
}
|
||||
cardRevealers.get(i).setBounds(x, y, cardWidth, cardHeight);
|
||||
}
|
||||
else {
|
||||
x += cardWidth + PADDING;
|
||||
}
|
||||
cardRevealers.get(i).setBounds(x, y, cardWidth, cardHeight);
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
}
|
||||
|
||||
return new ScrollBounds(visibleWidth, y + cardHeight + PADDING);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,13 @@ import forge.assets.FSkinProp;
|
||||
import forge.assets.IHasSkinProp;
|
||||
import forge.assets.TextRenderer;
|
||||
import forge.assets.FSkinColor.Colors;
|
||||
import forge.card.CardFaceSymbols;
|
||||
import forge.card.CardRenderer;
|
||||
import forge.card.CardZoom;
|
||||
import forge.card.CardRenderer.CardStackPosition;
|
||||
import forge.card.CardZoom.ActivateHandler;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostParser;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.IHasCardView;
|
||||
import forge.game.player.PlayerView;
|
||||
@@ -29,8 +32,11 @@ import forge.itemmanager.filters.ItemFilter;
|
||||
import forge.screens.match.MatchController;
|
||||
import forge.screens.match.views.VAvatar;
|
||||
import forge.screens.match.views.VStack;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.Utils;
|
||||
|
||||
import static forge.card.CardRenderer.MANA_SYMBOL_SIZE;
|
||||
|
||||
public class FChoiceList<T> extends FList<T> implements ActivateHandler {
|
||||
public static final FSkinColor ITEM_COLOR = FSkinColor.get(Colors.CLR_ZEBRA);
|
||||
public static final FSkinColor ALT_ITEM_COLOR = ITEM_COLOR.getContrastColor(-20);
|
||||
@@ -337,7 +343,17 @@ public class FChoiceList<T> extends FList<T> implements ActivateHandler {
|
||||
|
||||
@Override
|
||||
public void drawValue(Graphics g, T value, FSkinFont font, FSkinColor foreColor, boolean pressed, float x, float y, float w, float h) {
|
||||
g.drawText(getChoiceText(value), font, foreColor, x, y, w, h, allowDefaultItemWrap(), Align.left, true);
|
||||
//update manacost text to draw symbols instead
|
||||
if (value.toString().contains(" {")){
|
||||
String[] values = value.toString().split(" ");
|
||||
String cost = TextUtil.fastReplace(values[1],"}{", " ");
|
||||
cost = TextUtil.fastReplace(TextUtil.fastReplace(cost,"{", ""),"}", "");
|
||||
ManaCost manaCost = new ManaCost(new ManaCostParser(cost));
|
||||
CardFaceSymbols.drawManaCost(g, manaCost, x + font.getBounds(values[0]+" ").width, y + (h - MANA_SYMBOL_SIZE) / 2, MANA_SYMBOL_SIZE);
|
||||
g.drawText(values[0], font, foreColor, x, y, w, h, allowDefaultItemWrap(), Align.left, true);
|
||||
} else {
|
||||
g.drawText(getChoiceText(value), font, foreColor, x, y, w, h, allowDefaultItemWrap(), Align.left, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected class NumberRenderer extends DefaultItemRenderer {
|
||||
|
||||
@@ -12,4 +12,5 @@ SVar:X:Count$xPaid
|
||||
SVar:Y:Count$RememberedSize
|
||||
SVar:XLands:Number$0
|
||||
DeckHas:Ability$Sacrifice
|
||||
AI:RemoveDeck:All
|
||||
Oracle:Sacrifice X lands. For each land sacrificed this way, draw a card. You may play X additional lands this turn. Lands you control enter the battlefield tapped this turn.
|
||||
|
||||
@@ -494,6 +494,7 @@ lblCreateaDeck=Erzeuge ein Deck.
|
||||
#CSubmenuQuestPrefs.java
|
||||
lblEnteraNumber=Nummer eingeben
|
||||
lblSavefailed=Speichern fehlgeschlagen
|
||||
lblEnteraDecimal=Eine Zahl eingeben
|
||||
#DialogChooseFormats.java
|
||||
cbWantReprints=Erlaube passende Drucke aus anderen Sets
|
||||
lblChooseFormats=Wähle Format
|
||||
@@ -734,6 +735,8 @@ lblWinsperDraftRotation=Siege pro Draft notwendig
|
||||
ttWinsperDraftRotation=Wenn ein Draft nicht soweit fertig gespielt wird, wird er entfernt oder ersetzt.
|
||||
lblRotationType=Austauschtyp
|
||||
ttRotationType=Bei 0 verschwinden alte Drafts, bei 1 wird er durch einen neuen ersetzt.
|
||||
lblWildOpponentMultiplier=Wild-Multiplikator
|
||||
lblWildOpponentNumber=Anzahl der Wild-Gegner
|
||||
#StatTypeFilter.java
|
||||
lblclicktotoogle=Klicke zum Umschalten des Filters, Rechtsklick für Einzelanzeige von:
|
||||
#SItemManagerUtil.java
|
||||
@@ -2587,7 +2590,5 @@ lblEnterMessageToSend=Nachricht zum Senden eingeben
|
||||
lblDetectedInvalidHostAddress=Ungültige Host-Adresse ({0}) wurde festgestellt.
|
||||
#Player.java
|
||||
lblChooseACompanion=Wähle einen Gefährten
|
||||
lblWildOpponentMultiplier=Wild-Multiplikator
|
||||
lblEnteraDecimal=Eine Zahl eingeben
|
||||
lblWildOpponentNumber=Anzahl der Wild-Gegner
|
||||
#QuestPreferences.java
|
||||
lblWildOpponentNumberError=Anzahl der Wild-Gegner kann nur 0 bis 3 sein
|
||||
|
||||
@@ -494,6 +494,7 @@ lblCreateaDeck=Create a Deck.
|
||||
#CSubmenuQuestPrefs.java
|
||||
lblEnteraNumber=Enter a number
|
||||
lblSavefailed=Save failed
|
||||
lblEnteraDecimal=Enter a decimal
|
||||
#DialogChooseFormats.java
|
||||
cbWantReprints=Allow compatible reprints from other sets
|
||||
lblChooseFormats=Choose formats
|
||||
@@ -734,6 +735,8 @@ lblWinsperDraftRotation=Wins per Draft Rotation
|
||||
ttWinsperDraftRotation=If a Draft is not played for this many match wins, it will be removed or replaced.
|
||||
lblRotationType=Rotation Type
|
||||
ttRotationType=If set to 0, old drafts disappear, if set to 1, they are replaced with another one using different sets.
|
||||
lblWildOpponentNumber=Number of Wild Opponents
|
||||
lblWildOpponentMultiplier=Wild Multiplier
|
||||
#StatTypeFilter.java
|
||||
lblclicktotoogle=click to toggle the filter, right-click to show only
|
||||
#SItemManagerUtil.java
|
||||
@@ -2587,7 +2590,5 @@ lblEnterMessageToSend=Enter message to send
|
||||
lblDetectedInvalidHostAddress=Invalid host address ({0}) was detected.
|
||||
#Player.java
|
||||
lblChooseACompanion=Choose a companion
|
||||
lblWildOpponentMultiplier=Wild Multiplier
|
||||
lblEnteraDecimal=Enter a decimal
|
||||
lblWildOpponentNumber=Number of Wild Opponents
|
||||
#QuestPreferences.java
|
||||
lblWildOpponentNumberError=Wild Opponents can only be 0 to 3
|
||||
|
||||
@@ -494,6 +494,7 @@ lblCreateaDeck=Crear un Mazo.
|
||||
#CSubmenuQuestPrefs.java
|
||||
lblEnteraNumber=Ingrese un numero
|
||||
lblSavefailed=Error al guardar
|
||||
lblEnteraDecimal=Enter a decimal
|
||||
#DialogChooseFormats.java
|
||||
cbWantReprints=Permitir reimpresiones compatibles de otras ediciones.
|
||||
lblChooseFormats=Elije Formatos
|
||||
@@ -734,6 +735,8 @@ lblWinsperDraftRotation=Victorias Rotación de Draft
|
||||
ttWinsperDraftRotation=Si no se juega un Draft para esta cantidad de victorias, se eliminará o reemplazará.
|
||||
lblRotationType=Tipo de Rotación
|
||||
ttRotationType=Si se establece en 0, los anteriores Draft desaparecen, si se establece en 1, se reemplazan por otros que utilizan sets diferentes.
|
||||
lblWildOpponentNumber=Number of Wild Opponents
|
||||
lblWildOpponentMultiplier=Wild Multiplier
|
||||
#StatTypeFilter.java
|
||||
lblclicktotoogle=haga clic para alternar el filtro, haga clic con el botón derecho para mostrar solo
|
||||
#SItemManagerUtil.java
|
||||
@@ -2587,3 +2590,5 @@ lblEnterMessageToSend=Ingrese el mensaje para enviar
|
||||
lblDetectedInvalidHostAddress=Se detectó una dirección de host no válida ({0}).
|
||||
#Player.java
|
||||
lblChooseACompanion=Elige un compañero
|
||||
#QuestPreferences.java
|
||||
lblWildOpponentNumberError=Wild Opponents can only be 0 to 3
|
||||
|
||||
@@ -494,6 +494,7 @@ lblCreateaDeck=Crea un mazzo.
|
||||
#CSubmenuQuestPrefs.java
|
||||
lblEnteraNumber=Inserisci un numero
|
||||
lblSavefailed=Salvataggio fallito
|
||||
lblEnteraDecimal=Enter a decimal
|
||||
#DialogChooseFormats.java
|
||||
cbWantReprints=Consenti ristampe compatibili da altri set
|
||||
lblChooseFormats=Scegli i formati
|
||||
@@ -734,6 +735,8 @@ lblWinsperDraftRotation=Vittorie per Draft Rotation
|
||||
ttWinsperDraftRotation=Se una Draft non viene giocata per questo numero di vittorie, verrà rimossa o sostituita.
|
||||
lblRotationType=Tipo di rotazione
|
||||
ttRotationType=Se impostato su 0, le vecchie bozze scompaiono, se impostate su 1, vengono sostituite con un''altra utilizzando set diversi.
|
||||
lblWildOpponentNumber=Number of Wild Opponents
|
||||
lblWildOpponentMultiplier=Wild Multiplier
|
||||
#StatTypeFilter.java
|
||||
lblclicktotoogle=fai clic per attivare o disattivare il filtro, fai clic con il pulsante destro del mouse per mostrare solo
|
||||
#SItemManagerUtil.java
|
||||
@@ -2586,4 +2589,6 @@ lblEnterMessageToSend=Enter message to send
|
||||
#OnlineLobbyScreen.java
|
||||
lblDetectedInvalidHostAddress=Invalid host address ({0}) was detected.
|
||||
#Player.java
|
||||
lblChooseACompanion=Choose a companion
|
||||
lblChooseACompanion=Choose a companion
|
||||
#QuestPreferences.java
|
||||
lblWildOpponentNumberError=Wild Opponents can only be 0 to 3
|
||||
|
||||
@@ -494,6 +494,7 @@ lblCreateaDeck=创建一个套牌
|
||||
#CSubmenuQuestPrefs.java
|
||||
lblEnteraNumber=输入一个数
|
||||
lblSavefailed=保存错误
|
||||
lblEnteraDecimal=输入一个十进制小数
|
||||
#DialogChooseFormats.java
|
||||
cbWantReprints=允许来自其他系列的重印牌
|
||||
lblChooseFormats=选择赛制
|
||||
@@ -734,6 +735,8 @@ lblWinsperDraftRotation=每次轮抓胜利轮替
|
||||
ttWinsperDraftRotation=如果轮抓没有赢这么多场,那么它将被删除或者替换。
|
||||
lblRotationType=轮替类型
|
||||
ttRotationType=如果设置为0,旧系列消失,如果设置为1,则用不同系列替换。
|
||||
lblWildOpponentNumber=野外对手数量
|
||||
lblWildOpponentMultiplier=野外对手倍数
|
||||
#StatTypeFilter.java
|
||||
lblclicktotoogle=单击以切换筛选器,右键单机以仅显示
|
||||
#SItemManagerUtil.java
|
||||
@@ -2586,4 +2589,6 @@ lblEnterMessageToSend=输入要发送的信息
|
||||
#OnlineLobbyScreen.java
|
||||
lblDetectedInvalidHostAddress=检测到无效的主机地址({0})。
|
||||
#Player.java
|
||||
lblChooseACompanion=选择一个行侣
|
||||
lblChooseACompanion=选择一个行侣
|
||||
#QuestPreferences.java
|
||||
lblWildOpponentNumberError=野外对手数只能在0-3之间
|
||||
|
||||
BIN
forge-gui/res/skins/darkforge/sprite_avatars.png
Normal file
BIN
forge-gui/res/skins/darkforge/sprite_avatars.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 758 KiB |
BIN
forge-gui/res/skins/default/sprite_deckbox.png
Normal file
BIN
forge-gui/res/skins/default/sprite_deckbox.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 504 KiB |
@@ -1,11 +1,15 @@
|
||||
package forge.deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import forge.card.CardSplitType;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
@@ -260,6 +264,29 @@ public class DeckProxy implements InventoryItem {
|
||||
return highestRarity;
|
||||
}
|
||||
|
||||
public PaperCard getHighestCMCCard() {
|
||||
PaperCard key = null;
|
||||
Map<PaperCard, Integer> keyCMC = new HashMap<>(64);
|
||||
|
||||
for (final Entry <PaperCard, Integer> pc : getDeck().getAllCardsInASinglePool()) {
|
||||
if (pc.getKey().getRules().getManaCost() != null) {
|
||||
if (pc.getKey().getRules().getSplitType() != CardSplitType.Split)
|
||||
keyCMC.put(pc.getKey(),pc.getKey().getRules().getManaCost().getCMC());
|
||||
}
|
||||
}
|
||||
|
||||
if (!keyCMC.isEmpty()) {
|
||||
int max = Collections.max(keyCMC.values());
|
||||
//get any max cmc
|
||||
for (Entry<PaperCard, Integer> entry : keyCMC.entrySet()) {
|
||||
if (entry.getValue()==max) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public Set<GameFormat> getFormats() {
|
||||
if (formats == null) {
|
||||
formats = FModel.getFormats().getAllFormatsOfDeck(getDeck());
|
||||
|
||||
@@ -100,6 +100,7 @@ public final class ForgeConstants {
|
||||
public static final String SPRITE_ABILITY_FILE = "sprite_ability.png";
|
||||
public static final String SPRITE_BORDER_FILE = "sprite_border.png";
|
||||
public static final String SPRITE_BUTTONS_FILE = "sprite_buttons.png";
|
||||
public static final String SPRITE_DECKBOX_FILE = "sprite_deckbox.png";
|
||||
public static final String SPRITE_START_FILE = "sprite_start.png";
|
||||
public static final String SPRITE_MANAICONS_FILE = "sprite_manaicons.png";
|
||||
public static final String SPRITE_AVATARS_FILE = "sprite_avatars.png";
|
||||
|
||||
@@ -18,16 +18,15 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestEvent;
|
||||
import forge.quest.QuestEventDifficulty;
|
||||
import forge.quest.QuestEventDuel;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
|
||||
public class MainWorldDuelReader extends StorageReaderFolder<QuestEventDuel> {
|
||||
@@ -77,10 +76,11 @@ public class MainWorldDuelReader extends StorageReaderFolder<QuestEventDuel> {
|
||||
}
|
||||
|
||||
// then I add wild decks in constructed directory
|
||||
IStorage<Deck> constructedDecks = FModel.getDecks().getConstructed();
|
||||
Iterator it = constructedDecks.iterator();
|
||||
Iterable<DeckProxy> constructedDecks = DeckProxy.getAllConstructedDecks();
|
||||
Iterator<DeckProxy> it = constructedDecks.iterator();
|
||||
|
||||
while(it.hasNext()) {
|
||||
Deck currDeck = (Deck) it.next();
|
||||
Deck currDeck = it.next().getDeck();
|
||||
final QuestEventDuel newDeck = read(currDeck);
|
||||
String newKey = keySelector.apply(newDeck);
|
||||
if (result.containsKey(newKey)) {
|
||||
|
||||
Reference in New Issue
Block a user