diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 6855e97581a..9dd21fd33ca 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -854,16 +854,6 @@ public class CardView extends GameEntityView { public void updateNeedsTransformAnimation(boolean value) { set(TrackableProperty.NeedsTransformAnimation, value); } - public Float getTargetingOriginVectorX() { - return get(TrackableProperty.TargetingOriginVectorX); - } - public Float getTargetingOriginVectorY() { - return get(TrackableProperty.TargetingOriginVectorY); - } - public void setTargetingOriginVector(float x, float y) { - set(TrackableProperty.TargetingOriginVectorX, x); - set(TrackableProperty.TargetingOriginVectorY, y); - } void updateState(Card c) { updateName(c); updateZoneText(c); diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index 676b6a1d940..4fad645e8b6 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -83,8 +83,6 @@ public enum TrackableProperty { NeedsTransformAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze), NeedsUntapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze), NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze), - TargetingOriginVectorX(TrackableTypes.FloatType, FreezeMode.IgnoresFreeze), - TargetingOriginVectorY(TrackableTypes.FloatType, FreezeMode.IgnoresFreeze), ImprintedCards(TrackableTypes.CardViewCollectionType), HauntedBy(TrackableTypes.CardViewCollectionType), diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index 129b5667ce4..fe2475d90f6 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -328,6 +328,51 @@ public class Graphics { batch.begin(); } + public void drawLineArrow(float arrowThickness, FSkinColor skinColor, float x1, float y1, float x2, float y2) { + fillCircle(skinColor.getColor(), x2, y2, arrowThickness); + drawLineArrow(arrowThickness, skinColor.getColor(), x1, y1, x2, y2); + fillCircle(Color.WHITE, x2, y2, arrowThickness/2); + drawLine(arrowThickness/3, Color.WHITE, x1, y1, x2, y2); + } + public void drawLineArrow(float thickness, Color color, float x1, float y1, float x2, float y2) { + batch.end(); //must pause batch while rendering shapes + + float angle = new Vector2(x1 - x2, y1 - y2).angleRad(); + float arrowHeadRotation = (float)(Math.PI * 0.8f); + Vector2 arrowCorner3 = new Vector2(x2 + (thickness/3) * (float)Math.cos(angle + arrowHeadRotation), y2 + (thickness/3) * (float)Math.sin(angle + arrowHeadRotation)); + Vector2 arrowCorner4 = new Vector2(x2 + (thickness/3) * (float)Math.cos(angle - arrowHeadRotation), y2 + (thickness/3) * (float)Math.sin(angle - arrowHeadRotation)); + + if (thickness > 1) { + Gdx.gl.glLineWidth(thickness); + } + if (alphaComposite < 1) { + color = FSkinColor.alphaColor(color, color.a * alphaComposite); + } + boolean needSmoothing = (x1 != x2 && y1 != y2); + if (color.a < 1 || needSmoothing) { //enable blending so alpha colored shapes work properly + Gdx.gl.glEnable(GL_BLEND); + } + if (needSmoothing) { + Gdx.gl.glEnable(GL_LINE_SMOOTH); + } + + startShape(ShapeType.Line); + shapeRenderer.setColor(color); + shapeRenderer.line(adjustX(x1), adjustY(y1, 0), adjustX(x2), adjustY(y2, 0)); + endShape(); + + if (needSmoothing) { + Gdx.gl.glDisable(GL_LINE_SMOOTH); + } + if (color.a < 1 || needSmoothing) { + Gdx.gl.glDisable(GL_BLEND); + } + if (thickness > 1) { + Gdx.gl.glLineWidth(1); + } + + batch.begin(); + } public void drawArrow(float borderThickness, float arrowThickness, float arrowSize, FSkinColor skinColor, float x1, float y1, float x2, float y2) { drawArrow(borderThickness, arrowThickness, arrowSize, skinColor.getColor(), x1, y1, x2, y2); } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index c45a700d140..0593814b155 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -389,36 +389,33 @@ public class MatchScreen extends FScreen { final CombatView combat = game.getCombat(); if (combat != null) { for (final CardView attacker : combat.getAttackers()) { + final Vector2 vAttacker = CardAreaPanel.get(attacker).getTargetingArrowOrigin(); //connect each attacker with planeswalker it's attacking if applicable final GameEntityView defender = combat.getDefender(attacker); if (defender instanceof CardView) { - final Vector2 vDefender = new Vector2(((CardView) defender).getTargetingOriginVectorX(), ((CardView) defender).getTargetingOriginVectorY()); - final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY()); + final Vector2 vDefender = CardAreaPanel.get(((CardView) defender)).getTargetingArrowOrigin(); TargetingOverlay.drawArrow(g, vAttacker, vDefender, TargetingOverlay.ArcConnection.FoesAttacking); } final Iterable blockers = combat.getBlockers(attacker); if (blockers != null) { //connect each blocker with the attacker it's blocking for (final CardView blocker : blockers) { - final Vector2 vBlocker = new Vector2(blocker.getTargetingOriginVectorX(), blocker.getTargetingOriginVectorY()); - final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY()); + final Vector2 vBlocker = CardAreaPanel.get(blocker).getTargetingArrowOrigin(); TargetingOverlay.drawArrow(g, vBlocker, vAttacker, TargetingOverlay.ArcConnection.FoesBlocking); } } final Iterable plannedBlockers = combat.getPlannedBlockers(attacker); if (plannedBlockers != null) { //connect each planned blocker with the attacker it's blocking - for (final CardView blocker : plannedBlockers) { - final Vector2 vBlocker = new Vector2(blocker.getTargetingOriginVectorX(), blocker.getTargetingOriginVectorY()); - final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY()); - TargetingOverlay.drawArrow(g, vBlocker, vAttacker, TargetingOverlay.ArcConnection.FoesBlocking); + for (final CardView plannedBlocker : plannedBlockers) { + final Vector2 vPlannedBlocker = CardAreaPanel.get(plannedBlocker).getTargetingArrowOrigin(); + TargetingOverlay.drawArrow(g, vPlannedBlocker, vAttacker, TargetingOverlay.ArcConnection.FoesBlocking); } } //player if (is4Player() || is3Player()) { for (final PlayerView p : game.getPlayers()) { if (combat.getAttackersOf(p).contains(attacker)) { - final Vector2 vAttacker = new Vector2(attacker.getTargetingOriginVectorX(), attacker.getTargetingOriginVectorY()); final Vector2 vPlayer = MatchController.getView().getPlayerPanel(p).getAvatar().getTargetingArrowOrigin(); TargetingOverlay.drawArrow(g, vAttacker, vPlayer, TargetingOverlay.ArcConnection.FoesAttacking); } @@ -430,9 +427,9 @@ public class MatchScreen extends FScreen { for (VPlayerPanel playerPanel : playerPanels.values()) { for (CardView card : playerPanel.getField().getRow1().getOrderedCards()) { if (card != null) { + final Vector2 vCard = CardAreaPanel.get(card).getTargetingArrowOrigin(); if (card.getPairedWith() != null) { - final Vector2 vCard = new Vector2(card.getTargetingOriginVectorX(), card.getTargetingOriginVectorY()); - final Vector2 vPairedWith = new Vector2(card.getPairedWith().getTargetingOriginVectorX(), card.getPairedWith().getTargetingOriginVectorY()); + final Vector2 vPairedWith = CardAreaPanel.get(card.getPairedWith()).getTargetingArrowOrigin(); TargetingOverlay.drawArrow(g, vCard, vPairedWith, TargetingOverlay.ArcConnection.Friends); } } diff --git a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java index 05d32fafa95..6a6261db737 100644 --- a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java +++ b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java @@ -23,6 +23,8 @@ import com.badlogic.gdx.math.Vector2; import forge.Graphics; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; +import forge.localinstance.properties.ForgePreferences; +import forge.model.FModel; import forge.util.Utils; public class TargetingOverlay { @@ -77,6 +79,9 @@ public class TargetingOverlay { color = foeDefColor; } - g.drawArrow(BORDER_THICKNESS, ARROW_THICKNESS, ARROW_SIZE, color, start.x, start.y, end.x, end.y); + if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_USE_LASER_ARROWS)) + g.drawLineArrow(Utils.scale(3), color, start.x, start.y, end.x, end.y); + else + g.drawArrow(BORDER_THICKNESS, ARROW_THICKNESS, ARROW_SIZE, color, start.x, start.y, end.x, end.y); } } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index a011fae1505..ef253fcafa0 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -229,7 +229,7 @@ public class VStack extends FDropDown { while (instance != null) { for (CardView c : instance.getTargetCards()) { TargetingOverlay.ArcConnection conn = activator.isOpponentOf(c.getController()) ? TargetingOverlay.ArcConnection.FoesStackTargeting : TargetingOverlay.ArcConnection.FriendsStackTargeting; - TargetingOverlay.drawArrow(g, arrowOrigin, new Vector2(c.getTargetingOriginVectorX(), c.getTargetingOriginVectorY()), conn); + TargetingOverlay.drawArrow(g, arrowOrigin, VCardDisplayArea.CardAreaPanel.get(c).getTargetingArrowOrigin(), conn); } for (PlayerView p : instance.getTargetPlayers()) { TargetingOverlay.ArcConnection conn = activator.isOpponentOf(p) ? TargetingOverlay.ArcConnection.FoesStackTargeting : TargetingOverlay.ArcConnection.FriendsStackTargeting; diff --git a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java index af6d06c2310..fca57671c7b 100644 --- a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java @@ -598,6 +598,10 @@ public class SettingsPage extends TabPage { localizer.getMessage("lblShowAbilityIconsOverlays"), localizer.getMessage("nlShowAbilityIconsOverlays")), 5); + lstSettings.addItem(new BooleanSetting(FPref.UI_USE_LASER_ARROWS, + localizer.getMessage("lblUseLaserArrows"), + localizer.getMessage("nlUseLaserArrows")), + 5); //Vibration Options lstSettings.addItem(new BooleanSetting(FPref.UI_VIBRATE_ON_LIFE_LOSS, localizer.getMessage("lblVibrateWhenLosingLife"), diff --git a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java index dd000a2dde0..195990253d5 100644 --- a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java +++ b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java @@ -101,16 +101,12 @@ public class FCardPanel extends FDisplayObject { float x = padding-mod/2; float y = padding-mod/2; float w = (getWidth() - 2 * padding)+mod; - float xoffset = w / 2f; float h = (getHeight() - 2 * padding)+mod; - float yoffset = h / 2f; if (w == h) { //adjust width if needed to make room for tapping w = h / ASPECT_RATIO; } float edgeOffset = w / 2f; - card.setTargetingOriginVector(tapped? this.screenPos.x + yoffset : this.screenPos.x + edgeOffset, tapped ? this.screenPos.y + h - yoffset/1.5f : this.screenPos.y + h - xoffset); - if (!ZoneType.Battlefield.equals(card.getZone())) { rotateTransform(g, x, y, w, h, edgeOffset, false); return; diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 22d7e6ccc04..5e70ab50890 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1061,6 +1061,8 @@ lblDisposeTextures=Texturen anordnen nlDisposeTextures=Wenn aktiviert, wird der Bildspeicher angeordnet. (Im Zweifel bitte ausschalten) lblAutoCacheSize=Aktiviere automatische Cache-Größe nlAutoCacheSize=Wenn aktiviert, wird die Cache-Größe beim Start automatisch ermittelt und eingestellt. (Im Zweifel bitte ausschalten) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=Spieler lblLog=Bericht diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 40629ca94a8..96cb98464b1 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1062,6 +1062,8 @@ lblDisposeTextures=Dispose Textures nlDisposeTextures=When enabled, disposes the card art caches. (If unsure, turn OFF this option) lblAutoCacheSize=Enable Auto Cache Size nlAutoCacheSize=When enabled, Cache size are automatically determined on startup. (If unsure, turn OFF this option) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=Players lblLog=Log diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 0c5478ba9a3..4ecaff5bcfd 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1061,6 +1061,8 @@ lblDisposeTextures=Desechar texturas nlDisposeTextures=Cuando está activado, elimina la caché de las imágenes de las cartas. (Si no estás seguro, deshabilita esta opción) lblAutoCacheSize=Activar tamaño de caché automático nlAutoCacheSize=Cuando se activa, el tamaño de la caché se determina automáticamente al inicio. (Si no estás seguro, desactiva esta opción) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=Jugadores lblLog=Log diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 3bd43331460..9232d5e399a 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1060,6 +1060,8 @@ lblDisposeTextures=Rimuovi Texture nlDisposeTextures=Quando abilitato, rimuove la cache delle immagini delle carte. (Nel dubbio, DISABILITARE questa opzione) lblAutoCacheSize=Abilita dimensione automatica della cache nlAutoCacheSize=Se abilitato, la dimensione della cache è stabilita automaticamente all''avvio. (Nel dubbio, DISABILITARE questa opzione) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=Giocatori lblLog=Registro diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 1a554aaf845..fde62405af1 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1062,6 +1062,8 @@ lblDisposeTextures=テキスチャー廃棄 nlDisposeTextures=有効にすると、カード画像キャッシュを廃棄します。 (分からない場合はオフにしてください) lblAutoCacheSize=キャッシュサイズ自動計算 nlAutoCacheSize=有効にすると、キャッシュサイズは起動時に自動計算されます。 (分からない場合はオフにしてください) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=プレイヤー lblLog=ログ diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 6cb02a36374..584cc3df691 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1062,6 +1062,8 @@ lblDisposeTextures=释放纹理 nlDisposeTextures=如果启用,卡图缓存将被释放。(如果你不清楚此选项的作用,请将此选项设为OFF) lblAutoCacheSize=启用自动缓存大小 nlAutoCacheSize=启用后,Forge将于启动时自动确定缓存大小。(如果不清楚此选项的作用,请关闭此选项) +lblUseLaserArrows=Use Laser Arrows +nlUseLaserArrows=When enabled, Forge will use the new Targeting Arrows Overlay. #MatchScreen.java lblPlayers=玩家列表 lblLog=日志 diff --git a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java index b63dac51c90..24def10e2a2 100644 --- a/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/localinstance/properties/ForgePreferences.java @@ -160,6 +160,7 @@ public class ForgePreferences extends PreferencesStore { UI_LOAD_NONLEGAL_CARDS("true"), ALLOW_CUSTOM_CARDS_IN_DECKS_CONFORMANCE("false"), UI_AUTO_CACHE_SIZE("false"), + UI_USE_LASER_ARROWS("true"), UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("Never"), UI_DEFAULT_FONT_SIZE("12"), UI_CARD_ART_FORMAT("Full"),