diff --git a/forge-gui-android/AndroidManifest.xml b/forge-gui-android/AndroidManifest.xml index 5fbb2247567..c8617a41c1b 100644 --- a/forge-gui-android/AndroidManifest.xml +++ b/forge-gui-android/AndroidManifest.xml @@ -12,6 +12,7 @@ + forge-android-${alpha-version} + + + gdx-nightlies + https://oss.sonatype.org/content/repositories/snapshots/ + + com.google.android @@ -167,6 +173,12 @@ gson 2.9.0 + + com.badlogicgames.gdx-controllers + gdx-controllers-android + 2.2.3-SNAPSHOT + aar + @@ -401,6 +413,7 @@ + diff --git a/forge-gui-android/proguard.cfg b/forge-gui-android/proguard.cfg index 885c9e477c0..35c2b4eae3d 100644 --- a/forge-gui-android/proguard.cfg +++ b/forge-gui-android/proguard.cfg @@ -64,6 +64,7 @@ -keep class io.sentry.android.core.SentryInitProvider -keep class io.sentry.android.core.SentryPerformanceProvider +-keep class com.badlogic.gdx.controllers.android.AndroidControllers { *; } -keep class com.github.tommyettinger.textra.** { *; } -keep class io.sentry.android.ndk.SentryNdk diff --git a/forge-gui-desktop/pom.xml b/forge-gui-desktop/pom.xml index 218e6410966..ac3df2e206b 100644 --- a/forge-gui-desktop/pom.xml +++ b/forge-gui-desktop/pom.xml @@ -550,6 +550,7 @@ + @@ -677,6 +678,7 @@ + diff --git a/forge-gui-mobile-dev/pom.xml b/forge-gui-mobile-dev/pom.xml index af58c410c50..59f448e7b33 100644 --- a/forge-gui-mobile-dev/pom.xml +++ b/forge-gui-mobile-dev/pom.xml @@ -64,7 +64,12 @@ - + + + gdx-nightlies + https://oss.sonatype.org/content/repositories/snapshots/ + + forge @@ -94,5 +99,10 @@ commons-cli 1.4 + + com.badlogicgames.gdx-controllers + gdx-controllers-desktop + 2.2.3-SNAPSHOT + diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index 0c4ef128e59..46e4ceb5423 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -23,7 +23,12 @@ - + + + gdx-nightlies + https://oss.sonatype.org/content/repositories/snapshots/ + + forge @@ -45,6 +50,11 @@ forge-gui ${project.version} + + com.badlogicgames.gdx-controllers + gdx-controllers-core + 2.2.3-SNAPSHOT + com.badlogicgames.gdx gdx diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index e4faa7acef1..376cc2f6dc5 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -5,6 +5,10 @@ import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.ControllerAdapter; +import com.badlogic.gdx.controllers.ControllerListener; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.graphics.Cursor; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Pixmap; @@ -18,6 +22,7 @@ import com.badlogic.gdx.utils.Clipboard; import forge.adventure.scene.*; import forge.adventure.stage.MapStage; import forge.adventure.util.Config; +import forge.adventure.world.WorldSave; import forge.animation.ForgeAnimation; import forge.assets.Assets; import forge.assets.AssetsDownloader; @@ -67,6 +72,9 @@ public class Forge implements ApplicationListener { private static Graphics graphics; private static FrameRate frameRate; private static FScreen currentScreen; + private static ControllerListener controllerListener; + private static boolean hasGamepad = false; + public static Texture lastPreview = null; protected static SplashScreen splashScreen; protected static ClosingScreen closingScreen; protected static TransitionScreen transitionScreen; @@ -163,6 +171,171 @@ public class Forge implements ApplicationListener { frameRate = new FrameRate(); animationBatch = new SpriteBatch(); inputProcessor = new MainInputProcessor(); + controllerListener = new ControllerAdapter() { + @Override + public void connected(final Controller controller) { + Gdx.app.log("Controller", "Controller connected: " + controller.getName() + + "/" + controller.getUniqueId()); + controller.addListener(controllerListener); + hasGamepad = true; + if (controller.canVibrate()) + controller.startVibration(200,1); + if (Forge.isMobileAdventureMode && Forge.currentScene instanceof UIScene) { + ((UIScene) Forge.currentScene).selectCurrent(); + } + } + @Override + public void disconnected(Controller controller) { + Gdx.app.log("Controller", "Controller disconnected: " + controller.getName() + + "/" + controller.getUniqueId()); + hasGamepad = false; + } + + @Override + public boolean buttonDown(Controller controller, int buttonIndex) { + //System.out.println(controller.getName()+"["+controller.getUniqueId()+"]: "+buttonIndex); + hasGamepad = true; + translateButtons(controller, buttonIndex, true); + return super.buttonDown(controller, buttonIndex); + } + + @Override + public boolean buttonUp(Controller controller, int buttonIndex) { + hasGamepad = true; + translateButtons(controller, buttonIndex, false); + return super.buttonUp(controller, buttonIndex); + } + + @Override + public boolean axisMoved(Controller controller, int axisIndex, float value) { + //System.out.println(controller.getName()+"["+controller.getUniqueId()+"]: axis: "+axisIndex+" - "+value); + hasGamepad = true; + translateAxis(controller, axisIndex, value);//prevent multi press axis + return super.axisMoved(controller, axisIndex, value); + } + private void translateAxis(Controller controller, int axisIndex, float value) { + if (!hasGamepad()) + return;//adventure only + FContainer container = FOverlay.getTopOverlay(); + if (container == null) { + container = currentScreen; + } + if (container != null) { + if (currentScreen instanceof MatchScreen) { + if (4 == axisIndex && value == 1f) { //others are L2Button if missing this axis + container.keyDown(Keys.ENTER); + } + if (5 == axisIndex && value == 1f) { //others are R2 Button if missing this axis + container.keyDown(Keys.ESCAPE); + } + if (controller.getMapping().axisLeftY == axisIndex) { + if (value == 1f) + container.keyDown(Keys.PAGE_DOWN); + } + /*if (controller.getMapping().axisLeftX == axisIndex) { + if (value == 1f) { + + } + }*/ + } + } + } + private void translateButtons(Controller controller, int buttonIndex, boolean keyDown) { + if (!hasGamepad()) + return; //adventure only + if (!keyDown) + return; //prevent keyup on forgescene + //overlay shoud have priority + FContainer container = FOverlay.getTopOverlay(); + if (container == null) { + container = currentScreen; + } + if (container != null) { + if (currentScreen instanceof MatchScreen) { + if (controller.getMapping().buttonL2 == buttonIndex) {//others are axis-4 + container.keyDown(Keys.ENTER); + } + if (controller.getMapping().buttonR2 == buttonIndex) {//others are axis-5 + container.keyDown(Keys.ESCAPE); + } + if (controller.getMapping().buttonX == buttonIndex) { + container.keyDown(Keys.BUTTON_X); + } + if (controller.getMapping().buttonY == buttonIndex) { + container.keyDown(Keys.BUTTON_Y); + } + if (controller.getMapping().buttonR1 == buttonIndex) { + container.keyDown(Keys.BUTTON_R1); + } + if (controller.getMapping().buttonL1 == buttonIndex) { + container.keyDown(Keys.BUTTON_L1); + } + if (controller.getMapping().buttonDpadDown == buttonIndex) { + container.keyDown(Keys.DPAD_DOWN); + } + if (controller.getMapping().buttonDpadLeft == buttonIndex) { + container.keyDown(Keys.DPAD_LEFT); + } + if (controller.getMapping().buttonDpadRight == buttonIndex) { + container.keyDown(Keys.DPAD_RIGHT); + } + if (controller.getMapping().buttonDpadUp == buttonIndex) { + container.keyDown(Keys.DPAD_UP); + } + if (controller.getMapping().buttonA == buttonIndex) { + container.keyDown(Keys.BUTTON_A); + } + if (controller.getMapping().buttonB == buttonIndex) { + container.keyDown(Keys.BUTTON_B); + } + } else {//Others + /*if (controller.getMapping().buttonL2 == buttonIndex) {//others are axis-4 + container.keyDown(Keys.ENTER); + } + if (controller.getMapping().buttonR2 == buttonIndex) {//others are axis-5 + container.keyDown(Keys.ESCAPE); + }*/ + if (controller.getMapping().buttonDpadDown == buttonIndex) { + container.keyDown(Keys.DPAD_DOWN); + } + if (controller.getMapping().buttonDpadLeft == buttonIndex) { + container.keyDown(Keys.DPAD_LEFT); + } + if (controller.getMapping().buttonDpadRight == buttonIndex) { + container.keyDown(Keys.DPAD_RIGHT); + } + if (controller.getMapping().buttonDpadUp == buttonIndex) { + container.keyDown(Keys.DPAD_UP); + } + if (controller.getMapping().buttonBack == buttonIndex) { + container.keyDown(Keys.BUTTON_SELECT); + } + if (controller.getMapping().buttonB == buttonIndex) { + container.keyDown(Keys.BUTTON_B); + } + if (controller.getMapping().buttonA == buttonIndex) { + container.keyDown(Keys.BUTTON_A); + } + if (controller.getMapping().buttonX == buttonIndex) { + container.keyDown(Keys.BUTTON_X); + } + if (controller.getMapping().buttonY == buttonIndex) { + container.keyDown(Keys.BUTTON_Y); + } + if (controller.getMapping().buttonR1 == buttonIndex) { + container.keyDown(Keys.BUTTON_R1); + } + if (controller.getMapping().buttonL1 == buttonIndex) { + container.keyDown(Keys.BUTTON_L1); + } + } + } + } + }; + Controllers.addListener(controllerListener); + if (Controllers.getCurrent() != null) + System.out.println("Gamepad: " + Controllers.getCurrent().getName()); + Gdx.input.setInputProcessor(inputProcessor); /* @@ -250,6 +423,13 @@ public class Forge implements ApplicationListener { }); }); } + public static boolean hasGamepad() { + //Classic Mode Various Screen GUI are not yet supported, needs control mapping for each screens + if (isMobileAdventureMode) { + return hasGamepad && Forge.isLandscapeMode(); //portrait is not supported for Gamepad + } + return false; + } public static InputProcessor getInputProcessor() { return inputProcessor; @@ -974,6 +1154,7 @@ public class Forge implements ApplicationListener { SoundSystem.instance.dispose(); try { ExceptionHandler.unregisterErrorHandling(); + lastPreview.dispose(); } catch (Exception e) { } } @@ -983,6 +1164,10 @@ public class Forge implements ApplicationListener { return ((Forge)Gdx.app.getApplicationListener()).assets; } public static boolean switchScene(Scene newScene) { + if (newScene instanceof RewardScene || newScene instanceof SpellSmithScene || newScene instanceof DeckSelectScene || newScene instanceof PlayerStatisticScene) { + if (!(currentScene instanceof ForgeScene)) //prevent overwriting the last preview if last scene is instance of ForgeScene + WorldSave.getCurrentSave().header.createPreview(); + } if (currentScene != null) { if (!currentScene.leave()) return false; @@ -1360,6 +1545,7 @@ public class Forge implements ApplicationListener { magnify = true; mouseMovedX = screenX; mouseMovedY = screenY; + hasGamepad = false; //prevent drawing some panels //todo: mouse listener for android? if (GuiBase.isAndroid()) return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java b/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java index 8362057f3e0..dcc922651ca 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java +++ b/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java @@ -1,5 +1,6 @@ package forge.adventure.scene; +import com.badlogic.gdx.Input; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Align; import com.google.common.base.Function; @@ -41,6 +42,7 @@ import java.util.Map; private static final FLabel lblGold = new FLabel.Builder().text("0").icon(FSkinImage.QUEST_COINSTACK).font(FSkinFont.get(16)).insets(new Vector2(Utils.scale(5), 0)).build(); private static ItemPool decksUsingMyCards=new ItemPool<>(InventoryItem.class); + private int selected = 0; public static void leave() { AdventurePlayer.current().getNewCards().clear(); Forge.clearCurrentScreen(); @@ -97,12 +99,7 @@ import java.util.Map; boolean isShop=false; public AdventureDeckEditor(boolean createAsShop) { - super(new FEvent.FEventHandler() { - @Override - public void handleEvent(FEvent e) { - leave(); - } - },getPages()); + super(e -> leave(),getPages()); isShop=createAsShop; @@ -137,12 +134,7 @@ import java.util.Map; FPopupMenu menu = new FPopupMenu() { @Override protected void buildMenu() { - addItem(new FMenuItem(Forge.getLocalizer().getMessage("btnCopyToClipboard"), Forge.hdbuttons ? FSkinImage.HDEXPORT : FSkinImage.BLANK, new FEvent.FEventHandler() { - @Override - public void handleEvent(FEvent e1) { - FDeckViewer.copyDeckToClipboard(getDeck()); - } - })); + addItem(new FMenuItem(Forge.getLocalizer().getMessage("btnCopyToClipboard"), Forge.hdbuttons ? FSkinImage.HDEXPORT : FSkinImage.BLANK, e1 -> FDeckViewer.copyDeckToClipboard(getDeck()))); ((DeckEditorPage)getSelectedPage()).buildDeckMenu(this); } }; @@ -244,12 +236,7 @@ import java.util.Map; protected CardManagerPage(ItemManagerConfig config0, String caption0, FImage icon0) { super(caption0, icon0); config = config0; - cardManager.setItemActivateHandler(new FEvent.FEventHandler() { - @Override - public void handleEvent(FEvent e) { - CardManagerPage.this.onCardActivated(cardManager.getSelectedItem()); - } - }); + cardManager.setItemActivateHandler(e -> CardManagerPage.this.onCardActivated(cardManager.getSelectedItem())); cardManager.setContextMenuBuilder(new ItemManager.ContextMenuBuilder() { @Override public void buildMenu(final FDropDownMenu menu, final PaperCard card) { @@ -257,30 +244,10 @@ import java.util.Map; } }); } - private final Function, Comparable> fnNewCompare = new Function, Comparable>() { - @Override - public Comparable apply(Map.Entry from) { - return AdventurePlayer.current().getNewCards().contains(from.getKey()) ? Integer.valueOf(1) : Integer.valueOf(0); - } - }; - private final Function, Object> fnNewGet = new Function, Object>() { - @Override - public Object apply(Map.Entry from) { - return AdventurePlayer.current().getNewCards().contains(from.getKey()) ? "NEW" : ""; - } - }; - public static final Function, Comparable> fnDeckCompare = new Function, Comparable>() { - @Override - public Comparable apply(Map.Entry from) { - return decksUsingMyCards.count(from.getKey()); - } - }; - public static final Function, Object> fnDeckGet = new Function, Object>() { - @Override - public Object apply(Map.Entry from) { - return Integer.valueOf(decksUsingMyCards.count(from.getKey())).toString(); - } - }; + private final Function, Comparable> fnNewCompare = from -> AdventurePlayer.current().getNewCards().contains(from.getKey()) ? Integer.valueOf(1) : Integer.valueOf(0); + private final Function, Object> fnNewGet = from -> AdventurePlayer.current().getNewCards().contains(from.getKey()) ? "NEW" : ""; + public static final Function, Comparable> fnDeckCompare = from -> decksUsingMyCards.count(from.getKey()); + public static final Function, Object> fnDeckGet = from -> Integer.valueOf(decksUsingMyCards.count(from.getKey())).toString(); protected void initialize() { @@ -410,14 +377,11 @@ import java.util.Map; if (!StringUtils.isEmpty(dest)) { label += " " + dest; } - menu.addItem(new FMenuItem(label, icon, new FEvent.FEventHandler() { - @Override - public void handleEvent(FEvent e) { - if (max == 1) { - callback.run(max); - } else { - GuiChoose.getInteger(cardManager.getSelectedItem() + " - " + verb + " " + Forge.getLocalizer().getMessage("lblHowMany"), 1, max, 20, callback); - } + menu.addItem(new FMenuItem(label, icon, e -> { + if (max == 1) { + callback.run(max); + } else { + GuiChoose.getInteger(cardManager.getSelectedItem() + " - " + verb + " " + Forge.getLocalizer().getMessage("lblHowMany"), 1, max, 20, callback); } })); } @@ -535,6 +499,30 @@ import java.util.Map; protected CatalogPage(ItemManagerConfig config, String caption0, FImage icon0) { super(config, caption0, icon0); } + private void setNextSelected() { + setNextSelected(1); + } + private void setNextSelected(int val) { + if (cardManager.getItemCount() < 1) + return; + if ((cardManager.getSelectedIndex()+val) < cardManager.getItemCount()) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()+val); + } else if ((cardManager.getSelectedIndex()+1) < cardManager.getItemCount()) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()+1); + } + } + private void setPreviousSelected() { + setPreviousSelected(1); + } + private void setPreviousSelected(int val) { + if (cardManager.getItemCount() < 1) + return; + if ((cardManager.getSelectedIndex()-val) > -1) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()-val); + } else if ((cardManager.getSelectedIndex()-1) > -1) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()-1); + } + } @Override protected void initialize() { @@ -660,14 +648,11 @@ import java.util.Map; @Override protected void buildDeckMenu(FPopupMenu menu) { if (cardManager.getConfig().getShowUniqueCardsOption()) { - menu.addItem(new FCheckBoxMenuItem(Forge.getLocalizer().getMessage("lblUniqueCardsOnly"), cardManager.getWantUnique(), new FEvent.FEventHandler() { - @Override - public void handleEvent(FEvent e) { - boolean wantUnique = !cardManager.getWantUnique(); - cardManager.setWantUnique(wantUnique); - CatalogPage.this.refresh(); - cardManager.getConfig().setUniqueCardsOnly(wantUnique); - } + menu.addItem(new FCheckBoxMenuItem(Forge.getLocalizer().getMessage("lblUniqueCardsOnly"), cardManager.getWantUnique(), e -> { + boolean wantUnique = !cardManager.getWantUnique(); + cardManager.setWantUnique(wantUnique); + CatalogPage.this.refresh(); + cardManager.getConfig().setUniqueCardsOnly(wantUnique); })); } } @@ -676,6 +661,30 @@ import java.util.Map; protected static class DeckSectionPage extends CardManagerPage { private final String captionPrefix; private final DeckSection deckSection; + private void setNextSelected() { + setNextSelected(1); + } + private void setNextSelected(int val) { + if (cardManager.getItemCount() < 1) + return; + if ((cardManager.getSelectedIndex()+val) < cardManager.getItemCount()) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()+val); + } else if ((cardManager.getSelectedIndex()+1) < cardManager.getItemCount()) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()+1); + } + } + private void setPreviousSelected() { + setPreviousSelected(1); + } + private void setPreviousSelected(int val) { + if (cardManager.getItemCount() < 1) + return; + if ((cardManager.getSelectedIndex()-val) > -1) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()-val); + } else if ((cardManager.getSelectedIndex()-1) > -1) { + cardManager.setSelectedIndex(cardManager.getSelectedIndex()-1); + } + } protected DeckSectionPage(DeckSection deckSection0, ItemManagerConfig config) { super(config, null, null); @@ -836,5 +845,150 @@ import java.util.Map; } } + @Override + public boolean keyDown(int keyCode) { + if (keyCode == Input.Keys.BUTTON_SELECT) { + return this.tabHeader.btnBack.trigger(); + } else if (keyCode == Input.Keys.BUTTON_R1) { + if (getSelectedPage() instanceof CatalogPage) + ((CatalogPage) getSelectedPage()).cardManager.closeMenu(); + else if (getSelectedPage() instanceof DeckSectionPage) + ((DeckSectionPage) getSelectedPage()).cardManager.closeMenu(); + selected++; + if (selected > 2) + selected = 0; + setSelectedPage(tabPages[selected]); + if (getSelectedPage() instanceof CatalogPage) { + ((CatalogPage) getSelectedPage()).cardManager.getConfig().setPileBy(null); + ((CatalogPage) getSelectedPage()).cardManager.setHideFilters(true); + } else if (getSelectedPage() instanceof DeckSectionPage) { + ((DeckSectionPage) getSelectedPage()).cardManager.getConfig().setPileBy(null); + ((DeckSectionPage) getSelectedPage()).cardManager.setHideFilters(true); + } + } else if (keyCode == Input.Keys.DPAD_RIGHT) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((CatalogPage) getSelectedPage()).setNextSelected(); + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((DeckSectionPage) getSelectedPage()).setNextSelected(); + } + } else if (keyCode == Input.Keys.DPAD_LEFT) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((CatalogPage) getSelectedPage()).setPreviousSelected(); + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((DeckSectionPage) getSelectedPage()).setPreviousSelected(); + } + } else if (keyCode == Input.Keys.DPAD_DOWN) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((CatalogPage) getSelectedPage()).cardManager.selectNextContext(); + } else { + if (((CatalogPage) getSelectedPage()).cardManager.getSelectedIndex() < 0) + ((CatalogPage) getSelectedPage()).setNextSelected(); + else if (((CatalogPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((CatalogPage) getSelectedPage()).setNextSelected(((CatalogPage) getSelectedPage()).cardManager.getConfig().getImageColumnCount()); + else + ((CatalogPage) getSelectedPage()).setNextSelected(); + } + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((DeckSectionPage) getSelectedPage()).cardManager.selectNextContext(); + } else { + if (((DeckSectionPage) getSelectedPage()).cardManager.getSelectedIndex() < 0) + ((DeckSectionPage) getSelectedPage()).setNextSelected(); + else if (((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((DeckSectionPage) getSelectedPage()).setNextSelected(((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getImageColumnCount()); + else + ((DeckSectionPage) getSelectedPage()).setNextSelected(); + } + } + } else if (keyCode == Input.Keys.DPAD_UP) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((CatalogPage) getSelectedPage()).cardManager.selectPreviousContext(); + } else { + if (((CatalogPage) getSelectedPage()).cardManager.getSelectedIndex() < 0) + ((CatalogPage) getSelectedPage()).setNextSelected(); + else if (((CatalogPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((CatalogPage) getSelectedPage()).setPreviousSelected(((CatalogPage) getSelectedPage()).cardManager.getConfig().getImageColumnCount()); + else + ((CatalogPage) getSelectedPage()).setPreviousSelected(); + } + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((DeckSectionPage) getSelectedPage()).cardManager.selectPreviousContext(); + } else { + if (((DeckSectionPage) getSelectedPage()).cardManager.getSelectedIndex() < 0) + ((DeckSectionPage) getSelectedPage()).setNextSelected(); + else if (((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1) + ((DeckSectionPage) getSelectedPage()).setPreviousSelected(((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getImageColumnCount()); + else + ((DeckSectionPage) getSelectedPage()).setPreviousSelected(); + } + } + } else if (keyCode == Input.Keys.BUTTON_A) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.isContextMenuOpen()) + ((CatalogPage) getSelectedPage()).cardManager.activateSelectedContext(); + else + ((CatalogPage) getSelectedPage()).cardManager.showMenu(true); + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.isContextMenuOpen() ) + ((DeckSectionPage) getSelectedPage()).cardManager.activateSelectedContext(); + else + ((DeckSectionPage) getSelectedPage()).cardManager.showMenu(true); + } + } else if (keyCode == Input.Keys.BUTTON_B) { + if (getSelectedPage() instanceof CatalogPage) { + if (((CatalogPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((CatalogPage) getSelectedPage()).cardManager.closeMenu(); + } else + return this.tabHeader.btnBack.trigger(); + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (((DeckSectionPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + ((DeckSectionPage) getSelectedPage()).cardManager.closeMenu(); + } else + return this.tabHeader.btnBack.trigger(); + } + } else if (keyCode == Input.Keys.BUTTON_Y) { + if (getSelectedPage() instanceof CatalogPage) { + if (!((CatalogPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + if (((CatalogPage) getSelectedPage()).cardManager.getCurrentView().getSelectionCount() > 0) { + ((CatalogPage) getSelectedPage()).cardManager.getCurrentView().zoomSelected(); + } + } else { + ((CatalogPage) getSelectedPage()).cardManager.closeMenu(); + if (((CatalogPage) getSelectedPage()).cardManager.getCurrentView().getSelectionCount() > 0) { + ((CatalogPage) getSelectedPage()).cardManager.getCurrentView().zoomSelected(); + } + } + } else if (getSelectedPage() instanceof DeckSectionPage) { + if (!((DeckSectionPage) getSelectedPage()).cardManager.isContextMenuOpen()) { + if (((DeckSectionPage) getSelectedPage()).cardManager.getCurrentView().getSelectionCount() > 0) { + ((DeckSectionPage) getSelectedPage()).cardManager.getCurrentView().zoomSelected(); + } + } else { + ((DeckSectionPage) getSelectedPage()).cardManager.closeMenu(); + if (((DeckSectionPage) getSelectedPage()).cardManager.getCurrentView().getSelectionCount() > 0) { + ((DeckSectionPage) getSelectedPage()).cardManager.getCurrentView().zoomSelected(); + } + } + } + } else if (keyCode == Input.Keys.BUTTON_L1) { + if (getSelectedPage() instanceof CatalogPage) { + ((CatalogPage) getSelectedPage()).cardManager.closeMenu(); + int index = ((CatalogPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1 ? 0 : 1; + ((CatalogPage) getSelectedPage()).cardManager.setViewIndex(index); + } else if (getSelectedPage() instanceof DeckSectionPage) { + ((DeckSectionPage) getSelectedPage()).cardManager.closeMenu(); + int index = ((DeckSectionPage) getSelectedPage()).cardManager.getConfig().getViewIndex() == 1 ? 0 : 1; + ((DeckSectionPage) getSelectedPage()).cardManager.setViewIndex(index); + } + } + return true; + } } diff --git a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java index c92ee4d4e4a..08a23a17174 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java @@ -19,8 +19,9 @@ public class DeckSelectScene extends UIScene { TextField textInput; Table layout; Label header; - TextButton back, edit, rename; + TextButton back, edit, rename, dialogRenameBtn, dialogAbortBtn; int currentSlot = 0; + ScrollPane scrollPane; public DeckSelectScene() { super(Forge.isLandscapeMode() ? "ui/deck_selector.json" : "ui/deck_selector_portrait.json"); @@ -60,6 +61,7 @@ public class DeckSelectScene extends UIScene { if (buttons.containsKey(slot)) { TextButton button = buttons.get(slot); button.setColor(Color.RED); + selectActor(button, false); } Current.player().setSelectedDeckSlot(slot); @@ -72,17 +74,104 @@ public class DeckSelectScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } + if (kbVisible) { + if (keycode == Input.Keys.BUTTON_START) + keyOK(); + else if (keycode == Input.Keys.BUTTON_L1) + toggleShiftOrBackspace(true); + else if (keycode == Input.Keys.BUTTON_R1) + toggleShiftOrBackspace(false); + else if (keycode == Input.Keys.BUTTON_B) + hideOnScreenKeyboard(); + else if (keycode == Input.Keys.BUTTON_A) { + if (selectedKey != null) + performTouch(selectedKey); + } else if (keycode == Input.Keys.DPAD_UP || keycode == Input.Keys.DPAD_DOWN || keycode == Input.Keys.DPAD_LEFT || keycode == Input.Keys.DPAD_RIGHT) + setSelectedKey(keycode); + } else if (dialog.getColor().a == 1f) { + if (keycode == Input.Keys.BUTTON_A) { + if (selectedActor == textInput) { + lastInputField = textInput; + showOnScreenKeyboard(textInput.getText()); + } else if (selectedActor == dialogAbortBtn || selectedActor == dialogRenameBtn) { + performTouch(selectedActor); + select(Current.player().getSelectedDeckIndex()); + } + } else if (keycode == Input.Keys.BUTTON_B) { + performTouch(dialogAbortBtn); + select(Current.player().getSelectedDeckIndex()); + } + else if (keycode == Input.Keys.DPAD_DOWN) { + if (selectedActor == null) { + selectActor(textInput, false); + } else if (selectedActor == textInput) + selectActor(dialogRenameBtn, false); + } else if (keycode == Input.Keys.DPAD_UP) { + if (selectedActor == null) + selectActor(dialogRenameBtn, false); + else if (selectedActor == dialogRenameBtn || selectedActor == dialogAbortBtn) { + selectActor(textInput, false); + } + } else if (keycode == Input.Keys.DPAD_LEFT) { + if (selectedActor == dialogAbortBtn) + selectActor(dialogRenameBtn, false); + } else if (keycode == Input.Keys.DPAD_RIGHT) { + if (selectedActor == dialogRenameBtn) + selectActor(dialogAbortBtn, false); + } + } else { + if (keycode == Input.Keys.BUTTON_B) + performTouch(back); + else if (keycode == Input.Keys.BUTTON_Y) + performTouch(rename); + else if (keycode == Input.Keys.BUTTON_X) + performTouch(edit); + else if (keycode == Input.Keys.BUTTON_L1) { + scrollPane.fling(1f, 0, -300); + } + else if (keycode == Input.Keys.BUTTON_R1) { + scrollPane.fling(1f, 0, +300); + } else if (keycode == Input.Keys.BUTTON_A) + performTouch(selectedActor); + else if (keycode == Input.Keys.DPAD_DOWN) { + if (selectedActorIndex == 9) { + selectActor(actorObjectMap.get(0), false); + scrollPane.fling(1f, 0, +300); + } else { + selectNextActor(false); + } + if (selectedActorIndex == 6) + scrollPane.fling(1f, 0, -300); + } else if (keycode == Input.Keys.DPAD_UP) { + if (selectedActorIndex == 0) { + selectActor(actorObjectMap.get(9), false); + scrollPane.fling(1f, 0, -300); + } else { + selectPreviousActor(false); + } + if (selectedActorIndex == 5) + scrollPane.fling(1f, 0, +300); + } + } return true; } @Override public void enter() { - select(Current.player().getSelectedDeckIndex()); + clearActorObjects(); for (int i = 0; i < AdventurePlayer.NUMBER_OF_DECKS; i++) { if (buttons.containsKey(i)) { buttons.get(i).setText(Current.player().getDeck(i).getName()); + addActorObject(buttons.get(i)); } } + addActorObject(back); + addActorObject(rename); + addActorObject(edit); + addActorObject(textInput); + addActorObject(dialogRenameBtn); + addActorObject(dialogAbortBtn); + select(Current.player().getSelectedDeckIndex()); super.enter(); } @@ -105,8 +194,12 @@ public class DeckSelectScene extends UIScene { dialog.getButtonTable().add(Controls.newLabel(Forge.getLocalizer().getMessage("lblName")+": ")).align(Align.left); dialog.getButtonTable().add(textInput).fillX().expandX(); dialog.getButtonTable().row(); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblRename"), () -> DeckSelectScene.this.rename())).align(Align.left); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblAbort"), () -> dialog.hide())).align(Align.left); + dialogRenameBtn = Controls.newTextButton(Forge.getLocalizer().getMessage("lblRename"), () -> DeckSelectScene.this.rename()); + dialog.getButtonTable().add(dialogRenameBtn).align(Align.left).padLeft(15); + dialogAbortBtn = Controls.newTextButton(Forge.getLocalizer().getMessage("lblAbort"), () -> dialog.hide()); + dialog.getButtonTable().add(dialogAbortBtn).align(Align.right).padRight(15); + dialog.getColor().a = 0f; + dialog.hide(); back = ui.findActor("return"); back.getLabel().setText(Forge.getLocalizer().getMessage("lblBack")); @@ -119,11 +212,11 @@ public class DeckSelectScene extends UIScene { ui.onButtonPress("rename", () -> { textInput.setText(Current.player().getSelectedDeck().getName()); dialog.show(stage); - stage.setKeyboardFocus(textInput); + selectActor(textInput, false); }); defColor = ui.findActor("return").getColor(); - ScrollPane scrollPane = ui.findActor("deckSlots"); + scrollPane = ui.findActor("deckSlots"); scrollPane.setActor(layout); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/HudScene.java b/forge-gui-mobile/src/forge/adventure/scene/HudScene.java index b7f2827039f..8ad44398295 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/HudScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/HudScene.java @@ -3,8 +3,10 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.graphics.GL20; +import forge.Forge; import forge.adventure.stage.GameHUD; import forge.adventure.stage.GameStage; +import forge.adventure.stage.MapStage; /** * Hud base scene @@ -60,11 +62,16 @@ public abstract class HudScene extends Scene implements InputProcessor { @Override public boolean keyDown(int keycode) { - + if (Forge.hasGamepad()) { + if (MapStage.getInstance().isDialogOnlyInput()) { + return MapStage.getInstance().buttonPress(keycode); + } + } if (hud.keyDown(keycode)) return true; - if(isInHudOnlyMode()) + if(isInHudOnlyMode()) { return false; + } return stage.keyDown(keycode); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java index 1a79e724c1d..f7b15c1ea4f 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java @@ -85,6 +85,10 @@ public class InnScene extends UIScene { tempHitPointCost = ui.findActor("tempHitPointCost"); tempHitPointCost.setDisabled(!purchaseable); tempHitPointCost.getLabel().setText("$" + tempHealthCost); + clearActorObjects(); + addActorObject(tempHitPointCost); + addActorObject(sell); + addActorObject(leave); } private void sell() { @@ -96,6 +100,24 @@ public class InnScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { done(); } + if (keycode == Input.Keys.DPAD_RIGHT) { + if (selectedActor == null) + selectActor(tempHitPointCost, false); + else + selectNextActor(false); + } else if ( keycode == Input.Keys.DPAD_LEFT) { + if (selectedActor == null) + selectActor(leave, false); + else + selectPreviousActor(false); + + } else if (keycode == Input.Keys.BUTTON_B) { + performTouch(leave); + + } else if (keycode == Input.Keys.BUTTON_A) { + performTouch(selectedActor); + + } return true; } diff --git a/forge-gui-mobile/src/forge/adventure/scene/InventoryScene.java b/forge-gui-mobile/src/forge/adventure/scene/InventoryScene.java index 6d03ba899fb..3cba8dac5e9 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/InventoryScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/InventoryScene.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Timer; import forge.Forge; import forge.adventure.data.ItemData; import forge.adventure.stage.GameHUD; @@ -201,6 +202,7 @@ public class InventoryScene extends UIScene { } private void updateInventory() { + clearActorObjects(); inventoryButtons.clear(); inventory.clear(); for(int i=0;i slot :equipmentSlots.entrySet()) { if(slot.getValue().getChildren().size>=2) @@ -277,6 +280,27 @@ public class InventoryScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { done(); } + if (keycode == Input.Keys.BUTTON_SELECT) + performTouch(ui.findActor("return")); + else if (keycode == Input.Keys.BUTTON_B) + performTouch(ui.findActor("return")); + else if (keycode == Input.Keys.BUTTON_A) { + if (selectedActor instanceof ImageButton) { + performTouch(equipButton); + Timer.schedule(new Timer.Task() { + @Override + public void run() { + selectCurrent(); + } + }, 0.25f); + + } else { + performTouch(selectedActor); + } + } else if (keycode == Input.Keys.DPAD_RIGHT || keycode == Input.Keys.DPAD_DOWN) + selectNextActor(false); + else if (keycode == Input.Keys.DPAD_LEFT || keycode == Input.Keys.DPAD_UP) + selectPreviousActor(false); return true; } } diff --git a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java index e0d0f37b6eb..63cb859b396 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java @@ -3,6 +3,8 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; @@ -16,6 +18,7 @@ import forge.adventure.util.UIActor; import forge.adventure.world.WorldSave; import forge.card.ColorSet; import forge.deck.DeckProxy; +import forge.gui.GuiBase; import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.player.GamePlayerUtil; @@ -39,6 +42,7 @@ public class NewGameScene extends UIScene { private Selector difficulty; private Array stringList, random, custom; private Label colorLabel; + private int selected = -1; public NewGameScene() { super(Forge.isLandscapeMode() ? "ui/new_game.json" : "ui/new_game_portrait.json"); @@ -74,6 +78,16 @@ public class NewGameScene extends UIScene { super.resLoaded(); selectedName = ui.findActor("nameField"); selectedName.setText(NameGenerator.getRandomName("Any", "Any", "")); + selectedName.addListener(new InputListener() { + @Override + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + if (!GuiBase.isAndroid() && showGamepadSelector) { + //show onscreen keyboard + return true; + } + return super.touchDown(event, x, y, pointer, button); + } + }); avatarImage = ui.findActor("avatarPreview"); gender = ui.findActor("gender"); mode = ui.findActor("mode"); @@ -175,12 +189,153 @@ public class NewGameScene extends UIScene { GamePlayerUtil.getGuiPlayer().setName(selectedName.getText()); Forge.switchScene(SceneType.GameScene.instance); } + clearActorObjects(); + addActorObject(selectedName); + addActorObject(race); + addActorObject(gender); + addActorObject(difficulty); + addActorObject(colorId); + addActorObject(mode); + addActorObject(ui.findActor("back")); + addActorObject(ui.findActor("start")); + unselectActors(); + } + @Override + public boolean pointerMoved(int screenX, int screenY) { + ui.screenToLocalCoordinates(pointer.set(screenX,screenY)); + if (showGamepadSelector) { + unselectActors(); + showGamepadSelector = false; + } + if (kbVisible) + return super.pointerMoved(screenX, screenY); + updateHovered(); + return super.pointerMoved(screenX, screenY); } - @Override public boolean keyPressed(int keycode) { + if (Forge.hasGamepad()) + showGamepadSelector = true; if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { - back(); + if(!kbVisible) + back(); + } + if (keycode == Input.Keys.BUTTON_SELECT) { + if (showGamepadSelector) { + if(!kbVisible) + performTouch(ui.findActor("back")); + } + } else if (keycode == Input.Keys.BUTTON_START) { + if (showGamepadSelector) { + if(kbVisible) + keyOK(); + else + performTouch(ui.findActor("start")); + } + } else if (keycode == Input.Keys.BUTTON_L2) { + if(!kbVisible) + selectedName.setText(NameGenerator.getRandomName("Female", "Any", selectedName.getText())); + } else if (keycode == Input.Keys.BUTTON_R2) { + if(!kbVisible) + selectedName.setText(NameGenerator.getRandomName("Male", "Any", selectedName.getText())); + } else if (keycode == Input.Keys.BUTTON_L1) { + if (showGamepadSelector) { + if (kbVisible) + toggleShiftOrBackspace(true); + else + performTouch(ui.findActor("leftAvatar")); + } + } else if (keycode == Input.Keys.BUTTON_R1) { + if (showGamepadSelector) { + if(kbVisible) + toggleShiftOrBackspace(false); + else + performTouch(ui.findActor("rightAvatar")); + } + } else if (keycode == Input.Keys.DPAD_DOWN) { + if (showGamepadSelector) { + if (kbVisible) { + setSelectedKey(keycode); + } else { + if (selectedActor == mode) + selectActor(selectedName, false); + else if (selectedActor == ui.findActor("back")) + selectActor(ui.findActor("start"), false); + else if (selectedActor == ui.findActor("start")) + selectActor(ui.findActor("back"), false); + else + selectNextActor(false); + } + } + } else if (keycode == Input.Keys.DPAD_UP) { + if (showGamepadSelector) { + if (kbVisible) { + setSelectedKey(keycode); + } else { + if (selectedActor == selectedName) + selectActor(mode, false); + else if (selectedActor == ui.findActor("start")) + selectActor(ui.findActor("back"), false); + else if (selectedActor == ui.findActor("back")) + selectActor(ui.findActor("start"), false); + else + selectPreviousActor(false); + } + } + } else if (keycode == Input.Keys.DPAD_LEFT) { + if (showGamepadSelector) { + if (kbVisible) { + setSelectedKey(keycode); + } else { + if (selectedActor == ui.findActor("back") || selectedActor == ui.findActor("start")) + selectActor(mode, false); + } + } + } else if (keycode == Input.Keys.DPAD_RIGHT) { + if (showGamepadSelector) { + if (kbVisible) { + setSelectedKey(keycode); + } else { + if (!(selectedActor == ui.findActor("back") || selectedActor == ui.findActor("start"))) + selectActor(ui.findActor("start"), false); + } + } + } else if (keycode == Input.Keys.BUTTON_A) { + if (showGamepadSelector) { + if (kbVisible) { + if (selectedKey != null) + performTouch(selectedKey); + } else { + if (selectedActor != null) { + if (selectedActor instanceof TextButton) + performTouch(selectedActor); + else if (selectedActor instanceof TextField && !kbVisible) { + lastInputField = selectedActor; + showOnScreenKeyboard(""); + } + } + } + } + } else if (keycode == Input.Keys.BUTTON_B) { + if (showGamepadSelector) { + if (kbVisible) { + hideOnScreenKeyboard(); + } else { + performTouch(ui.findActor("back")); + } + } + } else if (keycode == Input.Keys.BUTTON_X) { + if (showGamepadSelector) { + if(!kbVisible) + if (selectedActor != null && selectedActor instanceof Selector) + performTouch(((Selector) selectedActor).getLeftArrow()); + } + } else if (keycode == Input.Keys.BUTTON_Y) { + if (showGamepadSelector) { + if(!kbVisible) + if (selectedActor != null && selectedActor instanceof Selector) + performTouch(((Selector) selectedActor).getRightArrow()); + } } return true; } diff --git a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java index a17cb764ae8..7bc1bbfd5b5 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java @@ -34,6 +34,7 @@ public class PlayerStatisticScene extends UIScene { TextButton back; private Table enemiesGroup; Label blessingScroll; + ScrollPane scrollPane, blessing; public PlayerStatisticScene() { super(Forge.isLandscapeMode() ? "ui/statistic.json" : "ui/statistic_portrait.json"); @@ -51,6 +52,16 @@ public class PlayerStatisticScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } + if (keycode == Input.Keys.BUTTON_B) + performTouch(ui.findActor("return")); + else if (keycode == Input.Keys.BUTTON_A) + performTouch(selectedActor); + else if (keycode == Input.Keys.BUTTON_L1 || keycode == Input.Keys.DPAD_UP) { + scrollPane.fling(1f, 0, -300); + } else if (keycode == Input.Keys.BUTTON_R1 || keycode == Input.Keys.DPAD_DOWN) { + scrollPane.fling(1f, 0, +300); + } else if (keycode == Input.Keys.DPAD_LEFT || keycode == Input.Keys.DPAD_RIGHT || keycode == Input.Keys.DPAD_UP || keycode == Input.Keys.DPAD_DOWN) + selectActor(back, false); return true; } @@ -93,20 +104,10 @@ public class PlayerStatisticScene extends UIScene { avatar.setDrawable(new TextureRegionDrawable(Current.player().avatar())); } if (life != null) { - AdventurePlayer.current().onLifeChange(new Runnable() { - @Override - public void run() { - life.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife()); - } - }); + AdventurePlayer.current().onLifeChange(() -> life.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife())); } if (money != null) { - WorldSave.getCurrentSave().getPlayer().onGoldChange(new Runnable() { - @Override - public void run() { - money.setText(String.valueOf(AdventurePlayer.current().getGold())); - } - }); + WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText(String.valueOf(AdventurePlayer.current().getGold()))); } if (totalWins != null) { totalWins.setText(Current.player().getStatistic().totalWins()); @@ -142,8 +143,8 @@ public class PlayerStatisticScene extends UIScene { enemiesGroup.add((entry.getValue().getRight().toString())).align(Align.center).space(3, 2, 3, 2); enemiesGroup.row().space(8); } - - + clearActorObjects(); + addActorObject(back); } @Override @@ -155,12 +156,7 @@ public class PlayerStatisticScene extends UIScene { blessingScroll.setStyle(new Label.LabelStyle(Controls.getBitmapFont("default"), Color.BLACK)); blessingScroll.setAlignment(Align.topLeft); blessingScroll.setWrap(true); - ui.onButtonPress("return", new Runnable() { - @Override - public void run() { - PlayerStatisticScene.this.back(); - } - }); + ui.onButtonPress("return", () -> PlayerStatisticScene.this.back()); avatar = ui.findActor("avatar"); avatarBorder = ui.findActor("avatarBorder"); @@ -181,9 +177,9 @@ public class PlayerStatisticScene extends UIScene { lossWinRatio = ui.findActor("lossWinRatio"); back = ui.findActor("return"); back.getLabel().setText(Forge.getLocalizer().getMessage("lblBack")); - ScrollPane scrollPane = ui.findActor("enemies"); + scrollPane = ui.findActor("enemies"); scrollPane.setActor(enemiesGroup); - ScrollPane blessing = ui.findActor("blessingInfo"); + blessing = ui.findActor("blessingInfo"); blessing.setActor(blessingScroll); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java index 6e708079824..92ab57e2053 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java @@ -8,6 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.Timer; import forge.Forge; import forge.adventure.character.ShopActor; import forge.adventure.player.AdventurePlayer; @@ -25,6 +26,7 @@ import forge.sound.SoundSystem; public class RewardScene extends UIScene { private TextButton doneButton; private Label goldLabel; + private boolean showTooltips = false; public enum Type { Shop, Loot @@ -40,7 +42,7 @@ public class RewardScene extends UIScene { super(Forge.isLandscapeMode() ? "ui/items.json" : "ui/items_portrait.json"); } - boolean doneClicked = false; + boolean doneClicked = false, shown = false; float flipCountDown = 1.0f; float exitCountDown = 0.0f; //Serves as additional check for when scene is exiting, so you can't double tap too fast. @@ -137,11 +139,91 @@ public class RewardScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { done(); } + if (keycode == Input.Keys.BUTTON_B || keycode == Input.Keys.BUTTON_START) + showLootOrDone(); + else if (keycode == Input.Keys.BUTTON_A) + performTouch(selectedActor); + else if (keycode == Input.Keys.DPAD_RIGHT) { + hideTooltips(); + selectNextActor(false); + if (selectedActor != null && Type.Loot == type) { + selectedActor.fire(eventEnter); + } + showHideTooltips(); + } else if (keycode == Input.Keys.DPAD_LEFT) { + hideTooltips(); + selectPreviousActor(false); + if (selectedActor != null && Type.Loot == type) { + selectedActor.fire(eventEnter); + } + showHideTooltips(); + } else if (keycode == Input.Keys.BUTTON_Y) { + showTooltips = !showTooltips; + showHideTooltips(); + } return true; } + private void showHideTooltips() { + if (selectedActor instanceof RewardActor) { + if (showTooltips) { + if (((RewardActor) selectedActor).isFlipped()) + ((RewardActor) selectedActor).showTooltip(); + } else { + ((RewardActor) selectedActor).hideTooltip(); + } + } else if (selectedActor instanceof BuyButton) { + if (showTooltips) + ((BuyButton) selectedActor).reward.showTooltip(); + else + ((BuyButton) selectedActor).reward.hideTooltip(); + } + } + private void hideTooltips() { + if (selectedActor instanceof RewardActor) { + ((RewardActor) selectedActor).hideTooltip(); + } else if (selectedActor instanceof BuyButton) { + ((BuyButton) selectedActor).reward.hideTooltip(); + } + } + private void showLootOrDone() { + boolean exit = true; + for (Actor actor : new Array.ArrayIterator<>(generated)) { + if (!(actor instanceof RewardActor)) { + continue; + } + RewardActor reward = (RewardActor) actor; + if (!reward.isFlipped()) { + exit = false; + break; + } + } + if (exit) + performTouch(doneButton); + else if (type == Type.Loot && !shown) { + shown = true; + for (Actor actor : new Array.ArrayIterator<>(generated)) { + if (!(actor instanceof RewardActor)) { + continue; + } + RewardActor reward = (RewardActor) actor; + AdventurePlayer.current().addReward(reward.getReward()); + if (!reward.isFlipped()) { + Timer.schedule(new Timer.Task() { + @Override + public void run() { + reward.flip(); + } + }, 0.09f); + } + } + } else { + performTouch(doneButton); + } + } public void loadRewards(Array newRewards, Type type, ShopActor shopActor) { + clearActorObjects(); this.type = type; doneClicked = false; for (Actor actor : new Array.ArrayIterator<>(generated)) { @@ -276,7 +358,10 @@ public class RewardScene extends UIScene { generated.add(buyCardButton); if (!skipCard) { stage.addActor(buyCardButton); + addActorObject(buyCardButton); } + } else { + addActorObject(actor); } generated.add(actor); if (!skipCard) { diff --git a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java index ca2fe753a36..1d24aa2c839 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java @@ -3,6 +3,7 @@ package forge.adventure.scene; import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; @@ -43,10 +44,10 @@ public class SaveLoadScene extends UIScene { Image previewImage; Label previewDate; Image previewBorder; - TextButton saveLoadButton, back; - TextButton quickSave; - TextButton autoSave; + TextButton saveLoadButton, back, quickSave, autoSave, dialogSaveBtn, dialogAbortBtn; + Actor lastHighlightedSave; SelectBox difficulty; + ScrollPane scrollPane; public SaveLoadScene() { super(Forge.isLandscapeMode() ? "ui/save_load.json" : "ui/save_load_portrait.json"); @@ -91,7 +92,7 @@ public class SaveLoadScene extends UIScene { previewImage.setVisible(true); previewDate.setVisible(true); if (header.saveDate != null) - previewDate.setText(DateFormat.getDateInstance().format(header.saveDate)+"\n"+DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate)); + previewDate.setText(DateFormat.getDateInstance().format(header.saveDate) + "\n" + DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate)); else previewDate.setText(""); } @@ -107,6 +108,7 @@ public class SaveLoadScene extends UIScene { if (buttons.containsKey(slot)) { TextButton button = buttons.get(slot); button.setColor(Color.RED); + selectActor(button, false); } return true; @@ -119,6 +121,7 @@ public class SaveLoadScene extends UIScene { //prevent NPE, allowed saveslot is 1 to 10.. textInput.setText(buttons.get(currentSlot).getText().toString()); dialog.show(stage); + selectActor(textInput, false); stage.setKeyboardFocus(textInput); } break; @@ -159,7 +162,6 @@ public class SaveLoadScene extends UIScene { } public boolean saveAbort() { - dialog.hide(); return true; } @@ -169,6 +171,124 @@ public class SaveLoadScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } + if (kbVisible) { + if (keycode == Input.Keys.BUTTON_START) + keyOK(); + else if (keycode == Input.Keys.BUTTON_L1) + toggleShiftOrBackspace(true); + else if (keycode == Input.Keys.BUTTON_R1) + toggleShiftOrBackspace(false); + else if (keycode == Input.Keys.BUTTON_B) + hideOnScreenKeyboard(); + else if (keycode == Input.Keys.BUTTON_A) { + if (selectedKey != null) + performTouch(selectedKey); + } else if (keycode == Input.Keys.DPAD_UP || keycode == Input.Keys.DPAD_DOWN || keycode == Input.Keys.DPAD_LEFT || keycode == Input.Keys.DPAD_RIGHT) + setSelectedKey(keycode); + } else if (dialog.getColor().a != 0f) { + if (keycode == Input.Keys.BUTTON_A) { + if (selectedActor == textInput) { + lastInputField = textInput; + showOnScreenKeyboard(textInput.getText()); + } else if (selectedActor == dialogAbortBtn || selectedActor == dialogSaveBtn) { + performTouch(selectedActor); + if (lastSelectedSlot > 0) + select(lastSelectedSlot); + else + select(-3); + } + } else if (keycode == Input.Keys.BUTTON_B) { + performTouch(dialogAbortBtn); + if (lastSelectedSlot > 0) + select(lastSelectedSlot); + else + select(-3); + } + else if (keycode == Input.Keys.DPAD_DOWN) { + if (selectedActor == null) { + selectActor(textInput, false); + } else if (selectedActor == textInput) + selectActor(dialogSaveBtn, false); + } else if (keycode == Input.Keys.DPAD_UP) { + if (selectedActor == null) + selectActor(dialogSaveBtn, false); + else if (selectedActor == dialogSaveBtn || selectedActor == dialogAbortBtn) { + selectActor(textInput, false); + } + } else if (keycode == Input.Keys.DPAD_LEFT) { + if (selectedActor == dialogAbortBtn) + selectActor(dialogSaveBtn, false); + } else if (keycode == Input.Keys.DPAD_RIGHT) { + if (selectedActor == dialogSaveBtn) + selectActor(dialogAbortBtn, false); + } + } else { + if (keycode == Input.Keys.BUTTON_B) + performTouch(back); + else if (keycode == Input.Keys.BUTTON_Y) { + if (difficulty != null && difficulty.isVisible()) { + int index = difficulty.getSelectedIndex()-1; + if (index < 0) + index = 0; + difficulty.setSelectedIndex(index); + } + } else if (keycode == Input.Keys.BUTTON_X) { + if (difficulty != null && difficulty.isVisible()) { + int index = difficulty.getSelectedIndex()+1; + if (index >= 2) + index = 2; + difficulty.setSelectedIndex(index); + } + } else if (keycode == Input.Keys.BUTTON_L1) { + scrollPane.fling(1f, 0, -300); + } else if (keycode == Input.Keys.BUTTON_R1) { + scrollPane.fling(1f, 0, +300); + } else if (keycode == Input.Keys.BUTTON_A) { + performTouch(selectedActor); + } else if (keycode == Input.Keys.DPAD_LEFT) { + if (selectedActor == back || selectedActor == saveLoadButton) { + if (lastHighlightedSave != null) + selectActor(lastHighlightedSave, false); + else + selectActor(actorObjectMap.get(0), false); + lastHighlightedSave = selectedActor; + } + } else if (keycode == Input.Keys.DPAD_RIGHT) { + if (!(selectedActor == back || selectedActor == saveLoadButton)) { + lastHighlightedSave = selectedActor; + selectActor(saveLoadButton, false); + } + } else if (keycode == Input.Keys.DPAD_DOWN) { + int index = mode == Modes.Save ? 9 : 11; + if (selectedActor == back) + selectActor(saveLoadButton, false); + else if (selectedActorIndex == index) { + selectActor(actorObjectMap.get(0), false); + scrollPane.fling(1f, 0, +300); + } else { + selectNextActor(false); + } + if (selectedActorIndex == 6) + scrollPane.fling(1f, 0, -300); + if (!(selectedActor == back || selectedActor == saveLoadButton)) + lastHighlightedSave = selectedActor; + } else if (keycode == Input.Keys.DPAD_UP) { + if (selectedActor == saveLoadButton) + selectActor(back, false); + else if (selectedActorIndex == 0) { + selectActor(buttons.get(10), false); + scrollPane.fling(1f, 0, -300); + } else { + selectPreviousActor(false); + } + if (selectedActorIndex == 5) + scrollPane.fling(1f, 0, +300); + if (!(selectedActor == back || selectedActor == saveLoadButton)) + lastHighlightedSave = selectedActor; + } else if (keycode == Input.Keys.BUTTON_START) { + performTouch(saveLoadButton); + } + } return true; } @@ -241,7 +361,7 @@ public class SaveLoadScene extends UIScene { saveLoadButton.setText(Forge.getLocalizer().getMessage("lblLoad")); break; case NewGamePlus: - header.setText(Forge.getLocalizer().getMessage("lblNewGame")+"+"); + header.setText(Forge.getLocalizer().getMessage("lblNewGame") + "+"); saveLoadButton.setText(Forge.getLocalizer().getMessage("lblStart")); break; } @@ -252,6 +372,8 @@ public class SaveLoadScene extends UIScene { @Override public void enter() { + unselectActors(); + clearActorObjects(); if (lastSelectedSlot > 0) select(lastSelectedSlot); else @@ -269,6 +391,28 @@ public class SaveLoadScene extends UIScene { difficulty.setVisible(false); } } + if (!autoSave.isDisabled()) + addActorObject(autoSave); + if (!quickSave.isDisabled()) + addActorObject(quickSave); + for (int i=0; i <= 10; i++) { + if (buttons.containsKey(i)) + addActorObject(buttons.get(i)); + } + addActorObject(textInput); + addActorObject(dialogSaveBtn); + addActorObject(dialogAbortBtn); + addActorObject(back); + addActorObject(saveLoadButton); + if (scrollPane != null) { + if (lastSelectedSlot >= 6) { + scrollPane.fling(1f, 0, -300); + selectActor(buttons.get(lastSelectedSlot), false); + } else if (lastSelectedSlot > 0 && lastSelectedSlot < 6) { + scrollPane.fling(1f, 0, +300); + selectActor(buttons.get(lastSelectedSlot), false); + } + } super.enter(); } @@ -296,11 +440,14 @@ public class SaveLoadScene extends UIScene { dialog.getButtonTable().add(Controls.newLabel(Forge.getLocalizer().getMessage("lblName") + ": ")).align(Align.left).pad(2, 15, 2, 2); dialog.getButtonTable().add(textInput).fillX().expandX().padRight(15); dialog.getButtonTable().row(); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblSave"), () -> SaveLoadScene.this.save())).align(Align.left).padLeft(15); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblAbort"), () -> SaveLoadScene.this.saveAbort())).align(Align.right).padRight(15); + dialogSaveBtn = Controls.newTextButton(Forge.getLocalizer().getMessage("lblSave"), () -> SaveLoadScene.this.save()); + dialog.getButtonTable().add(dialogSaveBtn).align(Align.left).padLeft(15); + dialogAbortBtn = Controls.newTextButton(Forge.getLocalizer().getMessage("lblAbort"), () -> SaveLoadScene.this.saveAbort()); + dialog.getButtonTable().add(dialogAbortBtn).align(Align.right).padRight(15); //makes dialog hidden immediately when you open saveload scene.. dialog.getColor().a = 0; + dialog.hide(); previewImage = ui.findActor("preview"); previewDate = ui.findActor("saveDate"); header = Controls.newLabel(Forge.getLocalizer().getMessage("lblSave")); @@ -321,7 +468,7 @@ public class SaveLoadScene extends UIScene { defColor = saveLoadButton.getColor(); - ScrollPane scrollPane = ui.findActor("saveSlots"); + scrollPane = ui.findActor("saveSlots"); scrollPane.setActor(layout); ui.addActor(difficulty); difficulty.setSelectedIndex(1); diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index 35917ff8bf1..4760c35d3ca 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -25,6 +25,7 @@ public class SettingsScene extends UIScene { Texture Background; private Table settingGroup; TextButton back; + ScrollPane scrollPane; public SettingsScene() { super(Forge.isLandscapeMode() ? "ui/settings.json" : "ui/settings_portrait.json"); @@ -54,6 +55,13 @@ public class SettingsScene extends UIScene { if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } + if (keycode == Input.Keys.BUTTON_B) + performTouch(back); + else if (keycode == Input.Keys.BUTTON_L1) { + scrollPane.fling(1f, 0, -300); + } else if (keycode == Input.Keys.BUTTON_R1) { + scrollPane.fling(1f, 0, +300); + } return true; } @@ -267,7 +275,7 @@ public class SettingsScene extends UIScene { back.getLabel().setText(Forge.getLocalizer().getMessage("lblBack")); ui.onButtonPress("return", () -> SettingsScene.this.back()); - ScrollPane scrollPane = ui.findActor("settings"); + scrollPane = ui.findActor("settings"); scrollPane.setActor(settingGroup); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index e6c02a9733f..7b86fb6c48a 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -20,8 +20,9 @@ import forge.screens.TransitionScreen; */ public class StartScene extends UIScene { - TextButton saveButton, resumeButton, continueButton, newGameButton, newGameButtonPlus, loadButton, settingsButton, exitButton, switchButton; + TextButton saveButton, resumeButton, continueButton, newGameButton, newGameButtonPlus, loadButton, settingsButton, exitButton, switchButton, dialogOk, dialogCancel, dialogButtonSelected; Dialog dialog; + private int selected = -1; public StartScene() { super(Forge.isLandscapeMode() ? "ui/start_menu.json" : "ui/start_menu_portrait.json"); @@ -82,6 +83,8 @@ public class StartScene extends UIScene { public boolean Exit() { if (dialog != null) dialog.show(stage); + if (showGamepadSelector) + dialogOk.fire(eventEnter); return true; } @@ -123,15 +126,226 @@ public class StartScene extends UIScene { } + @Override + public boolean pointerMoved(int screenX, int screenY) { + ui.screenToLocalCoordinates(pointer.set(screenX,screenY)); + if (showGamepadSelector) { + unSelectAll(); + showGamepadSelector = false; + } + updateSelected(); + return super.pointerMoved(screenX, screenY); + } + @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { - if (WorldSave.getCurrentSave().getWorld().getData() != null) - Resume(); + if (Forge.hasGamepad()) + showGamepadSelector = true; + if (dialog.getColor().a != 1) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { + if (WorldSave.getCurrentSave().getWorld().getData() != null) { + if (showGamepadSelector) + performTouch(resumeButton); + else + Resume(); + } + } + if (keycode == Input.Keys.DPAD_DOWN) { + selected++; + if (selected == 1 && Forge.isLandscapeMode()) + selected++; + if (!saveButton.isVisible() && selected == 3) + selected++; + if (!resumeButton.isVisible() && selected == 4) + selected++; + if (!continueButton.isVisible() && selected == 5) + selected++; + if (selected > 7 && Forge.isLandscapeMode()) + selected = 0; + if (selected > 8 && !Forge.isLandscapeMode()) + selected = 8; + setSelected(selected, false); + } else if (keycode == Input.Keys.DPAD_UP) { + selected--; + if (selected == 7 && Forge.isLandscapeMode()) + selected--; + if (!continueButton.isVisible() && selected == 5) + selected--; + if (!resumeButton.isVisible() && selected == 4) + selected--; + if (!saveButton.isVisible() && selected == 3) + selected--; + if (selected == 1 && Forge.isLandscapeMode()) + selected--; + if (selected < 0) + selected = Forge.isLandscapeMode() ? 7 : 0; + setSelected(selected, false); + } else if (keycode == Input.Keys.DPAD_RIGHT && Forge.isLandscapeMode()) { + if (selected == 0 || selected == 7) + selected++; + if (selected > 8) + selected = 8; + setSelected(selected, false); + } else if (keycode == Input.Keys.DPAD_LEFT && Forge.isLandscapeMode()) { + if (selected == 1 || selected == 8) + selected--; + if (selected < 0) + selected = 0; + setSelected(selected, false); + } else if (keycode == Input.Keys.BUTTON_A) + setSelected(selected, true); + } else { + if (keycode == Input.Keys.DPAD_RIGHT) { + dialogOk.fire(eventExit); + dialogCancel.fire(eventEnter); + dialogButtonSelected = dialogCancel; + } else if (keycode == Input.Keys.DPAD_LEFT) { + dialogOk.fire(eventEnter); + dialogCancel.fire(eventExit); + dialogButtonSelected = dialogOk; + } else if (keycode == Input.Keys.BUTTON_A) { + dialogOk.fire(eventExit); + dialogCancel.fire(eventExit); + performTouch(dialogButtonSelected); + } } return true; } - + private void setSelected(int select, boolean press) { + if (!showGamepadSelector) + return; + unSelectAll(); + switch (select) { + case 0: + newGameButton.fire(eventEnter); + if (press) + performTouch(newGameButton); + break; + case 1: + newGameButtonPlus.fire(eventEnter); + if (press) + performTouch(newGameButtonPlus); + break; + case 2: + loadButton.fire(eventEnter); + if (press) + performTouch(loadButton); + break; + case 3: + saveButton.fire(eventEnter); + if (press) + performTouch(saveButton); + break; + case 4: + resumeButton.fire(eventEnter); + if (press) + performTouch(resumeButton); + break; + case 5: + continueButton.fire(eventEnter); + if (press) { + performTouch(continueButton); + setSelected(4, false); + selected = 4; + } + break; + case 6: + settingsButton.fire(eventEnter); + if (press) + performTouch(settingsButton); + break; + case 7: + if (Forge.isLandscapeMode()) { + exitButton.fire(eventEnter); + if (press) + performTouch(exitButton); + } else { + switchButton.fire(eventEnter); + if (press) + performTouch(switchButton); + } + break; + case 8: + if (Forge.isLandscapeMode()) { + switchButton.fire(eventEnter); + if (press) + performTouch(switchButton); + } else { + exitButton.fire(eventEnter); + if (press) + performTouch(exitButton); + } + break; + default: + break; + } + } + private void unSelectAll() { + if (!showGamepadSelector) + return; + newGameButton.fire(eventExit); + newGameButtonPlus.fire(eventExit); + loadButton.fire(eventExit); + saveButton.fire(eventExit); + resumeButton.fire(eventExit); + continueButton.fire(eventExit); + settingsButton.fire(eventExit); + exitButton.fire(eventExit); + switchButton.fire(eventExit); + dialogOk.fire(eventExit); + dialogCancel.fire(eventExit); + } + private void updateSelected() { + if (dialog.getColor().a == 1) { + if (Controls.actorContainsVector(dialogOk, pointer)) { + dialogCancel.fire(eventExit); + dialogOk.fire(eventEnter); + dialogButtonSelected = dialogOk; + } + if (Controls.actorContainsVector(dialogCancel, pointer)) { + dialogOk.fire(eventExit); + dialogCancel.fire(eventEnter); + dialogButtonSelected = dialogCancel; + } + return; + } + if (Controls.actorContainsVector(newGameButton, pointer)) { + newGameButton.fire(eventEnter); + selected = 0; + } + if (Controls.actorContainsVector(newGameButtonPlus, pointer)) { + newGameButtonPlus.fire(eventEnter); + selected = 1; + } + if (Controls.actorContainsVector(loadButton, pointer)) { + loadButton.fire(eventEnter); + selected = 2; + } + if (Controls.actorContainsVector(saveButton, pointer)) { + saveButton.fire(eventEnter); + selected = 3; + } + if (Controls.actorContainsVector(resumeButton, pointer)) { + resumeButton.fire(eventEnter); + selected = 4; + } + if (Controls.actorContainsVector(continueButton, pointer)) { + continueButton.fire(eventEnter); + selected = 5; + } + if (Controls.actorContainsVector(settingsButton, pointer)) { + settingsButton.fire(eventEnter); + selected = 6; + } + if (Controls.actorContainsVector(exitButton, pointer)) { + exitButton.fire(eventEnter); + selected = Forge.isLandscapeMode() ? 7 : 8; + } + if (Controls.actorContainsVector(switchButton, pointer)) { + switchButton.fire(eventEnter); + selected = Forge.isLandscapeMode() ? 8 : 7; + } + } @Override public void resLoaded() { super.resLoaded(); @@ -169,8 +383,11 @@ public class StartScene extends UIScene { dialog = Controls.newDialog(Forge.getLocalizer().getMessage("lblExitForge")); dialog.getButtonTable().add(Controls.newLabel(Forge.getLocalizer().getMessage("lblAreYouSureYouWishExitForge"))).colspan(2).pad(2, 15, 2, 15); dialog.getButtonTable().row(); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblExit"), () -> Forge.exit(true))).width(60).align(Align.left).padLeft(15); - dialog.getButtonTable().add(Controls.newTextButton(Forge.getLocalizer().getMessage("lblCancel"), () -> dialog.hide())).width(60).align(Align.right).padRight(15); + dialogOk = Controls.newTextButton(Forge.getLocalizer().getMessage("lblExit"), () -> Forge.exit(true)); + dialogButtonSelected = dialogOk; + dialog.getButtonTable().add(dialogOk).width(60).align(Align.left).padLeft(15); + dialogCancel = Controls.newTextButton(Forge.getLocalizer().getMessage("lblCancel"), () -> dialog.hide()); + dialog.getButtonTable().add(dialogCancel).width(60).align(Align.right).padRight(15); dialog.getColor().a = 0; } diff --git a/forge-gui-mobile/src/forge/adventure/scene/UIScene.java b/forge-gui-mobile/src/forge/adventure/scene/UIScene.java index dd92874b727..947b373a09b 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/UIScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/UIScene.java @@ -1,16 +1,30 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; +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.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.Dialog; import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.Scaling; +import com.badlogic.gdx.utils.Timer; import com.badlogic.gdx.utils.viewport.ScalingViewport; +import forge.Forge; import forge.adventure.util.Config; +import forge.adventure.util.Controls; +import forge.adventure.util.Selector; import forge.adventure.util.UIActor; /** @@ -21,6 +35,20 @@ public class UIScene extends Scene { Stage stage; String uiFile; + private Dialog keyboardDialog; + private Label kbLabel; + private TextButton keyA, keyB, keyC, keyD, keyE, keyF, keyG, keyH, keyI, keyJ, keyK, keyL, keyM, keyN, keyO, keyP, + keyQ, keyR, keyS, keyT, keyU, keyV, keyW, keyX, keyY, keyZ, key1, key2, key3, key4, key5, key6, key7, key8, + key9, key0, keyDot, keyComma, keyShift, keyBackspace, keySpace, keyOK; + public Actor lastInputField; + public boolean showGamepadSelector = false, lowercaseKey = true, kbVisible=false; + + public InputEvent eventEnter, eventExit, eventTouchDown, eventTouchUp; + + public Vector2 pointer = new Vector2(); + public ObjectMap actorObjectMap; + public Actor selectedActor, selectedKey, lastSelectedKey; + public int selectedActorIndex = 0; public UIScene(String uiFilePath) { @@ -53,45 +81,668 @@ public class UIScene extends Scene { return true; } + public boolean pointerMoved(int screenX, int screenY) { + return false; + } + + public void performTouch(Actor actor) { + if (actor == null) + return; + actor.fire(eventTouchDown); + Timer.schedule(new Timer.Task() { + @Override + public void run() { + actor.fire(eventTouchUp); + } + }, 0.10f); + } + @Override public void resLoaded() { - stage = new Stage(new ScalingViewport(Scaling.stretch, getIntendedWidth(), getIntendedHeight())) { + stage = new Stage(new ScalingViewport(Scaling.stretch, getIntendedWidth(), getIntendedHeight())) { + @Override + public boolean keyUp(int keycode) { + if (Forge.hasGamepad()) + return false; + return keyPressed(keycode); + } + @Override + public boolean keyDown(int keyCode) { + if (!Forge.hasGamepad()) + return false; + return keyPressed(keyCode); + } + @Override + public boolean mouseMoved(int screenX, int screenY) { + pointerMoved(screenX, screenY); + return super.mouseMoved(screenX, screenY); + } + }; + ui = new UIActor(Config.instance().getFile(uiFile)); + screenImage = ui.findActor("lastScreen"); + stage.addActor(ui); - @Override - public boolean keyUp(int keycode) { - return keyPressed(keycode); + eventTouchDown = new InputEvent(); + eventTouchDown.setPointer(-1); + eventTouchDown.setType(InputEvent.Type.touchDown); + eventTouchUp = new InputEvent(); + eventTouchUp.setPointer(-1); + eventTouchUp.setType(InputEvent.Type.touchUp); + eventEnter = new InputEvent(); + eventEnter.setPointer(-1); + eventEnter.setType(InputEvent.Type.enter); + eventExit = new InputEvent(); + eventExit.setPointer(-1); + eventExit.setType(InputEvent.Type.exit); + actorObjectMap = new ObjectMap<>(); + keyboardDialog = Controls.newDialog(""); + kbLabel = Controls.newLabel(""); + kbLabel.setAlignment(Align.center); + kbLabel.setColor(Color.CYAN); + kbLabel.setFontScale(1.5f,1.5f); + keyA = Controls.newTextButton("A", () -> kbLabel.setText(kbLabel.getText()+transformKey("A"))); + keyB = Controls.newTextButton("B", () -> kbLabel.setText(kbLabel.getText()+transformKey("B"))); + keyC = Controls.newTextButton("C", () -> kbLabel.setText(kbLabel.getText()+transformKey("C"))); + keyD = Controls.newTextButton("D", () -> kbLabel.setText(kbLabel.getText()+transformKey("D"))); + keyE = Controls.newTextButton("E", () -> kbLabel.setText(kbLabel.getText()+transformKey("E"))); + keyF = Controls.newTextButton("F", () -> kbLabel.setText(kbLabel.getText()+transformKey("F"))); + keyG = Controls.newTextButton("G", () -> kbLabel.setText(kbLabel.getText()+transformKey("G"))); + keyH = Controls.newTextButton("H", () -> kbLabel.setText(kbLabel.getText()+transformKey("H"))); + keyI = Controls.newTextButton("I", () -> kbLabel.setText(kbLabel.getText()+transformKey("I"))); + keyJ = Controls.newTextButton("J", () -> kbLabel.setText(kbLabel.getText()+transformKey("J"))); + keyK = Controls.newTextButton("K", () -> kbLabel.setText(kbLabel.getText()+transformKey("K"))); + keyL = Controls.newTextButton("L", () -> kbLabel.setText(kbLabel.getText()+transformKey("L"))); + keyM = Controls.newTextButton("M", () -> kbLabel.setText(kbLabel.getText()+transformKey("M"))); + keyN = Controls.newTextButton("N", () -> kbLabel.setText(kbLabel.getText()+transformKey("N"))); + keyO = Controls.newTextButton("O", () -> kbLabel.setText(kbLabel.getText()+transformKey("O"))); + keyP = Controls.newTextButton("P", () -> kbLabel.setText(kbLabel.getText()+transformKey("P"))); + keyQ = Controls.newTextButton("Q", () -> kbLabel.setText(kbLabel.getText()+transformKey("Q"))); + keyR = Controls.newTextButton("R", () -> kbLabel.setText(kbLabel.getText()+transformKey("R"))); + keyS = Controls.newTextButton("S", () -> kbLabel.setText(kbLabel.getText()+transformKey("S"))); + keyT = Controls.newTextButton("T", () -> kbLabel.setText(kbLabel.getText()+transformKey("T"))); + keyU = Controls.newTextButton("U", () -> kbLabel.setText(kbLabel.getText()+transformKey("U"))); + keyV = Controls.newTextButton("V", () -> kbLabel.setText(kbLabel.getText()+transformKey("V"))); + keyW = Controls.newTextButton("W", () -> kbLabel.setText(kbLabel.getText()+transformKey("W"))); + keyX = Controls.newTextButton("X", () -> kbLabel.setText(kbLabel.getText()+transformKey("X"))); + keyY = Controls.newTextButton("Y", () -> kbLabel.setText(kbLabel.getText()+transformKey("Y"))); + keyZ = Controls.newTextButton("Z", () -> kbLabel.setText(kbLabel.getText()+transformKey("Z"))); + key1 = Controls.newTextButton("1", () -> kbLabel.setText(kbLabel.getText()+"1")); + key2 = Controls.newTextButton("2", () -> kbLabel.setText(kbLabel.getText()+"2")); + key3 = Controls.newTextButton("3", () -> kbLabel.setText(kbLabel.getText()+"3")); + key4 = Controls.newTextButton("4", () -> kbLabel.setText(kbLabel.getText()+"4")); + key5 = Controls.newTextButton("5", () -> kbLabel.setText(kbLabel.getText()+"5")); + key6 = Controls.newTextButton("6", () -> kbLabel.setText(kbLabel.getText()+"6")); + key7 = Controls.newTextButton("7", () -> kbLabel.setText(kbLabel.getText()+"7")); + key8 = Controls.newTextButton("8", () -> kbLabel.setText(kbLabel.getText()+"8")); + key9 = Controls.newTextButton("9", () -> kbLabel.setText(kbLabel.getText()+"9")); + key0 = Controls.newTextButton("0", () -> kbLabel.setText(kbLabel.getText()+"0")); + keyDot = Controls.newTextButton(".", () -> kbLabel.setText(kbLabel.getText()+".")); + keyComma = Controls.newTextButton(",", () -> kbLabel.setText(kbLabel.getText()+",")); + keyShift = Controls.newTextButton("Aa", () -> shiftKey()); + keyBackspace = Controls.newTextButton("<<", () -> kbLabel.setText(removeLastChar(String.valueOf(kbLabel.getText())))); + keySpace = Controls.newTextButton("SPACE", () -> kbLabel.setText(kbLabel.getText()+" ")); + keyOK = Controls.newTextButton("OK", () -> setKeyboardDialogText()); + keyboardDialog.getContentTable().add(kbLabel).width(220).height(20).colspan(10).expandX().align(Align.center); + keyboardDialog.getButtonTable().row(); + keyboardDialog.getButtonTable().add(key1).width(20).height(20); + keyboardDialog.getButtonTable().add(key2).width(20).height(20); + keyboardDialog.getButtonTable().add(key3).width(20).height(20); + keyboardDialog.getButtonTable().add(key4).width(20).height(20); + keyboardDialog.getButtonTable().add(key5).width(20).height(20); + keyboardDialog.getButtonTable().add(key6).width(20).height(20); + keyboardDialog.getButtonTable().add(key7).width(20).height(20); + keyboardDialog.getButtonTable().add(key8).width(20).height(20); + keyboardDialog.getButtonTable().add(key9).width(20).height(20); + keyboardDialog.getButtonTable().add(key0).width(20).height(20); + keyboardDialog.getButtonTable().row(); + keyboardDialog.getButtonTable().add(keyQ).width(20).height(20); + keyboardDialog.getButtonTable().add(keyW).width(20).height(20); + keyboardDialog.getButtonTable().add(keyE).width(20).height(20); + keyboardDialog.getButtonTable().add(keyR).width(20).height(20); + keyboardDialog.getButtonTable().add(keyT).width(20).height(20); + keyboardDialog.getButtonTable().add(keyY).width(20).height(20); + keyboardDialog.getButtonTable().add(keyU).width(20).height(20); + keyboardDialog.getButtonTable().add(keyI).width(20).height(20); + keyboardDialog.getButtonTable().add(keyO).width(20).height(20); + keyboardDialog.getButtonTable().add(keyP).width(20).height(20); + keyboardDialog.getButtonTable().row(); + keyboardDialog.getButtonTable().add(keyA).width(20).height(20); + keyboardDialog.getButtonTable().add(keyS).width(20).height(20); + keyboardDialog.getButtonTable().add(keyD).width(20).height(20); + keyboardDialog.getButtonTable().add(keyF).width(20).height(20); + keyboardDialog.getButtonTable().add(keyG).width(20).height(20); + keyboardDialog.getButtonTable().add(keyH).width(20).height(20); + keyboardDialog.getButtonTable().add(keyJ).width(20).height(20); + keyboardDialog.getButtonTable().add(keyK).width(20).height(20); + keyboardDialog.getButtonTable().add(keyL).width(20).height(20); + keyboardDialog.getButtonTable().add(keyBackspace).width(20).height(20); + keyboardDialog.getButtonTable().row(); + keyboardDialog.getButtonTable().add(keyShift).width(20).height(20); + keyboardDialog.getButtonTable().add(keyZ).width(20).height(20); + keyboardDialog.getButtonTable().add(keyX).width(20).height(20); + keyboardDialog.getButtonTable().add(keyC).width(20).height(20); + keyboardDialog.getButtonTable().add(keyV).width(20).height(20); + keyboardDialog.getButtonTable().add(keyB).width(20).height(20); + keyboardDialog.getButtonTable().add(keyN).width(20).height(20); + keyboardDialog.getButtonTable().add(keyM).width(20).height(20); + keyboardDialog.getButtonTable().add(keyDot).width(20).height(20); + keyboardDialog.getButtonTable().add(keyComma).width(20).height(20); + keyboardDialog.getButtonTable().row(); + keyboardDialog.getButtonTable().add(keySpace).width(150).height(20).colspan(6); + keyboardDialog.getButtonTable().add(keyOK).width(100).height(20).colspan(4); + keyboardDialog.setKeepWithinStage(true); + keyboardDialog.setResizable(false); + //keyboardDialog.getColor().a = 0f; + } + private String transformKey(String c) { + return lowercaseKey ? c.toLowerCase() : c.toUpperCase(); + } + public void toggleShiftOrBackspace(boolean shift) { + if (shift) + performTouch(keyShift); + else + performTouch(keyBackspace); + } + public void hideOnScreenKeyboard() { + kbVisible = false; + keyboardDialog.hide(); + selectedActor = lastInputField; + } + private void shiftKey() { + lowercaseKey = !lowercaseKey; + keyShift.getLabel().setColor(lowercaseKey ? Color.WHITE : Color.CYAN); + keyA.getLabel().setText(lowercaseKey ? "a" : "A"); + keyB.getLabel().setText(lowercaseKey ? "b" : "B"); + keyC.getLabel().setText(lowercaseKey ? "c" : "C"); + keyD.getLabel().setText(lowercaseKey ? "d" : "D"); + keyE.getLabel().setText(lowercaseKey ? "e" : "E"); + keyF.getLabel().setText(lowercaseKey ? "f" : "F"); + keyG.getLabel().setText(lowercaseKey ? "g" : "G"); + keyH.getLabel().setText(lowercaseKey ? "h" : "H"); + keyI.getLabel().setText(lowercaseKey ? "i" : "I"); + keyJ.getLabel().setText(lowercaseKey ? "j" : "J"); + keyK.getLabel().setText(lowercaseKey ? "k" : "K"); + keyL.getLabel().setText(lowercaseKey ? "l" : "L"); + keyM.getLabel().setText(lowercaseKey ? "m" : "M"); + keyN.getLabel().setText(lowercaseKey ? "n" : "N"); + keyO.getLabel().setText(lowercaseKey ? "o" : "O"); + keyP.getLabel().setText(lowercaseKey ? "p" : "P"); + keyQ.getLabel().setText(lowercaseKey ? "q" : "Q"); + keyR.getLabel().setText(lowercaseKey ? "r" : "R"); + keyS.getLabel().setText(lowercaseKey ? "s" : "S"); + keyT.getLabel().setText(lowercaseKey ? "t" : "T"); + keyU.getLabel().setText(lowercaseKey ? "u" : "U"); + keyV.getLabel().setText(lowercaseKey ? "v" : "V"); + keyW.getLabel().setText(lowercaseKey ? "w" : "W"); + keyX.getLabel().setText(lowercaseKey ? "x" : "X"); + keyY.getLabel().setText(lowercaseKey ? "y" : "Y"); + keyZ.getLabel().setText(lowercaseKey ? "z" : "Z"); + } + public void setSelectedKey(int keyCode) { + switch(keyCode) { + case Input.Keys.DPAD_DOWN: + if (selectedKey == null) + selectActor(key1, false); + else if (selectedKey == key1) + selectActor(keyQ, false); + else if (selectedKey == keyQ) + selectActor(keyA, false); + else if (selectedKey == keyA) + selectActor(keyShift, false); + else if (selectedKey == keyShift) + selectActor(keySpace, false); + else if (selectedKey == key2) + selectActor(keyW, false); + else if (selectedKey == keyW) + selectActor(keyS, false); + else if (selectedKey == keyS) + selectActor(keyZ, false); + else if (selectedKey == keyZ) + selectActor(keySpace, false); + else if (selectedKey == key3) + selectActor(keyE, false); + else if (selectedKey == keyE) + selectActor(keyD, false); + else if (selectedKey == keyD) + selectActor(keyX, false); + else if (selectedKey == keyX) + selectActor(keySpace, false); + else if (selectedKey == key4) + selectActor(keyR, false); + else if (selectedKey == keyR) + selectActor(keyF, false); + else if (selectedKey == keyF) + selectActor(keyC, false); + else if (selectedKey == keyC) + selectActor(keySpace, false); + else if (selectedKey == key5) + selectActor(keyT, false); + else if (selectedKey == keyT) + selectActor(keyG, false); + else if (selectedKey == keyG) + selectActor(keyV, false); + else if (selectedKey == keyV) + selectActor(keySpace, false); + else if (selectedKey == key6) + selectActor(keyY, false); + else if (selectedKey == keyY) + selectActor(keyH, false); + else if (selectedKey == keyH) + selectActor(keyB, false); + else if (selectedKey == keyB) + selectActor(keySpace, false); + else if (selectedKey == key7) + selectActor(keyU, false); + else if (selectedKey == keyU) + selectActor(keyJ, false); + else if (selectedKey == keyJ) + selectActor(keyN, false); + else if (selectedKey == keyN) + selectActor(keyOK, false); + else if (selectedKey == key8) + selectActor(keyI, false); + else if (selectedKey == keyI) + selectActor(keyK, false); + else if (selectedKey == keyK) + selectActor(keyM, false); + else if (selectedKey == keyM) + selectActor(keyOK, false); + else if (selectedKey == key9) + selectActor(keyO, false); + else if (selectedKey == keyO) + selectActor(keyL, false); + else if (selectedKey == keyL) + selectActor(keyDot, false); + else if (selectedKey == keyDot) + selectActor(keyOK, false); + else if (selectedKey == key0) + selectActor(keyP, false); + else if (selectedKey == keyP) + selectActor(keyBackspace, false); + else if (selectedKey == keyBackspace) + selectActor(keyComma, false); + else if (selectedKey == keyComma) + selectActor(keyOK, false); + break; + case Input.Keys.DPAD_UP: + if (selectedKey == null) + selectActor(key1, false); + else if (selectedKey == keySpace || selectedKey == keyOK) + selectActor(lastSelectedKey, false); + else if (selectedKey == keyShift) + selectActor(keyA, false); + else if (selectedKey == keyA) + selectActor(keyQ, false); + else if (selectedKey == keyQ) + selectActor(key1, false); + else if (selectedKey == keyZ) + selectActor(keyS, false); + else if (selectedKey == keyS) + selectActor(keyW, false); + else if (selectedKey == keyW) + selectActor(key2, false); + else if (selectedKey == keyX) + selectActor(keyD, false); + else if (selectedKey == keyD) + selectActor(keyE, false); + else if (selectedKey == keyE) + selectActor(key3, false); + else if (selectedKey == keyC) + selectActor(keyF, false); + else if (selectedKey == keyF) + selectActor(keyR, false); + else if (selectedKey == keyR) + selectActor(key4, false); + else if (selectedKey == keyV) + selectActor(keyG, false); + else if (selectedKey == keyG) + selectActor(keyT, false); + else if (selectedKey == keyT) + selectActor(key5, false); + else if (selectedKey == keyB) + selectActor(keyH, false); + else if (selectedKey == keyH) + selectActor(keyY, false); + else if (selectedKey == keyY) + selectActor(key6, false); + else if (selectedKey == keyN) + selectActor(keyJ, false); + else if (selectedKey == keyJ) + selectActor(keyU, false); + else if (selectedKey == keyU) + selectActor(key7, false); + else if (selectedKey == keyM) + selectActor(keyK, false); + else if (selectedKey == keyK) + selectActor(keyI, false); + else if (selectedKey == keyI) + selectActor(key8, false); + else if (selectedKey == keyDot) + selectActor(keyL, false); + else if (selectedKey == keyL) + selectActor(keyO, false); + else if (selectedKey == keyO) + selectActor(key9, false); + else if (selectedKey == keyComma) + selectActor(keyBackspace, false); + else if (selectedKey == keyBackspace) + selectActor(keyP, false); + else if (selectedKey == keyP) + selectActor(key0, false); + break; + case Input.Keys.DPAD_LEFT: + if (selectedKey == null) + selectActor(key1, false); + else if (selectedKey == keyOK) + selectActor(keySpace, false); + else if (selectedKey == keyComma) + selectActor(keyDot, false); + else if (selectedKey == keyDot) + selectActor(keyM, false); + else if (selectedKey == keyM) + selectActor(keyN, false); + else if (selectedKey == keyN) + selectActor(keyB, false); + else if (selectedKey == keyB) + selectActor(keyV, false); + else if (selectedKey == keyV) + selectActor(keyC, false); + else if (selectedKey == keyC) + selectActor(keyX, false); + else if (selectedKey == keyX) + selectActor(keyZ, false); + else if (selectedKey == keyZ) + selectActor(keyShift, false); + else if (selectedKey == keyBackspace) + selectActor(keyL, false); + else if (selectedKey == keyL) + selectActor(keyK, false); + else if (selectedKey == keyK) + selectActor(keyJ, false); + else if (selectedKey == keyJ) + selectActor(keyH, false); + else if (selectedKey == keyH) + selectActor(keyG, false); + else if (selectedKey == keyG) + selectActor(keyF, false); + else if (selectedKey == keyF) + selectActor(keyD, false); + else if (selectedKey == keyD) + selectActor(keyS, false); + else if (selectedKey == keyS) + selectActor(keyA, false); + else if (selectedKey == keyP) + selectActor(keyO, false); + else if (selectedKey == keyO) + selectActor(keyI, false); + else if (selectedKey == keyI) + selectActor(keyU, false); + else if (selectedKey == keyU) + selectActor(keyY, false); + else if (selectedKey == keyY) + selectActor(keyT, false); + else if (selectedKey == keyT) + selectActor(keyR, false); + else if (selectedKey == keyR) + selectActor(keyE, false); + else if (selectedKey == keyE) + selectActor(keyW, false); + else if (selectedKey == keyW) + selectActor(keyQ, false); + else if (selectedKey == key0) + selectActor(key9, false); + else if (selectedKey == key9) + selectActor(key8, false); + else if (selectedKey == key8) + selectActor(key7, false); + else if (selectedKey == key7) + selectActor(key6, false); + else if (selectedKey == key6) + selectActor(key5, false); + else if (selectedKey == key5) + selectActor(key4, false); + else if (selectedKey == key4) + selectActor(key3, false); + else if (selectedKey == key3) + selectActor(key2, false); + else if (selectedKey == key2) + selectActor(key1, false); + break; + case Input.Keys.DPAD_RIGHT: + if (selectedKey == null) + selectActor(key1, false); + else if (selectedKey == key1) + selectActor(key2, false); + else if (selectedKey == key2) + selectActor(key3, false); + else if (selectedKey == key3) + selectActor(key4, false); + else if (selectedKey == key4) + selectActor(key5, false); + else if (selectedKey == key5) + selectActor(key6, false); + else if (selectedKey == key6) + selectActor(key7, false); + else if (selectedKey == key7) + selectActor(key8, false); + else if (selectedKey == key8) + selectActor(key9, false); + else if (selectedKey == key9) + selectActor(key0, false); + else if (selectedKey == keyQ) + selectActor(keyW, false); + else if (selectedKey == keyW) + selectActor(keyE, false); + else if (selectedKey == keyE) + selectActor(keyR, false); + else if (selectedKey == keyR) + selectActor(keyT, false); + else if (selectedKey == keyT) + selectActor(keyY, false); + else if (selectedKey == keyY) + selectActor(keyU, false); + else if (selectedKey == keyU) + selectActor(keyI, false); + else if (selectedKey == keyI) + selectActor(keyO, false); + else if (selectedKey == keyO) + selectActor(keyP, false); + else if (selectedKey == keyA) + selectActor(keyS, false); + else if (selectedKey == keyS) + selectActor(keyD, false); + else if (selectedKey == keyD) + selectActor(keyF, false); + else if (selectedKey == keyF) + selectActor(keyG, false); + else if (selectedKey == keyG) + selectActor(keyH, false); + else if (selectedKey == keyH) + selectActor(keyJ, false); + else if (selectedKey == keyJ) + selectActor(keyK, false); + else if (selectedKey == keyK) + selectActor(keyL, false); + else if (selectedKey == keyL) + selectActor(keyBackspace, false); + else if (selectedKey == keyShift) + selectActor(keyZ, false); + else if (selectedKey == keyZ) + selectActor(keyX, false); + else if (selectedKey == keyX) + selectActor(keyC, false); + else if (selectedKey == keyC) + selectActor(keyV, false); + else if (selectedKey == keyV) + selectActor(keyB, false); + else if (selectedKey == keyB) + selectActor(keyN, false); + else if (selectedKey == keyN) + selectActor(keyM, false); + else if (selectedKey == keyM) + selectActor(keyDot, false); + else if (selectedKey == keyDot) + selectActor(keyComma, false); + else if (selectedKey == keySpace) + selectActor(keyOK, false); + break; + default: + break; + } + } + private String removeLastChar(String s) { + return (s == null || s.length() == 0) + ? "" + : (s.substring(0, s.length() - 1)); + } + private void setKeyboardDialogText() { + if (lastInputField == null) + return; + if (lastInputField instanceof TextField) { + if (!kbLabel.getText().isEmpty()) { + ((TextField) lastInputField).setText(String.valueOf(kbLabel.getText())); + kbLabel.setText(""); + } + } + kbVisible = false; + keyboardDialog.hide(); + selectActor(lastInputField, false); + } + public void showOnScreenKeyboard(String text) { + kbVisible = true; + if (lowercaseKey) + shiftKey(); + kbLabel.setText(text); + keyboardDialog.show(stage); + selectActor(key1, false); + } + public void keyOK() { + selectActor(keyOK, false); + } + + public void clearActorObjects() { + actorObjectMap.clear(); + selectedActor = null; + } + public void addActorObject(Actor actor) { + int index = actorObjectMap.size; + actorObjectMap.put(index, actor); + } + public void unselectActors() { + if (actorObjectMap.isEmpty()) + return; + for (Actor actor : actorObjectMap.values()) { + if (actor != null) { + if (actor instanceof TextButton) + ((TextButton) actor).fire(eventExit); + else if (actor instanceof Selector) + ((Selector) actor).getLabel().fire(eventExit); + else if (actor instanceof TextField) { + if (stage.getKeyboardFocus() == actor) + stage.setKeyboardFocus(null); + } else if (actor instanceof ImageButton) { + ((ImageButton) actor).setChecked(false); + } else { + actor.fire(eventExit); } - }; - ui = new UIActor(Config.instance().getFile(uiFile)); - screenImage = ui.findActor("lastScreen"); - stage.addActor(ui); + } + } + } + public void selectNextActor(boolean press) { + if (actorObjectMap.isEmpty()) + return; + if (selectedActor == null) { + selectActor(actorObjectMap.get(0), press); + } else { + selectActor(actorObjectMap.get(selectedActorIndex+1), press); + } + } + public void selectPreviousActor(boolean press) { + if (actorObjectMap.isEmpty()) + return; + if (selectedActor == null) { + selectActor(actorObjectMap.get(0), press); + } else { + selectActor(actorObjectMap.get(selectedActorIndex-1), press); + } + } + public void selectActor(Actor actor, boolean press) { + if (actor == null) + return; + if (kbVisible) { + if (selectedKey != null) { + selectedKey.fire(eventExit); + if (selectedKey instanceof TextButton) + if (!(((TextButton) selectedKey) == keyOK || ((TextButton) selectedKey) == keySpace)) + lastSelectedKey = selectedKey; + } + selectedKey = actor; + selectedKey.fire(eventEnter); + if (press) + performTouch(selectedKey); + } else { + unselectActors(); + if (actorObjectMap.isEmpty()) + return; + Integer key = actorObjectMap.findKey(actor, true); + if (key == null) + return; + Actor a = actorObjectMap.get(key); + if (a != null) { + if (a instanceof TextButton) + ((TextButton) a).fire(eventEnter); + else if (a instanceof Selector) + ((Selector) a).getLabel().fire(eventEnter); + else if (a instanceof TextField) { + stage.setKeyboardFocus(a); + } else if (a instanceof ImageButton) { + ((ImageButton) a).setChecked(true); + } + selectedActor = a; + selectedActorIndex = key; + if (press) + performTouch(a); + } + } + } + public void selectCurrent() { + Actor current = actorObjectMap.get(selectedActorIndex); + if (current == null) + current = actorObjectMap.get(0); + selectActor(current, false); + } + public void updateHovered() { + for (Actor a : actorObjectMap.values()) { + if (a != null && Controls.actorContainsVector(a, pointer)) { + selectActor(a, false); + break; + } + } } Image screenImage; TextureRegion backgroundTexture; - TextureRegion market, tavern; @Override public void enter() { - if (screenImage != null) { - if (backgroundTexture != null) - backgroundTexture.getTexture().dispose(); - - final Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - final Pixmap potPixmap = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Pixmap.Format.RGBA8888); - potPixmap.setBlending(Pixmap.Blending.SourceOver); - potPixmap.drawPixmap(pixmap, 0, 0); - potPixmap.setColor(0, 0, 0, 0.75f); - potPixmap.fillRectangle(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - backgroundTexture = new TextureRegion(new Texture(potPixmap), 0, Gdx.graphics.getHeight(), Gdx.graphics.getWidth(), -Gdx.graphics.getHeight()); - screenImage.setDrawable(new TextureRegionDrawable(backgroundTexture)); - pixmap.dispose(); - potPixmap.dispose(); + //create from lastPreview from header... + try { + backgroundTexture = new TextureRegion(Forge.lastPreview); + backgroundTexture.flip(false, true); + screenImage.setDrawable(new TextureRegionDrawable(backgroundTexture)); + } catch (Exception e) { + e.printStackTrace(); + } } Gdx.input.setInputProcessor(stage); //Start taking input from the ui super.enter(); } - + @Override + public boolean leave() { + clearActorObjects(); + selectedActor = null; + return super.leave(); + } } diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java index d5d25df4268..ae7a5eb5312 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java @@ -2,6 +2,9 @@ package forge.adventure.stage; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.ControllerListener; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; @@ -16,11 +19,14 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Scaling; +import com.badlogic.gdx.utils.Timer; import com.badlogic.gdx.utils.viewport.ScalingViewport; import forge.Forge; import forge.adventure.player.AdventurePlayer; +import forge.adventure.scene.HudScene; import forge.adventure.scene.Scene; import forge.adventure.scene.SceneType; +import forge.adventure.scene.UIScene; import forge.adventure.util.Config; import forge.adventure.util.Controls; import forge.adventure.util.Current; @@ -33,7 +39,7 @@ import forge.gui.GuiBase; /** * Stage to handle everything rendered in the HUD */ -public class GameHUD extends Stage { +public class GameHUD extends Stage implements ControllerListener { static public GameHUD instance; private final GameStage gameStage; @@ -50,6 +56,7 @@ public class GameHUD extends Stage { float TOUCHPAD_SCALE = 70f, referenceX; boolean isHiding = false, isShowing = false; float opacity = 1f; + private InputEvent eventTouchDown, eventTouchUp; private GameHUD(GameStage gameStage) { super(new ScalingViewport(Scaling.stretch, Scene.getIntendedWidth(), Scene.getIntendedHeight()), gameStage.getBatch()); @@ -110,19 +117,9 @@ public class GameHUD extends Stage { ui.onButtonPress("deck", () -> openDeck()); lifePoints = ui.findActor("lifePoints"); lifePoints.setText("20/20"); - AdventurePlayer.current().onLifeChange(new Runnable() { - @Override - public void run() { - lifePoints.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife()); - } - }); + AdventurePlayer.current().onLifeChange(() -> lifePoints.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife())); money = ui.findActor("money"); - WorldSave.getCurrentSave().getPlayer().onGoldChange(new Runnable() { - @Override - public void run() { - money.setText(String.valueOf(AdventurePlayer.current().getGold())); - } - }) ; + WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText(String.valueOf(AdventurePlayer.current().getGold()))) ; addActor(ui); addActor(miniMapPlayer); console=new Console(); @@ -134,12 +131,14 @@ public class GameHUD extends Stage { avatarborder.addListener(new ConsoleToggleListener()); gamehud.addListener(new ConsoleToggleListener()); } - WorldSave.getCurrentSave().onLoad(new Runnable() { - @Override - public void run() { - GameHUD.this.enter(); - } - }); + WorldSave.getCurrentSave().onLoad(() -> GameHUD.this.enter()); + eventTouchDown = new InputEvent(); + eventTouchDown.setPointer(-1); + eventTouchDown.setType(InputEvent.Type.touchDown); + eventTouchUp = new InputEvent(); + eventTouchUp.setPointer(-1); + eventTouchUp.setType(InputEvent.Type.touchUp); + Controllers.addListener(this); } private void statistic() { @@ -327,8 +326,31 @@ public class GameHUD extends Stage { showButtons(); } } + if (keycode == Input.Keys.BUTTON_B) { + performTouch(statsActor); + } + if (keycode == Input.Keys.BUTTON_Y) { + performTouch(inventoryActor); + } + if (keycode == Input.Keys.BUTTON_X) { + performTouch(deckActor); + } + if (keycode == Input.Keys.BUTTON_A) { + performTouch(menuActor); + } return super.keyDown(keycode); } + public void performTouch(Actor actor) { + if (actor == null) + return; + actor.fire(eventTouchDown); + Timer.schedule(new Timer.Task() { + @Override + public void run() { + actor.fire(eventTouchUp); + } + }, 0.10f); + } public void hideButtons() { if (isShowing) return; @@ -355,6 +377,123 @@ public class GameHUD extends Stage { deckActor.addAction(Actions.sequence(Actions.delay(0.25f), Actions.parallel(Actions.show(), Actions.alpha(opacity,0.1f), Actions.moveTo(referenceX, deckActor.getY(), 0.25f)))); FThreads.delayInEDT(300, () -> isShowing = false); } + + @Override + public void connected(Controller controller) { + + } + + @Override + public void disconnected(Controller controller) { + + } + + @Override + public boolean buttonDown(Controller controller, int buttonIndex) { + if (Forge.getCurrentScene() instanceof HudScene) { + if (controller.getMapping().buttonA == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.BUTTON_A); + if (controller.getMapping().buttonB == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.BUTTON_B); + if (controller.getMapping().buttonX == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.BUTTON_X); + if (controller.getMapping().buttonY == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.BUTTON_Y); + if (controller.getMapping().buttonDpadUp == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_UP); + if (controller.getMapping().buttonDpadRight == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_RIGHT); + if (controller.getMapping().buttonDpadDown == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_DOWN); + if (controller.getMapping().buttonDpadLeft == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_LEFT); + } else if (Forge.getCurrentScene() instanceof UIScene) { + if (controller.getMapping().buttonDpadUp == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.DPAD_UP); + if (controller.getMapping().buttonDpadRight == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.DPAD_RIGHT); + if (controller.getMapping().buttonDpadDown == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.DPAD_DOWN); + if (controller.getMapping().buttonDpadLeft == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.DPAD_LEFT); + if (controller.getMapping().buttonA == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_A); + if (controller.getMapping().buttonB == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_B); + if (controller.getMapping().buttonX == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_X); + if (controller.getMapping().buttonY == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_Y); + if (controller.getMapping().buttonR1 == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_R1); + if (controller.getMapping().buttonL1 == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_L1); + if (controller.getMapping().buttonR2 == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_R2); + if (controller.getMapping().buttonL2 == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_L2); + if (controller.getMapping().buttonBack == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_SELECT); + if (controller.getMapping().buttonStart == buttonIndex) + return ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_START); + } + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonIndex) { + if (Forge.getCurrentScene() instanceof HudScene) { + if (controller.getMapping().buttonA == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.BUTTON_A); + if (controller.getMapping().buttonB == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.BUTTON_B); + if (controller.getMapping().buttonX == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.BUTTON_X); + if (controller.getMapping().buttonY == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.BUTTON_Y); + if (controller.getMapping().buttonDpadUp == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_UP); + if (controller.getMapping().buttonDpadRight == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_RIGHT); + if (controller.getMapping().buttonDpadDown == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_DOWN); + if (controller.getMapping().buttonDpadLeft == buttonIndex) + return ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_LEFT); + } + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisIndex, float value) { + if (Forge.hasGamepad()) { + if (Forge.getCurrentScene() instanceof HudScene) { + if (controller.getAxis(controller.getMapping().axisLeftX) > 0.5f) { + ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_RIGHT); + } else if (controller.getAxis(controller.getMapping().axisLeftX) < -0.5f) { + ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_LEFT); + } else { + ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_LEFT); + ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_RIGHT); + } + if (controller.getAxis(controller.getMapping().axisLeftY) > 0.5f) { + ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_DOWN); + } else if (controller.getAxis(controller.getMapping().axisLeftY) < -0.5f) { + ((HudScene) Forge.getCurrentScene()).keyDown(Input.Keys.DPAD_UP); + } else { + ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_UP); + ((HudScene) Forge.getCurrentScene()).keyUp(Input.Keys.DPAD_DOWN); + } + } else if (Forge.getCurrentScene() instanceof UIScene) { + if (controller.getAxis(4) == 1f) //L2 + ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_L2); + if (controller.getAxis(5) == 1f) //R2 + ((UIScene) Forge.getCurrentScene()).keyPressed(Input.Keys.BUTTON_R2); + } + } + + return true; + } + class ConsoleToggleListener extends ActorGestureListener { public ConsoleToggleListener() { getGestureDetector().setLongPressSeconds(0.6f); diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameStage.java b/forge-gui-mobile/src/forge/adventure/stage/GameStage.java index daa2b3370f6..c1a8fbc719d 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameStage.java @@ -55,15 +55,12 @@ public abstract class GameStage extends Stage { public GameStage() { super(new ScalingViewport(Scaling.stretch, Scene.getIntendedWidth(), Scene.getIntendedHeight(), new OrthographicCamera())); - WorldSave.getCurrentSave().onLoad(new Runnable() { - @Override - public void run() { - if (player == null) - return; - foregroundSprites.removeActor(player); - player = null; - GameStage.this.GetPlayer(); - } + WorldSave.getCurrentSave().onLoad(() -> { + if (player == null) + return; + foregroundSprites.removeActor(player); + player = null; + GameStage.this.GetPlayer(); }); camera = (OrthographicCamera) getCamera(); @@ -154,19 +151,19 @@ public abstract class GameStage extends Stage { @Override public boolean keyDown(int keycode) { super.keyDown(keycode); - if (keycode == Input.Keys.LEFT || keycode == Input.Keys.A)//todo config + if (keycode == Input.Keys.LEFT || keycode == Input.Keys.A || keycode == Input.Keys.DPAD_LEFT)//todo config { player.getMovementDirection().x = -1; } - if (keycode == Input.Keys.RIGHT || keycode == Input.Keys.D)//todo config + if (keycode == Input.Keys.RIGHT || keycode == Input.Keys.D || keycode == Input.Keys.DPAD_RIGHT)//todo config { player.getMovementDirection().x = +1; } - if (keycode == Input.Keys.UP || keycode == Input.Keys.W)//todo config + if (keycode == Input.Keys.UP || keycode == Input.Keys.W || keycode == Input.Keys.DPAD_UP)//todo config { player.getMovementDirection().y = +1; } - if (keycode == Input.Keys.DOWN || keycode == Input.Keys.S)//todo config + if (keycode == Input.Keys.DOWN || keycode == Input.Keys.S || keycode == Input.Keys.DPAD_DOWN)//todo config { player.getMovementDirection().y = -1; } diff --git a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java index 43e939355c1..9c53058c9d5 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java @@ -2,6 +2,8 @@ package forge.adventure.stage; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; @@ -15,7 +17,9 @@ import com.badlogic.gdx.maps.tiled.TiledMapTileLayer; import com.badlogic.gdx.maps.tiled.objects.TiledMapTileMapObject; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +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.Stage; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.ui.Dialog; @@ -24,7 +28,9 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; +import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.Scaling; +import com.badlogic.gdx.utils.Timer; import com.github.tommyettinger.textra.TypingAdapter; import com.github.tommyettinger.textra.TypingLabel; import forge.Forge; @@ -81,6 +87,10 @@ public class MapStage extends GameStage { //These maps are defined as embedded properties within the Tiled maps. private EffectData effect; //"Dungeon Effect": Character Effect applied to all adversaries within the map. private boolean preventEscape = false; //Prevents player from escaping the dungeon by any means that aren't an exit. + private ObjectMap dialogButtonMap; + private int selected = 0; + public InputEvent eventEnter, eventExit, eventTouchDown, eventTouchUp; + TextButton selectedKey; public boolean getDialogOnlyInput() { @@ -124,6 +134,18 @@ public class MapStage extends GameStage { public void resLoaded() { dialog = Controls.newDialog(""); + eventTouchDown = new InputEvent(); + eventTouchDown.setPointer(-1); + eventTouchDown.setType(InputEvent.Type.touchDown); + eventTouchUp = new InputEvent(); + eventTouchUp.setPointer(-1); + eventTouchUp.setType(InputEvent.Type.touchUp); + eventEnter = new InputEvent(); + eventEnter.setPointer(-1); + eventEnter.setType(InputEvent.Type.enter); + eventExit = new InputEvent(); + eventExit.setPointer(-1); + eventExit.setType(InputEvent.Type.exit); } public void addMapActor(MapObject obj, MapActor newActor) { @@ -643,6 +665,8 @@ public class MapStage extends GameStage { break; } else if (actor instanceof RewardSprite) { Gdx.input.vibrate(50); + if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) + Controllers.getCurrent().startVibration(100,1); startPause(0.1f, () -> { //Switch to item pickup scene. RewardSprite RS = (RewardSprite) actor; ((RewardScene) SceneType.RewardScene.instance).loadRewards(RS.getRewards(), RewardScene.Type.Loot, null); @@ -664,6 +688,9 @@ public class MapStage extends GameStage { mob.setAnimation(CharacterSprite.AnimationTypes.Attack); SoundSystem.instance.play(SoundEffectType.Block, false); Gdx.input.vibrate(50); + int duration = mob.getData().boss ? 400 : 200; + if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) + Controllers.getCurrent().startVibration(duration,1); startPause(0.8f, () -> { Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); @@ -691,16 +718,30 @@ public class MapStage extends GameStage { public boolean isInMap() { return isInMap; } + public boolean isDialogOnlyInput() { + return dialogOnlyInput; + } public void showDialog() { + if (dialogButtonMap == null) + dialogButtonMap = new ObjectMap<>(); + else + dialogButtonMap.clear(); + for (int i = 0; i < dialog.getButtonTable().getCells().size; i++) { + dialogButtonMap.put(i, (TextButton) dialog.getButtonTable().getCells().get(i).getActor()); + } dialog.show(dialogStage, Actions.show()); dialog.setPosition((dialogStage.getWidth() - dialog.getWidth()) / 2, (dialogStage.getHeight() - dialog.getHeight()) / 2); dialogOnlyInput = true; + if (Forge.hasGamepad()) + selectDialogButton(dialogButtonMap.get(0), false); } public void hideDialog() { dialog.hide(Actions.sequence(Actions.sizeTo(dialog.getOriginX(), dialog.getOriginY(), 0.3f), Actions.hide())); dialogOnlyInput = false; + selected = 0; + selectedKey = null; } public void setDialogStage(Stage dialogStage) { @@ -736,4 +777,62 @@ public class MapStage extends GameStage { public void resetQuestFlags() { changes.getMapFlags().clear(); } + + public boolean buttonPress(int keycode) { + if (dialogOnlyInput) { + if (keycode == Input.Keys.DPAD_UP) { + selectPreviousDialogButton(); + } + if (keycode == Input.Keys.DPAD_DOWN) { + selectNextDialogButton(); + } + if (keycode == Input.Keys.BUTTON_A) { + selectDialogButton(selectedKey, true); + } + } + return true; + } + + private void selectDialogButton(TextButton dialogButton, boolean press) { + if (dialogOnlyInput) { + if (selectedKey != null) + selectedKey.fire(eventExit); + if (dialogButton != null && dialogButton.isVisible()) { + dialogButton.fire(eventEnter); + selectedKey = dialogButton; + selected = getButtonIndexKey(dialogButton); + if (press) + performTouch(dialogButton); + } + } + } + public void performTouch(Actor actor) { + if (actor == null) + return; + actor.fire(eventTouchDown); + Timer.schedule(new Timer.Task() { + @Override + public void run() { + actor.fire(eventTouchUp); + } + }, 0.10f); + } + private int getButtonIndexKey(TextButton dialogbutton) { + if (dialogButtonMap.isEmpty()) + return 0; + Integer key = dialogButtonMap.findKey(dialogbutton, true); + if (key == null) + return 0; + return key; + } + private void selectNextDialogButton() { + if (dialogButtonMap.size < 2) + return; + selectDialogButton(dialogButtonMap.get(selected+1), false); + } + private void selectPreviousDialogButton() { + if (dialogButtonMap.size < 2) + return; + selectDialogButton(dialogButtonMap.get(selected-1), false); + } } diff --git a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java index 7682e4a3df6..0b34325fcc3 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java @@ -1,6 +1,7 @@ package forge.adventure.stage; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; @@ -109,6 +110,9 @@ public class WorldStage extends GameStage implements SaveFileContent { mob.setAnimation(CharacterSprite.AnimationTypes.Attack); SoundSystem.instance.play(SoundEffectType.Block, false); Gdx.input.vibrate(50); + int duration = mob.getData().boss ? 400 : 200; + if (Controllers.getCurrent() != null && Controllers.getCurrent().canVibrate()) + Controllers.getCurrent().startVibration(duration,1); startPause(0.8f, () -> { Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); diff --git a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java index 3871c6bef05..4d7be35c604 100644 --- a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java +++ b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java @@ -68,7 +68,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb boolean flipOnClick; private boolean hover; boolean loaded = true; - boolean alternate = false; + boolean alternate = false, shown = false; public static int renderedCount = 0; //Counter for cards that require rendering a preview. static final ImageFetcher fetcher = GuiBase.getInterface().getImageFetcher(); @@ -118,7 +118,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb } toolTipImage.remove(); toolTipImage = new Image(processDrawable(image)); - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { if (holdTooltip.tooltip_image.getDrawable() instanceof TextureRegionDrawable) { ((TextureRegionDrawable) holdTooltip.tooltip_image.getDrawable()).getRegion().getTexture().dispose(); } @@ -262,14 +262,22 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb break; } } - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { if (flipOnClick) flip(); } + @Override + public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { + hover = true; + } + @Override + public void exit(InputEvent event, float x, float y, int pointer, Actor fromActor) { + hover = false; + } @Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { hover = true; @@ -312,7 +320,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb return; Texture alt = ImageCache.getImage(reward.getCard().getImageKey(true), false); PaperCard altCard = ImageUtil.getPaperCardFromImageKey(reward.getCard().getCardAltImageKey()); - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { if (alternate) { if (alt != null) { holdTooltip.tooltip_actor.clear(); @@ -401,7 +409,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb image.setFilter(Texture.TextureFilter.MipMapLinearLinear, Texture.TextureFilter.Linear); if (toolTipImage == null) toolTipImage = new Image(processDrawable(image)); - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { if (holdTooltip == null) holdTooltip = new HoldTooltip(toolTipImage); if (frontSideUp()) @@ -414,6 +422,16 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb addListener(tooltip); } } + public void showTooltip() { + if (holdTooltip != null) { + holdTooltip.show(); + } + } + public void hideTooltip() { + if (holdTooltip != null) { + holdTooltip.hide(); + } + } private Texture renderPlaceholder(Graphics g, PaperCard card){ //Use CardImageRenderer to output a Texture. if(renderedCount++ == 0) { @@ -473,7 +491,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb toolTipImage = new Image(processDrawable(generatedTooltip)); if (frontSideUp()) { - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { if (holdTooltip == null) holdTooltip = new HoldTooltip(toolTipImage); addListener(holdTooltip); @@ -531,7 +549,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb else flipProcess = 1; - if (GuiBase.isAndroid()) { + if (GuiBase.isAndroid()||Forge.hasGamepad()) { if (holdTooltip != null && frontSideUp() && !getListeners().contains(holdTooltip, true)) { addListener(holdTooltip); } @@ -737,5 +755,16 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb } super.tap(event, x, y, count, button); } + public void show() { + tooltip_actor.setX(Scene.getIntendedWidth() / 2 - tooltip_actor.getWidth() / 2); + tooltip_actor.setY(Scene.getIntendedHeight() / 2 - tooltip_actor.getHeight() / 2); + getStage().addActor(tooltip_actor); + shown = true; + } + public void hide() { + tooltip_actor.remove(); + switchButton.remove(); + shown = false; + } } } diff --git a/forge-gui-mobile/src/forge/adventure/util/Selector.java b/forge-gui-mobile/src/forge/adventure/util/Selector.java index e359ff2c8fe..c396951d01a 100644 --- a/forge-gui-mobile/src/forge/adventure/util/Selector.java +++ b/forge-gui-mobile/src/forge/adventure/util/Selector.java @@ -91,6 +91,15 @@ public class Selector extends Group { public String getText() { return textList.get(currentIndex); } + public TextButton getLabel() { + return label; + } + public ImageButton getLeftArrow() { + return leftArrow; + } + public ImageButton getRightArrow() { + return rightArrow; + } public Array getTextList() { return textList; diff --git a/forge-gui-mobile/src/forge/adventure/world/WorldSaveHeader.java b/forge-gui-mobile/src/forge/adventure/world/WorldSaveHeader.java index dfcbb80a202..be6ef762410 100644 --- a/forge-gui-mobile/src/forge/adventure/world/WorldSaveHeader.java +++ b/forge-gui-mobile/src/forge/adventure/world/WorldSaveHeader.java @@ -2,10 +2,12 @@ package forge.adventure.world; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.utils.Disposable; +import forge.util.BlurUtils; import forge.Forge; import forge.Graphics; import forge.adventure.scene.Scene; @@ -59,11 +61,16 @@ public class WorldSaveHeader implements java.io.Serializable, Disposable { g.end(); g.endClip(); Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + if (Forge.lastPreview != null) + Forge.lastPreview.dispose(); + Pixmap blurred = BlurUtils.blur(pixmap, 4, 2, false, true); + Forge.lastPreview = new Texture(blurred); Pixmap scaled = new Pixmap(WorldSaveHeader.previewImageWidth, (int) (WorldSaveHeader.previewImageWidth / (Scene.getIntendedWidth() / (float) Scene.getIntendedHeight())), Pixmap.Format.RGBA8888); scaled.drawPixmap(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(), 0, 0, scaled.getWidth(), scaled.getHeight()); pixmap.dispose(); + blurred.dispose(); if (preview != null) preview.dispose(); preview = scaled; diff --git a/forge-gui-mobile/src/forge/assets/FSkinFont.java b/forge-gui-mobile/src/forge/assets/FSkinFont.java index b7fa468dd58..f37611d6998 100644 --- a/forge-gui-mobile/src/forge/assets/FSkinFont.java +++ b/forge-gui-mobile/src/forge/assets/FSkinFont.java @@ -411,7 +411,7 @@ public class FSkinFont { if (fontFile != null && fontFile.exists()) { FThreads.invokeInEdtNowOrLater(() -> { //font must be initialized on UI thread try { - if (!Forge.getAssets().manager().contains(fontFile.path(), BitmapFont.class)) { + if (!Forge.getAssets().manager().contains(fontFile.path(), BitmapFont.class) && fontFile.toString().endsWith(".fnt")) { Forge.getAssets().manager().load(fontFile.path(), BitmapFont.class); Forge.getAssets().manager().finishLoadingAsset(fontFile.path()); } diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 2100a310b9b..80f1ae7b14d 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map.Entry; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.utils.Align; @@ -78,6 +79,8 @@ public class CardZoom extends FOverlay { } public static void hideZoom() { + if (activateHandler != null) + activateHandler.setSelectedIndex(currentIndex); cardZoom.hide(); } @@ -381,4 +384,30 @@ public class CardZoom extends FOverlay { if(!MatchController.instance.isGamePaused()) MatchController.instance.pauseMatch(); } + + @Override + public boolean keyDown(int keyCode) { + if (Forge.hasGamepad()) { + if (keyCode == Input.Keys.DPAD_LEFT) + fling(300, 0); + else if (keyCode == Input.Keys.DPAD_RIGHT) + fling(-300, 0); + else if (keyCode == Input.Keys.BUTTON_B) + hideZoom(); + else if (keyCode == Input.Keys.BUTTON_A) + fling(0, -300f); + else if (keyCode == Input.Keys.BUTTON_X) { + if (mutateIconBounds != null) { + tap(mutateIconBounds.x, mutateIconBounds.y, 1); + } + if (flipIconBounds != null) { + tap(flipIconBounds.x, flipIconBounds.y, 1); + } + } + else if (keyCode == Input.Keys.BUTTON_Y) + fling(0, 300f); + return true; + } + return super.keyDown(keyCode); + } } diff --git a/forge-gui-mobile/src/forge/itemmanager/ItemManager.java b/forge-gui-mobile/src/forge/itemmanager/ItemManager.java index c026f10d756..119b34d5e64 100644 --- a/forge-gui-mobile/src/forge/itemmanager/ItemManager.java +++ b/forge-gui-mobile/src/forge/itemmanager/ItemManager.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -144,64 +143,40 @@ public abstract class ItemManager extends FContainer im add(currentView.getPnlOptions()); add(currentView.getScroller()); - btnSearch.setCommand(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - FPopupMenu menu = new FPopupMenu() { - @Override - protected void buildMenu() { - addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblAdvancedSearch"), Forge.hdbuttons ? FSkinImage.HDSEARCH : FSkinImage.SEARCH, new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - if (advancedSearchFilter == null) { - advancedSearchFilter = createAdvancedSearchFilter(); - ItemManager.this.add(advancedSearchFilter.getWidget()); - } - advancedSearchFilter.edit(); - } - })); - addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblResetFilters"), Forge.hdbuttons ? FSkinImage.HDDELETE : FSkinImage.DELETE, new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - resetFilters(); - } - })); - } - }; - menu.show(btnSearch, 0, btnSearch.getHeight()); - } - }); - btnView.setCommand(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - FPopupMenu menu = new FPopupMenu() { - @Override - protected void buildMenu() { - for (int i = 0; i < views.size(); i++) { - final int index = i; - ItemView view = views.get(i); - FMenuItem item = new FMenuItem(view.getCaption(), view.getIcon(), new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - setViewIndex(index); - } - }); - if (currentView == view) { - item.setSelected(true); - } - addItem(item); + btnSearch.setCommand(e -> { + FPopupMenu menu = new FPopupMenu() { + @Override + protected void buildMenu() { + addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblAdvancedSearch"), Forge.hdbuttons ? FSkinImage.HDSEARCH : FSkinImage.SEARCH, e1 -> { + if (advancedSearchFilter == null) { + advancedSearchFilter = createAdvancedSearchFilter(); + ItemManager.this.add(advancedSearchFilter.getWidget()); } + advancedSearchFilter.edit(); + })); + addItem(new FMenuItem(Forge.getLocalizer().getMessage("lblResetFilters"), Forge.hdbuttons ? FSkinImage.HDDELETE : FSkinImage.DELETE, e12 -> resetFilters())); + } + }; + menu.show(btnSearch, 0, btnSearch.getHeight()); + }); + btnView.setCommand(e -> { + FPopupMenu menu = new FPopupMenu() { + @Override + protected void buildMenu() { + for (int i = 0; i < views.size(); i++) { + final int index = i; + ItemView view = views.get(i); + FMenuItem item = new FMenuItem(view.getCaption(), view.getIcon(), e13 -> setViewIndex(index)); + if (currentView == view) { + item.setSelected(true); + } + addItem(item); } - }; - menu.show(btnView, 0, btnView.getHeight()); - } - }); - btnAdvancedSearchOptions.setCommand(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - setHideFilters(!hideFilters); - } + } + }; + menu.show(btnView, 0, btnView.getHeight()); }); + btnAdvancedSearchOptions.setCommand(e -> setHideFilters(!hideFilters)); //setup initial filters addDefaultFilters(); @@ -239,12 +214,7 @@ public abstract class ItemManager extends FContainer im cols.add(colOverrides.get(colConfig.getDef())); } } - Collections.sort(cols, new Comparator() { - @Override - public int compare(ItemColumn arg0, ItemColumn arg1) { - return Integer.compare(arg0.getConfig().getIndex(), arg1.getConfig().getIndex()); - } - }); + Collections.sort(cols, (arg0, arg1) -> Integer.compare(arg0.getConfig().getIndex(), arg1.getConfig().getIndex())); sortCols.clear(); if (cbxSortOptions != null) { @@ -287,14 +257,11 @@ public abstract class ItemManager extends FContainer im } if (cbxSortOptions != null) { - cbxSortOptions.setDropDownItemTap(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - model.getCascadeManager().add((ItemColumn)e.getArgs(), false); - model.refreshSort(); - ItemManagerConfig.save(); - updateView(true, null); - } + cbxSortOptions.setDropDownItemTap(e -> { + model.getCascadeManager().add((ItemColumn)e.getArgs(), false); + model.refreshSort(); + ItemManagerConfig.save(); + updateView(true, null); }); } @@ -735,16 +702,13 @@ public abstract class ItemManager extends FContainer im } else { viewUpdating = true; - FThreads.invokeInBackgroundThread(new Runnable() { - @Override - public void run() { - do { - needSecondUpdate = false; - updateView(true, null); - Gdx.graphics.requestRendering(); - } while (needSecondUpdate); - viewUpdating = false; - } + FThreads.invokeInBackgroundThread(() -> { + do { + needSecondUpdate = false; + updateView(true, null); + Gdx.graphics.requestRendering(); + } while (needSecondUpdate); + viewUpdating = false; }); } } @@ -895,12 +859,9 @@ public abstract class ItemManager extends FContainer im contextMenu = new ContextMenu(); } if (delay) { //delay showing menu to prevent it hiding right away - FThreads.delayInEDT(50, new Runnable() { - @Override - public void run() { - contextMenu.show(); - Gdx.graphics.requestRendering(); - } + FThreads.delayInEDT(50, () -> { + contextMenu.show(); + Gdx.graphics.requestRendering(); }); } else { @@ -908,10 +869,28 @@ public abstract class ItemManager extends FContainer im } } } + public void closeMenu() { + if (isContextMenuOpen()) + contextMenu.hide(); + } public boolean isContextMenuOpen() { return contextMenu != null && contextMenu.isVisible(); } + public void selectNextContext() { + if (contextMenu != null) { + contextMenu.setNextSelected(); + } + } + public void selectPreviousContext() { + if (contextMenu != null) { + contextMenu.setPreviousSelected(); + } + } + public void activateSelectedContext() { + if (contextMenu != null) + contextMenu.tapChild(); + } public static abstract class ContextMenuBuilder { public abstract void buildMenu(final FDropDownMenu menu, final T item); diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java index 9af61b8325c..815fd508bec 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ImageView.java @@ -26,7 +26,6 @@ import forge.itemmanager.filters.ItemFilter; import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.toolbox.*; -import forge.toolbox.FEvent.FEventHandler; import forge.util.ImageUtil; import forge.util.TextUtil; import forge.util.Utils; @@ -67,20 +66,17 @@ public class ImageView extends ItemView { private ExpandCollapseButton() { super(new FLabel.ButtonBuilder()); - setCommand(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - if (groupBy == null || model.getItems().isEmpty()) { return; } + setCommand(e -> { + if (groupBy == null || model.getItems().isEmpty()) { return; } - boolean collapsed = !isAllCollapsed; - for (Group group : groups) { - group.isCollapsed = collapsed; - } - - updateIsAllCollapsed(); - clearSelection(); //must clear selection since indices and visible items will be changing - updateLayout(false); + boolean collapsed = !isAllCollapsed; + for (Group group : groups) { + group.isCollapsed = collapsed; } + + updateIsAllCollapsed(); + clearSelection(); //must clear selection since indices and visible items will be changing + updateLayout(false); }); } @@ -139,26 +135,20 @@ public class ImageView extends ItemView { SItemManagerUtil.populateImageViewOptions(itemManager0, cbGroupByOptions, cbPileByOptions); - cbGroupByOptions.setChangedHandler(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - if (cbGroupByOptions.getSelectedIndex() > 0) { - setGroupBy((GroupDef) cbGroupByOptions.getSelectedItem()); - } - else { - setGroupBy(null); - } + cbGroupByOptions.setChangedHandler(e -> { + if (cbGroupByOptions.getSelectedIndex() > 0) { + setGroupBy((GroupDef) cbGroupByOptions.getSelectedItem()); + } + else { + setGroupBy(null); } }); - cbPileByOptions.setChangedHandler(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - if (cbPileByOptions.getSelectedIndex() > 0) { - setPileBy((ColumnDef) cbPileByOptions.getSelectedItem()); - } - else { - setPileBy(null); - } + cbPileByOptions.setChangedHandler(e -> { + if (cbPileByOptions.getSelectedIndex() > 0) { + setPileBy((ColumnDef) cbPileByOptions.getSelectedItem()); + } + else { + setPileBy(null); } }); @@ -761,6 +751,22 @@ public class ImageView extends ItemView { itemInfo.getWidth() + 2 * SEL_BORDER_SIZE, itemInfo.getHeight() + 2 * SEL_BORDER_SIZE); } + @Override + public void zoomSelected() { + if (selectedIndices.isEmpty()) { return; } + int index=selectedIndices.get(0); + if(index<0||orderedItems.size()<=index) { return ; } + + ItemInfo itemInfo = orderedItems.get(index); + if (itemInfo != null) { + if(itemInfo.getKey() instanceof CardThemedDeckGenerator || itemInfo.getKey() instanceof CommanderDeckGenerator + || itemInfo.getKey() instanceof ArchetypeDeckGenerator || itemInfo.getKey() instanceof DeckProxy){ + FDeckViewer.show(((DeckProxy)itemInfo.getKey()).getDeck()); + } + CardZoom.show(orderedItems, orderedItems.indexOf(itemInfo), itemManager); + } + } + private class Group extends FScrollPane { private final List items = new ArrayList<>(); private final List piles = new ArrayList<>(); diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ItemListView.java b/forge-gui-mobile/src/forge/itemmanager/views/ItemListView.java index 2c8881865be..1de1c6feaad 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ItemListView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ItemListView.java @@ -134,6 +134,13 @@ public final class ItemListView extends ItemView { return new Rectangle(list.screenPos.x, list.screenPos.y + list.getItemStartPosition(getSelectedIndex()), list.getWidth(), list.getListItemRenderer().getItemHeight()); } + @Override + public void zoomSelected() { + if (selectedIndices.isEmpty()) + return; + list.longPress(list.screenPos.x, list.screenPos.y+list.getItemStartPosition(getSelectedIndex())-list.getListItemRenderer().getItemHeight()); + } + @Override public void selectAll() { selectedIndices.clear(); diff --git a/forge-gui-mobile/src/forge/itemmanager/views/ItemView.java b/forge-gui-mobile/src/forge/itemmanager/views/ItemView.java index 3a33ae11a2d..beb594e6740 100644 --- a/forge-gui-mobile/src/forge/itemmanager/views/ItemView.java +++ b/forge-gui-mobile/src/forge/itemmanager/views/ItemView.java @@ -277,6 +277,7 @@ public abstract class ItemView { public abstract int getIndexAtPoint(float x, float y); public abstract void scrollSelectionIntoView(); public abstract Rectangle getSelectionBounds(); + public abstract void zoomSelected(); public abstract FImage getIcon(); public abstract String getCaption(); protected abstract void onSetSelectedIndex(int index); diff --git a/forge-gui-mobile/src/forge/menu/FDropDown.java b/forge-gui-mobile/src/forge/menu/FDropDown.java index 84ccde8799d..6dd7ebd01b0 100644 --- a/forge-gui-mobile/src/forge/menu/FDropDown.java +++ b/forge-gui-mobile/src/forge/menu/FDropDown.java @@ -20,6 +20,7 @@ public abstract class FDropDown extends FScrollPane { private Backdrop backdrop; private FMenuTab menuTab; private FContainer dropDownContainer; + private FDisplayObject selectedChild; protected ScrollBounds paneSize; public FDropDown() { @@ -64,6 +65,12 @@ public abstract class FDropDown extends FScrollPane { public void hide() { setVisible(false); } + public void setNextSelected() { + scrollToHoveredChild(true); + } + public void setPreviousSelected() { + scrollToHoveredChild(false); + } @Override public boolean press(float x, float y) { @@ -190,6 +197,33 @@ public abstract class FDropDown extends FScrollPane { FDisplayObject owner = getDropDownOwner(); return owner == null || !owner.screenPos.contains(x, y); //auto-hide when backdrop pressed unless over owner } + public void tapChild() { + if (selectedChild != null) { + selectedChild.tap(0, 0, 1); + if (getMenuTab() != null) + getMenuTab().clearSelected(); + if (autoHide()) + hide(); + } + } + public void cancel() { + if (getMenuTab() != null) + getMenuTab().clearSelected(); + hide(); + } + public void scrollToHoveredChild(boolean down) { + selectedChild = null; + for (FDisplayObject fDisplayObject : getChildren()) { + if (fDisplayObject.isHovered()) { + //System.out.println(fDisplayObject.screenPos.x+"|"+fDisplayObject.screenPos.y); + float mod = down ? 0 : -fDisplayObject.screenPos.height; + float y = fDisplayObject.screenPos.y+mod; + scrollIntoView(fDisplayObject.screenPos.x, y, fDisplayObject.screenPos.width, fDisplayObject.screenPos.height, 0); + selectedChild = fDisplayObject; + break; + } + } + } protected boolean preventOwnerHandlingBackupTap(float x, float y, int count) { //prevent owner handling this tap unless it's a sub menu and not over it diff --git a/forge-gui-mobile/src/forge/menu/FDropDownMenu.java b/forge-gui-mobile/src/forge/menu/FDropDownMenu.java index 62a9946557a..725426fdc87 100644 --- a/forge-gui-mobile/src/forge/menu/FDropDownMenu.java +++ b/forge-gui-mobile/src/forge/menu/FDropDownMenu.java @@ -5,6 +5,7 @@ import java.util.List; public abstract class FDropDownMenu extends FDropDown { protected final List items = new ArrayList<>(); + private int selected = -1; public FDropDownMenu() { } @@ -73,4 +74,49 @@ public abstract class FDropDownMenu extends FDropDown { super.tap(x, y, count); return !(getDropDownOwner() instanceof FSubMenu); //return false so owning sub menu can be hidden } + + @Override + public void setNextSelected() { + selected++; + clearHighlight(); + if (selected > items.size()) { + selected = 0; + } + try { + items.get(selected).setHovered(true); + } catch (Exception e){} + if (selected > items.size()) { + clearHighlight(); + selected = items.size(); + } + super.setNextSelected(); + } + + @Override + public void setPreviousSelected() { + selected--; + if (selected < 0) { + selected = items.size(); + } + clearHighlight(); + try { + items.get(selected).setHovered(true); + } catch (Exception e){} + if (selected < 0) { + clearHighlight(); + selected = -1; + } + super.setPreviousSelected(); + } + private void clearHighlight() { + for (FMenuItem item : items) { + item.setHovered(false); + } + } + + @Override + public void hide() { + selected = -1; + super.hide(); + } } diff --git a/forge-gui-mobile/src/forge/menu/FMenuBar.java b/forge-gui-mobile/src/forge/menu/FMenuBar.java index 58096d0293e..27e8a1a0cdb 100644 --- a/forge-gui-mobile/src/forge/menu/FMenuBar.java +++ b/forge-gui-mobile/src/forge/menu/FMenuBar.java @@ -3,11 +3,13 @@ package forge.menu; import java.util.ArrayList; import java.util.List; +import com.badlogic.gdx.Input; import forge.Graphics; import forge.screens.FScreen.Header; public class FMenuBar extends Header { private final List tabs = new ArrayList<>(); + private int selected = -1; public void addTab(String text0, FDropDown dropDown0) { FMenuTab tab = new FMenuTab(text0, this, dropDown0, tabs.size()); @@ -59,4 +61,54 @@ public class FMenuBar extends Header { public float doLandscapeLayout(float screenWidth, float screenHeight) { return 0; } + public void setNextSelected() { + selected++; + closeAll(); + if (selected > tabs.size()) + selected = 0; + try { + tabs.get(selected).showDropDown(); + } catch (Exception e) {} + if (selected > tabs.size()) { + closeAll(); + selected = tabs.size(); + return; + } + } + public void setPreviousSelected() { + selected--; + closeAll(); + if (selected < 0) + selected = tabs.size(); + try { + tabs.get(selected).showDropDown(); + } catch (Exception e) {} + if (selected < 0) { + closeAll(); + selected = -1; + return; + } + } + public void closeAll() { + for (FMenuTab fMenuTab : tabs) { + fMenuTab.hideDropDown(); + } + } + public boolean isShowingMenu(boolean anyDropdown) { + return tabs.stream().anyMatch(tab -> tab.isShowingDropdownMenu(anyDropdown)); + } + public void clearSelected() { + selected--; + if (selected < -1) + selected = tabs.size(); + } + + @Override + public boolean keyDown(int keyCode) { + if (keyCode == Input.Keys.BUTTON_L1) { + setNextSelected(); + return true; + } + return super.keyDown(keyCode); + } } diff --git a/forge-gui-mobile/src/forge/menu/FMenuTab.java b/forge-gui-mobile/src/forge/menu/FMenuTab.java index 34198ae06d4..b8846cbafa5 100644 --- a/forge-gui-mobile/src/forge/menu/FMenuTab.java +++ b/forge-gui-mobile/src/forge/menu/FMenuTab.java @@ -1,7 +1,9 @@ package forge.menu; +import com.badlogic.gdx.Input; import com.badlogic.gdx.utils.Align; +import forge.Forge; import forge.Graphics; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; @@ -43,6 +45,29 @@ public class FMenuTab extends FDisplayObject { } return true; } + public void hideDropDown() { + if (dropDown.isVisible()) + dropDown.hide(); + } + public void showDropDown() { + if (!dropDown.isVisible()) + dropDown.show(); + } + + @Override + public boolean keyDown(int keyCode) { + if (Forge.hasGamepad() && dropDown.isVisible()) { + if (keyCode == Input.Keys.DPAD_UP) + dropDown.setPreviousSelected(); + if (keyCode == Input.Keys.DPAD_DOWN) + dropDown.setNextSelected(); + if (keyCode == Input.Keys.BUTTON_A) + dropDown.tapChild(); + if (keyCode == Input.Keys.BUTTON_B) + dropDown.cancel(); + } + return super.keyDown(keyCode); + } public void setText(String text0) { text = text0; @@ -103,4 +128,15 @@ public class FMenuTab extends FDisplayObject { g.fillRect(SEL_BACK_COLOR.brighter(), x, y, w, h); g.drawText(text, FONT, foreColor, x, y, w, h, false, Align.center, true); } + public boolean isShowingDropdownMenu(boolean any) { + if (dropDown == null) + return false; + if (any) + return dropDown.isVisible(); + return dropDown.isVisible() && dropDown instanceof FDropDownMenu; + } + public void clearSelected() { + if (menuBar != null) + menuBar.clearSelected(); + } } diff --git a/forge-gui-mobile/src/forge/screens/TabPageScreen.java b/forge-gui-mobile/src/forge/screens/TabPageScreen.java index 0c369d6ac42..8ea70182a64 100644 --- a/forge-gui-mobile/src/forge/screens/TabPageScreen.java +++ b/forge-gui-mobile/src/forge/screens/TabPageScreen.java @@ -13,7 +13,6 @@ import forge.menu.FPopupMenu; import forge.model.FModel; import forge.toolbox.FContainer; import forge.toolbox.FDisplayObject; -import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FLabel; import forge.toolbox.FScrollPane; @@ -137,7 +136,7 @@ public class TabPageScreen> extends FScreen { private static final FSkinColor SEPARATOR_COLOR = BACK_COLOR.stepColor(-40); private final TabPage[] tabPages; - private final FLabel btnBack; + public final FLabel btnBack; private boolean isScrollable; private FDisplayObject finalVisibleTab; private boolean showBottomBorder = true; @@ -188,12 +187,7 @@ public class TabPageScreen> extends FScreen { public TabHeader(TabPage[] tabPages0, boolean showBackButton) { tabPages = tabPages0; if (showBackButton) { - btnBack = add(new FLabel.Builder().icon(new BackIcon(BACK_BUTTON_WIDTH, BACK_BUTTON_WIDTH)).pressedColor(BTN_PRESSED_COLOR).align(Align.center).command(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - Forge.back(); - } - }).build()); + btnBack = add(new FLabel.Builder().icon(new BackIcon(BACK_BUTTON_WIDTH, BACK_BUTTON_WIDTH)).pressedColor(BTN_PRESSED_COLOR).align(Align.center).command(e -> Forge.back()).build()); } else { btnBack = null; @@ -206,12 +200,7 @@ public class TabPageScreen> extends FScreen { public TabHeader(TabPage[] tabPages0, FEventHandler backButton) { tabPages = tabPages0; if(backButton==null) { - btnBack = add(new FLabel.Builder().icon(new BackIcon(BACK_BUTTON_WIDTH, BACK_BUTTON_WIDTH)).pressedColor(BTN_PRESSED_COLOR).align(Align.center).command(new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - Forge.back(); - } - }).build()); + btnBack = add(new FLabel.Builder().icon(new BackIcon(BACK_BUTTON_WIDTH, BACK_BUTTON_WIDTH)).pressedColor(BTN_PRESSED_COLOR).align(Align.center).command(e -> Forge.back()).build()); } else { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index b9c01727900..dac58fa83a6 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -11,6 +11,7 @@ import forge.card.CardRenderer; import forge.card.CardZoom; import forge.game.spellability.StackItemView; import forge.gui.interfaces.IGuiGame; +import forge.screens.match.views.VField; import forge.toolbox.FDisplayObject; import forge.util.Utils; import forge.util.collect.FCollectionView; @@ -27,7 +28,6 @@ import forge.animation.AbilityEffect; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; import forge.assets.FSkinTexture; -import forge.game.GameEntityView; import forge.game.GameView; import forge.game.card.CardView; import forge.game.combat.CombatView; @@ -62,8 +62,6 @@ import forge.screens.match.winlose.ViewWinLose; import forge.sound.MusicPlaylist; import forge.sound.SoundSystem; import forge.toolbox.FCardPanel; -import forge.toolbox.FEvent; -import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FScrollPane; import forge.util.Callback; @@ -83,7 +81,8 @@ public class MatchScreen extends FScreen { private AbilityEffect activeEffect; private BGAnimation bgAnimation; private ViewWinLose viewWinLose = null; - private List potentialListener; + private static List potentialListener; + private int selectedPlayer; public MatchScreen(List playerPanels0) { super(new FMenuBar()); @@ -107,39 +106,19 @@ public class MatchScreen extends FScreen { //reorder list so bottom player is at the end of the list ensuring top to bottom turn order playerPanelsList.remove(bottomPlayerPanel); playerPanelsList.add(bottomPlayerPanel); - + selectedPlayer = playerPanelsList.size()-1; bottomPlayerPrompt = add(new VPrompt("", "", - new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - getGameController().selectButtonOk(); - } - }, - new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - getGameController().selectButtonCancel(); - } - })); + e -> getGameController().selectButtonOk(), + e -> getGameController().selectButtonCancel())); if (humanCount < 2 || MatchController.instance.hotSeatMode() || GuiBase.isNetworkplay()) topPlayerPrompt = null; else { //show top prompt if multiple human players and not playing in Hot Seat mode and not in network play topPlayerPrompt = add(new VPrompt("", "", - new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - getGameController().selectButtonOk(); - } - }, - new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - getGameController().selectButtonCancel(); - } - })); + e -> getGameController().selectButtonOk(), + e -> getGameController().selectButtonCancel())); topPlayerPrompt.setRotate180(true); topPlayerPanel.setRotate180(true); getHeader().setRotate90(true); @@ -225,19 +204,16 @@ public class MatchScreen extends FScreen { private class MenuItem extends FMenuItem { private MenuItem(String text0, final FDropDown dropDown) { - super(text0, new FEventHandler() { - @Override - public void handleEvent(FEvent e) { - dropDown.setRotate180(PlayerSpecificMenu.this.getRotate180()); - Rectangle menuScreenPos = PlayerSpecificMenu.this.screenPos; - if (dropDown.getRotate180()) { - dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y); - } - else { - dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y + menuScreenPos.height); - } - dropDown.show(); + super(text0, e -> { + dropDown.setRotate180(PlayerSpecificMenu.this.getRotate180()); + Rectangle menuScreenPos = PlayerSpecificMenu.this.screenPos; + if (dropDown.getRotate180()) { + dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y); } + else { + dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y + menuScreenPos.height); + } + dropDown.show(); }); } } @@ -380,11 +356,6 @@ public class MatchScreen extends FScreen { } if (devMenu!=null) { if (devMenu.isVisible()){ - if (viewWinLose == null) - devMenu.setEnabled(true); - else - devMenu.setEnabled(false); - try { //rollbackphase enable -- todo limit by gametype? devMenu.getChildAt(2).setEnabled(game.getPlayers().size() == 2 && game.getStack().size() == 0 && !GuiBase.isNetworkplay() && game.getPhase().isMain() && !game.getPlayerTurn().isAI()); @@ -392,57 +363,6 @@ public class MatchScreen extends FScreen { } } - //draw arrows for combat - 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 = 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 = 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 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 vPlayer = MatchController.getView().getPlayerPanel(p).getAvatar().getTargetingArrowOrigin(); - TargetingOverlay.drawArrow(g, vAttacker, vPlayer, TargetingOverlay.ArcConnection.FoesAttacking); - } - } - } - } - } - //draw arrows for paired cards - 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 vPairedWith = CardAreaPanel.get(card.getPairedWith()).getTargetingArrowOrigin(); - TargetingOverlay.drawArrow(g, vCard, vPairedWith, TargetingOverlay.ArcConnection.Friends); - } - } - } - } - if (activeEffect != null) { activeEffect.draw(g, 10, 10, 100, 100); } @@ -457,6 +377,7 @@ public class MatchScreen extends FScreen { } } } + drawArcs(g); if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_MAGNIFIER) && Forge.magnify && Forge.magnifyToggle) { if (Forge.isLandscapeMode() && !GuiBase.isAndroid() && !CardZoom.isOpen() && potentialListener != null) { for (FDisplayObject object : potentialListener) { @@ -527,11 +448,147 @@ public class MatchScreen extends FScreen { } } } + void drawArcs(Graphics g) { + //get all card targeting arrow origins on the battlefield + final Map endpoints = new HashMap<>(); + final Set cardsonBattlefield = new HashSet<>(); + final Set playerViewSet = new HashSet<>(); + final GameView game = MatchController.instance.getGameView(); + try { + for (PlayerView p : game.getPlayers()) { + if (p != null && playerPanelsList.contains(getPlayerPanel(p))) { + playerViewSet.add(p); + if (p.getBattlefield() != null) { + for (CardView c : p.getBattlefield()) { + endpoints.put(c.getId(), CardAreaPanel.get(c).getTargetingArrowOrigin()); + cardsonBattlefield.add(c); + } + } + } + } + //draw arrows for combat + final CombatView combat = game.getCombat(); + for (CardView c : cardsonBattlefield) { + TargetingOverlay.assembleArrows(g, c, endpoints, combat, is4Player() || is3Player() ? playerViewSet : null); + } + } catch (Exception e) { + } + } @Override public boolean keyDown(int keyCode) { // TODO: make the keyboard shortcuts configurable on Mobile + if (Forge.hasGamepad() && ((FMenuBar)getHeader()).isShowingMenu(false) && (keyCode == Keys.ESCAPE || keyCode == Keys.ENTER)) + return false; switch (keyCode) { + case Keys.DPAD_DOWN: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + selectedPlayerPanel().getSelectedTab().getDisplayArea().setNextSelected(2); + } else { + nullPotentialListener(); + VField.FieldRow row = selectedPlayerPanel() != getBottomPlayerPanel() + ? selectedPlayerPanel().getField().getRow2() + : selectedPlayerPanel().getField().getRow1(); + if (selectedPlayerPanel().getSelectedRow() == row) { + selectedPlayerPanel().getSelectedRow().unselectCurrent(); + selectedPlayerPanel().switchRow(); + selectedPlayerPanel().getSelectedRow().selectCurrent(); + } else { + selectedPlayerPanel().getSelectedRow().selectCurrent(); + } + } + revalidate(true); + } catch (Exception e) {} + } + break; + case Keys.DPAD_RIGHT: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + selectedPlayerPanel().getSelectedTab().getDisplayArea().setNextSelected(1); + } else { + selectedPlayerPanel().getSelectedRow().setNextSelected(1); + } + revalidate(true); + } catch (Exception e) {} + } + break; + case Keys.DPAD_UP: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + selectedPlayerPanel().getSelectedTab().getDisplayArea().setPreviousSelected(2); + } else { + nullPotentialListener(); + VField.FieldRow row = selectedPlayerPanel() != getBottomPlayerPanel() + ? selectedPlayerPanel().getField().getRow1() + : selectedPlayerPanel().getField().getRow2(); + if (selectedPlayerPanel().getSelectedRow() == row) { + selectedPlayerPanel().getSelectedRow().unselectCurrent(); + selectedPlayerPanel().switchRow(); + selectedPlayerPanel().getSelectedRow().selectCurrent(); + } else { + selectedPlayerPanel().getSelectedRow().selectCurrent(); + } + } + revalidate(true); + } catch (Exception e) {} + } + break; + case Keys.DPAD_LEFT: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + selectedPlayerPanel().getSelectedTab().getDisplayArea().setPreviousSelected(1); + } else { + selectedPlayerPanel().getSelectedRow().setPreviousSelected(1); + } + revalidate(true); + } catch (Exception e) {} + } + break; + case Keys.BUTTON_Y: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + selectedPlayerPanel().getSelectedTab().getDisplayArea().showZoom(); + } else { + selectedPlayerPanel().getSelectedRow().showZoom(); + } + } catch (Exception e) {} + } + break; + case Keys.BUTTON_A: + if (!((FMenuBar)getHeader()).isShowingMenu(true)) { + try { + InfoTab selected = selectedPlayerPanel().getSelectedTab(); + if (selected != null && selected.getDisplayArea().isVisible()) { + //nullPotentialListener(); + selectedPlayerPanel().getSelectedTab().getDisplayArea().tapChild(); + } else { + //nullPotentialListener(); + selectedPlayerPanel().getSelectedRow().tapChild(); + } + } catch (Exception e) {} + } + break; + case Keys.PAGE_DOWN: + if (Forge.hasGamepad()) { + //nullPotentialListener(); + selectedPlayerPanel().hideSelectedTab(); + selectedPlayer--; + if (selectedPlayer < 0) + selectedPlayer=playerPanelsList.size()-1; + selectedPlayerPanel().setNextSelectedTab(true); + } + break; case Keys.ENTER: case Keys.SPACE: if (getActivePrompt().getBtnOk().trigger()) { //trigger OK on Enter or Space @@ -539,7 +596,7 @@ public class MatchScreen extends FScreen { } return getActivePrompt().getBtnCancel().trigger(); //trigger Cancel if can't trigger OK case Keys.ESCAPE: - if (!FModel.getPreferences().getPrefBoolean(FPref.UI_ALLOW_ESC_TO_END_TURN)) { + if (!FModel.getPreferences().getPrefBoolean(FPref.UI_ALLOW_ESC_TO_END_TURN) && !Forge.hasGamepad()) {//bypass check if (getActivePrompt().getBtnCancel().getText().equals(Forge.getLocalizer().getInstance().getMessage("lblEndTurn"))) { return false; } @@ -548,7 +605,7 @@ public class MatchScreen extends FScreen { case Keys.BACK: return true; //suppress Back button so it's not bumped when trying to press OK or Cancel buttons case Keys.A: //alpha strike on Ctrl+A on Android, A when running on desktop - if (KeyInputAdapter.isCtrlKeyDown() || GuiBase.getInterface().isRunningOnDesktop()) { + if (KeyInputAdapter.isCtrlKeyDown() || GuiBase.getInterface().isRunningOnDesktop() || Forge.hasGamepad()) { getGameController().alphaStrike(); return true; } @@ -566,7 +623,7 @@ public class MatchScreen extends FScreen { } break; case Keys.Z: //undo on Ctrl+Z - if (KeyInputAdapter.isCtrlKeyDown()) { + if (KeyInputAdapter.isCtrlKeyDown() || Forge.hasGamepad()) { getGameController().undoLastAction(); return true; } @@ -859,12 +916,23 @@ public class MatchScreen extends FScreen { if (!losers.isEmpty()) { float height = 0; for (VPlayerPanel p : losers) { - height = p.getAvatar().getHeight(); - p.setVisible(false); - playerPanelsList.remove(p); - System.out.println("Removed panels: "+p.getPlayer().toString()); + if (playerPanelsList.size() > 2) { + height = p.getAvatar().getHeight(); + p.setVisible(false); + playerPanelsList.remove(p); + System.out.println("Removed panel: "+p.getPlayer().toString()); + } } losers.clear(); + if (playerPanelsList.size() == 2) { + //reset avatar size + for (VPlayerPanel playerPanel : playerPanelsList) { + float size = playerPanel.getAvatar().getWidth()*2; + playerPanel.getAvatar().setSize(size, size); + playerPanel.revalidate(true); + System.out.println("Panel Resized: "+playerPanel.getPlayer().toString()); + } + } zoom(0,0, height); } } @@ -1004,7 +1072,26 @@ public class MatchScreen extends FScreen { @Override public void buildTouchListeners(float screenX, float screenY, List listeners) { - potentialListener = listeners; + setPotentialListener(listeners); super.buildTouchListeners(screenX, screenY, listeners); } + public VPlayerPanel selectedPlayerPanel() { + if (selectedPlayer >= playerPanelsList.size()) + selectedPlayer = playerPanelsList.size()-1; + if (playerPanelsList.isEmpty()) + return null; + return playerPanelsList.get(selectedPlayer); + } + public static void setPotentialListener(List listener) { + if (potentialListener != null) + for (FDisplayObject f: potentialListener) + f.setHovered(false); + potentialListener = listener; + } + public static void nullPotentialListener() { + if (potentialListener != null) + for (FDisplayObject f: potentialListener) + f.setHovered(false); + potentialListener = null; + } } diff --git a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java index 6a6261db737..c920dbfa339 100644 --- a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java +++ b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java @@ -23,10 +23,17 @@ import com.badlogic.gdx.math.Vector2; import forge.Graphics; import forge.assets.FSkinColor; import forge.assets.FSkinColor.Colors; +import forge.game.GameEntityView; +import forge.game.card.CardView; +import forge.game.combat.CombatView; +import forge.game.player.PlayerView; import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.util.Utils; +import java.util.Map; +import java.util.Set; + public class TargetingOverlay { private static final float BORDER_THICKNESS = Utils.scale(1); private static final float ARROW_THICKNESS = Utils.scale(5); @@ -60,8 +67,54 @@ public class TargetingOverlay { private TargetingOverlay() { } - - public static void drawArrow(Graphics g, Vector2 start, Vector2 end, ArcConnection connects) { + public static void assembleArrows(final Graphics g, final CardView c, final Map endpoints, final CombatView combat, final Set playerViewSet) { + final CardView attachedTo = c.getAttachedTo(); + final Iterable attachedCards = c.getAttachedCards(); + final CardView paired = c.getPairedWith(); + if (null != attachedTo) { + if (attachedTo.getController() != null && !attachedTo.getController().equals(c.getController())) { + drawArrow(g, endpoints.get(attachedTo.getId()), endpoints.get(c.getId()), ArcConnection.Friends); + } + } + if (null != attachedCards) { + for (final CardView enc : attachedCards) { + if (enc.getController() != null && !enc.getController().equals(c.getController())) { + drawArrow(g, endpoints.get(c.getId()), endpoints.get(enc.getId()), ArcConnection.Friends); + } + } + } + if (null != paired) { + drawArrow(g, endpoints.get(paired.getId()), endpoints.get(c.getId()), ArcConnection.Friends); + } + if (null != combat) { + final GameEntityView defender = combat.getDefender(c); + // if c is attacking a planeswalker + if (defender instanceof CardView) { + drawArrow(g, endpoints.get(defender.getId()), endpoints.get(c.getId()), ArcConnection.FoesAttacking); + } + // if c is a planeswalker that's being attacked + for (final CardView pwAttacker : combat.getAttackersOf(c)) { + drawArrow(g, endpoints.get(c.getId()), endpoints.get(pwAttacker.getId()), ArcConnection.FoesAttacking); + } + for (final CardView attackingCard : combat.getAttackers()) { + final Iterable cards = combat.getPlannedBlockers(attackingCard); + if (cards == null) continue; + for (final CardView blockingCard : cards) { + if (!attackingCard.equals(c) && !blockingCard.equals(c)) { continue; } + drawArrow(g, endpoints.get(attackingCard.getId()), endpoints.get(blockingCard.getId()), ArcConnection.FoesBlocking); + } + if (playerViewSet != null) { + for (final PlayerView p : playerViewSet) { + if (combat.getAttackersOf(p).contains(attackingCard)) { + final Vector2 vPlayer = MatchController.getView().getPlayerPanel(p).getAvatar().getTargetingArrowOrigin(); + drawArrow(g, endpoints.get(attackingCard.getId()), vPlayer, TargetingOverlay.ArcConnection.FoesAttacking); + } + } + } + } + } + } + public static void drawArrow(final Graphics g, final Vector2 start, final Vector2 end, final ArcConnection connects) { if (start == null || end == null) { return; } FSkinColor color = foeDefColor; diff --git a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java index f4a8bba7681..a089e8b4657 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java @@ -404,7 +404,7 @@ public abstract class VCardDisplayArea extends VDisplayArea implements ActivateH return false; } - private void showZoom() { + public void showZoom() { if (displayArea == null) { return; } final List cards = displayArea.orderedCards; diff --git a/forge-gui-mobile/src/forge/screens/match/views/VDisplayArea.java b/forge-gui-mobile/src/forge/screens/match/views/VDisplayArea.java index 1f33bba72f4..48a8aadb930 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VDisplayArea.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VDisplayArea.java @@ -1,11 +1,68 @@ package forge.screens.match.views; +import forge.screens.match.MatchScreen; +import forge.toolbox.FCardPanel; +import forge.toolbox.FDisplayObject; import forge.toolbox.FScrollPane; +import java.util.Arrays; + public abstract class VDisplayArea extends FScrollPane { + private FDisplayObject selectedChild; + private int selectedIndex = -1; public VDisplayArea() { setVisible(false); //hide by default } public abstract int getCount(); public abstract void update(); + public void setNextSelected(int val) { + if (getChildCount() < 1) { + selectedIndex = -1; + return; + } + if (selectedIndex == -1) { + selectedIndex++; + if (selectedChild != null) + selectedChild.setHovered(false); + selectedChild = getChildAt(selectedIndex); + selectedChild.setHovered(true); + scrollIntoView(selectedChild); + MatchScreen.setPotentialListener(Arrays.asList(selectedChild)); + return; + } + if (selectedIndex+val < getChildCount()) { + selectedIndex+=val; + if (selectedChild != null) + selectedChild.setHovered(false); + selectedChild = getChildAt(selectedIndex); + selectedChild.setHovered(true); + scrollIntoView(selectedChild); + MatchScreen.setPotentialListener(Arrays.asList(selectedChild)); + } + } + public void setPreviousSelected(int val) { + if (getChildCount() < 1) { + selectedIndex = -1; + return; + } + if (selectedIndex-val > -1) { + selectedIndex-=val; + if (selectedChild != null) + selectedChild.setHovered(false); + selectedChild = getChildAt(selectedIndex); + selectedChild.setHovered(true); + scrollIntoView(selectedChild); + MatchScreen.setPotentialListener(Arrays.asList(selectedChild)); + } + } + public void tapChild() { + if (selectedChild instanceof FCardPanel) + VCardDisplayArea.CardAreaPanel.get(((FCardPanel) selectedChild).getCard()).selectCard(false); + else if (selectedChild instanceof VManaPool.ManaLabel) + ((VManaPool.ManaLabel) selectedChild).activate(); + } + public void showZoom() { + if (selectedChild instanceof FCardPanel) + VCardDisplayArea.CardAreaPanel.get(((FCardPanel) selectedChild).getCard()).showZoom(); + } } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VField.java b/forge-gui-mobile/src/forge/screens/match/views/VField.java index 615afc93982..45d08855645 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VField.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VField.java @@ -1,14 +1,18 @@ package forge.screens.match.views; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import forge.game.card.CardView; import forge.game.card.CardView.CardStateView; import forge.game.player.PlayerView; import forge.gui.FThreads; +import forge.screens.match.MatchScreen; import forge.screens.match.views.VCardDisplayArea.CardAreaPanel; +import forge.toolbox.FCardPanel; import forge.toolbox.FContainer; +import forge.toolbox.FDisplayObject; public class VField extends FContainer { private final PlayerView player; @@ -190,6 +194,9 @@ public class VField extends FContainer { } public class FieldRow extends VCardDisplayArea { + private int selected = -1; + private FDisplayObject selectedChild; + private FieldRow() { setVisible(true); //make visible by default unlike other display areas } @@ -202,5 +209,57 @@ public class VField extends FContainer { @Override public void update() { //no logic needed } + + @Override + public void setNextSelected(int val) { + this.selected++; + if (this.selected >= this.getChildCount()) + this.selected = this.getChildCount()-1; + if (this.selectedChild != null) + this.selectedChild.setHovered(false); + this.selectedChild = getChildAt(this.selected); + this.selectedChild.setHovered(true); + MatchScreen.setPotentialListener(Arrays.asList(this.selectedChild)); + } + public void selectCurrent() { + if (this.selectedChild != null) { + this.selectedChild.setHovered(true); + MatchScreen.setPotentialListener(Arrays.asList(this.selectedChild)); + } else { + this.setNextSelected(1); + } + } + public void unselectCurrent() { + if (this.selectedChild != null) { + this.selectedChild.setHovered(false); + MatchScreen.nullPotentialListener(); + } + } + + @Override + public void setPreviousSelected(int val) { + if (this.getChildCount() < 1) + return; + this.selected--; + if (this.selected < 0) + this.selected = 0; + if (this.selectedChild != null) + this.selectedChild.setHovered(false); + this.selectedChild = getChildAt(this.selected); + this.selectedChild.setHovered(true); + MatchScreen.setPotentialListener(Arrays.asList(this.selectedChild)); + } + + @Override + public void showZoom() { + if (this.selectedChild instanceof FCardPanel) + VCardDisplayArea.CardAreaPanel.get(((FCardPanel) this.selectedChild).getCard()).showZoom(); + } + + @Override + public void tapChild() { + if (this.selectedChild instanceof FCardPanel) + VCardDisplayArea.CardAreaPanel.get(((FCardPanel) this.selectedChild).getCard()).selectCard(false); + } } } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VManaPool.java b/forge-gui-mobile/src/forge/screens/match/views/VManaPool.java index 4d0bfbc56b8..42031887431 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VManaPool.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VManaPool.java @@ -90,7 +90,7 @@ public class VManaPool extends VDisplayArea { return new ScrollBounds(visibleWidth, visibleHeight); } - private class ManaLabel extends FDisplayObject { + public class ManaLabel extends FDisplayObject { private final FSkinImage image; private final byte colorCode; private String text = "0"; @@ -102,12 +102,14 @@ public class VManaPool extends VDisplayArea { @Override public boolean tap(float x, float y, int count) { + activate(); + return true; + } + public void activate() { if (player.isLobbyPlayer(GamePlayerUtil.getGuiPlayer())) { MatchController.instance.getGameController().useMana(colorCode); } - return true; } - @Override public boolean flick(float x, float y) { if (player.isLobbyPlayer(GamePlayerUtil.getGuiPlayer())) { @@ -141,6 +143,8 @@ public class VManaPool extends VDisplayArea { float x = (getWidth() - w) / 2; float y = gapY + (maxImageHeight - h) / 2; + if (isHovered()) + g.fillRect(FSkinColor.getStandardColor(50, 200, 150).alphaColor(0.3f), 0, 0, getWidth(), getHeight()); g.drawImage(image, x, y, w, h); x = 0; diff --git a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java index b7592677798..af7356b42bb 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Align; @@ -20,6 +21,7 @@ import forge.game.card.CounterEnumType; import forge.game.player.PlayerView; import forge.game.zone.ZoneType; import forge.localinstance.properties.ForgePreferences.FPref; +import forge.menu.FMenuBar; import forge.model.FModel; import forge.screens.match.MatchController; import forge.screens.match.MatchScreen; @@ -49,12 +51,12 @@ public class VPlayerPanel extends FContainer { private final Map zoneTabs = new HashMap<>(); private final List tabs = new ArrayList<>(); private InfoTab selectedTab; + private VField.FieldRow selectedRow; private float avatarHeight = VAvatar.HEIGHT; private float displayAreaHeightFactor = 1.0f; private boolean forMultiPlayer = false; public int adjustHeight = 1; - public boolean noBG = false; - + private int selected = 0; public VPlayerPanel(PlayerView player0, boolean showHand, int playerCount) { player = player0; phaseIndicator = add(new VPhaseIndicator()); @@ -65,6 +67,7 @@ public class VPlayerPanel extends FContainer { //displayAreaHeightFactor *= 0.7f; } field = add(new VField(player)); + selectedRow = field.getRow1(); avatar = add(new VAvatar(player, avatarHeight)); lblLife = add(new LifeLabel()); addZoneDisplay(ZoneType.Hand, Forge.hdbuttons ? FSkinImage.HDHAND : FSkinImage.HAND); @@ -138,6 +141,7 @@ public class VPlayerPanel extends FContainer { public void hideSelectedTab() { if (selectedTab != null) { selectedTab.displayArea.setVisible(false); + selectedTab = null; } } @@ -158,6 +162,38 @@ public class VPlayerPanel extends FContainer { MatchController.getView().revalidate(); } } + public void setNextSelectedTab(boolean change) { + if (change) { + if (selectedTab != null) { + selectedTab.displayArea.setVisible(false); + selectedTab = null; + } + if (MatchController.getView() != null) { //must revalidate entire screen so panel heights updated + MatchController.getView().revalidate(); + } + } + if (!change) + selected++; + else + hideSelectedTab(); + if (selected >= tabs.size()) + selected = 0; + if (selected < 0) + selected = 0; + setSelectedTab(tabs.get(selected)); + } + public void closeSelectedTab() { + if (selectedTab != null) { + selectedTab.displayArea.setVisible(false); + selectedTab = null; + } + if (MatchController.getView() != null) { //must revalidate entire screen so panel heights updated + MatchController.getView().revalidate(); + } + selected--; + if (selected < -1) + selected = -1; + } public InfoTab getManaPoolTab() { return tabManaPool; @@ -186,6 +222,15 @@ public class VPlayerPanel extends FContainer { public VField getField() { return field; } + public VField.FieldRow getSelectedRow() { + return selectedRow; + } + public void switchRow() { + if (selectedRow == field.getRow1()) + selectedRow = field.getRow2(); + else + selectedRow = field.getRow1(); + } public VPhaseIndicator getPhaseIndicator() { return phaseIndicator; @@ -377,8 +422,6 @@ public class VPlayerPanel extends FContainer { @Override public void drawBackground(Graphics g) { - if (noBG) - return; float y; if (selectedTab != null) { //draw background and border for selected zone if needed VDisplayArea selectedDisplayArea = selectedTab.displayArea; @@ -548,11 +591,15 @@ public class VPlayerPanel extends FContainer { @Override public void draw(Graphics g) { float x, y, w, h; - + boolean drawOverlay = MatchController.getView().selectedPlayerPanel().getPlayer() == player && Forge.hasGamepad(); if (Forge.altZoneTabs) { //draw extra - if (isAltZoneDisplay(this) && selectedTab == this) { - g.fillRect(DISPLAY_AREA_BACK_COLOR, 0, isFlipped() ? INFO_TAB_PADDING_Y : 0, getWidth(), getHeight() - INFO_TAB_PADDING_Y); + if (isAltZoneDisplay(this)) { + if (selectedTab == this) { + if (drawOverlay) + g.fillRect(FSkinColor.getStandardColor(50, 200, 150).alphaColor(0.3f), 0, isFlipped() ? INFO_TAB_PADDING_Y : 0, getWidth(), getHeight() - INFO_TAB_PADDING_Y); + g.fillRect(DISPLAY_AREA_BACK_COLOR, 0, isFlipped() ? INFO_TAB_PADDING_Y : 0, getWidth(), getHeight() - INFO_TAB_PADDING_Y); + } } } if (selectedTab == this) { @@ -571,6 +618,8 @@ public class VPlayerPanel extends FContainer { y--; h += 2; } + if (drawOverlay) + g.fillRect(FSkinColor.getStandardColor(50, 200, 150).alphaColor(0.3f), 0, isFlipped() ? INFO_TAB_PADDING_Y : 0, w, getHeight() - INFO_TAB_PADDING_Y); //change the graveyard tab selection color to active phase color to indicate the player has delirium if ((icon == FSkinImage.HDGRAVEYARD || icon == FSkinImage.GRAVEYARD) && player.hasDelirium()) { g.fillRect(DELIRIUM_HIGHLIGHT, 0 ,isFlipped() ? INFO_TAB_PADDING_Y : 0, w, getHeight() - INFO_TAB_PADDING_Y); @@ -674,4 +723,20 @@ public class VPlayerPanel extends FContainer { return false; } } + + @Override + public boolean keyDown(int keyCode) { + if (MatchController.getView().selectedPlayerPanel() == this && !((FMenuBar)MatchController.getView().getHeader()).isShowingMenu(true)) { + if (keyCode == Input.Keys.BUTTON_B) { + MatchScreen.nullPotentialListener(); + closeSelectedTab(); + return true; + } + if (keyCode == Input.Keys.BUTTON_R1) { + setNextSelectedTab(false); + return true; + } + } + return super.keyDown(keyCode); + } } diff --git a/forge-gui-mobile/src/forge/toolbox/FButton.java b/forge-gui-mobile/src/forge/toolbox/FButton.java index 4c62825ae36..9f99180b09b 100644 --- a/forge-gui-mobile/src/forge/toolbox/FButton.java +++ b/forge-gui-mobile/src/forge/toolbox/FButton.java @@ -1,5 +1,6 @@ package forge.toolbox; +import com.badlogic.gdx.utils.Timer; import org.apache.commons.lang3.StringUtils; import com.badlogic.gdx.Input.Keys; @@ -221,7 +222,19 @@ public class FButton extends FDisplayObject implements IButton { public boolean trigger() { if (isEnabled() && command != null) { - command.handleEvent(new FEvent(this, FEventType.TAP)); + FEvent fEvent = new FEvent(this, FEventType.TAP); + if (Forge.hasGamepad()) { + press(0, 0); + Timer.schedule(new Timer.Task() { + @Override + public void run() { + command.handleEvent(fEvent); + release(0,0); + } + }, 0.10f); + return true; + } + command.handleEvent(fEvent); return true; } return false; diff --git a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java index 10a33b9cb8e..f6dbbee0bad 100644 --- a/forge-gui-mobile/src/forge/toolbox/FCardPanel.java +++ b/forge-gui-mobile/src/forge/toolbox/FCardPanel.java @@ -1,5 +1,6 @@ package forge.toolbox; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import forge.Forge; import forge.Graphics; @@ -96,7 +97,7 @@ public class FCardPanel extends FDisplayObject { public void draw(Graphics g) { if (card == null) { return; } boolean animate = Forge.animatedCardTapUntap; - float mod = isHighlighted()||isHovered() ? getWidth()/16f : 0f; + float mod = (isHighlighted()||isHovered()) && !Forge.hasGamepad() ? getWidth()/16f : 0f; float padding = getPadding(); float x = padding-mod/2; float y = padding-mod/2; @@ -160,6 +161,8 @@ public class FCardPanel extends FDisplayObject { transformAnimation.drawCard(g, card, x, y, w, h); } else { CardRenderer.drawCardWithOverlays(g, card, x, y, w, h, getStackPosition()); + if (Forge.hasGamepad() && isHovered()) + g.drawRect(3f, Color.LIME, x, y, w, h); } if (tapped) { g.endTransform(); diff --git a/forge-gui-mobile/src/forge/toolbox/FContainer.java b/forge-gui-mobile/src/forge/toolbox/FContainer.java index bb0f248c431..b29d38b3916 100644 --- a/forge-gui-mobile/src/forge/toolbox/FContainer.java +++ b/forge-gui-mobile/src/forge/toolbox/FContainer.java @@ -150,11 +150,16 @@ public abstract class FContainer extends FDisplayObject { @Override public boolean keyDown(int keyCode) { //by default, give all enabled children a chance handle keyDown - for (FDisplayObject c : children) { - if (c.isEnabled() && c.keyDown(keyCode)) { - return true; + try { + for (FDisplayObject c : children) { + if (c.isEnabled() && c.keyDown(keyCode)) { + return true; + } } + return false; + } catch (Exception e) { + //e.printStackTrace(); + return false; } - return false; } } diff --git a/forge-gui-mobile/src/forge/util/BlurUtils.java b/forge-gui-mobile/src/forge/util/BlurUtils.java new file mode 100644 index 00000000000..1b6b917ef2a --- /dev/null +++ b/forge-gui-mobile/src/forge/util/BlurUtils.java @@ -0,0 +1,426 @@ +package forge.util; + +import java.nio.ByteBuffer; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Pixmap.Format; +import com.badlogic.gdx.utils.BufferUtils; +import com.badlogic.gdx.utils.GdxRuntimeException; + +/** + * A simple set of software blur utilities for mobile applications. + * + * @author davedes, blur algorithm by Romain Guy + */ +public class BlurUtils { + /* + * Copyright (c) 2007, Romain Guy All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * Redistributions + * in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. * Neither the name of the + * TimingFramework project nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + /** + *

+ * Blurs the source pixels into the destination pixels. The force of the + * blur is specified by the radius which must be greater than 0. + *

+ *

+ * The source and destination pixels arrays are expected to be in the RGBA + * format. + *

+ * + * @param srcPixels + * the source pixels + * @param dstPixels + * the destination pixels + * @param width + * the width of the source picture + * @param height + * the height of the source picture + * @param radius + * the radius of the blur effect + * @author Romain Guy + */ + public static void blurPass(int[] srcPixels, int[] dstPixels, int width, + int height, int radius) { + final int windowSize = radius * 2 + 1; + final int radiusPlusOne = radius + 1; + + int sumRed; + int sumGreen; + int sumBlue; + int sumAlpha; + + int srcIndex = 0; + int dstIndex; + int pixel; + + int[] sumLookupTable = new int[256 * windowSize]; + for (int i = 0; i < sumLookupTable.length; i++) { + sumLookupTable[i] = i / windowSize; + } + + int[] indexLookupTable = new int[radiusPlusOne]; + if (radius < width) { + for (int i = 0; i < indexLookupTable.length; i++) { + indexLookupTable[i] = i; + } + } else { + for (int i = 0; i < width; i++) { + indexLookupTable[i] = i; + } + for (int i = width; i < indexLookupTable.length; i++) { + indexLookupTable[i] = width - 1; + } + } + + for (int y = 0; y < height; y++) { + sumAlpha = sumRed = sumGreen = sumBlue = 0; + dstIndex = y; + + pixel = srcPixels[srcIndex]; + sumRed += radiusPlusOne * ((pixel >> 24) & 0xFF); + sumGreen += radiusPlusOne * ((pixel >> 16) & 0xFF); + sumBlue += radiusPlusOne * ((pixel >> 8) & 0xFF); + sumAlpha += radiusPlusOne * (pixel & 0xFF); + + for (int i = 1; i <= radius; i++) { + pixel = srcPixels[srcIndex + indexLookupTable[i]]; + sumRed += (pixel >> 24) & 0xFF; + sumGreen += (pixel >> 16) & 0xFF; + sumBlue += (pixel >> 8) & 0xFF; + sumAlpha += pixel & 0xFF; + } + + for (int x = 0; x < width; x++) { + dstPixels[dstIndex] = sumLookupTable[sumRed] << 24 + | sumLookupTable[sumGreen] << 16 + | sumLookupTable[sumBlue] << 8 + | sumLookupTable[sumAlpha]; + dstIndex += height; + + int nextPixelIndex = x + radiusPlusOne; + if (nextPixelIndex >= width) { + nextPixelIndex = width - 1; + } + + int previousPixelIndex = x - radius; + if (previousPixelIndex < 0) { + previousPixelIndex = 0; + } + + int nextPixel = srcPixels[srcIndex + nextPixelIndex]; + int previousPixel = srcPixels[srcIndex + previousPixelIndex]; + + sumRed += (nextPixel >> 24) & 0xFF; + sumRed -= (previousPixel >> 24) & 0xFF; + + sumGreen += (nextPixel >> 16) & 0xFF; + sumGreen -= (previousPixel >> 16) & 0xFF; + + sumBlue += (nextPixel >> 8) & 0xFF; + sumBlue -= (previousPixel >> 8) & 0xFF; + + sumAlpha += nextPixel & 0xFF; + sumAlpha -= previousPixel & 0xFF; + } + + srcIndex += width; + } + } + + /** + * Blurs (in both horizontal and vertical directions) the specified RGBA + * image with the given radius and iterations. + * + * @param inputRGBA + * the image pixels, in RGBA format + * @param width + * the width of the image in pixels + * @param height + * the height of the image in pixels + * @param radius + * the radius of the blur effect + * @param iterations + * the number of times to perform the blur; i.e. to increase + * quality + * @return the blurred pixels + */ + public static int[] blur(int[] inputRGBA, int width, int height, + int radius, int iterations) { + int[] srcPixels = new int[width * height]; + int[] dstPixels = new int[width * height]; + + // copy input into srcPixels + System.arraycopy(inputRGBA, 0, srcPixels, 0, srcPixels.length); + + for (int i = 0; i < iterations; i++) { + // horizontal pass + blurPass(srcPixels, dstPixels, width, height, radius); + // vertical pass + blurPass(dstPixels, srcPixels, height, width, radius); + } + + // the result is now stored in srcPixels due to the 2nd pass + return srcPixels; + } + + /** + * Convenience method to blur using ByteBuffers instead of arrays. + * Note that this requires unnecessary copies of data and is only + * for convenience; a proper solution would be + * to re-write the blur algorithm using a ByteBuffer. + * + * @param inputRGBA + * @param width + * @param height + * @param radius + * @param iterations + * @return + */ + public static ByteBuffer blur(ByteBuffer inputRGBA, int width, + int height, int radius, int iterations) { + if (inputRGBA.limit() != (width * height * 4)) + throw new IllegalArgumentException( + "inputRGBA must be in RGBA format"); + int[] pixels = pack(inputRGBA); + int[] out = blur(pixels, width, height, radius, iterations); + return unpack(out); + } + + /** + * Converts an RGBA byte buffer into an array of RGBA packed ints. + * + * @param rgba + * @return + */ + public static int[] pack(ByteBuffer rgba) { + int[] pixels = new int[rgba.limit() / 4]; + for (int i = 0; i < pixels.length; i++) { + int r = rgba.get() & 0xFF; + int g = rgba.get() & 0xFF; + int b = rgba.get() & 0xFF; + int a = rgba.get() & 0xFF; + pixels[i] = (r << 24) | (g << 16) | (b << 8) | a; + } + return pixels; + } + + /** + * Unpacks the RGBA pixels array into a ByteBuffer with red, green, blue, + * and alpha bytes in order; it is then flipped to "read mode" before being + * returned. + * + * @param pixels + * the pixels to use + * @return the new byte buffer using RGBA bytes + */ + public static ByteBuffer unpack(int[] pixels) { + ByteBuffer buf = BufferUtils.newByteBuffer(pixels.length * 4); + for (int src = 0; src < pixels.length; src++) { + int value = pixels[src]; + buf.put((byte) ((value & 0xff000000) >>> 24)) + .put((byte) ((value & 0x00ff0000) >>> 16)) + .put((byte) ((value & 0x0000ff00) >>> 8)) + .put((byte) ((value & 0x000000ff))); + } + buf.flip(); + return buf; + } + + /** + * A convenience method to apply the blur to the entire Pixmap. + * + * @param pixmap + * the pixmap to blur + * @param radius + * the radius of the blur effect + * @param iterations + * the number of iterations to blur + * @param disposePixmap + * whether to dispose the given pixmap after blurring + * @return a new Pixmap containing the blurred image + */ + public static Pixmap blur(Pixmap pixmap, int radius, int iterations, boolean disposePixmap) { + return blur(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(), 0, 0, + pixmap.getWidth(), pixmap.getHeight(), radius, iterations, + disposePixmap); + } + public static Pixmap blur(Pixmap pixmap, int radius, int iterations, boolean disposePixmap, boolean crop) { + int x = (int)(pixmap.getWidth()*0.35f); + int y = (int)(pixmap.getHeight()*0.35f); + int width = pixmap.getWidth()-x; + int height = pixmap.getHeight()-y; + return blur(pixmap, x/2, y/2, width, height, 0, 0, width, height, radius, iterations, disposePixmap); + } + + /** + * Blurs the specified pixmap with the given source and destination regions. + * + * The pixmap does not need to be in RGBA8888 format, however, it is + * recommended for better performance. + * + * A new pixmap will be returned containing the blurred image. The old + * pixmap will only be disposed of if disposePixmap returns true. + * + * @param pixmap + * the pixmap to blur + * @param srcx + * the x of the pixmap region to blur + * @param srcy + * the y of the pixmap region to blur + * @param srcwidth + * the width of the pixmap region to blur + * @param srcheight + * the height of the pixmap region to blur + * @param dstx + * the destination x to place the blurred image on the resulting + * pixmap + * @param dsty + * the destination y to place the blurred image on the resulting + * pixmap + * @param dstwidth + * the desired width of the resulting pixmap + * @param dstheight + * the desired height of the resulting pixmap + * @param radius + * the radius of the blur effect, in pixels + * @param iterations + * the number of iterations to apply the blur + * @param disposePixmap + * whether to dispose the specified pixmap after applying the + * blur + * @return a new RGBA8888 Pixmap containing the blurred image + */ + public static Pixmap blur(Pixmap pixmap, int srcx, int srcy, int srcwidth, + int srcheight, int dstx, int dsty, int dstwidth, int dstheight, + int radius, int iterations, boolean disposePixmap) { + boolean srcEq = srcx == 0 && srcy == 0 && srcwidth == pixmap.getWidth() + && srcheight == pixmap.getHeight(); + boolean dstEq = dstx == 0 && dsty == 0 && dstwidth == pixmap.getWidth() + && dstheight == pixmap.getHeight(); + + // we may need to re-draw the pixmap if a different region or format is + // passed + if (pixmap.getFormat() != Format.RGBA8888 || !srcEq || !dstEq) { + Pixmap tmp = new Pixmap(dstwidth, dstheight, Format.RGBA8888); + tmp.drawPixmap(pixmap, srcx, srcy, srcwidth, srcheight, dstx, dsty, + dstwidth, dstheight); + if (disposePixmap) { + pixmap.dispose(); // discard old pixmap + disposePixmap = false; + } + pixmap = tmp; + } + + // blur the pixmap + ByteBuffer blurred = BlurUtils.blur(pixmap.getPixels(), dstwidth, + dstheight, radius, iterations); + + Pixmap newPixmap = new Pixmap(dstwidth, dstheight, Format.RGBA8888); + ByteBuffer newRGBA = newPixmap.getPixels(); + newRGBA.clear(); + newRGBA.put(blurred); + newRGBA.flip(); + + if (disposePixmap) + pixmap.dispose(); + return newPixmap; + } + + /** + * Blurs the mipmaps of the currently bound texture with the given settings. + * + * For each mipmap level, the image will be scaled to half (using + * nearest-neighbour scaling) and then blurred in software, before sending + * the bytes to GL. + * + * The first mipmap level should already be uploaded to GL, i.e. through the + * Texture constructor. No blur will be applied to it. + * + * The texture needs to have been created with format RGBA8888 to work + * correctly on all devices. + * + * @param pixmap + * the original pixmap to work with + * @param textureWidth + * the width of the texture + * @param textureHeight + * the height of the texture + * @param radius + * the radius of the blur to use at each level + * @param iterations + * the number of iterations to blur at each level + * @param disposePixmap + * whether to dispose the specified pixmap after building the + * mipmaps + */ + public static void generateBlurredMipmaps(Pixmap pixmap, int textureWidth, + int textureHeight, int radius, int iterations, + boolean disposePixmap) { + if (textureWidth != textureHeight) + throw new GdxRuntimeException( + "texture width and height must be square when using mipmapping."); + + Pixmap origPixmap = pixmap; + int width = pixmap.getWidth() / 2; + int height = pixmap.getHeight() / 2; + int level = 1; + //Blending blending = Pixmap.Blending; + //Pixmap.setBlending(Blending.None); + // for each mipmap level > 0 ... + while (width > 0 && height > 0) { + // apply blur + pixmap = blur(origPixmap, 0, 0, origPixmap.getWidth(), origPixmap.getHeight(), + 0, 0, width, height, radius, iterations, false); + + // upload pixels + Gdx.gl.glTexImage2D(GL20.GL_TEXTURE_2D, level, + pixmap.getGLInternalFormat(), pixmap.getWidth(), + pixmap.getHeight(), 0, pixmap.getGLFormat(), + pixmap.getGLType(), pixmap.getPixels()); + + // reduce size for next level + width = pixmap.getWidth() / 2; + height = pixmap.getHeight() / 2; + level++; + + //dispose pixmap at this level + pixmap.dispose(); + + // NOTE: We can play with the radius and iterations here, e.g. + // increment them for + // each level. +// radius++; + } + //Pixmap.setBlending(blending); + + if (disposePixmap) { + origPixmap.dispose(); + } + } +} \ No newline at end of file diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index 7a2288737a9..7d2b1f0b4f5 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -45,11 +45,6 @@ textratypist 0.7.1
- - com.github.tommyettinger - regexodus - 0.1.13 - com.thoughtworks.xstream xstream diff --git a/forge-gui/release-files/GAMEPAD_README.txt b/forge-gui/release-files/GAMEPAD_README.txt new file mode 100644 index 00000000000..cdb3056e814 --- /dev/null +++ b/forge-gui/release-files/GAMEPAD_README.txt @@ -0,0 +1,66 @@ +Basic Gamepad Support for Adventure Mode + +Tested using DS4 COntroller on Windows and Android. + +If using on Windows OS and you have DS4Windows installed, you might experience dual input because of Emulated/Virtual Controller. To fix this you must use HidHide (better than exclusive mode). Refer to the guide here: +https://vigem.org/projects/HidHide/Simple-Setup-Guide/ + +DS4Windows latest: +https://github.com/Ryochan7/DS4Windows/releases/ + +HidHide latest: +https://github.com/ViGEm/HidHide/releases + +Other XInput Controller should work, XBox or DS4 Preferaably and other similar XInput Controller with comparable button layout. Custom Key Mapping is not yet supported. + +Controls: + +UIScenes + +DPAD Up/Down/Left/Right - for selecting texboxes and textfield, Scroll Up or Down +Button A - Ok, Show Context +Button B - Cancel +Button X - Increase Difficulty in NewGame Plus/Flip Backside Deck Editor +Button Y - Decrease Difficulty in NewGame Plus/Zoom or Text Mode in Deck Editor +Left/Right Shoulder Button - Scroll Up or Scroll Down on some UIScenes + +RewardScene + +DPAD Left/Right - Selector +Button A - Confirm/Flip Reward +Button B - Show Rewards/Done +Button Y - Show/Hide Zoom Card + +TextInput + +DPAD Up/Down/Left/Right - Key Selector +Left Shoulder Button - Shift Keys +Right Shoulder Button - Backspace +Button Start - Jump to Ok +Button A - Confirm +Button B - Cancel + +World/Gamescene + +DPAD Up/Down/Left/Right - Character Movement +Left Analog - Character Movement +Button A - Menu/Confirm +Button B - Statistics/Edit +Button X - Deck Select/Deck Edit +Button Y - Inventory/Rename + +Match/Battle + +Left Trigger - Play/Draw/OK (Bottom Left Button) +Right Trigger - Keep/Mulligan/Cancel/End Turn/Alpha Strike (Bottom Right Button) + +(To select cards on the battlefield, close Zone tabs first (Button B), then use DPAD) + +DPAD Up/Down/Left/Right - Selector +Left Shoulder - Tab Selector/Show +Right Shoulder - Zone Selector/Show +Left Analog Down - Switch Player for Selector + +Button A - Confirm +Button B - Cancel/Hide +Button Y - Show Zoom \ No newline at end of file diff --git a/forge-gui/res/adventure/Shandalar/ui/deck_selector.json b/forge-gui/res/adventure/Shandalar/ui/deck_selector.json index fb2b62e6e16..bb40c5d45ed 100644 --- a/forge-gui/res/adventure/Shandalar/ui/deck_selector.json +++ b/forge-gui/res/adventure/Shandalar/ui/deck_selector.json @@ -5,7 +5,7 @@ "elements": [ { "type": "Image", - "image": "ui/title_bg.png", + "name": "lastScreen", "width": 480, "height": 270 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/deck_selector_portrait.json b/forge-gui/res/adventure/Shandalar/ui/deck_selector_portrait.json index d27fb943d46..0e2ae74007d 100644 --- a/forge-gui/res/adventure/Shandalar/ui/deck_selector_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/deck_selector_portrait.json @@ -5,7 +5,7 @@ "elements": [ { "type": "Image", - "image": "ui/title_bg_portrait.png", + "name": "lastScreen", "width": 270, "height": 480 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/inventory.json b/forge-gui/res/adventure/Shandalar/ui/inventory.json index 27790c85833..fbf2db8ef76 100644 --- a/forge-gui/res/adventure/Shandalar/ui/inventory.json +++ b/forge-gui/res/adventure/Shandalar/ui/inventory.json @@ -5,7 +5,7 @@ "elements": [ { "type": "Image", - "image": "ui/title_bg.png", + "name": "lastScreen", "width": 480, "height": 270 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/inventory_portrait.json b/forge-gui/res/adventure/Shandalar/ui/inventory_portrait.json index 56109660bde..9f39f15b1ce 100644 --- a/forge-gui/res/adventure/Shandalar/ui/inventory_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/inventory_portrait.json @@ -3,12 +3,13 @@ "height": 480, "yDown": true, "elements": [ - { + { "type": "Image", - "image": "ui/title_bg_portrait.png", + "name": "lastScreen", "width": 270, "height": 480 - }, { + }, + { "type": "Image", "image": "ui/equipment.png", "x": 8, diff --git a/forge-gui/res/adventure/Shandalar/ui/statistic.json b/forge-gui/res/adventure/Shandalar/ui/statistic.json index ae71365194c..6f3d2b663bf 100644 --- a/forge-gui/res/adventure/Shandalar/ui/statistic.json +++ b/forge-gui/res/adventure/Shandalar/ui/statistic.json @@ -5,7 +5,7 @@ "elements": [ { "type": "Image", - "image": "ui/title_bg.png", + "name": "lastScreen", "width": 480, "height": 270 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json b/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json index 5ca37dab220..9a61e1ae9c1 100644 --- a/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json @@ -5,7 +5,7 @@ "elements": [ { "type": "Image", - "image": "ui/title_bg_portrait.png", + "name": "lastScreen", "width": 270, "height": 480 },