- support showing sprite icons on tooltips via TextraLabel

- fix AdventureScreen gifAnimation height using tall screens
- preload back texture for hot swapping actor
This commit is contained in:
Anthony Calosa
2023-02-19 12:02:26 +08:00
parent 98a3c7ff3e
commit 50358b4471
2 changed files with 129 additions and 89 deletions

View File

@@ -16,9 +16,9 @@ import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.Tooltip;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
@@ -27,6 +27,7 @@ import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.Scaling;
import com.github.tommyettinger.textra.TextraButton;
import com.github.tommyettinger.textra.TextraLabel;
import forge.Forge;
import forge.Graphics;
import forge.ImageKeys;
@@ -60,7 +61,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
final int preview_w = 488; //Width and height for generated images.
final int preview_h = 680;
static TextureRegion backTexture;
TextureRegion backTexture;
Texture image, T, Talt;
Graphics graphics;
Texture generatedTooltip = null; //Storage for a generated tooltip. To dispose of on exit.
@@ -76,6 +77,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
public static int renderedCount = 0; //Counter for cards that require rendering a preview.
static final ImageFetcher fetcher = GuiBase.getInterface().getImageFetcher();
RewardImage toolTipImage;
String description = "";
@Override
public void dispose() {
@@ -115,9 +117,14 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
if (imageFile == null)
return;
if (!Forge.getAssets().manager().contains(imageFile.getPath())) {
Forge.getAssets().manager().load(imageFile.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(imageFile.getPath());
count += 1;
try {
Forge.getAssets().manager().load(imageFile.getPath(), Texture.class, Forge.getAssets().getTextureFilter());
Forge.getAssets().manager().finishLoadingAsset(imageFile.getPath());
count += 1;
} catch (Exception e) {
//e.printStackTrace();
return;
}
}
Texture replacement = Forge.getAssets().manager().get(imageFile.getPath(), Texture.class, false);
if (replacement == null)
@@ -131,13 +138,13 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
toolTipImage.remove();
toolTipImage = new RewardImage(processDrawable(image));
if (GuiBase.isAndroid() || Forge.hasGamepad()) {
if (holdTooltip.tooltip_image.getDrawable() instanceof TextureRegionDrawable) {
((TextureRegionDrawable) holdTooltip.tooltip_image.getDrawable()).getRegion().getTexture().dispose();
if (holdTooltip.getImage() != null && holdTooltip.getImage().getDrawable() instanceof TextureRegionDrawable) {
((TextureRegionDrawable) holdTooltip.getImage().getDrawable()).getRegion().getTexture().dispose();
}
holdTooltip.tooltip_actor.clear();
holdTooltip.tooltip_actor.add(toolTipImage);
holdTooltip.tooltip_actor = new ComplexTooltip(toolTipImage);
} else {
tooltip.setActor(toolTipImage);
tooltip.setActor(new ComplexTooltip(toolTipImage));
}
}
if (T != null)
@@ -192,6 +199,26 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
Forge.getAssets().manager().finishLoadingAsset(backFace.getPath());
ImageCache.updateSynqCount(backFace, 1);
}
Texture back = Forge.getAssets().manager().get(backFace.getPath(), Texture.class, false);
if (back != null) {
if (holdTooltip != null) {
if (holdTooltip.tooltip_actor.getChildren().size <= 2) {
holdTooltip.tooltip_actor.altcImage = new RewardImage(processDrawable(back));
holdTooltip.tooltip_actor.addActorAt(2, holdTooltip.tooltip_actor.altcImage);
holdTooltip.tooltip_actor.swapActor(holdTooltip.tooltip_actor.altcImage, holdTooltip.tooltip_actor.cImage);
}
}
} else {
if (holdTooltip != null) {
if (Talt == null)
Talt = renderPlaceholder(new Graphics(), reward.getCard(), true);
if (holdTooltip.tooltip_actor.getChildren().size <= 2) {
holdTooltip.tooltip_actor.altcImage = new RewardImage(processDrawable(Talt));
holdTooltip.tooltip_actor.addActorAt(2, holdTooltip.tooltip_actor.altcImage);
holdTooltip.tooltip_actor.swapActor(holdTooltip.tooltip_actor.altcImage, holdTooltip.tooltip_actor.cImage);
}
}
}
} catch (Exception e) {
System.err.println("Failed to load image: " + backFace.getPath());
}
@@ -334,37 +361,24 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
return;
if (!reward.getCard().hasBackFace())
return;
Texture alt = ImageCache.getImage(reward.getCard().getImageKey(true), false);
if (GuiBase.isAndroid() || Forge.hasGamepad()) {
if (alternate) {
if (alt != null) {
holdTooltip.tooltip_actor.clear();
holdTooltip.tooltip_actor.add(new RewardImage(processDrawable(alt)));
} else {
if (Talt == null)
Talt = renderPlaceholder(new Graphics(), reward.getCard(), true);
holdTooltip.tooltip_actor.clear();
holdTooltip.tooltip_actor.add(new RewardImage(processDrawable(Talt)));
}
} else {
if (toolTipImage != null) {
holdTooltip.tooltip_actor.clear();
holdTooltip.tooltip_actor.add(toolTipImage);
}
if (holdTooltip.tooltip_actor.altcImage != null) {
holdTooltip.tooltip_actor.swapActor(holdTooltip.tooltip_actor.cImage, holdTooltip.tooltip_actor.altcImage);
}
} else {
Texture alt = ImageCache.getImage(reward.getCard().getImageKey(true), false);
if (hover) {
if (alternate) {
if (alt != null) {
tooltip.setActor(new RewardImage(processDrawable(alt)));
tooltip.setActor(new ComplexTooltip(new RewardImage(processDrawable(alt))));
} else {
if (Talt == null)
Talt = renderPlaceholder(new Graphics(), reward.getCard(), true);
tooltip.setActor(new RewardImage(processDrawable(Talt)));
tooltip.setActor(new ComplexTooltip(new RewardImage(processDrawable(Talt))));
}
} else {
if (toolTipImage != null)
tooltip.setActor(toolTipImage);
tooltip.setActor(new ComplexTooltip(toolTipImage));
}
}
}
@@ -428,11 +442,11 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
toolTipImage = new RewardImage(processDrawable(image));
if (GuiBase.isAndroid() || Forge.hasGamepad()) {
if (holdTooltip == null)
holdTooltip = new HoldTooltip(toolTipImage);
holdTooltip = new HoldTooltip(new ComplexTooltip(toolTipImage));
addListener(holdTooltip);
} else {
if (tooltip == null)
tooltip = new ImageToolTip(toolTipImage);
tooltip = new ImageToolTip(new ComplexTooltip(toolTipImage));
tooltip.setInstant(true);
addListener(tooltip);
}
@@ -451,7 +465,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
}
private Texture renderPlaceholder(Graphics g, PaperCard card, boolean alternate) { //Use CardImageRenderer to output a Texture.
if (renderedCount++ == 0) {
if (renderedCount < 1) {
renderedCount++;
//The first time we find a card that has no art, render one out of view to fully initialize CardImageRenderer.
g.begin(preview_w, preview_h);
CardImageRenderer.drawCardImage(g, CardView.getCardForUi(reward.getCard()), false, -(preview_w + 20), 0, preview_w, preview_h, CardRenderer.CardStackPosition.Top, Forge.allowCardBG, true);
@@ -477,6 +492,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
}
private void setItemTooltips(Sprite icon, Sprite backSprite, TextureAtlas atlas) {
int align = Align.left;
if (generatedTooltip == null) {
Matrix4 m = new Matrix4();
GlyphLayout layout = new GlyphLayout();
@@ -494,43 +510,23 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
BitmapFont font = Controls.getBitmapFont("default", 4 / (preview_h / preview_w));
layout.setText(font, itemExists ? item.name : getReward().type.name(), Color.WHITE, preview_w - 64, Align.center, true);
getGraphics().drawText(font, layout, 32, preview_h - 70);
font = Controls.getBitmapFont("default", 3.5f / (preview_h / preview_w));
float xDescription = 64f;
float yDescription = (preview_h / 2.5f);
float targetWidth = preview_w - 128;
int align = itemExists ? Align.left : Align.center;
float scale = font.getLineHeight();
align = itemExists ? Align.topLeft : Align.top;
if (itemExists) {
String text = item.getDescription();
if (text.contains("[+Shards]")) {
Sprite iconSprite = atlas.createSprite("Shards");
if (iconSprite == null) {
layout.setText(font, text, Color.WHITE, targetWidth, Align.left, true);
} else {
int index = text.lastIndexOf("\n");//currently [+Shards] is the last line in the description
GlyphLayout shardsCount = new GlyphLayout();
shardsCount.setText(font, text.substring(index < 0 ? 0 : index, text.indexOf(" [+")));
String newText = text.replace("[+Shards]", "");
layout.setText(font, newText, Color.WHITE, targetWidth, Align.left, true);
getGraphics().drawImage(iconSprite, xDescription + shardsCount.width, yDescription + shardsCount.height + layout.height + scale/1.5f, scale, scale);
}
} else {
layout.setText(font, text, Color.WHITE, targetWidth, align, true);
}
description = item.getDescription();
layout.reset();
} else {
layout.setText(font, "Adds " + String.valueOf(getReward().getCount()) + " " + getReward().type, Color.WHITE, targetWidth, align, true);
description = "Adds " + String.valueOf(getReward().getCount()) + " " + getReward().type;
}
getGraphics().drawText(font, layout, xDescription, yDescription);
getGraphics().end();
getGraphics().endClip();
generatedTooltip = new Texture(Pixmap.createFromFrameBuffer(0, 0, preview_w, preview_h), Forge.isTextureFilteringEnabled());
} catch (Exception e) {
e.printStackTrace();
//e.printStackTrace();
} finally {
frameBuffer.end();
getGraphics().dispose();
frameBuffer.dispose();
//reset bitmapfont to default
Controls.getBitmapFont("default");
}
}
@@ -542,11 +538,11 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
if (GuiBase.isAndroid() || Forge.hasGamepad()) {
if (holdTooltip == null)
holdTooltip = new HoldTooltip(toolTipImage);
holdTooltip = new HoldTooltip(new ComplexTooltip(toolTipImage, align));
addListener(holdTooltip);
} else {
if (tooltip == null) {
tooltip = new ImageToolTip(toolTipImage);
tooltip = new ImageToolTip(new ComplexTooltip(toolTipImage, align));
tooltip.setInstant(true);
}
addListener(tooltip);
@@ -763,11 +759,53 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
return computedTransform;
}
class ImageToolTip extends Tooltip<Image> {
public ImageToolTip(Image contents) {
class ComplexTooltip extends Group {
private TextraLabel cLabel;
private Image cImage, altcImage;
private float inset, width, x, y;
private int ARP;
public ComplexTooltip(Image i) {
this(i, Align.left);
}
public ComplexTooltip(Image i, int align) {
cImage = i;
setSize(cImage.getPrefWidth(), cImage.getPrefHeight());
setPosition(0, 0, Align.center);
inset = cImage.getPrefWidth() * 0.13f;
width = cImage.getPrefWidth() - inset * 2;
x = cImage.getX() + inset;
y = cImage.getPrefHeight() / 2.5f;
ARP = Forge.isLandscapeMode() ? 125 : 175;
cLabel = new TextraLabel("[%" + ARP + "]" + description, Controls.getSkin(), Controls.getTextraFont());
cLabel.setAlignment(align);
cLabel.setWrap(true);
cLabel.setWidth(width);
cLabel.setX(x);
cLabel.setY(y);
addActorAt(0, cImage);
addActorAt(1, cLabel);
}
public Image getStoredImage() {
return cImage;
}
public TextraLabel getStoredLabel() {
return cLabel;
}
}
class ImageToolTip extends Tooltip<ComplexTooltip> {
public ImageToolTip(ComplexTooltip contents) {
super(contents);
}
public Image getImage() {
return getActor().getStoredImage();
}
@Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
if (!frontSideUp())
@@ -777,21 +815,11 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
}
class HoldTooltip extends ActorGestureListener {
RewardImage tooltip_image;
Table tooltip_actor;
float height;
TextraButton switchButton;
//Vector2 tmp = new Vector2();
private ComplexTooltip tooltip_actor;
private TextraButton switchButton;
public HoldTooltip(RewardImage tooltip_image) {
this.tooltip_image = tooltip_image;
tooltip_actor = new Table();
tooltip_actor.add(this.tooltip_image);
tooltip_actor.align(Align.center);
tooltip_actor.setSize(this.tooltip_image.getPrefWidth(), this.tooltip_image.getPrefHeight());
tooltip_actor.setX(Scene.getIntendedWidth() / 2 - tooltip_actor.getWidth() / 2);
tooltip_actor.setY(Scene.getIntendedHeight() / 2 - tooltip_actor.getHeight() / 2);
this.height = tooltip_actor.getHeight();
public HoldTooltip(ComplexTooltip complexTooltip) {
tooltip_actor = complexTooltip;
switchButton = Controls.newTextButton("Flip");
switchButton.addListener(new ClickListener() {
@Override
@@ -804,6 +832,10 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
getGestureDetector().setLongPressSeconds(0.1f);
}
public Image getImage() {
return tooltip_actor.getStoredImage();
}
@Override
public boolean longPress(Actor actor, float x, float y) {
if (!frontSideUp())
@@ -814,15 +846,13 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
if (reward.getCard().hasBackFace())
actor.getStage().addActor(switchButton);
}
actor.getStage().addActor(tooltip_actor);
show();
return super.longPress(actor, x, y);
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
tooltip_actor.remove();
switchButton.remove();
hide();
super.touchUp(event, x, y, pointer, button);
}
@@ -838,8 +868,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
public void show() {
if (!frontSideUp())
return;
tooltip_actor.setX(Scene.getIntendedWidth() / 2 - tooltip_actor.getWidth() / 2);
tooltip_actor.setY(Scene.getIntendedHeight() / 2 - tooltip_actor.getHeight() / 2);
tooltip_actor.setBounds(tooltip_actor.cImage.getX(), tooltip_actor.cImage.getY(), tooltip_actor.cImage.getPrefWidth(), tooltip_actor.cImage.getPrefHeight());
tooltip_actor.cLabel.setX(Scene.getIntendedWidth() / 2 - tooltip_actor.width / 2);
getStage().addActor(tooltip_actor);
shown = true;
}
@@ -862,12 +892,13 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
public void draw(Batch batch, float parentAlpha) {
try {
if (getDrawable() instanceof TextureRegionDrawable) {
Texture t = ((TextureRegionDrawable) getDrawable()).getRegion().getTexture();
TextureRegion tr = ((TextureRegionDrawable) getDrawable()).getRegion();
Texture t = tr.getTexture();
if (t != null) {
float x = GuiBase.isAndroid() || Forge.hasGamepad() ? Scene.getIntendedWidth() / 2 - holdTooltip.tooltip_actor.getWidth() / 2 : tooltip.getActor().getImageX();
float y = GuiBase.isAndroid() || Forge.hasGamepad() ? Scene.getIntendedHeight() / 2 - holdTooltip.tooltip_actor.getHeight() / 2 : tooltip.getActor().getImageY();
float w = GuiBase.isAndroid() || Forge.hasGamepad() ? holdTooltip.tooltip_actor.getPrefWidth() : tooltip.getActor().getPrefWidth();
float h = GuiBase.isAndroid() || Forge.hasGamepad() ? holdTooltip.tooltip_actor.getPrefHeight() : tooltip.getActor().getPrefHeight();
float x = GuiBase.isAndroid() || Forge.hasGamepad() ? Scene.getIntendedWidth() / 2 - holdTooltip.tooltip_actor.getWidth() / 2 : tooltip.getActor().getStoredImage().getImageX();
float y = GuiBase.isAndroid() || Forge.hasGamepad() ? Scene.getIntendedHeight() / 2 - holdTooltip.tooltip_actor.getHeight() / 2 : tooltip.getActor().getStoredImage().getImageY();
float w = GuiBase.isAndroid() || Forge.hasGamepad() ? holdTooltip.tooltip_actor.getStoredImage().getPrefWidth() : tooltip.getActor().getStoredImage().getPrefWidth();
float h = GuiBase.isAndroid() || Forge.hasGamepad() ? holdTooltip.tooltip_actor.getStoredImage().getPrefHeight() : tooltip.getActor().getStoredImage().getPrefHeight();
if (t.toString().contains(".fullborder.") && Forge.enableUIMask.equals("Full")) {
batch.end();
shaderRoundRect.bind();
@@ -890,7 +921,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
batch.setShader(shaderGrayscale);
batch.begin();
//draw gray
batch.draw(t, x, y, w, h);
batch.draw(tr, x, y, w, h);
//reset
batch.end();
batch.setShader(null);
@@ -900,7 +931,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
}
}
} catch (Exception e) {
e.printStackTrace();
//e.printStackTrace();
}
super.draw(batch, parentAlpha);
}

View File

@@ -3,6 +3,7 @@ package forge.toolbox;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Align;
import forge.Forge;
import forge.Graphics;
import forge.animation.GifAnimation;
import forge.assets.FSkinColor;
@@ -22,9 +23,11 @@ public class FTextArea extends FScrollPane {
public FTextArea(boolean parseReminderText0) {
this(parseReminderText0, "");
}
public FTextArea(boolean parseReminderText0, String text0) {
this(parseReminderText0, text0, null);
}
public FTextArea(boolean parseReminderText0, String text0, GifAnimation gifAnimation) {
text = text0;
font = FSkinFont.get(14);
@@ -38,6 +41,7 @@ public class FTextArea extends FScrollPane {
public String getText() {
return text;
}
public void setText(String text0) {
text = text0;
revalidate();
@@ -46,6 +50,7 @@ public class FTextArea extends FScrollPane {
public int getAlignment() {
return alignment;
}
public void setAlignment(int alignment0) {
alignment = alignment0;
}
@@ -53,6 +58,7 @@ public class FTextArea extends FScrollPane {
public boolean getCenterVertically() {
return centerVertically;
}
public void setCenterVertically(boolean centerVertically0) {
centerVertically = centerVertically0;
}
@@ -60,6 +66,7 @@ public class FTextArea extends FScrollPane {
public FSkinFont getFont() {
return font;
}
public void setFont(FSkinFont font0) {
font = font0;
revalidate();
@@ -68,6 +75,7 @@ public class FTextArea extends FScrollPane {
public FSkinColor getTextColor() {
return textColor;
}
public void setTextColor(FSkinColor textColor0) {
textColor = textColor0;
}
@@ -92,7 +100,8 @@ public class FTextArea extends FScrollPane {
public void draw(Graphics g) {
if (animation != null) {
float w = getScrollWidth() - 2 * insets.x;
float h = w * 0.6f;
float multiplier = "extrawide".equalsIgnoreCase(Forge.extrawide) ? 0.5f : 0.6f;
float h = w * multiplier;
float y = getPreferredHeight(w);
animation.draw(g, insets.x - getScrollLeft(), (insets.y - getScrollTop()) + y, w, h);
}