mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Support flipping cards on reward dialog
Prevent concurrent modification exception from opening overlay from background thread
This commit is contained in:
@@ -223,6 +223,10 @@ public class ConquestRewardDialog extends FScrollPane {
|
|||||||
for (int i = currentIndex; i < index; i++) {
|
for (int i = currentIndex; i < index; i++) {
|
||||||
cardRevealers.get(i).progress = 1;
|
cardRevealers.get(i).progress = 1;
|
||||||
}
|
}
|
||||||
|
//ensure current card in view
|
||||||
|
if (getScrollHeight() > getHeight() && index < cardCount) {
|
||||||
|
scrollIntoView(cardRevealers.get(index), PADDING);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentIndex = index;
|
currentIndex = index;
|
||||||
@@ -237,10 +241,11 @@ public class ConquestRewardDialog extends FScrollPane {
|
|||||||
|
|
||||||
//skip remainder of animation
|
//skip remainder of animation
|
||||||
private void skip() {
|
private void skip() {
|
||||||
currentIndex = cardRevealers.size();
|
int cardCount = cardRevealers.size();
|
||||||
for (int i = currentIndex; i < currentIndex; i++) {
|
for (int i = currentIndex; i < cardCount; i++) {
|
||||||
cardRevealers.get(i).progress = 1;
|
cardRevealers.get(i).progress = 1;
|
||||||
}
|
}
|
||||||
|
currentIndex = cardCount;
|
||||||
animation.stop();
|
animation.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,18 +261,21 @@ public class ConquestRewardDialog extends FScrollPane {
|
|||||||
|
|
||||||
private class CardRevealer extends FLabel {
|
private class CardRevealer extends FLabel {
|
||||||
private static final float DUPLICATE_ALPHA_COMPOSITE = 0.35f;
|
private static final float DUPLICATE_ALPHA_COMPOSITE = 0.35f;
|
||||||
|
private static final float FLIP_DURATION = 0.85f;
|
||||||
|
private static final float FADE_DUPLICATE_DURATION = 0.1f; //give a brief interlude before the next flip
|
||||||
|
|
||||||
private final ConquestReward reward;
|
private final ConquestReward reward;
|
||||||
private float progress;
|
private float progress;
|
||||||
|
|
||||||
private CardRevealer(ConquestReward reward0) {
|
private CardRevealer(ConquestReward reward0) {
|
||||||
super(new FLabel.Builder().iconScaleFactor(1f));
|
super(new FLabel.Builder().iconScaleWithFont(true).iconScaleFactor(1));
|
||||||
|
|
||||||
reward = reward0;
|
reward = reward0;
|
||||||
if (reward.isDuplicate()) {
|
if (reward.isDuplicate()) {
|
||||||
setFont(FSkinFont.get(20));
|
setFont(FSkinFont.get(20));
|
||||||
setIcon(FSkinImage.QUEST_COIN);
|
setIcon(FSkinImage.QUEST_COIN);
|
||||||
setAlignment(HAlignment.CENTER);
|
setAlignment(HAlignment.CENTER);
|
||||||
|
setText(String.valueOf(reward.getReplacementShards()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,23 +299,35 @@ public class ConquestRewardDialog extends FScrollPane {
|
|||||||
float w = getWidth();
|
float w = getWidth();
|
||||||
float h = getHeight();
|
float h = getHeight();
|
||||||
|
|
||||||
if (progress > 0.9999f) { //account for floating point error
|
if (progress >= FLIP_DURATION) {
|
||||||
|
float fadeProgress = (progress - FLIP_DURATION) / FADE_DUPLICATE_DURATION;
|
||||||
if (reward.isDuplicate()) {
|
if (reward.isDuplicate()) {
|
||||||
g.setAlphaComposite(DUPLICATE_ALPHA_COMPOSITE);
|
float alphaComposite = DUPLICATE_ALPHA_COMPOSITE;
|
||||||
|
if (fadeProgress < 1) {
|
||||||
|
alphaComposite += (1 - fadeProgress) * (1 - DUPLICATE_ALPHA_COMPOSITE);
|
||||||
|
}
|
||||||
|
g.setAlphaComposite(alphaComposite);
|
||||||
}
|
}
|
||||||
CardRenderer.drawCard(g, reward.getCard(), 0, 0, w, h, CardStackPosition.Top);
|
CardRenderer.drawCard(g, reward.getCard(), 0, 0, w, h, CardStackPosition.Top);
|
||||||
if (reward.isDuplicate()) {
|
if (reward.isDuplicate()) {
|
||||||
g.resetAlphaComposite();
|
g.resetAlphaComposite();
|
||||||
drawContent(g, 0, 0, w, h);
|
if (fadeProgress >= 1) {
|
||||||
|
drawContent(g, 0, 0, w, h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (progress >= 0.5f) {
|
|
||||||
CardRenderer.drawCard(g, reward.getCard(), 0, 0, w, h, CardStackPosition.Top);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), true);
|
float halfDuration = FLIP_DURATION / 2;
|
||||||
if (cardBack != null) {
|
if (progress >= halfDuration) {
|
||||||
g.drawImage(cardBack, 0, 0, w, h);
|
float flipWidth = w * (progress - halfDuration) / halfDuration;
|
||||||
|
CardRenderer.drawCard(g, reward.getCard(), (w - flipWidth) / 2, 0, flipWidth, h, CardStackPosition.Top);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Texture cardBack = ImageCache.getImage(ImageKeys.getTokenKey(ImageKeys.HIDDEN_CARD), true);
|
||||||
|
if (cardBack != null) {
|
||||||
|
float flipWidth = w * (halfDuration - progress) / halfDuration;
|
||||||
|
g.drawImage(cardBack, (w - flipWidth) / 2, 0, flipWidth, h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,14 @@ public class FLabel extends FDisplayObject implements IButton {
|
|||||||
private HAlignment bldAlignment = HAlignment.LEFT;
|
private HAlignment bldAlignment = HAlignment.LEFT;
|
||||||
private Vector2 bldInsets = new Vector2(DEFAULT_INSETS, DEFAULT_INSETS);
|
private Vector2 bldInsets = new Vector2(DEFAULT_INSETS, DEFAULT_INSETS);
|
||||||
|
|
||||||
private boolean bldSelectable = false;
|
private boolean bldSelectable = false;
|
||||||
private boolean bldSelected = false;
|
private boolean bldSelected = false;
|
||||||
private boolean bldOpaque = false;
|
private boolean bldOpaque = false;
|
||||||
private boolean bldIconInBackground = false;
|
private boolean bldIconInBackground = false;
|
||||||
private boolean bldIconScaleAuto = true;
|
private boolean bldIconScaleWithFont = false;
|
||||||
private boolean bldEnabled = true;
|
private boolean bldIconScaleAuto = true;
|
||||||
private boolean bldParseSymbols = true;
|
private boolean bldEnabled = true;
|
||||||
|
private boolean bldParseSymbols = true;
|
||||||
|
|
||||||
private String bldText;
|
private String bldText;
|
||||||
private FImage bldIcon;
|
private FImage bldIcon;
|
||||||
@@ -60,6 +61,7 @@ public class FLabel extends FDisplayObject implements IButton {
|
|||||||
public Builder alphaComposite(final float a0) { this.bldAlphaComposite = a0; return this; }
|
public Builder alphaComposite(final float a0) { this.bldAlphaComposite = a0; return this; }
|
||||||
public Builder enabled(final boolean b0) { this.bldEnabled = b0; return this; }
|
public Builder enabled(final boolean b0) { this.bldEnabled = b0; return this; }
|
||||||
public Builder iconScaleAuto(final boolean b0) { this.bldIconScaleAuto = b0; return this; }
|
public Builder iconScaleAuto(final boolean b0) { this.bldIconScaleAuto = b0; return this; }
|
||||||
|
public Builder iconScaleWithFont(final boolean b0) { this.bldIconScaleWithFont = b0; return this; }
|
||||||
public Builder iconScaleFactor(final float f0) { this.bldIconScaleFactor = f0; return this; }
|
public Builder iconScaleFactor(final float f0) { this.bldIconScaleFactor = f0; return this; }
|
||||||
public Builder iconInBackground(final boolean b0) { this.bldIconInBackground = b0; return this; }
|
public Builder iconInBackground(final boolean b0) { this.bldIconInBackground = b0; return this; }
|
||||||
public Builder iconInBackground() { iconInBackground(true); return this; }
|
public Builder iconInBackground() { iconInBackground(true); return this; }
|
||||||
@@ -103,7 +105,7 @@ public class FLabel extends FDisplayObject implements IButton {
|
|||||||
private float alphaComposite;
|
private float alphaComposite;
|
||||||
private HAlignment alignment;
|
private HAlignment alignment;
|
||||||
private Vector2 insets;
|
private Vector2 insets;
|
||||||
private boolean selectable, selected, opaque, iconInBackground, iconScaleAuto, pressed;
|
private boolean selectable, selected, opaque, iconInBackground, iconScaleAuto, iconScaleWithFont, pressed;
|
||||||
|
|
||||||
private String text;
|
private String text;
|
||||||
private FImage icon;
|
private FImage icon;
|
||||||
@@ -123,6 +125,7 @@ public class FLabel extends FDisplayObject implements IButton {
|
|||||||
opaque = b0.bldOpaque;
|
opaque = b0.bldOpaque;
|
||||||
iconInBackground = b0.bldIconInBackground;
|
iconInBackground = b0.bldIconInBackground;
|
||||||
iconScaleAuto = b0.bldIconScaleAuto;
|
iconScaleAuto = b0.bldIconScaleAuto;
|
||||||
|
iconScaleWithFont = b0.bldIconScaleWithFont;
|
||||||
text = b0.bldText != null ? b0.bldText : "";
|
text = b0.bldText != null ? b0.bldText : "";
|
||||||
icon = b0.bldIcon;
|
icon = b0.bldIcon;
|
||||||
textColor = b0.bldTextColor;
|
textColor = b0.bldTextColor;
|
||||||
@@ -323,7 +326,11 @@ public class FLabel extends FDisplayObject implements IButton {
|
|||||||
float iconHeight = icon.getHeight();
|
float iconHeight = icon.getHeight();
|
||||||
float aspectRatio = iconWidth / iconHeight;
|
float aspectRatio = iconWidth / iconHeight;
|
||||||
|
|
||||||
if (iconInBackground || iconScaleAuto) {
|
if (iconScaleWithFont) {
|
||||||
|
iconHeight = font.getLineHeight() * iconScaleFactor;
|
||||||
|
iconWidth = iconHeight * aspectRatio;
|
||||||
|
}
|
||||||
|
else if (iconInBackground || iconScaleAuto) {
|
||||||
iconHeight = h * iconScaleFactor;
|
iconHeight = h * iconScaleFactor;
|
||||||
iconWidth = iconHeight * aspectRatio;
|
iconWidth = iconHeight * aspectRatio;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.Input.Keys;
|
|||||||
import com.badlogic.gdx.utils.Timer;
|
import com.badlogic.gdx.utils.Timer;
|
||||||
import com.badlogic.gdx.utils.Timer.Task;
|
import com.badlogic.gdx.utils.Timer.Task;
|
||||||
|
|
||||||
|
import forge.FThreads;
|
||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.Graphics;
|
import forge.Graphics;
|
||||||
import forge.assets.FSkinColor;
|
import forge.assets.FSkinColor;
|
||||||
@@ -90,6 +91,8 @@ public abstract class FOverlay extends FContainer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVisible(boolean visible0) {
|
public void setVisible(boolean visible0) {
|
||||||
|
FThreads.assertExecutedByEdt(true); //prevent showing or hiding overlays from background thread
|
||||||
|
|
||||||
if (this.isVisible() == visible0) { return; }
|
if (this.isVisible() == visible0) { return; }
|
||||||
|
|
||||||
//ensure task to hide temporary overlay cancelled and run if another overlay becomes shown or hidden
|
//ensure task to hide temporary overlay cancelled and run if another overlay becomes shown or hidden
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ public class ConquestController {
|
|||||||
//also build list of all rewards including replacement shards for each duplicate card
|
//also build list of all rewards including replacement shards for each duplicate card
|
||||||
//build this list in reverse order so commons appear first
|
//build this list in reverse order so commons appear first
|
||||||
int shards = 0;
|
int shards = 0;
|
||||||
List<ConquestReward> allRewards = new ArrayList<ConquestReward>();
|
final List<ConquestReward> allRewards = new ArrayList<ConquestReward>();
|
||||||
for (int i = rewards.size() - 1; i >= 0; i--) {
|
for (int i = rewards.size() - 1; i >= 0; i--) {
|
||||||
int replacementShards = 0;
|
int replacementShards = 0;
|
||||||
PaperCard card = rewards.get(i);
|
PaperCard card = rewards.get(i);
|
||||||
@@ -287,7 +287,12 @@ public class ConquestController {
|
|||||||
allRewards.add(new ConquestReward(card, replacementShards));
|
allRewards.add(new ConquestReward(card, replacementShards));
|
||||||
}
|
}
|
||||||
|
|
||||||
view.showConquestRewards("Booster Awarded", allRewards);
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
view.showConquestRewards("Booster Awarded", allRewards);
|
||||||
|
}
|
||||||
|
});
|
||||||
model.unlockCards(rewards);
|
model.unlockCards(rewards);
|
||||||
model.rewardAEtherShards(shards);
|
model.rewardAEtherShards(shards);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user