From 0dc412d90f6a4214af986d6b849809584464e0c1 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Wed, 28 Sep 2022 20:55:28 +0100 Subject: [PATCH 1/2] feat(nui): convert InventoryScreen and InventoryOperationsScreen classes to NUI --- .../game/screens/BuyItemsScreen.java | 71 ++- .../game/screens/ChangeShipScreen.java | 66 +- .../game/screens/ChooseMercenaryScreen.java | 121 ++-- .../game/screens/GameScreens.java | 3 +- .../game/screens/GiveItemsScreen.java | 78 ++- .../game/screens/HireShipsScreen.java | 56 +- .../screens/InventoryOperationsScreen.java | 22 +- .../game/screens/InventoryScreen.java | 410 ------------ .../game/screens/SellItems.java | 77 ++- .../game/screens/ShowInventory.java | 164 +++-- .../game/screens/TakeItems.java | 63 +- .../destinationsol/ui/TutorialManager.java | 58 +- .../ui/nui/screens/InventoryScreen.java | 591 ++++++++++++++++++ .../ui/nui/screens/MainGameScreen.java | 20 +- .../ui/nui/screens/TalkScreen.java | 17 +- .../assets/skins/inventoryScreen.skin | 24 + .../assets/skins/mainGameScreen.skin | 16 + .../assets/ui/inventoryScreen.ui | 150 +++++ 18 files changed, 1297 insertions(+), 710 deletions(-) delete mode 100644 engine/src/main/java/org/destinationsol/game/screens/InventoryScreen.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/InventoryScreen.java create mode 100644 engine/src/main/resources/org/destinationsol/assets/skins/inventoryScreen.skin create mode 100644 engine/src/main/resources/org/destinationsol/assets/ui/inventoryScreen.ui diff --git a/engine/src/main/java/org/destinationsol/game/screens/BuyItemsScreen.java b/engine/src/main/java/org/destinationsol/game/screens/BuyItemsScreen.java index 8bf70702f..a17c3e846 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/BuyItemsScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/BuyItemsScreen.java @@ -16,7 +16,6 @@ package org.destinationsol.game.screens; -import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.game.FactionInfo; import org.destinationsol.game.Hero; @@ -24,17 +23,42 @@ import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; import org.destinationsol.ui.nui.screens.TalkScreen; +import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen allows you to purchase items for the hero's ship. + * The purchased items are moved to the hero's inventory and the cost deducted from the hero's money. + */ public class BuyItemsScreen extends InventoryOperationsScreen { - public final SolUiControl buyControl; + private final UIButton[] actionButtons = new UIButton[1]; + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + UIWarnButton buyButton = new UIWarnButton(); + buyButton.setText("Buy"); + buyButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyBuyItem())); + buyButton.subscribe(button -> { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + TalkScreen talkScreen = game.getScreens().talkScreen; + SolShip target = talkScreen.getTarget(); + SolItem selectedItem = inventoryScreen.getSelectedItem(); + if (selectedItem == null) { + return; + } - BuyItemsScreen(InventoryScreen inventoryScreen, GameOptions gameOptions) { - buyControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyBuyItem()); - buyControl.setDisplayName("Buy"); - controls.add(buyControl); + target.getTradeContainer().getItems().remove(selectedItem); + hero.getItemContainer().add(selectedItem); + hero.setMoney(hero.getMoney() - selectedItem.getPrice()); + FactionInfo.setDisposition(target.getFactionID(), 1); + + inventoryScreen.updateItemRows(); + }); + actionButtons[0] = buyButton; } @Override @@ -48,28 +72,27 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + public UIWarnButton getBuyControl() { + return (UIWarnButton) actionButtons[0]; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen is = game.getScreens().inventoryScreen; Hero hero = game.getHero(); TalkScreen talkScreen = game.getScreens().talkScreen; - SolShip target = talkScreen.getTarget(); if (talkScreen.isTargetFar(hero)) { - solApplication.getInputManager().setScreen(solApplication, game.getScreens().oldMainGameScreen); + solApplication.getNuiManager().removeScreen(inventoryScreen); return; } - SolItem selItem = is.getSelectedItem(); + SolItem selItem = inventoryScreen.getSelectedItem(); boolean enabled = selItem != null && hero.getMoney() >= selItem.getPrice() && hero.getItemContainer().canAdd(selItem); - buyControl.setDisplayName(enabled ? "Buy" : "---"); - buyControl.setEnabled(enabled); - if (!enabled) { - return; - } - if (buyControl.isJustOff()) { - target.getTradeContainer().getItems().remove(selItem); - hero.getItemContainer().add(selItem); - hero.setMoney(hero.getMoney() - selItem.getPrice()); - FactionInfo.setDisposition(target.getFactionID(), 1); - } + UIButton buyButton = actionButtons[0]; + buyButton.setText(enabled ? "Buy" : "---"); + buyButton.setEnabled(enabled); } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/ChangeShipScreen.java b/engine/src/main/java/org/destinationsol/game/screens/ChangeShipScreen.java index 4c9390376..eb58af6ff 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ChangeShipScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ChangeShipScreen.java @@ -16,7 +16,6 @@ package org.destinationsol.game.screens; import com.badlogic.gdx.math.Vector2; -import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.game.Hero; import org.destinationsol.game.SolGame; @@ -29,17 +28,33 @@ import org.destinationsol.game.ship.SolShip; import org.destinationsol.game.ship.hulls.Hull; import org.destinationsol.game.ship.hulls.HullConfig; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; import org.destinationsol.ui.nui.screens.TalkScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen allows you to purchase a new ship for the hero. + * The hero's previous ship will be replaced with the purchased ship and the cost deducted from the hero's money. + */ public class ChangeShipScreen extends InventoryOperationsScreen { - private final SolUiControl changeControl; + private final UIButton[] actionButtons = new UIButton[1]; + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton changeButton = new KeyActivatedButton(); + changeButton.setText("Change"); + changeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyChangeShip())); + changeButton.subscribe(button -> { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + SolItem selectedItem = inventoryScreen.getSelectedItem(); - ChangeShipScreen(InventoryScreen inventoryScreen, GameOptions gameOptions) { - changeControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyChangeShip()); - changeControl.setDisplayName("Change"); - controls.add(changeControl); + hero.setMoney(hero.getMoney() - selectedItem.getPrice()); + changeShip(game, hero, (ShipItem) selectedItem); + }); + actionButtons[0] = changeButton; } @Override @@ -53,38 +68,39 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen is = game.getScreens().inventoryScreen; Hero hero = game.getHero(); TalkScreen talkScreen = game.getScreens().talkScreen; if (talkScreen.isTargetFar(hero)) { solApplication.getInputManager().setScreen(solApplication, game.getScreens().oldMainGameScreen); return; } - SolItem selItem = is.getSelectedItem(); + + UIButton changeButton = actionButtons[0]; + + SolItem selItem = inventoryScreen.getSelectedItem(); if (selItem == null) { - changeControl.setDisplayName("---"); - changeControl.setEnabled(false); + changeButton.setText("---"); + changeButton.setEnabled(false); return; } boolean enabled = hasMoneyToBuyShip(hero, selItem); boolean sameShip = isSameShip(hero, selItem); if (enabled && !sameShip) { - changeControl.setDisplayName("Change"); - changeControl.setEnabled(true); + changeButton.setText("Change"); + changeButton.setEnabled(true); } else if (enabled && sameShip) { - changeControl.setDisplayName("Have it"); - changeControl.setEnabled(false); - return; + changeButton.setText("Have it"); + changeButton.setEnabled(false); } else { - changeControl.setDisplayName("---"); - changeControl.setEnabled(false); - return; - } - if (changeControl.isJustOff()) { - hero.setMoney(hero.getMoney() - selItem.getPrice()); - changeShip(game, hero, (ShipItem) selItem); + changeButton.setText("---"); + changeButton.setEnabled(false); } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/ChooseMercenaryScreen.java b/engine/src/main/java/org/destinationsol/game/screens/ChooseMercenaryScreen.java index 3995c9ee3..ffc5b8bac 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ChooseMercenaryScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ChooseMercenaryScreen.java @@ -15,7 +15,6 @@ */ package org.destinationsol.game.screens; -import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.game.SolGame; import org.destinationsol.game.item.ItemContainer; @@ -23,60 +22,88 @@ import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.NUIManager; +import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen shows an overview of all the mercenaries that the hero has hired. + * You can manage each mercenary's independent inventory from here, as well as selecting their equipped items. + */ public class ChooseMercenaryScreen extends InventoryOperationsScreen { - private final SolUiControl giveControl; - private final SolUiControl takeControl; - private final SolUiControl equipControl; + private final UIButton[] actionButtons = new UIButton[3]; private final ItemContainer EMPTY_ITEM_CONTAINER = new ItemContainer(); - ChooseMercenaryScreen(InventoryScreen inventoryScreen, GameOptions gameOptions) { - giveControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyShoot()); - giveControl.setDisplayName("Give Items"); - controls.add(giveControl); + public ChooseMercenaryScreen() { + } + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton giveButton = new KeyActivatedButton(); + giveButton.setText("Give Items"); + giveButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyShoot())); + giveButton.subscribe(button -> { + SolItem selectedItem = inventoryScreen.getSelectedItem(); + SolInputManager inputManager = solApplication.getInputManager(); + NUIManager nuiManager = solApplication.getNuiManager(); + + SolShip solship = ((MercItem) selectedItem).getSolShip(); + inputManager.setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); + nuiManager.removeScreen(inventoryScreen); + inventoryScreen.getGiveItems().setTarget(solship); + inventoryScreen.setOperations(inventoryScreen.getGiveItems()); + nuiManager.pushScreen(inventoryScreen); + }); + actionButtons[0] = giveButton; + + KeyActivatedButton takeButton = new KeyActivatedButton(); + takeButton.setText("Take Items"); + takeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyShoot2())); + takeButton.subscribe(button -> { + SolItem selectedItem = inventoryScreen.getSelectedItem(); + SolInputManager inputManager = solApplication.getInputManager(); + NUIManager nuiManager = solApplication.getNuiManager(); - takeControl = new SolUiControl(inventoryScreen.itemCtrl(1), true, gameOptions.getKeyShoot2()); - takeControl.setDisplayName("Take Items"); - controls.add(takeControl); - - equipControl = new SolUiControl(inventoryScreen.itemCtrl(2), true, gameOptions.getKeyDrop()); - equipControl.setDisplayName("Equip Items"); - controls.add(equipControl); + SolShip solship = ((MercItem) selectedItem).getSolShip(); + inputManager.setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); + inventoryScreen.getTakeItems().setTarget(solship); + nuiManager.removeScreen(inventoryScreen); + inventoryScreen.setOperations(inventoryScreen.getTakeItems()); + nuiManager.pushScreen(inventoryScreen); + }); + actionButtons[1] = takeButton; + + KeyActivatedButton equipButton = new KeyActivatedButton(); + equipButton.setText("Equip Items"); + equipButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyDrop())); + equipButton.subscribe(button -> { + SolItem selectedItem = inventoryScreen.getSelectedItem(); + SolInputManager inputManager = solApplication.getInputManager(); + NUIManager nuiManager = solApplication.getNuiManager(); + + SolShip solship = ((MercItem) selectedItem).getSolShip(); + inputManager.setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); + nuiManager.removeScreen(inventoryScreen); + inventoryScreen.getShowInventory().setTarget(solship); + inventoryScreen.setOperations(inventoryScreen.getShowInventory()); + nuiManager.pushScreen(inventoryScreen); + }); + actionButtons[2] = equipButton; } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - SolGame game = solApplication.getGame(); - InventoryScreen is = game.getScreens().inventoryScreen; - SolInputManager inputMan = solApplication.getInputManager(); - GameScreens screens = game.getScreens(); - SolItem selItem = is.getSelectedItem(); - boolean selNull = selItem != null; + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { + boolean selNull = inventoryScreen.getSelectedItem() != null; - giveControl.setEnabled(selNull); - takeControl.setEnabled(selNull); - equipControl.setEnabled(selNull); + UIButton giveButton = actionButtons[0]; + UIButton takeButton = actionButtons[1]; + UIButton equipButton = actionButtons[2]; - if (giveControl.isJustOff() && selNull) { - SolShip solship = ((MercItem) selItem).getSolShip(); - inputMan.setScreen(solApplication, screens.oldMainGameScreen); - is.giveItemsScreen.setTarget(solship); - is.setOperations(is.giveItemsScreen); - inputMan.addScreen(solApplication, is); - } else if (takeControl.isJustOff() && selNull) { - SolShip solship = ((MercItem) selItem).getSolShip(); - inputMan.setScreen(solApplication, screens.oldMainGameScreen); - is.takeItems.setTarget(solship); - is.setOperations(is.takeItems); - inputMan.addScreen(solApplication, is); - } else if (equipControl.isJustOff() && selNull) { - SolShip solship = ((MercItem) selItem).getSolShip(); - inputMan.setScreen(solApplication, screens.oldMainGameScreen); - is.showInventory.setTarget(solship); - is.setOperations(is.showInventory); - inputMan.addScreen(solApplication, is); - } + giveButton.setEnabled(selNull); + takeButton.setEnabled(selNull); + equipButton.setEnabled(selNull); } @Override @@ -95,4 +122,8 @@ public String getHeader() { return "Mercenaries:"; } + @Override + public UIButton[] getActionButtons() { + return actionButtons; + } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java index ec16472a8..b72e9d99f 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java +++ b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java @@ -21,6 +21,7 @@ import org.destinationsol.ui.SolLayouts; import org.destinationsol.ui.nui.screens.MenuScreen; import org.destinationsol.ui.nui.screens.TalkScreen; +import org.destinationsol.ui.nui.screens.InventoryScreen; import javax.inject.Inject; @@ -49,7 +50,7 @@ public GameScreens(SolApplication cmp, Context context) { } mapScreen = new MapScreen(rightPaneLayout, cmp.isMobile(), cmp.getOptions()); menuScreen = (MenuScreen) cmp.getNuiManager().createScreen("engine:menuScreen"); - inventoryScreen = new InventoryScreen(cmp.getOptions()); + inventoryScreen = (InventoryScreen) cmp.getNuiManager().createScreen("engine:inventoryScreen"); talkScreen = (TalkScreen) cmp.getNuiManager().createScreen("engine:talkScreen"); waypointCreationScreen = new WaypointCreationScreen(layouts.menuLayout, cmp.getOptions(), mapScreen); consoleScreen = new ConsoleScreen(context.get(Console.class)); diff --git a/engine/src/main/java/org/destinationsol/game/screens/GiveItemsScreen.java b/engine/src/main/java/org/destinationsol/game/screens/GiveItemsScreen.java index b0862faa1..3dbe411a0 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/GiveItemsScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/GiveItemsScreen.java @@ -22,17 +22,37 @@ import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen allows the hero to gift items from their inventory to the targeted mercenary. + */ public class GiveItemsScreen extends InventoryOperationsScreen { - private final SolUiControl giveControl; + private final UIButton[] actionButtons = new UIButton[1]; private SolShip target; - GiveItemsScreen(InventoryScreen inventoryScreen, GameOptions gameOptions) { - giveControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeySellItem()); - giveControl.setDisplayName("Give"); - controls.add(giveControl); + public GiveItemsScreen() { + } + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton giveButton = new KeyActivatedButton(); + giveButton.setText("Give"); + giveButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeySellItem())); + giveButton.subscribe(button -> { + Hero hero = solApplication.getGame().getHero(); + SolItem selectedItem = inventoryScreen.getSelectedItem(); + + ItemContainer itemContainer = hero.getItemContainer(); + inventoryScreen.setSelected(itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected())); + itemContainer.remove(selectedItem); + target.getItemContainer().add(selectedItem); + inventoryScreen.updateItemRows(); + }); + actionButtons[0] = giveButton; } @Override @@ -53,40 +73,36 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen inventoryScreen = game.getScreens().inventoryScreen; Hero hero = game.getHero(); - SolItem selItem = inventoryScreen.getSelectedItem(); - if (selItem == null) { - giveControl.setDisplayName("----"); - giveControl.setEnabled(false); + UIButton giveButton = actionButtons[0]; + + SolItem selectedItem = inventoryScreen.getSelectedItem(); + if (selectedItem == null) { + giveButton.setText("----"); + giveButton.setEnabled(false); return; } - boolean isWornAndCanBeGiven = isItemEquippedAndGiveable(selItem, solApplication.getOptions()); - boolean enabled = isItemGiveable(selItem, target); + boolean isWornAndCanBeGiven = isItemEquippedAndGiveable(selectedItem, solApplication.getOptions()); + boolean enabled = isItemGiveable(selectedItem, target); if (enabled && isWornAndCanBeGiven) { - giveControl.setDisplayName("Give"); - giveControl.setEnabled(true); + giveButton.setText("Give"); + giveButton.setEnabled(true); } else if (enabled) { - giveControl.setDisplayName("Unequip it!"); - giveControl.setEnabled(false); + giveButton.setText("Unequip it!"); + giveButton.setEnabled(false); } else { - giveControl.setDisplayName("----"); - giveControl.setEnabled(false); - } - - if (!enabled || !isWornAndCanBeGiven) { - return; - } - if (giveControl.isJustOff()) { - ItemContainer itemContainer = hero.getItemContainer(); - inventoryScreen.setSelected(itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected())); - itemContainer.remove(selItem); - target.getItemContainer().add(selItem); + giveButton.setText("----"); + giveButton.setEnabled(false); } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/HireShipsScreen.java b/engine/src/main/java/org/destinationsol/game/screens/HireShipsScreen.java index 1b3af3928..acba08202 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/HireShipsScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/HireShipsScreen.java @@ -15,7 +15,6 @@ */ package org.destinationsol.game.screens; -import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.game.Hero; import org.destinationsol.game.SolGame; @@ -23,17 +22,33 @@ import org.destinationsol.game.item.MercItem; import org.destinationsol.game.item.SolItem; import org.destinationsol.mercenary.MercenaryUtils; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; import org.destinationsol.ui.nui.screens.TalkScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; public class HireShipsScreen extends InventoryOperationsScreen { - private final SolUiControl hireControl; + private final UIButton[] actionButtons = new UIButton[1]; - HireShipsScreen(InventoryScreen inventoryScreen, GameOptions gameOptions) { - hireControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyHireShip()); - hireControl.setDisplayName("Hire"); - controls.add(hireControl); + public HireShipsScreen() { + } + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton hireButton = new KeyActivatedButton(); + hireButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyHireShip())); + hireButton.subscribe(button -> { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + SolItem selectedItem = inventoryScreen.getSelectedItem(); + + boolean hired = MercenaryUtils.createMerc(game, hero, (MercItem) selectedItem); + if (hired) { + hero.setMoney(hero.getMoney() - selectedItem.getPrice()); + } + }); + actionButtons[0] = hireButton; } @Override @@ -47,27 +62,24 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen is = game.getScreens().inventoryScreen; Hero hero = game.getHero(); TalkScreen talkScreen = game.getScreens().talkScreen; if (talkScreen.isTargetFar(hero)) { solApplication.getInputManager().setScreen(solApplication, game.getScreens().oldMainGameScreen); return; } - SolItem selItem = is.getSelectedItem(); + + UIButton hireButton = actionButtons[0]; + SolItem selItem = inventoryScreen.getSelectedItem(); boolean enabled = selItem != null && hero.getMoney() >= selItem.getPrice(); - hireControl.setDisplayName(enabled ? "Hire" : "---"); - hireControl.setEnabled(enabled); - if (!enabled) { - return; - } - if (hireControl.isJustOff()) { - boolean hired = MercenaryUtils.createMerc(game, hero, (MercItem) selItem); - if (hired) { - hero.setMoney(hero.getMoney() - selItem.getPrice()); - } - } + hireButton.setText(enabled ? "Hire" : "---"); + hireButton.setEnabled(enabled); } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/InventoryOperationsScreen.java b/engine/src/main/java/org/destinationsol/game/screens/InventoryOperationsScreen.java index bffc7b70d..456994790 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/InventoryOperationsScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/InventoryOperationsScreen.java @@ -15,21 +15,35 @@ */ package org.destinationsol.game.screens; +import org.destinationsol.SolApplication; import org.destinationsol.game.SolGame; import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.ui.SolUiBaseScreen; +import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.terasology.nui.widgets.UIButton; +/** + * This is the base class for all inventory operations. + */ public abstract class InventoryOperationsScreen extends SolUiBaseScreen { - abstract ItemContainer getItems(SolGame game); + public abstract ItemContainer getItems(SolGame game); - boolean isUsing(SolGame game, SolItem item) { + public boolean isUsing(SolGame game, SolItem item) { return false; } - float getPriceMul() { + public float getPriceMul() { return 1; } - abstract String getHeader(); + public abstract String getHeader(); + + public abstract UIButton[] getActionButtons(); + + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + } + + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { + } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/InventoryScreen.java b/engine/src/main/java/org/destinationsol/game/screens/InventoryScreen.java deleted file mode 100644 index f4fe55c8b..000000000 --- a/engine/src/main/java/org/destinationsol/game/screens/InventoryScreen.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2018 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.destinationsol.game.screens; - -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import org.destinationsol.Const; -import org.destinationsol.GameOptions; -import org.destinationsol.SolApplication; -import org.destinationsol.common.SolColor; -import org.destinationsol.game.SolGame; -import org.destinationsol.game.item.ItemContainer; -import org.destinationsol.game.item.SolItem; -import org.destinationsol.menu.MenuLayout; -import org.destinationsol.ui.DisplayDimensions; -import org.destinationsol.ui.FontSize; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiBaseScreen; -import org.destinationsol.ui.SolUiControl; -import org.destinationsol.ui.UiDrawer; - -import java.util.ArrayList; -import java.util.List; - -public class InventoryScreen extends SolUiBaseScreen { - // TODO: Rename! - private static final ItemContainer EMPTY_CONTAINER = new ItemContainer(); - private static final float HEADER_TEXT_OFFSET = .005f; - private static final float SMALL_GAP = .004f; - private static final int BUTTON_ROWS = 4; - private static final float IMG_COL_PERC = .1f; - private static final float EQUI_COL_PERC = .1f; - private static final float PRICE_COL_PERC = .1f; - private static final float AMT_COL_PERC = .1f; - - public final ShowInventory showInventory; - public final BuyItemsScreen buyItemsScreen; - public final SellItems sellItems; - public final ChangeShipScreen changeShipScreen; - public final HireShipsScreen hireShipsScreen; - // The below screens deal with mercenaries - public final ChooseMercenaryScreen chooseMercenaryScreen; - public final GiveItemsScreen giveItemsScreen; - public final TakeItems takeItems; - - public final SolUiControl[] itemControls; - private final SolUiControl previousControl; - private final SolUiControl upControl; - public final SolUiControl nextControl; - public final SolUiControl closeControl; - public final SolUiControl downControl; - - private final Rectangle myArea; - private final Rectangle myListArea; - private final Rectangle myDetailArea; - private final Rectangle myItemCtrlArea; - private final Vector2 myDetailHeaderPos; - private final Vector2 myListHeaderPos; - - private int myPage; - private List mySelected; - private InventoryOperationsScreen myOperations; - - public InventoryScreen(GameOptions gameOptions) { - DisplayDimensions displayDimensions = SolApplication.displayDimensions; - - float contentW = .8f; - float col0 = displayDimensions.getRatio() / 2 - contentW / 2; - float row0 = .2f; - float row = row0; - float backgroundGap = MenuLayout.BG_BORDER; - float bigGap = SMALL_GAP * 6; - float headerH = .03f; - - // list header & controls - myListHeaderPos = new Vector2(col0 + HEADER_TEXT_OFFSET, row + HEADER_TEXT_OFFSET); // offset hack - float listCtrlW = contentW * .15f; - Rectangle nextArea = new Rectangle(col0 + contentW - listCtrlW, row, listCtrlW, headerH); - nextControl = new SolUiControl(nextArea, true, gameOptions.getKeyRight()); - nextControl.setDisplayName(">"); - controls.add(nextControl); - Rectangle prevArea = new Rectangle(nextArea.x - SMALL_GAP - listCtrlW, row, listCtrlW, headerH); - previousControl = new SolUiControl(prevArea, true, gameOptions.getKeyLeft()); - previousControl.setDisplayName("<"); - controls.add(previousControl); - row += headerH + SMALL_GAP; - - // list - float itemRowH = .04f; - float listRow0 = row; - itemControls = new SolUiControl[Const.ITEM_GROUPS_PER_PAGE]; - for (int i = 0; i < Const.ITEM_GROUPS_PER_PAGE; i++) { - Rectangle itemR = new Rectangle(col0, row, contentW, itemRowH); - SolUiControl itemCtrl = new SolUiControl(itemR, true); - itemControls[i] = itemCtrl; - controls.add(itemCtrl); - row += itemRowH + SMALL_GAP; - } - myListArea = new Rectangle(col0, row, contentW, row - SMALL_GAP - listRow0); - row += bigGap; - - // detail header & area - myDetailHeaderPos = new Vector2(col0 + HEADER_TEXT_OFFSET, row + HEADER_TEXT_OFFSET); // offset hack - row += headerH + SMALL_GAP; - float itemCtrlAreaW = contentW * .4f; - myItemCtrlArea = new Rectangle(col0 + contentW - itemCtrlAreaW, row, itemCtrlAreaW, .2f); - myDetailArea = new Rectangle(col0, row, contentW - itemCtrlAreaW - SMALL_GAP, myItemCtrlArea.height); - row += myDetailArea.height; - - // whole - myArea = new Rectangle(col0 - backgroundGap, row0 - backgroundGap, contentW + backgroundGap * 2, row - row0 + backgroundGap * 2); - - closeControl = new SolUiControl(itemCtrl(3), true, gameOptions.getKeyClose()); - closeControl.setDisplayName("Close"); - controls.add(closeControl); - - showInventory = new ShowInventory(this, gameOptions); - buyItemsScreen = new BuyItemsScreen(this, gameOptions); - sellItems = new SellItems(this, gameOptions); - changeShipScreen = new ChangeShipScreen(this, gameOptions); - hireShipsScreen = new HireShipsScreen(this, gameOptions); - chooseMercenaryScreen = new ChooseMercenaryScreen(this, gameOptions); - giveItemsScreen = new GiveItemsScreen(this, gameOptions); - takeItems = new TakeItems(this, gameOptions); - upControl = new SolUiControl(null, true, gameOptions.getKeyUp()); - controls.add(upControl); - downControl = new SolUiControl(null, true, gameOptions.getKeyDown()); - controls.add(downControl); - } - - @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - if (clickedOutside) { - closeControl.maybeFlashPressed(solApplication.getOptions().getKeyClose()); - return; - } - if (closeControl.isJustOff()) { - - SolGame game = solApplication.getGame(); - // Make sure the ChooseMercenaryScreen screen comes back up when we exit a mercenary related screen - if (myOperations == giveItemsScreen || myOperations == takeItems || (myOperations == showInventory && showInventory.getTarget() != game.getHero().getShip())) { - SolInputManager inputMan = solApplication.getInputManager(); - GameScreens screens = game.getScreens(); - InventoryScreen is = screens.inventoryScreen; - - inputMan.setScreen(solApplication, screens.oldMainGameScreen); - is.setOperations(is.chooseMercenaryScreen); - inputMan.addScreen(solApplication, is); - } - solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); - return; - } - if (previousControl.isJustOff()) { - myPage--; - } - if (nextControl.isJustOff()) { - myPage++; - } - - ItemContainer itemContainer = myOperations.getItems(solApplication.getGame()); - if (itemContainer == null) { - itemContainer = EMPTY_CONTAINER; - } - int groupCount = itemContainer.groupCount(); - int pageCount = groupCount / Const.ITEM_GROUPS_PER_PAGE; - if (pageCount == 0 || pageCount * Const.ITEM_GROUPS_PER_PAGE < groupCount) { - pageCount += 1; - } - if (myPage < 0) { - myPage = 0; - } - if (myPage >= pageCount) { - myPage = pageCount - 1; - } - - previousControl.setEnabled(0 < myPage); - nextControl.setEnabled(myPage < pageCount - 1); - - if (!itemContainer.containsGroup(mySelected)) { - mySelected = null; - } - int selIdx = -1; - int offset = myPage * Const.ITEM_GROUPS_PER_PAGE; - boolean hNew = showingHeroItems(solApplication); - for (int i = 0; i < itemControls.length; i++) { - SolUiControl itemCtrl = itemControls[i]; - int groupIdx = offset + i; - boolean ctrlEnabled = groupIdx < groupCount; - itemCtrl.setEnabled(ctrlEnabled); - if (!ctrlEnabled) { - continue; - } - List group = itemContainer.getGroup(groupIdx); - if (hNew && itemContainer.isNew(group)) { - itemCtrl.enableWarn(); - } - if (itemCtrl.isJustOff()) { - mySelected = group; - } - if (mySelected == group) { - selIdx = groupIdx; - } - } - if (selIdx < 0 && groupCount > 0) { - mySelected = itemContainer.getGroup(offset); - } - if (upControl.isJustOff() && selIdx > 0) { - selIdx--; - mySelected = itemContainer.getGroup(selIdx); - if (selIdx < offset) { - myPage--; - } - } - if (downControl.isJustOff() && selIdx < groupCount - 1) { - selIdx++; - mySelected = itemContainer.getGroup(selIdx); - if (selIdx >= offset + Const.ITEM_GROUPS_PER_PAGE) { - myPage++; - } - } - if (mySelected != null) { - itemContainer.seen(mySelected); - } - } - - @Override - public boolean isCursorOnBackground(SolInputManager.InputPointer inputPointer) { - return myArea.contains(inputPointer.x, inputPointer.y); - } - - @Override - public void onAdd(SolApplication solApplication) { - if (myOperations != null) { - solApplication.getInputManager().addScreen(solApplication, myOperations); - } - myPage = 0; - mySelected = null; - } - - @Override - public void drawBackground(UiDrawer uiDrawer, SolApplication solApplication) { - uiDrawer.draw(myArea, SolColor.UI_BG); - } - - @Override - public void drawImages(UiDrawer uiDrawer, SolApplication solApplication) { - SolGame game = solApplication.getGame(); - ItemContainer itemContainer = myOperations.getItems(game); - if (itemContainer == null) { - itemContainer = EMPTY_CONTAINER; - } - - float imgColW = myListArea.width * IMG_COL_PERC; - float rowH = itemControls[0].getScreenArea().height; - float imgSz = imgColW < rowH ? imgColW : rowH; - - uiDrawer.draw(myDetailArea, SolColor.UI_INACTIVE); - for (int i = 0; i < itemControls.length; i++) { - int groupIdx = myPage * Const.ITEM_GROUPS_PER_PAGE + i; - int groupCount = itemContainer.groupCount(); - if (groupCount <= groupIdx) { - continue; - } - SolUiControl itemCtrl = itemControls[i]; - List group = itemContainer.getGroup(groupIdx); - SolItem item = group.get(0); - TextureAtlas.AtlasRegion tex = item.getIcon(game); - Rectangle rect = itemCtrl.getScreenArea(); - float rowCenterY = rect.y + rect.height / 2; - uiDrawer.draw(uiDrawer.whiteTexture, imgSz, imgSz, imgSz / 2, imgSz / 2, rect.x + imgColW / 2, rowCenterY, 0, item.getItemType().uiColor); - uiDrawer.draw(tex, imgSz, imgSz, imgSz / 2, imgSz / 2, rect.x + imgColW / 2, rowCenterY, 0, SolColor.WHITE); - } - } - - @Override - public void drawText(UiDrawer uiDrawer, SolApplication solApplication) { - SolGame game = solApplication.getGame(); - ItemContainer itemContainer = myOperations.getItems(game); - if (itemContainer == null) { - itemContainer = EMPTY_CONTAINER; - } - - float imgColW = myListArea.width * IMG_COL_PERC; - float equiColW = myListArea.width * EQUI_COL_PERC; - float priceWidth = myListArea.width * PRICE_COL_PERC; - float amtWidth = myListArea.width * AMT_COL_PERC; - float nameWidth = myListArea.width - imgColW - equiColW - priceWidth - amtWidth; - for (int i = 0; i < itemControls.length; i++) { - int groupIdx = myPage * Const.ITEM_GROUPS_PER_PAGE + i; - int groupCount = itemContainer.groupCount(); - if (groupCount <= groupIdx) { - continue; - } - SolUiControl itemCtrl = itemControls[i]; - List group = itemContainer.getGroup(groupIdx); - SolItem item = group.get(0); - Rectangle rect = itemCtrl.getScreenArea(); - float rowCenterY = rect.y + rect.height / 2; - if (myOperations.isUsing(game, item)) { - uiDrawer.drawString("using", rect.x + imgColW + equiColW / 2, rowCenterY, FontSize.WINDOW, true, SolColor.WHITE); - } - uiDrawer.drawString(item.getDisplayName(), rect.x + equiColW + imgColW + nameWidth / 2, rowCenterY, FontSize.WINDOW, true, - mySelected == group ? SolColor.WHITE : SolColor.G); - int count = itemContainer.getCount(groupIdx); - if (count > 1) { - uiDrawer.drawString("x" + count, rect.x + rect.width - amtWidth / 2, rowCenterY, FontSize.WINDOW, true, SolColor.WHITE); - } - float mul = myOperations.getPriceMul(); - if (mul > 0) { - float price = item.getPrice() * mul; - uiDrawer.drawString("$" + (int) price, rect.x + rect.width - amtWidth - priceWidth / 2, rowCenterY, FontSize.WINDOW, true, SolColor.LG); - } - } - - uiDrawer.drawString(myOperations.getHeader(), myListHeaderPos.x, myListHeaderPos.y, FontSize.WINDOW, UiDrawer.TextAlignment.LEFT, false, SolColor.WHITE); - uiDrawer.drawString("Selected Item:", myDetailHeaderPos.x, myDetailHeaderPos.y, FontSize.WINDOW, UiDrawer.TextAlignment.LEFT, false, SolColor.WHITE); - if (mySelected != null && !mySelected.isEmpty()) { - SolItem selItem = mySelected.get(0); - String desc = selItem.getDisplayName() + "\n" + selItem.getDescription(); - uiDrawer.drawString(desc, myDetailArea.x + .015f, myDetailArea.y + .015f, FontSize.WINDOW, UiDrawer.TextAlignment.LEFT, false, SolColor.WHITE); - } - } - - @Override - public boolean reactsToClickOutside() { - return true; - } - - @Override - public void blurCustom(SolApplication solApplication) { - if (!showingHeroItems(solApplication)) { - return; - } - SolGame game = solApplication.getGame(); - ItemContainer items = myOperations.getItems(game); - if (items != null) { - items.markAllAsSeen(); - } - } - - private boolean showingHeroItems(SolApplication application) { - return application.getGame().getHero().getShip() == showInventory.getTarget() || myOperations == sellItems; - } - - public Rectangle itemCtrl(int row) { - float h = (myItemCtrlArea.height - SMALL_GAP * (BUTTON_ROWS - 1)) / BUTTON_ROWS; - return new Rectangle(myItemCtrlArea.x, myItemCtrlArea.y + (h + SMALL_GAP) * row, myItemCtrlArea.width, h); - } - - public List getSelected() { - return mySelected; - } - - public void setSelected(List selected) { - mySelected = selected; - } - - public SolItem getSelectedItem() { - return mySelected == null || mySelected.isEmpty() ? null : mySelected.get(0); - } - - public InventoryOperationsScreen getOperations() { - return myOperations; - } - - public void setOperations(InventoryOperationsScreen operations) { - myOperations = operations; - } - - public int getPage() { - return myPage; - } - - public List getEquippedItemUIControlsForTutorial(SolGame game) { - List controls = new ArrayList<>(); - ItemContainer itemContainer = myOperations.getItems(game); - if (itemContainer == null) { - return controls; - } - - for (int i = 0; i < itemControls.length; i++) { - int groupIdx = myPage * Const.ITEM_GROUPS_PER_PAGE + i; - int groupCount = itemContainer.groupCount(); - if (groupCount <= groupIdx) { - continue; - } - SolUiControl itemCtrl = itemControls[i]; - List group = itemContainer.getGroup(groupIdx); - SolItem item = group.get(0); - if (myOperations.isUsing(game, item)) { - controls.add(itemCtrl); - } - } - return controls; - } -} diff --git a/engine/src/main/java/org/destinationsol/game/screens/SellItems.java b/engine/src/main/java/org/destinationsol/game/screens/SellItems.java index 76c34d8a7..13f5333d8 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/SellItems.java +++ b/engine/src/main/java/org/destinationsol/game/screens/SellItems.java @@ -22,19 +22,45 @@ import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; import org.destinationsol.ui.nui.screens.TalkScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen allows the hero to sell their items in exchange for in-game currency (money). + * The sold items are moved into the vendor's inventory. + */ public class SellItems extends InventoryOperationsScreen { private static float PERC = .8f; - private final SolUiControl sellControl; + private final UIButton[] actionButtons = new UIButton[1]; - SellItems(InventoryScreen inventoryScreen, GameOptions gameOptions) { - sellControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeySellItem()); - sellControl.setDisplayName("Sell"); - controls.add(sellControl); + public SellItems() { + } + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton sellButton = new KeyActivatedButton(); + sellButton.setText("Sell"); + sellButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeySellItem())); + sellButton.subscribe(button -> { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + SolItem selectedItem = inventoryScreen.getSelectedItem(); + TalkScreen talkScreen = game.getScreens().talkScreen; + SolShip target = talkScreen.getTarget(); + + ItemContainer itemContainer = hero.getItemContainer(); + inventoryScreen.setSelected(itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected())); + itemContainer.remove(selectedItem); + target.getTradeContainer().getItems().add(selectedItem); + hero.setMoney(hero.getMoney() + selectedItem.getPrice() * PERC); + + inventoryScreen.updateItemRows(); + }); + actionButtons[0] = sellButton; } @Override @@ -60,9 +86,15 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen inventoryScreen = game.getScreens().inventoryScreen; + UIButton sellButton = actionButtons[0]; + TalkScreen talkScreen = game.getScreens().talkScreen; SolShip target = talkScreen.getTarget(); Hero hero = game.getHero(); @@ -72,8 +104,8 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi } SolItem selItem = inventoryScreen.getSelectedItem(); if (selItem == null) { - sellControl.setDisplayName("----"); - sellControl.setEnabled(false); + sellButton.setText("----"); + sellButton.setEnabled(false); return; } @@ -81,25 +113,14 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi boolean enabled = isItemSellable(selItem, target); if (enabled && isWornAndCanBeSold) { - sellControl.setDisplayName("Sell"); - sellControl.setEnabled(true); + sellButton.setText("Sell"); + sellButton.setEnabled(true); } else if (enabled) { - sellControl.setDisplayName("Unequip it!"); - sellControl.setEnabled(false); + sellButton.setText("Unequip it!"); + sellButton.setEnabled(false); } else { - sellControl.setDisplayName("----"); - sellControl.setEnabled(false); - } - - if (!enabled || !isWornAndCanBeSold) { - return; - } - if (sellControl.isJustOff()) { - ItemContainer itemContainer = hero.getItemContainer(); - inventoryScreen.setSelected(itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected())); - itemContainer.remove(selItem); - target.getTradeContainer().getItems().add(selItem); - hero.setMoney(hero.getMoney() + selItem.getPrice() * PERC); + sellButton.setText("----"); + sellButton.setEnabled(false); } } diff --git a/engine/src/main/java/org/destinationsol/game/screens/ShowInventory.java b/engine/src/main/java/org/destinationsol/game/screens/ShowInventory.java index 07d8dba0a..216c3266a 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ShowInventory.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ShowInventory.java @@ -21,81 +21,78 @@ import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +import java.util.List; + +/** + * This screen shows the current inventory of the targeted ship. + * You can also equip and de-equip items here, as well as force the ship to drop those items out into space. + */ public class ShowInventory extends InventoryOperationsScreen { - public final SolUiControl eq1Control; - private final SolUiControl eq2Control; - public final SolUiControl dropControl; - + private final UIButton[] actionButtons = new UIButton[3]; + private SolShip target; - ShowInventory(InventoryScreen inventoryScreen, GameOptions gameOptions) { - eq1Control = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyEquip()); - eq1Control.setDisplayName("Eq"); - controls.add(eq1Control); - - eq2Control = new SolUiControl(inventoryScreen.itemCtrl(1), true, gameOptions.getKeyEquip2()); - eq2Control.setDisplayName("Eq2"); - controls.add(eq2Control); - - dropControl = new SolUiControl(inventoryScreen.itemCtrl(2), true, gameOptions.getKeyDrop()); - dropControl.setDisplayName("Drop"); - controls.add(dropControl); + public ShowInventory() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - SolGame game = solApplication.getGame(); - InventoryScreen inventoryScreen = game.getScreens().inventoryScreen; - SolItem selItem = inventoryScreen.getSelectedItem(); - - eq1Control.setDisplayName("---"); - eq1Control.setEnabled(false); - eq2Control.setDisplayName("---"); - eq2Control.setEnabled(false); - dropControl.setEnabled(false); - - if (selItem == null || target == null) { - return; - } - - dropControl.setEnabled(true); - if (dropControl.isJustOff()) { - ItemContainer itemContainer = target.getItemContainer(); - inventoryScreen.setSelected(itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected())); - target.dropItem(solApplication.getGame(), selItem); - return; - } + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + GameOptions gameOptions = solApplication.getOptions(); - Boolean equipped1 = target.maybeUnequip(game, selItem, false, false); - boolean canEquip1 = target.maybeEquip(game, selItem, false, false); - Boolean equipped2 = target.maybeUnequip(game, selItem, true, false); - boolean canEquip2 = target.maybeEquip(game, selItem, true, false); + UIWarnButton equip1Button = new UIWarnButton(); + equip1Button.setText("Eq"); + equip1Button.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyEquip())); + equip1Button.subscribe(button -> { + SolGame game = solApplication.getGame(); + SolItem selItem = inventoryScreen.getSelectedItem(); + if (selItem == null) { + button.setEnabled(false); + return; + } - if (equipped1 || canEquip1) { - eq1Control.setDisplayName(equipped1 ? "Unequip" : "Equip"); - eq1Control.setEnabled(true); - } - if (equipped2 || canEquip2) { - eq2Control.setDisplayName(equipped2 ? "Unequip" : "Set Gun 2"); - eq2Control.setEnabled(true); - } - if (eq1Control.isJustOff()) { - if (equipped1) { + if (target.maybeUnequip(game, selItem, false, false)) { target.maybeUnequip(game, selItem, false, true); } else { target.maybeEquip(game, selItem, false, true); } - } - if (eq2Control.isJustOff()) { - if (equipped2) { + inventoryScreen.updateItemRows(); + }); + + UIWarnButton equip2Button = new UIWarnButton(); + equip2Button.setText("Eq2"); + equip2Button.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyEquip2())); + equip2Button.subscribe(button -> { + SolGame game = solApplication.getGame(); + SolItem selItem = inventoryScreen.getSelectedItem(); + if (target.maybeUnequip(game, selItem, true, false)) { target.maybeUnequip(game, selItem, true, true); } else { target.maybeEquip(game, selItem, true, true); } - } + inventoryScreen.updateItemRows(); + }); + + UIWarnButton dropButton = new UIWarnButton(); + dropButton.setText("Drop"); + dropButton.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyDrop())); + dropButton.subscribe(button -> { + SolItem selItem = inventoryScreen.getSelectedItem(); + ItemContainer itemContainer = target.getItemContainer(); + List newSelection = itemContainer.getSelectionAfterRemove(inventoryScreen.getSelected()); + target.dropItem(solApplication.getGame(), selItem); + inventoryScreen.updateItemRows(); + + inventoryScreen.setSelected(newSelection); + }); + + actionButtons[0] = equip1Button; + actionButtons[1] = equip2Button; + actionButtons[2] = dropButton; } @Override @@ -117,7 +114,56 @@ public float getPriceMul() { public String getHeader() { return "Items:"; } - + + @Override + public UIButton[] getActionButtons() { + return actionButtons; + } + + public UIWarnButton getEq1Control() { + return (UIWarnButton) actionButtons[0]; + } + + public UIWarnButton getDropControl() { + return (UIWarnButton) actionButtons[2]; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { + SolGame game = solApplication.getGame(); + SolItem selItem = inventoryScreen.getSelectedItem(); + + UIButton equip1Button = actionButtons[0]; + UIButton equip2Button = actionButtons[1]; + UIButton dropButton = actionButtons[2]; + + equip1Button.setText("---"); + equip1Button.setEnabled(false); + equip2Button.setText("---"); + equip2Button.setEnabled(false); + dropButton.setEnabled(false); + + if (selItem == null || target == null) { + return; + } + + dropButton.setEnabled(true); + + boolean equipped1 = target.maybeUnequip(game, selItem, false, false); + boolean canEquip1 = target.maybeEquip(game, selItem, false, false); + boolean equipped2 = target.maybeUnequip(game, selItem, true, false); + boolean canEquip2 = target.maybeEquip(game, selItem, true, false); + + if (equipped1 || canEquip1) { + equip1Button.setText(equipped1 ? "Unequip" : "Equip"); + equip1Button.setEnabled(true); + } + if (equipped2 || canEquip2) { + equip2Button.setText(equipped2 ? "Unequip" : "Set Gun 2"); + equip2Button.setEnabled(true); + } + } + /** * Sets the ship whose inventory we're viewing. * @param solship The mercenary being interacted with diff --git a/engine/src/main/java/org/destinationsol/game/screens/TakeItems.java b/engine/src/main/java/org/destinationsol/game/screens/TakeItems.java index 00e32cd6f..e5da23d26 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/TakeItems.java +++ b/engine/src/main/java/org/destinationsol/game/screens/TakeItems.java @@ -16,24 +16,42 @@ package org.destinationsol.game.screens; -import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.game.Hero; import org.destinationsol.game.SolGame; import org.destinationsol.game.item.ItemContainer; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.ship.SolShip; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; +/** + * This screen allows the hero to take items acquired by their hired mercenaries. + * The items taken will be transferred directly into the hero's inventory. + */ public class TakeItems extends InventoryOperationsScreen { - public final SolUiControl takeControl; + public final UIButton[] actionButtons = new UIButton[1]; private SolShip target; - TakeItems(InventoryScreen inventoryScreen, GameOptions gameOptions) { - takeControl = new SolUiControl(inventoryScreen.itemCtrl(0), true, gameOptions.getKeyShoot()); - takeControl.setDisplayName("Take"); - controls.add(takeControl); + public TakeItems() { + } + + @Override + public void initialise(SolApplication solApplication, InventoryScreen inventoryScreen) { + KeyActivatedButton takeButton = new KeyActivatedButton(); + takeButton.setText("Take"); + takeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyShoot())); + takeButton.subscribe(button -> { + SolItem selectedItem = inventoryScreen.getSelectedItem(); + Hero hero = solApplication.getGame().getHero(); + + target.getItemContainer().remove(selectedItem); + hero.getItemContainer().add(selectedItem); + inventoryScreen.updateItemRows(); + }); + actionButtons[0] = takeButton; } @Override @@ -47,24 +65,21 @@ public String getHeader() { } @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { + public UIButton[] getActionButtons() { + return actionButtons; + } + + @Override + public void update(SolApplication solApplication, InventoryScreen inventoryScreen) { SolGame game = solApplication.getGame(); - InventoryScreen is = game.getScreens().inventoryScreen; Hero hero = game.getHero(); - - SolItem selItem = is.getSelectedItem(); - boolean enabled = selItem != null && hero.getItemContainer().canAdd(selItem); - takeControl.setDisplayName(enabled ? "Take" : "---"); - takeControl.setEnabled(enabled); - - if (!enabled) { - return; - } - - if (takeControl.isJustOff()) { - target.getItemContainer().remove(selItem); - hero.getItemContainer().add(selItem); - } + + UIButton takeButton = actionButtons[0]; + + SolItem selectedItem = inventoryScreen.getSelectedItem(); + boolean enabled = selectedItem != null && hero.getItemContainer().canAdd(selectedItem); + takeButton.setText(enabled ? "Take" : "---"); + takeButton.setEnabled(enabled); } /** diff --git a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java index 69d733734..e407e8eba 100644 --- a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java +++ b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java @@ -15,6 +15,7 @@ */ package org.destinationsol.ui; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Rectangle; import org.destinationsol.GameOptions; import org.destinationsol.common.SolColor; @@ -22,9 +23,9 @@ import org.destinationsol.game.UpdateAwareSystem; import org.destinationsol.game.item.SolItem; import org.destinationsol.game.screens.GameScreens; -import org.destinationsol.game.screens.InventoryScreen; import org.destinationsol.game.screens.MainGameScreen; import org.destinationsol.game.screens.ShipMixedControl; +import org.destinationsol.ui.nui.screens.InventoryScreen; import org.destinationsol.ui.nui.screens.UIShipControlsScreen; import org.destinationsol.ui.nui.widgets.UIWarnButton; @@ -137,23 +138,22 @@ public void start() { } if (mouseCtrl || mobile) { - addStep("In the inventory,\nselect the second row", screens.inventoryScreen.itemControls[1]); + addStep("In the inventory,\nselect the second row", screens.inventoryScreen.getRowButton(1)); } else { - addStep("In the inventory,\nselect the next item (" + gameOptions.getKeyDownName() + " key)", - screens.inventoryScreen.downControl); + addStep("In the inventory,\nselect the next item (" + gameOptions.getKeyDownName() + " key)", gameOptions.getKeyDown()); } if (mouseCtrl || mobile) { - addStep("Go to the next page", screens.inventoryScreen.nextControl, true); + addStep("Go to the next page", screens.inventoryScreen.getNextButton(), true); } else { - addStep("Go to the next page\n(" + gameOptions.getKeyRightName() + " key)", screens.inventoryScreen.nextControl, true); + addStep("Go to the next page\n(" + gameOptions.getKeyRightName() + " key)", screens.inventoryScreen.getNextButton(), true); } if (mouseCtrl || mobile) { - addStep("Throw away some item\nyou don't use", screens.inventoryScreen.showInventory.dropControl); + addStep("Throw away some item\nyou don't use", screens.inventoryScreen.getShowInventory().getDropControl()); } else { addStep("Throw away some item\nyou don't use (" + gameOptions.getKeyDropName() + " key)", - screens.inventoryScreen.showInventory.dropControl); + screens.inventoryScreen.getShowInventory().getDropControl()); } // Extra step to make sure an equipped item is selected before asking player to unequip @@ -164,22 +164,22 @@ public void start() { } if (mobile) { - addStep("Unequip the item\nthat is used now", screens.inventoryScreen.showInventory.eq1Control); + addStep("Unequip the item\nthat is used now", screens.inventoryScreen.getShowInventory().getEq1Control()); } else { addStep("Unequip the item\nthat is used now (" + gameOptions.getKeyEquipName() + " key)", - screens.inventoryScreen.showInventory.eq1Control); + screens.inventoryScreen.getShowInventory().getEq1Control()); } if (mobile) { - addStep("Now equip it again", screens.inventoryScreen.showInventory.eq1Control); + addStep("Now equip it again", screens.inventoryScreen.getShowInventory().getEq1Control()); } else { - addStep("Now equip it again\n(" + gameOptions.getKeyEquipName() + " key)", screens.inventoryScreen.showInventory.eq1Control); + addStep("Now equip it again\n(" + gameOptions.getKeyEquipName() + " key)", screens.inventoryScreen.getShowInventory().getEq1Control()); } if (mobile) { - addStep("Close the inventory\n(Touch the screen outside inventory)", screens.inventoryScreen.closeControl, true); + addStep("Close the inventory\n(Touch the screen outside inventory)", screens.inventoryScreen.getCloseButton(), true); } else { - addStep("Close the inventory (" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.closeControl, true); + addStep("Close the inventory (" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.getCloseButton(), true); } if (mouseCtrl) { @@ -204,15 +204,15 @@ public void start() { } if (mobile) { - addStep("Buy some item", screens.inventoryScreen.buyItemsScreen.buyControl); + addStep("Buy some item", screens.inventoryScreen.getBuyItemsScreen().getBuyControl()); } else { - addStep("Buy some item\n(" + gameOptions.getKeyBuyItemName() + " key)", screens.inventoryScreen.buyItemsScreen.buyControl); + addStep("Buy some item\n(" + gameOptions.getKeyBuyItemName() + " key)", screens.inventoryScreen.getBuyItemsScreen().getBuyControl()); } if (mobile) { - addStep("Close the Buy screen\n(Touch the screen outside inventory)", screens.inventoryScreen.closeControl, true); + addStep("Close the Buy screen\n(Touch the screen outside inventory)", screens.inventoryScreen.getCloseButton(), true); } else { - addStep("Close the Buy screen\n(" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.closeControl, true); + addStep("Close the Buy screen\n(" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.getCloseButton(), true); } if (mouseCtrl) { @@ -250,6 +250,10 @@ private void addStep(String text, SolUiControl ctrl) { addStep(text, ctrl, false); } + private void addStep(String text, int key) { + steps.add(new KeyPressedStep(text, key)); + } + private void addStep(String text, UIWarnButton ctrl) { addStep(text, ctrl, false); } @@ -385,10 +389,24 @@ public boolean canProgressToNextStep() { // Highlight all equipped items on opened inventory page @Override public void highlight() { - List equippedItemControls = inventoryScreen.getEquippedItemUIControlsForTutorial(game); - for (SolUiControl control : equippedItemControls) { + List equippedItemControls = inventoryScreen.getEquippedItemUIControlsForTutorial(); + for (UIWarnButton control : equippedItemControls) { control.enableWarn(); } } } + + public static class KeyPressedStep extends Step { + private final int key; + + public KeyPressedStep(String text, int key) { + super(text, null, false); + this.key = key; + } + + @Override + public boolean canProgressToNextStep() { + return Gdx.input.isKeyJustPressed(key); + } + } } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/InventoryScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/InventoryScreen.java new file mode 100644 index 000000000..9f1534ac2 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/InventoryScreen.java @@ -0,0 +1,591 @@ +/* + * Copyright 2021 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.destinationsol.ui.nui.screens; + +import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import org.destinationsol.Const; +import org.destinationsol.SolApplication; +import org.destinationsol.assets.Assets; +import org.destinationsol.game.item.ItemContainer; +import org.destinationsol.game.item.SolItem; +import org.destinationsol.game.screens.BuyItemsScreen; +import org.destinationsol.game.screens.ChangeShipScreen; +import org.destinationsol.game.screens.ChooseMercenaryScreen; +import org.destinationsol.game.screens.GameScreens; +import org.destinationsol.game.screens.GiveItemsScreen; +import org.destinationsol.game.screens.HireShipsScreen; +import org.destinationsol.game.screens.InventoryOperationsScreen; +import org.destinationsol.game.screens.SellItems; +import org.destinationsol.game.screens.ShowInventory; +import org.destinationsol.game.screens.TakeItems; +import org.destinationsol.ui.SolInputManager; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.terasology.nui.Color; +import org.terasology.nui.HorizontalAlign; +import org.terasology.nui.UIWidget; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.backends.libgdx.GdxColorUtil; +import org.terasology.nui.backends.libgdx.LibGDXTexture; +import org.terasology.nui.events.NUIKeyEvent; +import org.terasology.nui.layouts.ColumnLayout; +import org.terasology.nui.layouts.ScrollableArea; +import org.terasology.nui.layouts.relative.HorizontalHint; +import org.terasology.nui.layouts.relative.RelativeLayout; +import org.terasology.nui.layouts.relative.RelativeLayoutHint; +import org.terasology.nui.layouts.relative.VerticalHint; +import org.terasology.nui.widgets.UIButton; +import org.terasology.nui.widgets.UIImage; +import org.terasology.nui.widgets.UILabel; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * The Inventory screen displays a paginate-able list of {@link SolItem} that you can select and view information on. + * Specialised functionality and logic for the screen is implemented via an assigned {@link InventoryOperationsScreen}, + * which can provide up to 3 additional "action buttons" placed in the bottom-right corner of the screen. + */ +public class InventoryScreen extends NUIScreenLayer { + private final SolApplication solApplication; + private UILabel titleLabel; + private ColumnLayout inventoryRows; + private UIWarnButton nextButton; + private UIWarnButton previousButton; + private ScrollableArea descriptionScrollArea; + private UILabel descriptionBox; + private ColumnLayout inventoryActionButtons; + private UIWarnButton closeButton; + private InventoryOperationsScreen inventoryOperations; + private int selectedIndex; + private int page; + + private ShowInventory showInventory; + private BuyItemsScreen buyItemsScreen; + private SellItems sellItems; + private ChangeShipScreen changeShipScreen; + private HireShipsScreen hireShipsScreen; + // The below screens deal with mercenaries + private ChooseMercenaryScreen chooseMercenaryScreen; + private GiveItemsScreen giveItemsScreen; + private TakeItems takeItems; + + @Inject + public InventoryScreen(SolApplication solApplication) { + this.solApplication = solApplication; + } + + @Override + public void initialise() { + titleLabel = find("title", UILabel.class); + + inventoryRows = find("inventoryRows", ColumnLayout.class); + + nextButton = find("nextButton", UIWarnButton.class); + nextButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyRight())); + nextButton.subscribe(button -> { + nextPage(button); + selectedIndex = 0; + updateItemRows(); + }); + + previousButton = find("previousButton", UIWarnButton.class); + previousButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyLeft())); + previousButton.subscribe(button -> { + previousPage(button); + selectedIndex = 0; + updateItemRows(); + }); + + for (int rowNo = 0; rowNo < Const.ITEM_GROUPS_PER_PAGE; rowNo++) { + inventoryRows.addWidget(createItemRow(rowNo)); + } + + descriptionScrollArea = find("itemDescriptionScrollArea", ScrollableArea.class); + descriptionBox = find("itemDescription", UILabel.class); + + inventoryActionButtons = find("inventoryActionButtons", ColumnLayout.class); + + closeButton = new UIWarnButton(); + closeButton.setText("Cancel"); + closeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyEscape())); + closeButton.subscribe(button -> { + // Go back to the "Choose Mercenaries" screen if it was probably the last one opened. + if (inventoryOperations == giveItemsScreen || inventoryOperations == takeItems || + (inventoryOperations == showInventory && showInventory.getTarget() != solApplication.getGame().getHero().getShip())) { + SolInputManager inputMan = solApplication.getInputManager(); + GameScreens screens = solApplication.getGame().getScreens(); + + inputMan.setScreen(solApplication, screens.oldMainGameScreen); + onRemoved(); + setOperations(chooseMercenaryScreen); + onAdded(); + } else { + nuiManager.removeScreen(this); + } + }); + + showInventory = new ShowInventory(); + showInventory.initialise(solApplication, this); + buyItemsScreen = new BuyItemsScreen(); + buyItemsScreen.initialise(solApplication, this); + sellItems = new SellItems(); + sellItems.initialise(solApplication, this); + changeShipScreen = new ChangeShipScreen(); + changeShipScreen.initialise(solApplication, this); + hireShipsScreen = new HireShipsScreen(); + hireShipsScreen.initialise(solApplication, this); + chooseMercenaryScreen = new ChooseMercenaryScreen(); + chooseMercenaryScreen.initialise(solApplication, this); + giveItemsScreen = new GiveItemsScreen(); + giveItemsScreen.initialise(solApplication, this); + takeItems = new TakeItems(); + takeItems.initialise(solApplication, this); + } + + @Override + public void onAdded() { + titleLabel.setText(inventoryOperations.getHeader()); + descriptionBox.setText(""); + + selectedIndex = 0; + page = 0; + inventoryOperations.onAdd(solApplication); + + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + nextButton.setEnabled(Const.ITEM_GROUPS_PER_PAGE < items.groupCount()); + previousButton.setEnabled(false); + + for (UIButton actionButton : inventoryOperations.getActionButtons()) { + inventoryActionButtons.addWidget(actionButton); + } + + inventoryActionButtons.addWidget(closeButton); + + updateItemRows(); + } + + /** + * Returns the current {@link InventoryOperationsScreen operations screen} being applied to this screen. + * @return the current operations screen + */ + public InventoryOperationsScreen getOperations() { + return inventoryOperations; + } + + /** + * Assigns the specified {@link InventoryOperationsScreen operations screen} to this screen. + * @param operations the operations that can be performed + */ + public void setOperations(InventoryOperationsScreen operations) { + this.inventoryOperations = operations; + } + + @Override + public void update(float delta) { + super.update(delta); + + if (solApplication.getGame().getHero().getShip() == showInventory.getTarget() || inventoryOperations == sellItems) { + int itemNo = page * Const.ITEM_GROUPS_PER_PAGE; + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + Iterator rowIterator = inventoryRows.iterator(); + rowIterator.next(); // Skip header + while (rowIterator.hasNext()) { + UIWidget row = rowIterator.next(); + if (itemNo >= items.groupCount()) { + break; + } + + UIWarnButton itemButton = row.find("itemButton", UIWarnButton.class); + if (itemButton != null && items.isNew(items.getGroup(itemNo))) { + itemButton.enableWarn(); + } + itemNo++; + } + } + + inventoryOperations.update(solApplication, this); + } + + @Override + public void onRemoved() { + super.onRemoved(); + + if (inventoryOperations != null) { + inventoryOperations.getItems(solApplication.getGame()).markAllAsSeen(); + inventoryActionButtons.removeAllWidgets(); + } + } + + @Override + public boolean onKeyEvent(NUIKeyEvent event) { + if (super.onKeyEvent(event)) { + return true; + } + + if (event.isDown()) { + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + if (event.getKey() == GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyUp())) { + if (selectedIndex < 1 && previousButton.isEnabled()) { + selectedIndex = Const.ITEM_GROUPS_PER_PAGE - 1; + previousPage(previousButton); + previousButton.getClickSound().play(previousButton.getClickVolume()); + } else if (selectedIndex > 0) { + selectedIndex--; + previousButton.getClickSound().play(previousButton.getClickVolume()); + } + + items.seen(items.getGroup(selectedIndex + page * Const.ITEM_GROUPS_PER_PAGE)); + + updateItemRows(); + return true; + } + + if (event.getKey() == GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyDown())) { + int itemsMaxIndex = items.groupCount() - 1; + int maxIndex = Math.min(Const.ITEM_GROUPS_PER_PAGE - 1, itemsMaxIndex - (page * Const.ITEM_GROUPS_PER_PAGE)); + if (selectedIndex >= maxIndex && nextButton.isEnabled()) { + selectedIndex = 0; + nextPage(nextButton); + nextButton.getClickSound().play(nextButton.getClickVolume()); + } else if (selectedIndex < maxIndex) { + selectedIndex++; + nextButton.getClickSound().play(nextButton.getClickVolume()); + } + + items.seen(items.getGroup(selectedIndex + page * Const.ITEM_GROUPS_PER_PAGE)); + + updateItemRows(); + return true; + } + } + + return false; + } + + /** + * Returns the currently selected item group. + * @return the selected item group + */ + public List getSelected() { + if (inventoryOperations == null || selectedIndex < 0 || selectedIndex >= Const.ITEM_GROUPS_PER_PAGE) { + return null; + } + + int itemGroupIndex = selectedIndex + page * Const.ITEM_GROUPS_PER_PAGE; + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + if (itemGroupIndex >= items.groupCount()) { + return null; + } + + return items.getGroup(itemGroupIndex); + } + + /** + * Retrieves the currently selected item. + * @return the current selected item + */ + public SolItem getSelectedItem() { + List itemGroup = getSelected(); + if (itemGroup == null) { + return null; + } + return itemGroup.isEmpty() ? null : itemGroup.get(0); + } + + /** + * Sets the selected item group. + * @param itemGroup the item group to select + */ + public void setSelected(List itemGroup) { + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + if (!items.containsGroup(itemGroup)) { + selectedIndex = 0; + } else { + for (int groupNo = 0; groupNo < items.groupCount(); groupNo++) { + if (items.getGroup(groupNo) == itemGroup) { + page = groupNo / Const.ITEM_GROUPS_PER_PAGE; + selectedIndex = groupNo % Const.ITEM_GROUPS_PER_PAGE; + } + } + } + + updateItemRows(); + } + + /** + * Returns the button representing the specified row. + * @param index the row to retrieve + * @return the row's item button + */ + public UIWarnButton getRowButton(int index) { + Iterator rowIterator = inventoryRows.iterator(); + rowIterator.next(); // Skip header + for (int rowNo = 0; rowNo < index; rowNo++) { + rowIterator.next(); + } + return rowIterator.next().find("itemButton", UIWarnButton.class); + } + + /** + * This is an internal API used by the tutorial. It just returns the buttons representing equipped items. + * @return The buttons representing currently equipped items. + */ + public List getEquippedItemUIControlsForTutorial() { + List controls = new ArrayList<>(); + + Iterator rowsIterator = inventoryRows.iterator(); + rowsIterator.next(); // Skip header + UIWidget row = rowsIterator.next(); + int startIndex = page * Const.ITEM_GROUPS_PER_PAGE; + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + for (int rowNo = 0; rowNo < Const.ITEM_GROUPS_PER_PAGE; rowNo++) { + int groupNo = startIndex + rowNo; + boolean emptyRow = groupNo >= items.groupCount(); + + UIWarnButton itemButton = row.find("itemButton", UIWarnButton.class); + if (emptyRow) { + break; + } else { + List itemGroup = items.getGroup(groupNo); + SolItem sample = itemGroup.get(0); + + if (inventoryOperations.isUsing(solApplication.getGame(), sample)) { + controls.add(itemButton); + } + } + + if (rowsIterator.hasNext()) { + row = rowsIterator.next(); + } + } + + return controls; + } + + /** + * @return the next button - used in the tutorial + */ + public UIWarnButton getNextButton() { + return nextButton; + } + + /** + * @return the previous button + */ + public UIWarnButton getPreviousButton() { + return previousButton; + } + + /** + * @return the close button - used in the tutorial + */ + public UIWarnButton getCloseButton() { + return closeButton; + } + + /** + * @return the {@link ShowInventory} inventory operations + */ + public ShowInventory getShowInventory() { + return showInventory; + } + + /** + * @return the {@link BuyItemsScreen} inventory operations + */ + public BuyItemsScreen getBuyItemsScreen() { + return buyItemsScreen; + } + + /** + * @return the {@link SellItems} inventory operations + */ + public SellItems getSellItems() { + return sellItems; + } + + /** + * @return the {@link ChangeShipScreen} inventory operations + */ + public ChangeShipScreen getChangeShipScreen() { + return changeShipScreen; + } + + /** + * @return the {@link HireShipsScreen} inventory operations + */ + public HireShipsScreen getHireShipsScreen() { + return hireShipsScreen; + } + + /** + * @return the {@link ChooseMercenaryScreen} inventory operations + */ + public ChooseMercenaryScreen getChooseMercenaryScreen() { + return chooseMercenaryScreen; + } + + /** + * @return the {@link GiveItemsScreen} inventory operations + */ + public GiveItemsScreen getGiveItems() { + return giveItemsScreen; + } + + /** + * @return the {@link TakeItems} inventory operations + */ + public TakeItems getTakeItems() { + return takeItems; + } + + private UIWidget createItemRow(int index) { + RelativeLayout itemRowLayout = new RelativeLayout(); + itemRowLayout.setFamily("inventoryRow"); + + UIWarnButton itemButton = new UIWarnButton("itemButton", ""); + itemButton.subscribe(button -> { + selectedIndex = index; + updateItemRows(); + }); + itemRowLayout.addWidget(itemButton, new RelativeLayoutHint()); + + UIImage itemIconBackground = new UIImage("itemIconBackground", Assets.getDSTexture("engine:whiteTex").getUiTexture()); + itemRowLayout.addWidget(itemIconBackground, new RelativeLayoutHint( + new HorizontalHint() + .alignLeftRelativeTo("itemIcon", HorizontalAlign.LEFT) + .alignRightRelativeTo("itemIcon", HorizontalAlign.RIGHT), + new VerticalHint() + )); + + UIImage itemIcon = new UIImage("itemIcon"); + itemRowLayout.addWidget(itemIcon, new RelativeLayoutHint( + new HorizontalHint().alignLeft(8), + new VerticalHint() + ).setUsingContentWidth(true)); + + itemRowLayout.addWidget(new UILabel("itemEquippedLabel", ""), new RelativeLayoutHint( + new HorizontalHint().alignLeftRelativeTo("itemIcon", HorizontalAlign.RIGHT, 8), + new VerticalHint() + ).setUsingContentWidth(true)); + + itemRowLayout.addWidget(new UILabel("itemQuantityLabel", ""), new RelativeLayoutHint( + new HorizontalHint().alignRight(8), + new VerticalHint() + ).setUsingContentWidth(true)); + + itemRowLayout.addWidget(new UILabel("itemPriceLabel", ""), new RelativeLayoutHint( + new HorizontalHint().alignRight(64), + new VerticalHint() + ).setUsingContentWidth(true)); + + return itemRowLayout; + } + + public void updateItemRows() { + ItemContainer items = inventoryOperations.getItems(solApplication.getGame()); + Iterator rowsIterator = inventoryRows.iterator(); + rowsIterator.next(); // Ignore the first row, since it's the header. + UIWidget row = rowsIterator.next(); + + int startIndex = page * Const.ITEM_GROUPS_PER_PAGE; + if (startIndex >= items.groupCount() && page > 0) { + // Empty page. This may have happened if the last item on a page was dropped from the inventory. + page = (items.groupCount() - 1) / Const.ITEM_GROUPS_PER_PAGE; + startIndex = page * Const.ITEM_GROUPS_PER_PAGE; + selectedIndex = 0; + } + + previousButton.setEnabled(page > 0); + nextButton.setEnabled(((page + 1) * Const.ITEM_GROUPS_PER_PAGE) < items.groupCount()); + + for (int rowNo = 0; rowNo < Const.ITEM_GROUPS_PER_PAGE; rowNo++) { + int groupNo = startIndex + rowNo; + boolean emptyRow = groupNo >= items.groupCount(); + + UIWarnButton itemButton = row.find("itemButton", UIWarnButton.class); + UIImage itemIconBackground = row.find("itemIconBackground", UIImage.class); + UIImage itemIcon = row.find("itemIcon", UIImage.class); + UILabel itemEquippedLabel = row.find("itemEquippedLabel", UILabel.class); + UILabel itemQuantityLabel = row.find("itemQuantityLabel", UILabel.class); + UILabel itemPriceLabel = row.find("itemPriceLabel", UILabel.class); + if (emptyRow) { + itemButton.setText(""); + itemIconBackground.setTint(new Color(Color.transparent)); + itemIcon.setImage(null); + itemEquippedLabel.setText(""); + itemQuantityLabel.setText(""); + itemPriceLabel.setText(""); + + itemButton.setEnabled(false); + } else { + List itemGroup = items.getGroup(groupNo); + SolItem sample = itemGroup.get(0); + + itemButton.setText(sample.getDisplayName()); + itemButton.setActive(selectedIndex == rowNo); + if (items.isNew(itemGroup)) { + itemButton.enableWarn(); + } + + itemIconBackground.setTint(GdxColorUtil.gdxToTerasologyColor(sample.getItemType().uiColor)); + + TextureAtlas.AtlasRegion iconTexture = sample.getIcon(solApplication.getGame()); + itemIcon.setImage(new LibGDXTexture(iconTexture)); + + itemEquippedLabel.setText(inventoryOperations.isUsing(solApplication.getGame(), sample) ? "using" : ""); + + itemQuantityLabel.setText(itemGroup.size() > 1 ? "x" + itemGroup.size() : ""); + + itemPriceLabel.setText(inventoryOperations.getPriceMul() > 0 ? "$" + sample.getPrice() * inventoryOperations.getPriceMul() : ""); + + itemButton.setEnabled(true); + } + + if (rowsIterator.hasNext()) { + row = rowsIterator.next(); + } + } + + int selectedGroup = (selectedIndex + page * Const.ITEM_GROUPS_PER_PAGE); + if (items.groupCount() > 0 && items.groupCount() > selectedGroup) { + List itemGroup = items.getGroup(selectedGroup); + items.seen(itemGroup); + SolItem sample = itemGroup.get(0); + // Add an extra newline to the end to ensure that the entire area is scrollable. + descriptionBox.setText(sample.getDisplayName() + "\n" + sample.getDescription() + "\n"); + // Scroll to top + descriptionScrollArea.setPosition(0); + } + } + + private void nextPage(UIWidget nextButton) { + int inputCount = inventoryOperations.getItems(solApplication.getGame()).groupCount(); + page++; + nextButton.setEnabled(((page + 1) * Const.ITEM_GROUPS_PER_PAGE) < inputCount); + previousButton.setEnabled(true); + } + + private void previousPage(UIWidget previousButton) { + page--; + previousButton.setEnabled(page > 0); + nextButton.setEnabled(true); + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java index fdb3a1282..d5ad208cd 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java @@ -445,7 +445,7 @@ public void update(float delta) { SolGame game = solApplication.getGame(); Hero hero = game.getHero(); - if (hero.isNonTranscendent() && !solInputManager.isScreenOn(gameScreens.inventoryScreen)) { + if (hero.isNonTranscendent() && !nuiManager.hasScreen(gameScreens.inventoryScreen)) { if (hero.getItemContainer().hasNew()) { inventoryButton.enableWarn(); } @@ -923,10 +923,12 @@ private void onItemsButtonClicked(UIWidget widget) { GameScreens gameScreens = game.getScreens(); solInputManager.setScreen(solApplication, gameScreens.oldMainGameScreen); - if (!solInputManager.isScreenOn(gameScreens.inventoryScreen)) { - gameScreens.inventoryScreen.showInventory.setTarget(hero.getShip()); - gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.showInventory); - solInputManager.addScreen(solApplication, gameScreens.inventoryScreen); + if (!nuiManager.hasScreen(gameScreens.inventoryScreen)) { + gameScreens.inventoryScreen.getShowInventory().setTarget(hero.getShip()); + gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.getShowInventory()); + nuiManager.pushScreen(gameScreens.inventoryScreen); + } else { + nuiManager.removeScreen(gameScreens.inventoryScreen); } } @@ -959,10 +961,12 @@ private void onMercsButtonClicked(UIWidget widget) { GameScreens gameScreens = game.getScreens(); solInputManager.setScreen(solApplication, gameScreens.oldMainGameScreen); - if (!solInputManager.isScreenOn(gameScreens.inventoryScreen)) { - gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.chooseMercenaryScreen); - solInputManager.addScreen(solApplication, gameScreens.inventoryScreen); + if (!nuiManager.hasScreen(gameScreens.inventoryScreen)) { + gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.getChooseMercenaryScreen()); + nuiManager.pushScreen(gameScreens.inventoryScreen); hero.getMercs().markAllAsSeen(); + } else { + nuiManager.removeScreen(gameScreens.inventoryScreen); } } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/TalkScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/TalkScreen.java index 2c6f5ed89..f315077ae 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/TalkScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/TalkScreen.java @@ -18,7 +18,6 @@ import org.destinationsol.SolApplication; import org.destinationsol.game.Hero; -import org.destinationsol.game.screens.InventoryScreen; import org.destinationsol.game.ship.SolShip; import org.destinationsol.game.ship.hulls.HullConfig; import org.destinationsol.ui.nui.NUIScreenLayer; @@ -51,36 +50,36 @@ public void initialise() { sellButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeySellMenu())); sellButton.subscribe(button -> { InventoryScreen inventoryScreen = solApplication.getGame().getScreens().inventoryScreen; - inventoryScreen.setOperations(inventoryScreen.sellItems); + inventoryScreen.setOperations(inventoryScreen.getSellItems()); nuiManager.removeScreen(this); - solApplication.getInputManager().addScreen(solApplication, inventoryScreen); + nuiManager.pushScreen(inventoryScreen); }); buyButton = find("buyButton", UIWarnButton.class); buyButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyBuyMenu())); buyButton.subscribe(button -> { InventoryScreen inventoryScreen = solApplication.getGame().getScreens().inventoryScreen; - inventoryScreen.setOperations(inventoryScreen.buyItemsScreen); + inventoryScreen.setOperations(inventoryScreen.getBuyItemsScreen()); nuiManager.removeScreen(this); - solApplication.getInputManager().addScreen(solApplication, inventoryScreen); + nuiManager.pushScreen(inventoryScreen); }); changeShipButton = find("changeShipButton", KeyActivatedButton.class); changeShipButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyChangeShipMenu())); changeShipButton.subscribe(button -> { InventoryScreen inventoryScreen = solApplication.getGame().getScreens().inventoryScreen; - inventoryScreen.setOperations(inventoryScreen.changeShipScreen); + inventoryScreen.setOperations(inventoryScreen.getChangeShipScreen()); nuiManager.removeScreen(this); - solApplication.getInputManager().addScreen(solApplication, inventoryScreen); + nuiManager.pushScreen(inventoryScreen); }); hireButton = find("hireButton", KeyActivatedButton.class); hireButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyHireShipMenu())); hireButton.subscribe(button -> { InventoryScreen inventoryScreen = solApplication.getGame().getScreens().inventoryScreen; - inventoryScreen.setOperations(inventoryScreen.hireShipsScreen); + inventoryScreen.setOperations(inventoryScreen.getHireShipsScreen()); nuiManager.removeScreen(this); - solApplication.getInputManager().addScreen(solApplication, inventoryScreen); + nuiManager.pushScreen(inventoryScreen); }); KeyActivatedButton closeButton = find("closeButton", KeyActivatedButton.class); diff --git a/engine/src/main/resources/org/destinationsol/assets/skins/inventoryScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/inventoryScreen.skin new file mode 100644 index 000000000..aed32aa82 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/skins/inventoryScreen.skin @@ -0,0 +1,24 @@ +{ + "inherit": "engine:mainGameScreen", + "families": { + "inventoryHeader": { + "text-align-vertical": "middle", + "text-align-horizontal": "left", + "min-height": 16 + }, + "inventoryRow": { + "font": "engine:main#0.675", + "text-align-vertical": "middle", + "text-align-horizontal": "center", + "min-height": 32, + "max-height": 64 + }, + "inventoryActionButtons": { + "font": "engine:main#0.4" + }, + "selectedItemLabel": { + "text-align-vertical": "middle", + "text-align-horizontal": "left" + } + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin index ef98162fc..c05e96ed0 100644 --- a/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin +++ b/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin @@ -54,6 +54,22 @@ } }, "font": "engine:main#0.8" + }, + "menuBox": { + "max-width": 800, + "max-height": 600, + "elements": { + "UIBox": { + "background": "engine:background" + } + } + }, + "uiBoxDefault": { + "elements": { + "UIBox": { + "background": "engine:area" + } + } } } } diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/inventoryScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/inventoryScreen.ui new file mode 100644 index 000000000..2be50a95b --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/inventoryScreen.ui @@ -0,0 +1,150 @@ +{ + "type": "InventoryScreen", + "skin": "engine:inventoryScreen", + "contents": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UIBackingBox", + "family": "menuBox", + "content": { + "type": "RelativeLayout", + "contents": [ + { + "type": "ColumnLayout", + "id": "inventoryRows", + "verticalSpacing": 8, + "contents": [ + { + "type": "RowLayout", + "id": "header", + "family": "inventoryHeader", + "horizontalSpacing": 8, + "contents": [ + { + "type": "UILabel", + "id": "title", + "text": "Inventory Screen", + "layoutInfo": { + "relativeWidth": 0.6 + } + }, + { + "type": "UIWarnButton", + "id": "previousButton", + "text": "<" + }, + { + "type": "UIWarnButton", + "id": "nextButton", + "text": ">" + } + ] + } + ], + "layoutInfo": { + "position-horizontal-center": {}, + "position-top": { + "offset": 8 + }, + "position-bottom": { + "widget": "selectedItemLabel", + "target": "TOP", + "offset": 8 + }, + "position-left": { + "offset": 8 + }, + "position-right": { + "offset": 8 + } + } + }, + { + "type": "UILabel", + "id": "selectedItemLabel", + "text": "Selected Item:", + "layoutInfo": { + "position-top": { + "target": "MIDDLE", + "offset": 64 + }, + "position-left": { + "offset": 8 + }, + "position-right": { + "offset": 8 + }, + "use-content-height": true + } + }, + { + "type": "RowLayout", + "id": "inventoryItemInfo", + "horizontalSpacing": 16, + "contents": [ + { + "type": "UIBox", + "id": "itemDescriptionBox", + "family": "uiBoxDefault", + "content": { + "type": "ScrollableArea", + "id": "itemDescriptionScrollArea", + "content": { + "type": "UILabel", + "id": "itemDescription", + "text": "This is a really long description. Longer than that. No, even longer!" + } + }, + "layoutInfo": { + "relativeWidth": 0.6 + } + }, + { + "type": "ColumnLayout", + "id": "inventoryActionButtons", + "family": "inputMapOptions", + "verticalSpacing": 8, + "contents": [ + ] + } + ], + "layoutInfo": { + "position-top": { + "widget": "selectedItemLabel", + "target": "BOTTOM", + "offset": 8 + }, + "position-bottom": { + "offset": 8 + }, + "position-left": { + "offset": 8 + }, + "position-right": { + "offset": 8 + } + } + } + ] + }, + "layoutInfo": { + "position-horizontal-center": {}, + "position-vertical-center": {}, + "position-top": { + "offset": 64 + }, + "position-bottom": { + "offset": 64 + }, + "position-left": { + "offset": 64 + }, + "position-right": { + "offset": 64 + } + } + } + ] + } +} \ No newline at end of file From ccb2cbfcd83c5132a962dd4c478689efea5006af Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Thu, 6 Oct 2022 20:52:59 +0100 Subject: [PATCH 2/2] feat(nui): convert MapScreen and WaypointCreationScreen to NUI --- .../org/destinationsol/FactionDisplay.java | 2 +- .../game/screens/GameScreens.java | 7 +- .../game/screens/MapScreen.java | 226 ------------ .../game/screens/ShipMouseControl.java | 2 +- .../game/screens/WaypointCreationScreen.java | 126 ------- .../destinationsol/ui/TutorialManager.java | 10 +- .../ui/nui/screens/MainGameScreen.java | 7 +- .../ui/nui/screens/MapScreen.java | 338 ++++++++++++++++++ .../ui/nui/screens/UIShipControlsScreen.java | 5 +- .../nui/screens/WaypointCreationScreen.java | 144 ++++++++ .../assets/skins/mapScreen.skin | 32 ++ .../assets/ui/mapScreen_desktop.ui | 51 +++ .../assets/ui/mapScreen_mobile.ui | 73 ++++ .../assets/ui/waypointCreationScreen.ui | 114 ++++++ 14 files changed, 771 insertions(+), 366 deletions(-) delete mode 100644 engine/src/main/java/org/destinationsol/game/screens/MapScreen.java delete mode 100644 engine/src/main/java/org/destinationsol/game/screens/WaypointCreationScreen.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/MapScreen.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/WaypointCreationScreen.java create mode 100644 engine/src/main/resources/org/destinationsol/assets/skins/mapScreen.skin create mode 100644 engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_desktop.ui create mode 100644 engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_mobile.ui create mode 100644 engine/src/main/resources/org/destinationsol/assets/ui/waypointCreationScreen.ui diff --git a/engine/src/main/java/org/destinationsol/FactionDisplay.java b/engine/src/main/java/org/destinationsol/FactionDisplay.java index 07e1968e1..db448e813 100644 --- a/engine/src/main/java/org/destinationsol/FactionDisplay.java +++ b/engine/src/main/java/org/destinationsol/FactionDisplay.java @@ -44,7 +44,7 @@ public void drawFactionNames(SolGame game, UiDrawer uiDrawer, SolInputManager in isPressed = !isPressed; } // angle must be zero as the camera angles on planets mess up the text display - if (isPressed && camera.getAngle() == 0 && !inputManager.isScreenOn(game.getScreens().mapScreen)) { + if (isPressed && camera.getAngle() == 0 && !game.getSolApplication().getNuiManager().hasScreen(game.getScreens().mapScreen)) { for (SolObject obj : objManager.getObjects()) { if (obj instanceof SolShip) { SolShip ship = (SolShip) obj; diff --git a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java index b72e9d99f..d7a4f125d 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java +++ b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java @@ -22,6 +22,8 @@ import org.destinationsol.ui.nui.screens.MenuScreen; import org.destinationsol.ui.nui.screens.TalkScreen; import org.destinationsol.ui.nui.screens.InventoryScreen; +import org.destinationsol.ui.nui.screens.MapScreen; +import org.destinationsol.ui.nui.screens.WaypointCreationScreen; import javax.inject.Inject; @@ -45,14 +47,15 @@ public GameScreens(SolApplication cmp, Context context) { boolean isMobile = cmp.isMobile(); if (!isMobile) { mainGameScreen = (org.destinationsol.ui.nui.screens.MainGameScreen) cmp.getNuiManager().createScreen(NUI_MAIN_GAME_SCREEN_DESKTOP_URI); + mapScreen = (MapScreen) cmp.getNuiManager().createScreen("engine:mapScreen_desktop"); } else { mainGameScreen = (org.destinationsol.ui.nui.screens.MainGameScreen) cmp.getNuiManager().createScreen(NUI_MAIN_GAME_SCREEN_MOBILE_URI); + mapScreen = (MapScreen) cmp.getNuiManager().createScreen("engine:mapScreen_mobile"); } - mapScreen = new MapScreen(rightPaneLayout, cmp.isMobile(), cmp.getOptions()); menuScreen = (MenuScreen) cmp.getNuiManager().createScreen("engine:menuScreen"); inventoryScreen = (InventoryScreen) cmp.getNuiManager().createScreen("engine:inventoryScreen"); talkScreen = (TalkScreen) cmp.getNuiManager().createScreen("engine:talkScreen"); - waypointCreationScreen = new WaypointCreationScreen(layouts.menuLayout, cmp.getOptions(), mapScreen); + waypointCreationScreen = (WaypointCreationScreen) cmp.getNuiManager().createScreen("engine:waypointCreationScreen"); consoleScreen = new ConsoleScreen(context.get(Console.class)); } diff --git a/engine/src/main/java/org/destinationsol/game/screens/MapScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MapScreen.java deleted file mode 100644 index ee71bf625..000000000 --- a/engine/src/main/java/org/destinationsol/game/screens/MapScreen.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2018 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.destinationsol.game.screens; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import org.destinationsol.GameOptions; -import org.destinationsol.SolApplication; -import org.destinationsol.game.MapDrawer; -import org.destinationsol.game.SolCam; -import org.destinationsol.game.SolGame; -import org.destinationsol.game.context.Context; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiBaseScreen; -import org.destinationsol.ui.SolUiControl; -import org.destinationsol.ui.Waypoint; - -import java.util.ArrayList; - -public class MapScreen extends SolUiBaseScreen { - private final SolUiControl zoomOutControl; - public final SolUiControl closeControl; - public final SolUiControl zoomInControl; - private final SolUiControl addWaypointControl; - private final SolUiControl removeWaypointControl; - - private final String NEW_WAYPOINT_TEXT = "Marker+"; - private final String REMOVE_WAYPOINT_TEXT = "Marker-"; - private final String CANCEL_TEXT = "Cancel"; - private final int MIN_WAYPOINT_DIST = 5; - - private boolean isPickingWaypointSpot = false; - private boolean isPickingWaypointToRemove = false; - - MapScreen(RightPaneLayout rightPaneLayout, boolean mobile, GameOptions gameOptions) { - Rectangle closeArea = mobile ? MainGameScreen.btn(0, MainGameScreen.HELPER_ROW_1, true) : rightPaneLayout.buttonRect(1); - closeControl = new SolUiControl(closeArea, true, gameOptions.getKeyMap(), gameOptions.getKeyClose()); - closeControl.setDisplayName("Close"); - controls.add(closeControl); - - float row0 = 1 - MainGameScreen.CELL_SZ; - float row1 = row0 - MainGameScreen.CELL_SZ; - - Rectangle zoomInArea = mobile ? MainGameScreen.btn(0, row1, false) : rightPaneLayout.buttonRect(2); - zoomInControl = new SolUiControl(zoomInArea, true, gameOptions.getKeyZoomIn()); - zoomInControl.setDisplayName("Zoom In"); - controls.add(zoomInControl); - - Rectangle zoomOutArea = mobile ? MainGameScreen.btn(0, row0, false) : rightPaneLayout.buttonRect(3); - zoomOutControl = new SolUiControl(zoomOutArea, true, gameOptions.getKeyZoomOut()); - zoomOutControl.setDisplayName("Zoom Out"); - controls.add(zoomOutControl); - - Rectangle addWaypointArea = mobile ? MainGameScreen.btn(0, 0, false) : rightPaneLayout.buttonRect(4); - addWaypointControl = new SolUiControl(addWaypointArea, true, gameOptions.getKeyShoot2()); - addWaypointControl.setDisplayName(NEW_WAYPOINT_TEXT); - controls.add(addWaypointControl); - - Rectangle removeWaypointArea = mobile ? MainGameScreen.btn(0, MainGameScreen.CELL_SZ, false) : rightPaneLayout.buttonRect(5); - removeWaypointControl = new SolUiControl(removeWaypointArea, true, gameOptions.getKeyShoot2()); - removeWaypointControl.setDisplayName(REMOVE_WAYPOINT_TEXT); - controls.add(removeWaypointControl); - } - - @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - SolGame game = solApplication.getGame(); - GameOptions gameOptions = solApplication.getOptions(); - boolean justClosed = closeControl.isJustOff(); - MapDrawer mapDrawer = game.getMapDrawer(); - mapDrawer.setToggled(!justClosed); - SolInputManager im = solApplication.getInputManager(); - - if (justClosed) { - mapDrawer.getMapDrawPositionAdditive().set(0, 0); - isPickingWaypointSpot = false; - addWaypointControl.setDisplayName(NEW_WAYPOINT_TEXT); - im.setScreen(solApplication, game.getScreens().oldMainGameScreen); - } - - boolean zoomIn = zoomInControl.isJustOff(); - if (zoomIn || zoomOutControl.isJustOff()) { - mapDrawer.changeZoom(zoomIn); - } - - float mapZoom = mapDrawer.getZoom(); - zoomInControl.setEnabled(mapZoom != MapDrawer.MIN_ZOOM); - zoomOutControl.setEnabled(mapZoom != MapDrawer.MAX_ZOOM); - ShipUiControl shipControl = game.getScreens().oldMainGameScreen.getShipControl(); - if (shipControl instanceof ShipMouseControl) { - shipControl.update(solApplication, true); - } - - Boolean scrolledUp = im.getScrolledUp(); - if (scrolledUp != null) { - if (scrolledUp) { - zoomOutControl.maybeFlashPressed(gameOptions.getKeyZoomOut()); - } else { - zoomInControl.maybeFlashPressed(gameOptions.getKeyZoomIn()); - } - } - - if (im.touchDragged) { - //Scroll factor negates the drag and adjusts it to map's zoom - float scrollFactor = -mapDrawer.getZoom() / Gdx.graphics.getHeight() * gameOptions.getMapScrollSpeed(); - float rotateAngle = game.getCam().getAngle(); - mapDrawer.getMapDrawPositionAdditive().add(im.getDrag().scl(scrollFactor).rotate(rotateAngle)); - } - - if (isPickingWaypointSpot) { - if (inputPointers[0].isJustUnPressed() && !addWaypointControl.isJustOff()) { - float camAngle = game.getCam().getAngle(); - Vector2 mapCamPos = game.getCam().getPosition().add(mapDrawer.getMapDrawPositionAdditive()); - Vector2 clickPosition = new Vector2(inputPointers[0].x, inputPointers[0].y); - Vector2 worldPosition = screenPositionToWorld(clickPosition, mapCamPos, camAngle, mapZoom); - ArrayList waypoints = game.getHero().getWaypoints(); - - //make sure waypoints aren't too close to each other - boolean canCreate = true; - for (int w = 0; w < waypoints.size(); w++) { - Waypoint waypoint = waypoints.get(w); - if (worldPosition.x > waypoint.position.x - MIN_WAYPOINT_DIST && worldPosition.x < waypoint.position.x + MIN_WAYPOINT_DIST && - worldPosition.y > waypoint.position.y - MIN_WAYPOINT_DIST && worldPosition.y < waypoint.position.y + MIN_WAYPOINT_DIST) { - canCreate = false; - break; - } - } - - if (canCreate) { - setWaypointButtonsEnabled(false); - WaypointCreationScreen waypointCreationScreen = game.getScreens().waypointCreationScreen; - waypointCreationScreen.setWaypointPos(worldPosition); - - solApplication.getInputManager().setScreen(solApplication, game.getScreens().mapScreen); - solApplication.getInputManager().addScreen(solApplication, waypointCreationScreen); - } - addWaypointControl.setDisplayName(NEW_WAYPOINT_TEXT); - isPickingWaypointSpot = false; - } - } - - if (isPickingWaypointToRemove) { - if (inputPointers[0].isJustUnPressed() && !removeWaypointControl.isJustOff()) { - Vector2 clickPosition = new Vector2(inputPointers[0].x, inputPointers[0].y); - SolCam camera = game.getCam(); - Vector2 realPosition = screenPositionToWorld(clickPosition, camera.getPosition(), camera.getAngle(), mapZoom); - - ArrayList waypoints = game.getHero().getWaypoints(); - for (int w = 0; w < waypoints.size(); w++) { - Waypoint waypoint = waypoints.get(w); - if (waypoint.position.x > realPosition.x - MIN_WAYPOINT_DIST && waypoint.position.x < realPosition.x + MIN_WAYPOINT_DIST && - waypoint.position.y > realPosition.y - MIN_WAYPOINT_DIST && waypoint.position.y < realPosition.y + MIN_WAYPOINT_DIST) { - game.getHero().removeWaypoint(waypoint); - game.getObjectManager().removeObjDelayed(waypoint); - } - } - addWaypointControl.setEnabled(true); - removeWaypointControl.setDisplayName(REMOVE_WAYPOINT_TEXT); - isPickingWaypointToRemove = false; - } - } - - if (addWaypointControl.isJustOff()) { - if (isPickingWaypointSpot) { - isPickingWaypointSpot = false; - addWaypointControl.setDisplayName(NEW_WAYPOINT_TEXT); - removeWaypointControl.setEnabled(true); - } else { - isPickingWaypointSpot = true; - addWaypointControl.setDisplayName(CANCEL_TEXT); - removeWaypointControl.setEnabled(false); - } - } - - if (removeWaypointControl.isJustOff()) { - if (isPickingWaypointToRemove) { - isPickingWaypointToRemove = false; - removeWaypointControl.setDisplayName(REMOVE_WAYPOINT_TEXT); - addWaypointControl.setEnabled(true); - } else { - isPickingWaypointToRemove = true; - removeWaypointControl.setDisplayName(CANCEL_TEXT); - addWaypointControl.setEnabled(false); - } - } - } - - public Vector2 screenPositionToWorld(Vector2 clickPosition, Vector2 camPos, float camAngle, float mapZoom) { - float screenWidth = (float) Gdx.graphics.getWidth(); - float screenHeight = (float) Gdx.graphics.getHeight(); - return ScreenToWorldMapper.screenClickPositionToWorldPosition( - new Vector2(screenWidth, screenHeight), - clickPosition, - camPos, - camAngle, - mapZoom - ); - } - - public void setWaypointButtonsEnabled(boolean value) { - removeWaypointControl.setEnabled(value); - addWaypointControl.setEnabled(value); - } - - public boolean isPickingWaypointSpot() { - return isPickingWaypointSpot; - } - - public boolean isPickingWaypointToRemove() { - return isPickingWaypointToRemove; - } -} diff --git a/engine/src/main/java/org/destinationsol/game/screens/ShipMouseControl.java b/engine/src/main/java/org/destinationsol/game/screens/ShipMouseControl.java index 6655e2139..ad1745653 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ShipMouseControl.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ShipMouseControl.java @@ -52,7 +52,7 @@ public void update(SolApplication solApplication, boolean enabled) { game.getCam().screenToWorld(myMouseWorldPos); SolInputManager im = solApplication.getInputManager(); boolean clicked = im.getPtrs()[0].pressed; - boolean onMap = im.isScreenOn(game.getScreens().mapScreen); + boolean onMap = solApplication.getNuiManager().hasScreen(game.getScreens().mapScreen); BeaconHandler.Action a = game.getBeaconHandler().processMouse(game, myMouseWorldPos, clicked, onMap); if (a == BeaconHandler.Action.ATTACK) { myCursor = myAttackCursor; diff --git a/engine/src/main/java/org/destinationsol/game/screens/WaypointCreationScreen.java b/engine/src/main/java/org/destinationsol/game/screens/WaypointCreationScreen.java deleted file mode 100644 index fba6620a9..000000000 --- a/engine/src/main/java/org/destinationsol/game/screens/WaypointCreationScreen.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2019 MovingBlocks - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.destinationsol.game.screens; - -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.math.Vector2; -import org.destinationsol.GameOptions; -import org.destinationsol.SolApplication; -import org.destinationsol.assets.Assets; -import org.destinationsol.common.SolColor; -import org.destinationsol.menu.MenuLayout; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiBaseScreen; -import org.destinationsol.ui.SolUiControl; -import org.destinationsol.ui.SolUiSlider; -import org.destinationsol.ui.UiDrawer; -import org.destinationsol.ui.Waypoint; - -public class WaypointCreationScreen extends SolUiBaseScreen { - - private final SolUiControl cancelControl; - private final SolUiControl doneControl; - - private final MapScreen mapScreen; - - private Vector2 waypointPos; - - private final Rectangle previewRect; - private final Rectangle background; - private final SolUiSlider sliderRed; - private final SolUiSlider sliderGreen; - private final SolUiSlider sliderBlue; - - private Color outcomeColor; - - public WaypointCreationScreen(MenuLayout menuLayout, GameOptions gameOptions, MapScreen mapScreen) { - this.mapScreen = mapScreen; - doneControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true, gameOptions.getKeyShoot()); - doneControl.setDisplayName("Done"); - controls.add(doneControl); - cancelControl = new SolUiControl(menuLayout.buttonRect(-1, 4), true, gameOptions.getKeyClose()); - cancelControl.setDisplayName("Cancel"); - controls.add(cancelControl); - - previewRect = menuLayout.buttonRect(-1, -1); - outcomeColor = Color.BLACK.cpy(); - - TextureAtlas.AtlasRegion sliderTexture = Assets.getAtlasRegion("engine:ui/slider"); - TextureAtlas.AtlasRegion sliderMarkerTexture = Assets.getAtlasRegion("engine:ui/sliderMarker"); - - sliderRed = new SolUiSlider(menuLayout.buttonRect(-1, 0), "Red: ", 1, 2,sliderTexture, sliderMarkerTexture); - sliderGreen = new SolUiSlider(menuLayout.buttonRect(-1, 1), "Green: ", 1, 2, sliderTexture, sliderMarkerTexture); - sliderBlue = new SolUiSlider(menuLayout.buttonRect(-1, 2), "Blue:", 1, 2, sliderTexture, sliderMarkerTexture); - - background = menuLayout.background(-1, -1, 6); - } - - @Override - public void onAdd(SolApplication solApplication) { - sliderRed.setValue(1f); - sliderGreen.setValue(1f); - sliderBlue.setValue(1f); - } - - @Override - public void drawBackground(UiDrawer uiDrawer, SolApplication solApplication) { - uiDrawer.draw(background, SolColor.UI_BG); - } - - @Override - public void drawImages(UiDrawer uiDrawer, SolApplication solApplication) { - uiDrawer.draw(previewRect, outcomeColor); - sliderRed.draw(uiDrawer); - sliderGreen.draw(uiDrawer); - sliderBlue.draw(uiDrawer); - } - - @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - if (doneControl.isJustOff()) { - Waypoint waypoint = new Waypoint(waypointPos, outcomeColor, solApplication.getGame().getMapDrawer().getWaypointTexture()); - solApplication.getGame().getHero().addWaypoint(waypoint); - solApplication.getGame().getObjectManager().addObjDelayed(waypoint); - solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().mapScreen); - mapScreen.setWaypointButtonsEnabled(true); - } - - if (cancelControl.isJustOff()) { - solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().mapScreen); - mapScreen.setWaypointButtonsEnabled(true); - } - - if (inputPointers[0].pressed) { - Vector2 clickPos = new Vector2(inputPointers[0].x, inputPointers[0].y); - sliderRed.click(clickPos); - sliderGreen.click(clickPos); - sliderBlue.click(clickPos); - } - - outcomeColor.r = sliderRed.getValue(); - outcomeColor.g = sliderGreen.getValue(); - outcomeColor.b = sliderBlue.getValue(); - } - - public void setWaypointPos(Vector2 position) { - outcomeColor = new Color(); - outcomeColor.a = 1.0f; - waypointPos = position; - } - -} diff --git a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java index e407e8eba..5b70fb20e 100644 --- a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java +++ b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java @@ -116,18 +116,18 @@ public void start() { } if (mouseCtrl) { - addStep("Zoom in the map\n(mouse wheel UP)", screens.mapScreen.zoomInControl); + addStep("Zoom in the map\n(mouse wheel UP)", screens.mapScreen.getZoomInButton()); } else if (mobile) { - addStep("Zoom in the map", screens.mapScreen.zoomInControl); + addStep("Zoom in the map", screens.mapScreen.getZoomInButton()); } else { - addStep("Zoom in the map\n(" + gameOptions.getKeyZoomInName() + " key)", screens.mapScreen.zoomInControl); + addStep("Zoom in the map\n(" + gameOptions.getKeyZoomInName() + " key)", screens.mapScreen.getZoomInButton()); } if (mobile) { - addStep("Close the map", screens.mapScreen.closeControl, true); + addStep("Close the map", screens.mapScreen.getCloseButton(), true); } else { addStep("Close the map\n(" + gameOptions.getKeyMapName() + " or " + gameOptions.getKeyCloseName() + " keys)", - screens.mapScreen.closeControl, true); + screens.mapScreen.getCloseButton(), true); } UIWarnButton inventoryButton = nuiMain.getInventoryButton(); diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java index d5ad208cd..756fa43be 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java @@ -427,7 +427,7 @@ public void update(float delta) { SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); if (!nuiManager.hasScreen(gameScreens.menuScreen) && - !solInputManager.isScreenOn(gameScreens.mapScreen)) { + !nuiManager.hasScreen(gameScreens.mapScreen)) { ((AbstractWidget) contents).setVisible(true); } else { ((AbstractWidget) contents).setVisible(false); @@ -535,7 +535,7 @@ public void onDraw(Canvas canvas) { super.onDraw(canvas); // Don't render the borders on-top of the map screen. - if (!solApplication.getInputManager().isScreenOn(solApplication.getGame().getScreens().mapScreen)) { + if (!nuiManager.hasScreen(solApplication.getGame().getScreens().mapScreen)) { try (NUIManager.LegacyUiDrawerWrapper wrapper = nuiManager.getLegacyUiDrawer()) { borderDrawer.draw(wrapper.getUiDrawer(), solApplication, solApplication.getGame().getContext()); zoneNameAnnouncer.drawText(wrapper.getUiDrawer()); @@ -906,10 +906,9 @@ private void onMenuButtonClicked(UIWidget widget) { } private void onMapButtonClicked(UIWidget widget) { - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - solInputManager.setScreen(solApplication, gameScreens.mapScreen); + nuiManager.pushScreen(gameScreens.mapScreen); } private void onItemsButtonClicked(UIWidget widget) { diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MapScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MapScreen.java new file mode 100644 index 000000000..1f010723f --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MapScreen.java @@ -0,0 +1,338 @@ +/* + * Copyright 2021 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.destinationsol.ui.nui.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.math.Vector2; +import org.destinationsol.GameOptions; +import org.destinationsol.SolApplication; +import org.destinationsol.game.MapDrawer; +import org.destinationsol.game.SolCam; +import org.destinationsol.game.SolGame; +import org.destinationsol.game.screens.ScreenToWorldMapper; +import org.destinationsol.game.screens.ShipMouseControl; +import org.destinationsol.game.screens.ShipUiControl; +import org.destinationsol.ui.Waypoint; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.joml.Vector2d; +import org.joml.Vector2i; +import org.terasology.input.MouseInput; +import org.terasology.nui.BaseInteractionListener; +import org.terasology.nui.Canvas; +import org.terasology.nui.InteractionListener; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.events.NUIMouseClickEvent; +import org.terasology.nui.events.NUIMouseDragEvent; +import org.terasology.nui.events.NUIMouseWheelEvent; +import org.terasology.nui.widgets.UIButton; + +import javax.inject.Inject; +import java.util.ArrayList; + +/** + * The map screen is responsible for rendering the UI controls for the in-game map. + * You can zoom-in, zoom-out, pan the map and place/remove waypoints. + * It is not responsible for rendering the map itself, which is done in {@link MapDrawer}. + * @see MapDrawer + */ +public class MapScreen extends NUIScreenLayer { + private enum WaypointOperation { + NONE, + ADDING, + REMOVING + } + + private static final int MIN_WAYPOINT_DIST = 5; + private static final String NEW_WAYPOINT_TEXT = "Marker+"; + private static final String REMOVE_WAYPOINT_TEXT = "Marker-"; + private static final String CANCEL_TEXT = "Cancel"; + + private final SolApplication solApplication; + private UIWarnButton closeButton; + private UIWarnButton zoomInButton; + private UIWarnButton zoomOutButton; + private KeyActivatedButton addWaypointButton; + private KeyActivatedButton removeWaypointButton; + private WaypointOperation waypointOperation; + private final InteractionListener dragListener = new BaseInteractionListener() { + @Override + public boolean onMouseClick(NUIMouseClickEvent event) { + if (event.getMouseButton() == MouseInput.MOUSE_LEFT) { + SolGame game = solApplication.getGame(); + MapDrawer mapDrawer = game.getMapDrawer(); + float mapZoom = mapDrawer.getZoom(); + SolCam solCam = solApplication.getGame().getCam(); + + float camAngle = solCam.getAngle(); + Vector2 mapCamPos = solCam.getPosition().add(mapDrawer.getMapDrawPositionAdditive()); + Vector2i mousePosition = event.getMouse().getPosition(); + // Canvas co-ordinates are relative to the virtual canvas size, rather than the physical canvas size. + // The scale factor is therefore needed to convert these virtual co-ordinates into screen co-ordinates. + float uiScale = nuiManager.getUiScale(); + // This is not a typo! The original InputManager code actually divides both x and y by the height! + Vector2 clickPosition = new Vector2(mousePosition.x * uiScale / Gdx.graphics.getHeight(), + mousePosition.y * uiScale / Gdx.graphics.getHeight()); + Vector2 worldPosition = screenPositionToWorld(clickPosition, mapCamPos, camAngle, mapZoom); + ArrayList waypoints = game.getHero().getWaypoints(); + + if (waypointOperation == WaypointOperation.ADDING) { + //make sure waypoints aren't too close to each other + boolean canCreate = true; + for (int w = 0; w < waypoints.size(); w++) { + Waypoint waypoint = waypoints.get(w); + if (worldPosition.x > waypoint.position.x - MIN_WAYPOINT_DIST && worldPosition.x < waypoint.position.x + MIN_WAYPOINT_DIST && + worldPosition.y > waypoint.position.y - MIN_WAYPOINT_DIST && worldPosition.y < waypoint.position.y + MIN_WAYPOINT_DIST) { + canCreate = false; + break; + } + } + + if (canCreate) { + addWaypointButton.setEnabled(true); + removeWaypointButton.setEnabled(true); + WaypointCreationScreen waypointCreationScreen = game.getScreens().waypointCreationScreen; + waypointCreationScreen.setWaypointPosition(worldPosition); + + nuiManager.pushScreen(waypointCreationScreen); + } + removeWaypointButton.setEnabled(true); + addWaypointButton.setText(NEW_WAYPOINT_TEXT); + waypointOperation = WaypointOperation.NONE; + } else if (waypointOperation == WaypointOperation.REMOVING) { + for (int w = 0; w < waypoints.size(); w++) { + Waypoint waypoint = waypoints.get(w); + if (waypoint.position.x > worldPosition.x - MIN_WAYPOINT_DIST && waypoint.position.x < worldPosition.x + MIN_WAYPOINT_DIST && + waypoint.position.y > worldPosition.y - MIN_WAYPOINT_DIST && waypoint.position.y < worldPosition.y + MIN_WAYPOINT_DIST) { + game.getHero().removeWaypoint(waypoint); + game.getObjectManager().removeObjDelayed(waypoint); + } + } + addWaypointButton.setEnabled(true); + removeWaypointButton.setText(REMOVE_WAYPOINT_TEXT); + waypointOperation = WaypointOperation.NONE; + } + + // Permit left-mouse button dragging by returning true. + return true; + } + + return false; + } + + @Override + public void onMouseDrag(NUIMouseDragEvent event) { + MapDrawer mapDrawer = solApplication.getGame().getMapDrawer(); + GameOptions gameOptions = solApplication.getOptions(); + SolCam solCam = solApplication.getGame().getCam(); + + Vector2d delta = event.getMouse().getDelta(); + Vector2 deltaPosition = new Vector2((float)delta.x, (float)delta.y); + + // Scroll factor negates the drag and adjusts it to map's zoom + float scrollFactor = -mapDrawer.getZoom() / Gdx.graphics.getHeight() * gameOptions.getMapScrollSpeed(); + float rotateAngle = solCam.getAngle(); + mapDrawer.getMapDrawPositionAdditive().add(deltaPosition.scl(scrollFactor).rotateDeg(rotateAngle)); + } + }; + + @Inject + public MapScreen(SolApplication solApplication) { + this.solApplication = solApplication; + } + + @Override + public void initialise() { + closeButton = find("closeButton", UIWarnButton.class); + closeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyMap())); + closeButton.subscribe(button -> { + if (nuiManager.hasScreen(solApplication.getGame().getScreens().waypointCreationScreen)) { + // Don't exit if the waypoint creation screen is open. + return; + } + + if (nuiManager.hasScreen(this)) { + nuiManager.popScreen(); + } + }); + + zoomInButton = find("zoomInButton", UIWarnButton.class); + zoomInButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyZoomIn())); + zoomInButton.subscribe(button -> { + MapDrawer mapDrawer = solApplication.getGame().getMapDrawer(); + mapDrawer.changeZoom(true); + + float mapZoom = mapDrawer.getZoom(); + zoomInButton.setEnabled(mapZoom != MapDrawer.MIN_ZOOM); + zoomOutButton.setEnabled(mapZoom != MapDrawer.MAX_ZOOM); + }); + + zoomOutButton = find("zoomOutButton", UIWarnButton.class); + zoomOutButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyZoomOut())); + zoomOutButton.subscribe(button -> { + MapDrawer mapDrawer = solApplication.getGame().getMapDrawer(); + mapDrawer.changeZoom(false); + + float mapZoom = mapDrawer.getZoom(); + zoomInButton.setEnabled(mapZoom != MapDrawer.MIN_ZOOM); + zoomOutButton.setEnabled(mapZoom != MapDrawer.MAX_ZOOM); + }); + + addWaypointButton = find("addWaypointButton", KeyActivatedButton.class); + addWaypointButton.subscribe(button -> { + if (waypointOperation == WaypointOperation.ADDING) { + // Cancel add + waypointOperation = WaypointOperation.NONE; + removeWaypointButton.setEnabled(true); + addWaypointButton.setText(NEW_WAYPOINT_TEXT); + } else { + waypointOperation = WaypointOperation.ADDING; + removeWaypointButton.setEnabled(false); + addWaypointButton.setText(CANCEL_TEXT); + } + }); + removeWaypointButton = find("removeWaypointButton", KeyActivatedButton.class); + removeWaypointButton.subscribe(button -> { + if (waypointOperation == WaypointOperation.REMOVING) { + // Cancel remove + waypointOperation = WaypointOperation.NONE; + addWaypointButton.setEnabled(true); + removeWaypointButton.setText(REMOVE_WAYPOINT_TEXT); + } else { + waypointOperation = WaypointOperation.REMOVING; + addWaypointButton.setEnabled(false); + removeWaypointButton.setText(CANCEL_TEXT); + } + }); + } + + @Override + public void onAdded() { + solApplication.getGame().getMapDrawer().setToggled(true); + waypointOperation = WaypointOperation.NONE; + } + + @Override + public void onRemoved() { + if (!closeButton.getMode().equals(UIButton.DOWN_MODE)) { + // Act as if we pressed the close button when the screen is removed. + // This fixes the escape key not advancing the tutorial. + closeButton.simulatePress(); + } + + SolGame solGame = solApplication.getGame(); + solGame.getMapDrawer().setToggled(false); + solApplication.getInputManager().setScreen(solApplication, solGame.getScreens().oldMainGameScreen); + } + + @Override + public void update(float delta) { + super.update(delta); + ShipUiControl shipControl = solApplication.getGame().getScreens().oldMainGameScreen.getShipControl(); + if (shipControl instanceof ShipMouseControl) { + shipControl.update(solApplication, true); + } + } + + @Override + public void onDraw(Canvas canvas) { + canvas.addInteractionRegion(dragListener); + super.onDraw(canvas); + } + + @Override + public void onMouseWheelEvent(NUIMouseWheelEvent event) { + if (event.getWheelTurns() == 0) { + return; + } + + MapDrawer mapDrawer = solApplication.getGame().getMapDrawer(); + + if (event.getWheelTurns() > 0 && mapDrawer.getZoom() != MapDrawer.MIN_ZOOM) { + zoomInButton.simulatePress(); + } + + if (event.getWheelTurns() < 0 && mapDrawer.getZoom() != MapDrawer.MAX_ZOOM) { + zoomOutButton.simulatePress(); + } + } + + /** + * Returns true, if the user is currently in the process of placing a waypoint, otherwise false. + * @return true, if the user is picking a waypoint spot, otherwise false. + */ + public boolean isPickingWaypointSpot() { + return waypointOperation == WaypointOperation.ADDING; + } + + /** + * Returns true, if the user is currently in the process of removing a waypoint, otherwise false. + * @return true, if the user is picking a waypoint to remove, otherwise false. + */ + public boolean isPickingWaypointToRemove() { + return waypointOperation == WaypointOperation.REMOVING; + } + + /** + * Enables or disables the waypoint buttons ("Marker+" and "Marker-") + * @param enabled if true, enables the buttons, otherwise disables them. + */ + public void setWaypointButtonsEnabled(boolean enabled) { + addWaypointButton.setEnabled(enabled); + removeWaypointButton.setEnabled(enabled); + } + + /** + * Returns the button used to zoom-in the map. + * This is mostly exposed for use in the tutorial. + * @return the button used to zoom-in the map. + */ + public UIWarnButton getZoomInButton() { + return zoomInButton; + } + + /** + * Returns the button used to zoom-out the map. + * This is mostly exposed for use in the tutorial. + * @return the button used to zoom-out the map. + */ + public UIWarnButton getZoomOutButton() { + return zoomOutButton; + } + + /** + * Returns the button used to close the map. + * This is mostly exposed for use in the tutorial. + * @return the button used to close the map. + */ + public UIWarnButton getCloseButton() { + return closeButton; + } + + private Vector2 screenPositionToWorld(Vector2 clickPosition, Vector2 camPos, float camAngle, float mapZoom) { + float screenWidth = (float) Gdx.graphics.getWidth(); + float screenHeight = (float) Gdx.graphics.getHeight(); + return ScreenToWorldMapper.screenClickPositionToWorldPosition( + new Vector2(screenWidth, screenHeight), + clickPosition, + camPos, + camAngle, + mapZoom + ); + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/UIShipControlsScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/UIShipControlsScreen.java index e3f0641e4..8168abc68 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/UIShipControlsScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/UIShipControlsScreen.java @@ -19,6 +19,7 @@ import org.destinationsol.SolApplication; import org.destinationsol.game.Hero; import org.destinationsol.game.item.Gun; +import org.destinationsol.game.screens.GameScreens; import org.destinationsol.game.screens.ShipUiControl; import org.destinationsol.ui.nui.NUIScreenLayer; import org.destinationsol.ui.nui.widgets.UIWarnButton; @@ -96,7 +97,9 @@ public void initialise() { @Override public void update(float delta) { // Hide and disable controls if the main game screen is not visible. - boolean mainGameScreenVisible = solApplication.getInputManager().isScreenOn(solApplication.getGame().getScreens().oldMainGameScreen); + GameScreens gameScreens = solApplication.getGame().getScreens(); + boolean mainGameScreenVisible = solApplication.getInputManager().isScreenOn(solApplication.getGame().getScreens().oldMainGameScreen) + && !nuiManager.hasScreen(gameScreens.mapScreen); ((AbstractWidget)contents).setVisible(mainGameScreenVisible); contents.setEnabled(mainGameScreenVisible); diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/WaypointCreationScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/WaypointCreationScreen.java new file mode 100644 index 000000000..6d6fb2750 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/WaypointCreationScreen.java @@ -0,0 +1,144 @@ +/* + * Copyright 2021 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.destinationsol.ui.nui.screens; + +import com.badlogic.gdx.math.Vector2; +import org.destinationsol.GameOptions; +import org.destinationsol.SolApplication; +import org.destinationsol.game.SolGame; +import org.destinationsol.ui.Waypoint; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.Color; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.backends.libgdx.GdxColorUtil; +import org.terasology.nui.databinding.Binding; +import org.terasology.nui.databinding.ReadOnlyBinding; +import org.terasology.nui.widgets.UIImage; +import org.terasology.nui.widgets.UISlider; + +import javax.inject.Inject; + +/** + * This screen is responsible for choosing the colour of a waypoint and then placing it. + * The position of the waypoint to place is decided in the {@link MapScreen}. + * + * TODO: This screen is essentially a basic colour picker. Maybe it should be adapted into a generic widget instead? + */ +public class WaypointCreationScreen extends NUIScreenLayer { + private final SolApplication solApplication; + private UISlider redSlider; + private UISlider greenSlider; + private UISlider blueSlider; + private UIImage colourPreview; + private KeyActivatedButton doneButtton; + private KeyActivatedButton cancelButton; + private Color chosenColour; + private Vector2 waypointPosition; + + @Inject + public WaypointCreationScreen(SolApplication solApplication) { + this.solApplication = solApplication; + } + + @Override + public void initialise() { + colourPreview = find("colourPreview", UIImage.class); + colourPreview.bindTint(new ReadOnlyBinding() { + @Override + public Color get() { + return chosenColour; + } + }); + + redSlider = find("redSlider", UISlider.class); + redSlider.bindValue(new Binding() { + @Override + public Float get() { + return (float) chosenColour.r(); + } + + @Override + public void set(Float value) { + chosenColour.setRed(value.intValue()); + } + }); + + greenSlider = find("greenSlider", UISlider.class); + greenSlider.bindValue(new Binding() { + @Override + public Float get() { + return (float) chosenColour.g(); + } + + @Override + public void set(Float value) { + chosenColour.setGreen(value.intValue()); + } + }); + + blueSlider = find("blueSlider", UISlider.class); + blueSlider.bindValue(new Binding() { + @Override + public Float get() { + return (float) chosenColour.b(); + } + + @Override + public void set(Float value) { + chosenColour.setBlue(value.intValue()); + } + }); + + GameOptions gameOptions = solApplication.getOptions(); + + doneButtton = find("doneButton", KeyActivatedButton.class); + doneButtton.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyShoot())); + doneButtton.subscribe(button -> { + SolGame solGame = solApplication.getGame(); + + Waypoint waypoint = new Waypoint(waypointPosition, GdxColorUtil.terasologyToGDXColor(chosenColour), + solGame.getMapDrawer().getWaypointTexture()); + solGame.getHero().addWaypoint(waypoint); + solGame.getObjectManager().addObjDelayed(waypoint); + + MapScreen mapScreen = solGame.getScreens().mapScreen; + mapScreen.setWaypointButtonsEnabled(true); + nuiManager.popScreen(); + }); + + cancelButton = find("cancelButton", KeyActivatedButton.class); + cancelButton.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyClose())); + cancelButton.subscribe(button -> { + MapScreen mapScreen = solApplication.getGame().getScreens().mapScreen; + mapScreen.setWaypointButtonsEnabled(true); + nuiManager.popScreen(); + }); + + chosenColour = new Color(1.0f, 1.0f, 1.0f); + waypointPosition = new Vector2(); + } + + public void setWaypointPosition(Vector2 waypointPosition) { + this.waypointPosition = waypointPosition; + } + + @Override + protected boolean escapeCloses() { + return false; + } +} diff --git a/engine/src/main/resources/org/destinationsol/assets/skins/mapScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/mapScreen.skin new file mode 100644 index 000000000..ae41542b0 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/skins/mapScreen.skin @@ -0,0 +1,32 @@ +{ + "inherit": "engine:mainGameScreen", + "families": { + "mapUIButton": { + "elements": { + "UIButton": { + "min-width": 164, + "min-height": 64 + } + }, + "font": "engine:main#0.95" + }, + "waypointColourPreview": { + "fixed-height": 32, + "texture-scale-mode": "stretch" + }, + "waypointScreenMenuBox": { + "max-width": 360, + "max-height": 600, + "elements": { + "UIBox": { + "background": "engine:background" + }, + "UILabel": { + "font": "engine:main#0.6", + "text-align-horizontal": "center", + "text-align-vertical": "middle" + } + } + } + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_desktop.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_desktop.ui new file mode 100644 index 000000000..4c982c8a7 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_desktop.ui @@ -0,0 +1,51 @@ +{ + "type": "MapScreen", + "skin": "engine:mainGameScreen", + "contents": { + "type": "relativeLayout", + "contents": [ + { + "type": "ColumnLayout", + "id": "menuList", + "layoutInfo": { + "use-content-width": true, + "use-content-height": true, + "position-vertical-center": { + "offset": -100 + }, + "position-right": {} + }, + "columns": 1, + "verticalSpacing": 8, + "family": "sideUIButton", + "contents": [ + { + "type": "UIWarnButton", + "text": "Close", + "id": "closeButton" + }, + { + "type": "UIWarnButton", + "text": "Zoom In", + "id": "zoomInButton" + }, + { + "type": "UIWarnButton", + "text": "Zoom Out", + "id": "zoomOutButton" + }, + { + "type": "UIWarnButton", + "text": "Marker+", + "id": "addWaypointButton" + }, + { + "type": "UIWarnButton", + "text": "Marker-", + "id": "removeWaypointButton" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_mobile.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_mobile.ui new file mode 100644 index 000000000..0f5c0a783 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mapScreen_mobile.ui @@ -0,0 +1,73 @@ +{ + "type": "MapScreen", + "skin": "engine:mapScreen", + "contents": { + "type": "relativeLayout", + "family": "mapUIButton", + "contents": [ + { + "type": "UIWarnButton", + "text": "Marker+", + "id": "addWaypointButton", + "layoutInfo": { + "position-left": {}, + "position-top": {}, + "use-content-width": true, + "use-content-height": true + } + }, + { + "type": "UIWarnButton", + "text": "Marker-", + "id": "removeWaypointButton", + "layoutInfo": { + "position-left": {}, + "position-top": { + "widget": "addWaypointButton", + "target": "BOTTOM", + "offset": 16 + }, + "use-content-width": true, + "use-content-height": true + } + }, + { + "type": "UIWarnButton", + "text": "Close", + "id": "closeButton", + "layoutInfo": { + "position-left": {}, + "position-vertical-center": {}, + "use-content-width": true, + "use-content-height": true + } + }, + { + "type": "UIWarnButton", + "text": "Zoom In", + "id": "zoomInButton", + "layoutInfo": { + "position-left": {}, + "position-bottom": { + "widget": "zoomOutButton", + "target": "TOP", + "offset": 16 + }, + "use-content-width": true, + "use-content-height": true + } + }, + { + "type": "UIWarnButton", + "text": "Zoom Out", + "id": "zoomOutButton", + "layoutInfo": { + "position-left": {}, + "position-bottom": {}, + "use-content-width": true, + "use-content-height": true + } + } + ] + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/waypointCreationScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/waypointCreationScreen.ui new file mode 100644 index 000000000..db57321e9 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/waypointCreationScreen.ui @@ -0,0 +1,114 @@ +{ + "type": "WaypointCreationScreen", + "skin": "engine:mapScreen", + "contents": { + "type": "relativeLayout", + "contents": [ + { + "type": "UIBackingBox", + "family": "waypointScreenMenuBox", + "layoutInfo": { + "position-top": { + "target": "MIDDLE", + "offset": 32 + }, + "position-bottom": { + "offset": 32 + }, + "position-left": { + "offset": 64 + }, + "position-right": { + "offset": 64 + }, + "position-horizontal-center": {} + }, + "content": { + "type": "ColumnLayout", + "verticalSpacing": 8, + "contents": [ + { + "type": "UIImage", + "id": "colourPreview", + "family": "waypointColourPreview", + "image": "engine:uiWhiteTex" + }, + { + "type": "RowLayout", + "contents": [ + { + "type": "UILabel", + "text": "Red", + "layoutInfo": { + "relativeWidth": 0.3 + } + }, + { + "type": "UISlider", + "id": "redSlider", + "precision": 0, + "minimum": 0, + "range": 255, + "value": 255, + "increment": 1 + } + ] + }, + { + "type": "RowLayout", + "contents": [ + { + "type": "UILabel", + "text": "Green", + "layoutInfo": { + "relativeWidth": 0.3 + } + }, + { + "type": "UISlider", + "id": "greenSlider", + "precision": 0, + "minimum": 0, + "range": 255, + "value": 255, + "increment": 1 + } + ] + }, + { + "type": "RowLayout", + "contents": [ + { + "type": "UILabel", + "text": "Blue", + "layoutInfo": { + "relativeWidth": 0.3 + } + }, + { + "type": "UISlider", + "id": "blueSlider", + "precision": 0, + "minimum": 0, + "range": 255, + "value": 255, + "increment": 1 + } + ] + }, + { + "type": "KeyActivatedButton", + "id": "doneButton", + "text": "Done" + }, + { + "type": "KeyActivatedButton", + "id": "cancelButton", + "text": "Cancel" + } + ] + } + } + ] + } +} \ No newline at end of file