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/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index aef9f9528..8cd6a54ba 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -362,7 +362,7 @@ public void play(boolean tut, String shipName, boolean isNewGame, WorldConfig wo factionDisplay = new FactionDisplay(gameContext.getBean(SolCam.class)); nuiManager.removeScreen(menuScreens.loading); - inputManager.setScreen(this, solGame.getScreens().mainGameScreen); + inputManager.setScreen(this, solGame.getScreens().oldMainGameScreen); } public SolInputManager getInputManager() { @@ -402,9 +402,11 @@ public SolLayouts getLayouts() { public void finishGame() { solGame.onGameEnd(gameContext.getBean(Context.class)); - solGame = null; // TODO: remove the following line when all screens have been ported to use NUI inputManager.setScreen(this, null); + inputManager.update(this); // Force an update to remove all the InputManager UI screens + + solGame = null; nuiManager.pushScreen(menuScreens.main); entityCreated = false; } diff --git a/engine/src/main/java/org/destinationsol/game/PlayerCreator.java b/engine/src/main/java/org/destinationsol/game/PlayerCreator.java index 7756b48a2..0203ed8b8 100644 --- a/engine/src/main/java/org/destinationsol/game/PlayerCreator.java +++ b/engine/src/main/java/org/destinationsol/game/PlayerCreator.java @@ -185,7 +185,7 @@ private Pilot createPilot(SolGame game, boolean isMouseControl) { if (isMouseControl) { return new AiPilot(new BeaconDestProvider(), true, Faction.LAANI, false, "you", Const.AI_DET_DIST); } else { - return new UiControlledPilot(game.getScreens().getMainGameScreen().getShipControl()); + return new UiControlledPilot(game.getScreens().getOldMainGameScreen().getShipControl()); } } diff --git a/engine/src/main/java/org/destinationsol/game/SolCam.java b/engine/src/main/java/org/destinationsol/game/SolCam.java index 55211335c..5f39f9abe 100644 --- a/engine/src/main/java/org/destinationsol/game/SolCam.java +++ b/engine/src/main/java/org/destinationsol/game/SolCam.java @@ -177,7 +177,7 @@ public void applyPos(float posX, float posY) { } private void applyInput(SolGame game) { - MainGameScreen screen = game.getScreens().mainGameScreen; + MainGameScreen screen = game.getScreens().oldMainGameScreen; boolean d = screen.isCameraDown(); boolean u = screen.isCameraUp(); boolean l = screen.isCameraLeft(); diff --git a/engine/src/main/java/org/destinationsol/game/SolGame.java b/engine/src/main/java/org/destinationsol/game/SolGame.java index 7fe5d3b95..36ddaf03e 100644 --- a/engine/src/main/java/org/destinationsol/game/SolGame.java +++ b/engine/src/main/java/org/destinationsol/game/SolGame.java @@ -22,7 +22,6 @@ import org.destinationsol.ContextWrapper; import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; -import org.destinationsol.assets.Assets; import org.destinationsol.assets.sound.OggSoundManager; import org.destinationsol.assets.sound.SpecialSounds; import org.destinationsol.common.DebugCol; @@ -68,10 +67,8 @@ import org.destinationsol.ui.nui.screens.MainGameScreen; import org.destinationsol.world.GalaxyBuilder; import org.terasology.context.exception.BeanNotFoundException; -import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.di.BeanContext; import org.terasology.gestalt.entitysystem.entity.EntityRef; -import org.terasology.nui.asset.UIElement; import javax.inject.Inject; import java.util.ArrayList; @@ -266,7 +263,7 @@ public void run() { } }, 0, 30); gameScreens.consoleScreen.init(this); - solApplication.getNuiManager().pushScreen(mainGameScreen); + solApplication.getNuiManager().pushScreen(gameScreens.mainGameScreen); tutorialManager.ifPresent(TutorialManager::start); } @@ -340,10 +337,11 @@ public void onGameEnd(Context context) { } catch (Exception e) { e.printStackTrace(); } - - // TODO: Remove this when context is reset after each game - context.get(EntitySystemManager.class).getEntityManager().allEntities().forEach(EntityRef::delete); } + + // TODO: Remove this when context is reset after each game + context.get(EntitySystemManager.class).getEntityManager().allEntities().forEach(EntityRef::delete); + FactionInfo.clearValues(); try { objectManager.close(); diff --git a/engine/src/main/java/org/destinationsol/game/item/ItemManager.java b/engine/src/main/java/org/destinationsol/game/item/ItemManager.java index caf4ff912..1b9787d9f 100644 --- a/engine/src/main/java/org/destinationsol/game/item/ItemManager.java +++ b/engine/src/main/java/org/destinationsol/game/item/ItemManager.java @@ -78,6 +78,14 @@ public void fillContainer(ItemContainer itemContainer, String items) { } } + public ItemConfig parseItem(String item) { + List items = parseItems(item); + if (items.isEmpty()) { + return null; + } + return items.get(0); + } + public List parseItems(String items) { ArrayList result = new ArrayList<>(); diff --git a/engine/src/main/java/org/destinationsol/game/screens/BorderDrawer.java b/engine/src/main/java/org/destinationsol/game/screens/BorderDrawer.java index b0e714d0a..182736b96 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/BorderDrawer.java +++ b/engine/src/main/java/org/destinationsol/game/screens/BorderDrawer.java @@ -56,7 +56,7 @@ public class BorderDrawer { private final ArrayList planetProximityIndicators; private final Vector2 myTmpVec = new Vector2(); - BorderDrawer() { + public BorderDrawer() { displayDimensions = SolApplication.displayDimensions; TextureAtlas.AtlasRegion texture = Assets.getAtlasRegion("engine:uiPlanetProximityIndicator"); 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 702ef2ebb..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,16 +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 @@ -47,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().mainGameScreen); + 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 049ec0ac6..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,16 +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 @@ -52,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().mainGameScreen); + 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 316021f2f..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.mainGameScreen); - 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.mainGameScreen); - 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.mainGameScreen); - 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/ConsoleScreen.java b/engine/src/main/java/org/destinationsol/game/screens/ConsoleScreen.java index d406300e4..f3d944509 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ConsoleScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ConsoleScreen.java @@ -162,7 +162,7 @@ public void onAdd(SolApplication solApplication) { @Override public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { if (exitControl.isJustOff()) { - solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().mainGameScreen); + solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); } if (commandHistoryUpControl.isJustOff()) { if (commandHistoryIndex > 0) { 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 5da379640..d7a4f125d 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java +++ b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java @@ -19,11 +19,19 @@ import org.destinationsol.game.console.Console; import org.destinationsol.game.context.Context; 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 org.destinationsol.ui.nui.screens.MapScreen; +import org.destinationsol.ui.nui.screens.WaypointCreationScreen; import javax.inject.Inject; public class GameScreens { - public final MainGameScreen mainGameScreen; + private static final String NUI_MAIN_GAME_SCREEN_DESKTOP_URI = "engine:mainGameScreen_desktop"; + private static final String NUI_MAIN_GAME_SCREEN_MOBILE_URI = "engine:mainGameScreen_mobile"; + public final MainGameScreen oldMainGameScreen; + public final org.destinationsol.ui.nui.screens.MainGameScreen mainGameScreen; public final MapScreen mapScreen; public final MenuScreen menuScreen; public final InventoryScreen inventoryScreen; @@ -35,18 +43,25 @@ public class GameScreens { public GameScreens(SolApplication cmp, Context context) { SolLayouts layouts = cmp.getLayouts(); RightPaneLayout rightPaneLayout = layouts.rightPaneLayout; - mainGameScreen = new MainGameScreen(rightPaneLayout, context); - mapScreen = new MapScreen(rightPaneLayout, cmp.isMobile(), cmp.getOptions()); - menuScreen = new MenuScreen(layouts.menuLayout, cmp.getOptions()); - inventoryScreen = new InventoryScreen(cmp.getOptions()); - talkScreen = new TalkScreen(layouts.menuLayout, cmp.getOptions()); - waypointCreationScreen = new WaypointCreationScreen(layouts.menuLayout, cmp.getOptions(), mapScreen); + oldMainGameScreen = new MainGameScreen(rightPaneLayout, 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"); + } + menuScreen = (MenuScreen) cmp.getNuiManager().createScreen("engine:menuScreen"); + inventoryScreen = (InventoryScreen) cmp.getNuiManager().createScreen("engine:inventoryScreen"); + talkScreen = (TalkScreen) cmp.getNuiManager().createScreen("engine:talkScreen"); + waypointCreationScreen = (WaypointCreationScreen) cmp.getNuiManager().createScreen("engine:waypointCreationScreen"); consoleScreen = new ConsoleScreen(context.get(Console.class)); } // This was added for PlayerCreatorTest.java (used in PlayerCreator) // so that it can successfully mock the returned result. - public MainGameScreen getMainGameScreen() { - return mainGameScreen; + public MainGameScreen getOldMainGameScreen() { + return oldMainGameScreen; } } 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 613776671..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,16 +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 @@ -46,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().mainGameScreen); + 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 cddbe0686..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.mainGameScreen); - is.setOperations(is.chooseMercenaryScreen); - inputMan.addScreen(solApplication, is); - } - solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().mainGameScreen); - 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/MainGameScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java index f725a33c1..855dbdfa5 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java @@ -15,92 +15,45 @@ */ package org.destinationsol.game.screens; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.g2d.TextureAtlas; -import com.badlogic.gdx.math.MathUtils; 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.assets.Assets; -import org.destinationsol.common.SolColor; -import org.destinationsol.common.SolMath; import org.destinationsol.game.DebugOptions; -import org.destinationsol.game.FactionManager; -import org.destinationsol.game.HardnessCalc; -import org.destinationsol.game.Hero; -import org.destinationsol.game.SolCam; import org.destinationsol.game.SolGame; -import org.destinationsol.game.SolObject; import org.destinationsol.game.context.Context; -import org.destinationsol.game.item.Gun; -import org.destinationsol.game.item.ItemManager; -import org.destinationsol.game.item.Shield; -import org.destinationsol.game.item.SolItem; -import org.destinationsol.game.planet.Planet; -import org.destinationsol.game.ship.ShipAbility; -import org.destinationsol.game.ship.SolShip; -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.SolUiScreen; import org.destinationsol.ui.UiDrawer; +import org.destinationsol.ui.nui.NUIManager; +import org.destinationsol.ui.nui.NUIScreenLayer; import org.destinationsol.ui.nui.screens.ConsoleScreen; +import org.destinationsol.ui.nui.screens.TutorialScreen; import org.destinationsol.ui.nui.screens.UIShipControlsScreen; -import org.terasology.gestalt.assets.ResourceUrn; -import org.terasology.nui.asset.UIElement; import java.util.ArrayList; import java.util.List; +/** + * @deprecated This class only exists for compatibility purposes whilst the rest of the code is + * transitions to the new NUI-based MainGameScreen. Almost all functionality is now implemented by the new screen. + * @see org.destinationsol.ui.nui.screens.MainGameScreen the new NUI-based MainGameScreen + */ +@Deprecated public class MainGameScreen extends SolUiBaseScreen { - // TODO: Rename! - private static final float ICON_SZ = .03f; - private static final float BAR_SZ = ICON_SZ * 5; - private static final int MAX_ICON_COUNT = 3; static final float CELL_SZ = .17f; - private static final float H_PAD = .005f; - private static final float V_PAD = H_PAD; static final float HELPER_ROW_1 = 1 - 3f * CELL_SZ; - private static final float HELPER_ROW_2 = HELPER_ROW_1 - .5f * CELL_SZ; - private static final float HELPER_ROW_3 = HELPER_ROW_2 - .5f * CELL_SZ; private final ShipUiControl shipControl; - private final SolUiControl freeCamControl; private final SolUiControl pauseControl; private final CameraKeyboardControl cameraControl; - - private final ZoneNameAnnouncer zoneNameAnnouncer; - private final BorderDrawer borderDrawer; - - private final TextureAtlas.AtlasRegion lifeTexture; - private final TextureAtlas.AtlasRegion infinityTexture; - private final TextureAtlas.AtlasRegion waitTexture; - private final TextureAtlas.AtlasRegion compassTexture; - - private final Color myCompassTint; - private final TextPlace myLifeTp; - private final TextPlace myRepairsExcessTp; - private final TextPlace myShieldLifeTp; - private final TextPlace myG1AmmoTp; - private final TextPlace myG1AmmoExcessTp; - private final TextPlace myG2AmmoTp; - private final TextPlace myG2AmmoExcessTp; - private final TextPlace myChargesExcessTp; - private final TextPlace myMoneyExcessTp; private final SolApplication solApplication; - private final Context context; private List gameOverlayScreens = new ArrayList<>(); private List warnDrawers = new ArrayList<>(); MainGameScreen(RightPaneLayout rightPaneLayout, Context context) { - DisplayDimensions displayDimensions = SolApplication.displayDimensions; - - this.context = context; solApplication = context.get(SolApplication.class); GameOptions gameOptions = solApplication.getOptions(); @@ -122,42 +75,9 @@ public class MainGameScreen extends SolUiBaseScreen { break; } - boolean mobile = solApplication.isMobile(); - float lastCol = displayDimensions.getRatio() - MainGameScreen.CELL_SZ; - // No button, since on mobile, it should be ideally controlled straightly by dragging. - freeCamControl = new SolUiControl(null, false, gameOptions.getKeyFreeCameraMovement()); - controls.add(freeCamControl); pauseControl = new SolUiControl(null, true, gameOptions.getKeyPause()); controls.add(pauseControl); cameraControl = new CameraKeyboardControl(gameOptions, controls); - - // possible warning messages in order of importance, so earlier one will be drawn on the center - warnDrawers.add(new SunWarnDrawer()); - warnDrawers.add(new DmgWarnDrawer()); - warnDrawers.add(new CollisionWarnDrawer()); - warnDrawers.add(new NoShieldWarn()); - warnDrawers.add(new NoArmorWarn()); - warnDrawers.add(new EnemyWarn()); - - zoneNameAnnouncer = new ZoneNameAnnouncer(); - borderDrawer = new BorderDrawer(); - - lifeTexture = Assets.getAtlasRegion("engine:iconLife"); - infinityTexture = Assets.getAtlasRegion("engine:iconInfinity"); - waitTexture = Assets.getAtlasRegion("engine:iconWait"); - - compassTexture = Assets.getAtlasRegion("engine:uiCompass"); - myCompassTint = SolColor.col(1, 0); - - myLifeTp = new TextPlace(SolColor.W50); - myRepairsExcessTp = new TextPlace(SolColor.WHITE); - myShieldLifeTp = new TextPlace(SolColor.W50); - myG1AmmoTp = new TextPlace(SolColor.W50); - myG1AmmoExcessTp = new TextPlace(SolColor.WHITE); - myG2AmmoTp = new TextPlace(SolColor.W50); - myG2AmmoExcessTp = new TextPlace(SolColor.WHITE); - myChargesExcessTp = new TextPlace(SolColor.WHITE); - myMoneyExcessTp = new TextPlace(SolColor.WHITE); } @Override @@ -180,34 +100,6 @@ public static Rectangle btn(float x, float y, boolean halfHeight) { return new Rectangle(x + gap, y + gap, CELL_SZ - gap * 2, cellH - gap * 2); } - private void maybeDrawHeight(UiDrawer drawer) { - SolGame game = solApplication.getGame(); - Planet np = game.getPlanetManager().getNearestPlanet(); - SolCam cam = context.get(SolCam.class); - Vector2 camPos = cam.getPosition(); - if (np != null && np.getPosition().dst(camPos) < np.getFullHeight()) { - drawHeight(drawer, np, camPos, cam.getAngle()); - } - } - - private void drawHeight(UiDrawer drawer, Planet np, Vector2 camPos, float camAngle) { - float toPlanet = camPos.dst(np.getPosition()); - toPlanet -= np.getGroundHeight(); - if (Const.ATM_HEIGHT < toPlanet) { - return; - } - float perc = toPlanet / Const.ATM_HEIGHT; - float sz = .08f; - float maxY = 1 - sz / 2; - float y = 1 - perc; - myCompassTint.a = SolMath.clamp(1.5f * y); - if (maxY < y) { - y = maxY; - } - float angle = np.getAngle() - camAngle; - drawer.draw(compassTexture, sz, sz, sz / 2, sz / 2, sz / 2, y, angle, myCompassTint); - } - @Override public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { if (DebugOptions.PRINT_BALANCE) { @@ -216,23 +108,23 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi } SolGame game = solApplication.getGame(); SolInputManager inputMan = solApplication.getInputManager(); + NUIManager nuiManager = solApplication.getNuiManager(); GameScreens screens = game.getScreens(); - Hero hero = game.getHero(); for (WarnDrawer warnDrawer : warnDrawers) { warnDrawer.update(game); } - zoneNameAnnouncer.update(game, context); - - boolean controlsEnabled = inputMan.getTopScreen() == this; + NUIScreenLayer topScreen = nuiManager.getTopScreen(); + boolean controlsEnabled = inputMan.getTopScreen() == this && + (topScreen instanceof org.destinationsol.ui.nui.screens.MainGameScreen || + topScreen instanceof UIShipControlsScreen || + topScreen instanceof TutorialScreen); shipControl.update(solApplication, controlsEnabled); - SolCam.DIRECT_CAM_CONTROL = freeCamControl.isOn(); - if (solApplication.getNuiManager().hasScreenOfType(ConsoleScreen.class)) { controls.forEach(x -> x.setEnabled(false)); - } else if (!inputMan.isScreenOn(screens.menuScreen)) { + } else if (!nuiManager.hasScreen(screens.menuScreen)) { game.setPaused(false); controls.forEach(x -> x.setEnabled(true)); } @@ -246,136 +138,8 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi } } - private boolean drawGunStat(UiDrawer uiDrawer, Hero hero, boolean secondary, float col0, float col1, - float col2, float y) { - Gun g = hero.getHull().getGun(secondary); - if (g == null) { - return false; - } - TextureAtlas.AtlasRegion tex = g.config.icon; - - uiDrawer.draw(tex, ICON_SZ, ICON_SZ, 0, 0, col0, y, 0, SolColor.WHITE); - float curr; - float max; - if (g.reloadAwait > 0) { - max = g.config.reloadTime; - curr = max - g.reloadAwait; - } else { - curr = g.ammo; - max = g.config.clipConf.size; - } - TextPlace ammoTp = g.reloadAwait > 0 ? null : secondary ? myG2AmmoTp : myG1AmmoTp; - drawBar(uiDrawer, col1, y, curr, max, ammoTp); - if (g.reloadAwait > 0) { - drawWait(uiDrawer, col1, y); - } - if (!g.config.clipConf.infinite) { - int clipCount = hero.getItemContainer().count(g.config.clipConf.example); - drawIcons(uiDrawer, col2, y, clipCount, g.config.clipConf.icon, secondary ? myG2AmmoExcessTp : myG1AmmoExcessTp); - } else { - uiDrawer.draw(infinityTexture, ICON_SZ, ICON_SZ, 0, 0, col2, y, 0, SolColor.WHITE); - } - return true; - } - - private void drawWait(UiDrawer uiDrawer, float x, float y) { - uiDrawer.draw(waitTexture, ICON_SZ, ICON_SZ, ICON_SZ / 2, ICON_SZ / 2, x + BAR_SZ / 2, y + ICON_SZ / 2, 0, SolColor.WHITE); - } - - private void drawBar(UiDrawer uiDrawer, float x, float y, float curr, float max, TextPlace tp) { - float perc = curr / max; - uiDrawer.draw(uiDrawer.whiteTexture, BAR_SZ, ICON_SZ, 0, 0, x, y, 0, SolColor.UI_DARK); - uiDrawer.draw(uiDrawer.whiteTexture, BAR_SZ * perc, ICON_SZ, 0, 0, x, y, 0, SolColor.UI_LIGHT); - if (tp != null && max > 1 && curr > 0) { - tp.text = (int) curr + "/" + (int) max; - tp.position.set(x + BAR_SZ / 2, y + ICON_SZ / 2); - } - } - - private void drawIcons(UiDrawer uiDrawer, float x, float y, int count, TextureAtlas.AtlasRegion tex, - TextPlace textPlace) { - int excess = count - MAX_ICON_COUNT; - int iconCount = excess > 0 ? MAX_ICON_COUNT : count; - for (int i = 0; i < iconCount; i++) { - uiDrawer.draw(tex, ICON_SZ, ICON_SZ, 0, 0, x, y, 0, SolColor.WHITE); - x += ICON_SZ + H_PAD; - } - if (excess > 0) { - updateTextPlace(x, y, "+" + excess, textPlace); - } - } - - private void updateTextPlace(float x, float y, String text, TextPlace textPlace) { - textPlace.text = text; - textPlace.position.set(x + ICON_SZ / 2, y + ICON_SZ / 2); - } - @Override public void drawImages(UiDrawer uiDrawer, SolApplication solApplication) { - myLifeTp.text = null; - myRepairsExcessTp.text = null; - myShieldLifeTp.text = null; - myG1AmmoTp.text = null; - myG1AmmoExcessTp.text = null; - myG2AmmoTp.text = null; - myG2AmmoExcessTp.text = null; - myChargesExcessTp.text = null; - myMoneyExcessTp.text = null; - - maybeDrawHeight(uiDrawer); - borderDrawer.draw(uiDrawer, solApplication, context); - - SolGame game = solApplication.getGame(); - Hero hero = game.getHero(); - if (hero.isNonTranscendent()) { - float row = BorderDrawer.PLANET_PROXIMITY_INDICATOR_SIZE + V_PAD; - float col0 = BorderDrawer.PLANET_PROXIMITY_INDICATOR_SIZE + H_PAD; - float col1 = col0 + ICON_SZ + H_PAD; - float col2 = col1 + BAR_SZ + H_PAD; - - Shield shield = hero.getShield(); - if (shield != null) { - uiDrawer.draw(shield.getIcon(game), ICON_SZ, ICON_SZ, 0, 0, col0, row, 0, SolColor.WHITE); - drawBar(uiDrawer, col1, row, MathUtils.floor(shield.getLife()), shield.getMaxLife(), myShieldLifeTp); - row += ICON_SZ + V_PAD; - } - - uiDrawer.draw(lifeTexture, ICON_SZ, ICON_SZ, 0, 0, col0, row, 0, SolColor.WHITE); - drawBar(uiDrawer, col1, row, MathUtils.floor(hero.getLife()), hero.getHull().config.getMaxLife(), myLifeTp); - int repairKitCount = hero.getItemContainer().count(game.getItemMan().getRepairExample()); - ItemManager itemManager = game.getItemMan(); - drawIcons(uiDrawer, col2, row, repairKitCount, itemManager.repairIcon, myRepairsExcessTp); - - row += ICON_SZ + V_PAD; - boolean consumed = drawGunStat(uiDrawer, hero, false, col0, col1, col2, row); - if (consumed) { - row += ICON_SZ + V_PAD; - } - consumed = drawGunStat(uiDrawer, hero, true, col0, col1, col2, row); - if (consumed) { - row += ICON_SZ + V_PAD; - } - - ShipAbility ability = hero.getAbility(); - SolItem abilityChargeEx = ability == null ? null : ability.getConfig().getChargeExample(); - if (abilityChargeEx != null) { - int abilityChargeCount = hero.getItemContainer().count(abilityChargeEx); - TextureAtlas.AtlasRegion icon = abilityChargeEx.getIcon(game); - uiDrawer.draw(icon, ICON_SZ, ICON_SZ, 0, 0, col0, row, 0, SolColor.WHITE); - float chargePercentage = 1 - SolMath.clamp(hero.getAbilityAwait() / ability.getConfig().getRechargeTime()); - drawBar(uiDrawer, col1, row, chargePercentage, 1, null); - if (chargePercentage < 1) { - drawWait(uiDrawer, col1, row); - } - drawIcons(uiDrawer, col2, row, abilityChargeCount, icon, myChargesExcessTp); - row += ICON_SZ + V_PAD; - } - uiDrawer.draw(game.getItemMan().moneyIcon, ICON_SZ, ICON_SZ, 0, 0, col0, row, 0, SolColor.WHITE); - myMoneyExcessTp.text = Integer.toString(Math.round(hero.getMoney())); - myMoneyExcessTp.position.set(col1, row + ICON_SZ / 2); - //updateTextPlace(col1, row, (int) hero.getMoney() + "", myMoneyExcessTp); - } - int drawPlace = 0; for (WarnDrawer wd : warnDrawers) { if (wd.drawPercentage > 0) { @@ -390,16 +154,6 @@ public void drawImages(UiDrawer uiDrawer, SolApplication solApplication) { @Override public void drawText(UiDrawer uiDrawer, SolApplication solApplication) { - myLifeTp.draw(uiDrawer); - myRepairsExcessTp.draw(uiDrawer); - myShieldLifeTp.draw(uiDrawer); - myG1AmmoTp.draw(uiDrawer); - myG1AmmoExcessTp.draw(uiDrawer); - myG2AmmoTp.draw(uiDrawer); - myG2AmmoExcessTp.draw(uiDrawer); - myChargesExcessTp.draw(uiDrawer); - myMoneyExcessTp.draw(uiDrawer, UiDrawer.TextAlignment.LEFT); - int drawPlace = 0; for (WarnDrawer warnDrawer : warnDrawers) { if (warnDrawer.drawPercentage > 0) { @@ -407,8 +161,6 @@ public void drawText(UiDrawer uiDrawer, SolApplication solApplication) { } } - zoneNameAnnouncer.drawText(uiDrawer); - for (SolUiScreen screen : gameOverlayScreens) { screen.drawText(uiDrawer, solApplication); } @@ -443,117 +195,71 @@ public boolean isCameraRight() { return cameraControl.isRight(); } + /** + * @deprecated Use NUI screens instead. All NUI screens are overlays. + * @see NUIScreenLayer + * @see NUIManager#createScreen(String) + * @see NUIManager#pushScreen(NUIScreenLayer) + */ + @Deprecated public void addOverlayScreen(SolUiScreen screen) { gameOverlayScreens.add(screen); screen.onAdd(solApplication); controls.addAll(screen.getControls()); } + /** + * @deprecated Use NUI screens instead. All NUI screens are overlays. + * @see NUIManager#removeScreen(NUIScreenLayer) + */ + @Deprecated public void removeOverlayScreen(SolUiScreen screen) { gameOverlayScreens.remove(screen); controls.removeAll(screen.getControls()); } + /** + * @deprecated Use NUI screens instead. All NUI screens are overlays. + * @see NUIManager#hasScreen(NUIScreenLayer) + */ + @Deprecated public boolean hasOverlay(SolUiScreen screen) { return gameOverlayScreens.contains(screen); } + /** + * @deprecated Use the new MainGameScreen and UIWarnDrawer instead. + * @see org.destinationsol.ui.nui.widgets.UIWarnDrawer + * @see org.destinationsol.ui.nui.screens.MainGameScreen#addWarnDrawer(String, org.terasology.nui.Color, String, org.terasology.nui.databinding.Binding) + * @see org.destinationsol.ui.nui.screens.MainGameScreen#addWarnDrawer(org.destinationsol.ui.nui.widgets.UIWarnDrawer) + */ + @Deprecated public void addWarnDrawer(WarnDrawer drawer) { if (!warnDrawers.contains(drawer)) { warnDrawers.add(drawer); } } + /** + * @deprecated Use the new MainGameScreen and UIWarnDrawer instead. + * @see org.destinationsol.ui.nui.widgets.UIWarnDrawer + * @see org.destinationsol.ui.nui.screens.MainGameScreen#removeWarnDrawer(String) + * @see org.destinationsol.ui.nui.screens.MainGameScreen#removeWarnDrawer(org.destinationsol.ui.nui.widgets.UIWarnDrawer) + */ + @Deprecated public void removeWarnDrawer(WarnDrawer drawer) { warnDrawers.remove(drawer); } + /** + * @deprecated Use the new MainGameScreen and UIWarnDrawer instead. + * @see org.destinationsol.ui.nui.widgets.UIWarnDrawer + * @see org.destinationsol.ui.nui.screens.MainGameScreen#hasWarnDrawer(String) + * @see org.destinationsol.ui.nui.screens.MainGameScreen#hasWarnDrawer(org.destinationsol.ui.nui.widgets.UIWarnDrawer) + */ + @Deprecated public boolean hasWarnDrawer(WarnDrawer drawer) { return warnDrawers.contains(drawer); } - - public static class TextPlace { - public final Color color; - public String text; - public Vector2 position = new Vector2(); - - TextPlace(Color col) { - color = new Color(col); - } - - public void draw(UiDrawer uiDrawer) { - uiDrawer.drawString(text, position.x, position.y, FontSize.HUD, true, color); - } - - public void draw(UiDrawer uiDrawer, UiDrawer.TextAlignment align) { - uiDrawer.drawString(text, position.x, position.y, FontSize.HUD, align, true, color); - } - } - - private static class NoShieldWarn extends WarnDrawer { - NoShieldWarn() { - super("No Shield"); - } - - protected boolean shouldWarn(SolGame game) { - Hero hero = game.getHero(); - return hero.isNonTranscendent() && hero.getShield() == null; - } - } - - private static class NoArmorWarn extends WarnDrawer { - NoArmorWarn() { - super("No Armor"); - } - - protected boolean shouldWarn(SolGame game) { - Hero hero = game.getHero(); - return hero.isNonTranscendent() && hero.getArmor() == null; - } - } - - private static class EnemyWarn extends WarnDrawer { - EnemyWarn() { - super("Dangerous\nEnemy"); - } - - protected boolean shouldWarn(SolGame game) { - Hero hero = game.getHero(); - if (hero.isTranscendent()) { - return false; - } - - float heroCap = HardnessCalc.getShipDmgCap(hero.getShip()); - List objs = game.getObjectManager().getObjects(); - FactionManager fm = game.getFactionMan(); - SolCam cam = game.getContext().get(SolCam.class); - float viewDist = cam.getViewDistance(); - float dps = 0; - - for (SolObject o : objs) { - if (!(o instanceof SolShip)) { - continue; - } - - SolShip ship = (SolShip) o; - - if (viewDist < ship.getPosition().dst(hero.getPosition())) { - continue; - } - - if (!fm.areEnemies(hero.getShip(), ship)) { - continue; - } - - dps += HardnessCalc.getShipDps(ship); - - if (HardnessCalc.isDangerous(heroCap, dps)) { - return true; - } - } - - return false; - } - } } 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 aaa9e60f2..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().mainGameScreen); - } - - 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().mainGameScreen.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/MenuScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MenuScreen.java deleted file mode 100644 index 34e4c569a..000000000 --- a/engine/src/main/java/org/destinationsol/game/screens/MenuScreen.java +++ /dev/null @@ -1,100 +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 org.destinationsol.GameOptions; -import org.destinationsol.SolApplication; -import org.destinationsol.common.SolColor; -import org.destinationsol.game.SolGame; -import org.destinationsol.menu.MenuLayout; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiBaseScreen; -import org.destinationsol.ui.SolUiControl; -import org.destinationsol.ui.UiDrawer; - -public class MenuScreen extends SolUiBaseScreen { - private final SolUiControl closeControl; - private final SolUiControl exitControl; - private final SolUiControl respawnControl; - private final SolUiControl soundVolControl; - private final SolUiControl musicVolumeControl; - private final SolUiControl doNotSellEquippedControl; - - public MenuScreen(MenuLayout menuLayout, GameOptions gameOptions) { - doNotSellEquippedControl = new SolUiControl(menuLayout.buttonRect(-1, -1), true); - doNotSellEquippedControl.setDisplayName("Can sell used items"); - controls.add(doNotSellEquippedControl); - soundVolControl = new SolUiControl(menuLayout.buttonRect(-1, 1), true); - soundVolControl.setDisplayName("Sound Volume"); - controls.add(soundVolControl); - musicVolumeControl = new SolUiControl(menuLayout.buttonRect(-1, 0), true); - musicVolumeControl.setDisplayName("Music Volume"); - controls.add(musicVolumeControl); - respawnControl = new SolUiControl(menuLayout.buttonRect(-1, 2), true); - respawnControl.setDisplayName("Respawn"); - controls.add(respawnControl); - exitControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true); - exitControl.setDisplayName("Exit"); - controls.add(exitControl); - closeControl = new SolUiControl(menuLayout.buttonRect(-1, 4), true, gameOptions.getKeyClose()); - closeControl.setDisplayName("Resume"); - controls.add(closeControl); - } - - @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - SolGame game = solApplication.getGame(); - game.setPaused(true); - SolInputManager im = solApplication.getInputManager(); - GameOptions options = solApplication.getOptions(); - soundVolControl.setDisplayName("Sound Volume: " + options.sfxVolume.getName()); - if (soundVolControl.isJustOff()) { - options.advanceSoundVolMul(); - } - musicVolumeControl.setDisplayName("Music Volume: " + options.musicVolume.getName()); - if (musicVolumeControl.isJustOff()) { - options.advanceMusicVolMul(); - solApplication.getMusicManager().changeVolume(options); - } - if (respawnControl.isJustOff()) { - game.respawn(); - im.setScreen(solApplication, game.getScreens().mainGameScreen); - game.setPaused(false); - } - if (exitControl.isJustOff()) { - solApplication.finishGame(); - } - if (closeControl.isJustOff()) { - game.setPaused(false); - im.setScreen(solApplication, game.getScreens().mainGameScreen); - } - doNotSellEquippedControl.setDisplayName("Can sell used items: " + - (options.canSellEquippedItems ? "Yes" : "No")); - if (doNotSellEquippedControl.isJustOff()) { - options.canSellEquippedItems = !options.canSellEquippedItems; - } - } - - @Override - public void drawBackground(UiDrawer uiDrawer, SolApplication solApplication) { - uiDrawer.draw(uiDrawer.filler, SolColor.UI_BG); - } - - @Override - public boolean isCursorOnBackground(SolInputManager.InputPointer inputPointer) { - return true; - } -} 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 bd02e33e6..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,18 +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 @@ -59,20 +86,26 @@ 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(); if (talkScreen.isTargetFar(hero)) { - solApplication.getInputManager().setScreen(solApplication, game.getScreens().mainGameScreen); + solApplication.getInputManager().setScreen(solApplication, game.getScreens().oldMainGameScreen); return; } SolItem selItem = inventoryScreen.getSelectedItem(); if (selItem == null) { - sellControl.setDisplayName("----"); - sellControl.setEnabled(false); + sellButton.setText("----"); + sellButton.setEnabled(false); return; } @@ -80,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/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/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/game/screens/TalkScreen.java b/engine/src/main/java/org/destinationsol/game/screens/TalkScreen.java deleted file mode 100644 index 5aa7e8b9b..000000000 --- a/engine/src/main/java/org/destinationsol/game/screens/TalkScreen.java +++ /dev/null @@ -1,128 +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.math.Rectangle; -import org.destinationsol.GameOptions; -import org.destinationsol.SolApplication; -import org.destinationsol.common.SolColor; -import org.destinationsol.game.Hero; -import org.destinationsol.game.SolGame; -import org.destinationsol.game.ship.SolShip; -import org.destinationsol.game.ship.hulls.HullConfig; -import org.destinationsol.menu.MenuLayout; -import org.destinationsol.ui.SolInputManager; -import org.destinationsol.ui.SolUiBaseScreen; -import org.destinationsol.ui.SolUiControl; -import org.destinationsol.ui.UiDrawer; - -public class TalkScreen extends SolUiBaseScreen { - public static final float MAX_TALK_DIST = 1f; - - public final SolUiControl buyControl; - public final SolUiControl closeControl; - private final SolUiControl sellControl; - private final SolUiControl shipsControl; - private final SolUiControl hireControl; - - private final Rectangle background; - private SolShip target; - - TalkScreen(MenuLayout menuLayout, GameOptions gameOptions) { - sellControl = new SolUiControl(menuLayout.buttonRect(-1, 0), true, gameOptions.getKeySellMenu()); - sellControl.setDisplayName("Sell"); - controls.add(sellControl); - - buyControl = new SolUiControl(menuLayout.buttonRect(-1, 1), true, gameOptions.getKeyBuyMenu()); - buyControl.setDisplayName("Buy"); - controls.add(buyControl); - - shipsControl = new SolUiControl(menuLayout.buttonRect(-1, 2), true, gameOptions.getKeyChangeShipMenu()); - shipsControl.setDisplayName("Change Ship"); - controls.add(shipsControl); - - hireControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true, gameOptions.getKeyHireShipMenu()); - hireControl.setDisplayName("Hire"); - controls.add(hireControl); - - closeControl = new SolUiControl(menuLayout.buttonRect(-1, 4), true, gameOptions.getKeyClose()); - closeControl.setDisplayName("Close"); - controls.add(closeControl); - - background = menuLayout.background(-1, 0, 5); - } - - @Override - public void updateCustom(SolApplication solApplication, SolInputManager.InputPointer[] inputPointers, boolean clickedOutside) { - if (clickedOutside) { - closeControl.maybeFlashPressed(solApplication.getOptions().getKeyClose()); - return; - } - SolGame game = solApplication.getGame(); - Hero hero = game.getHero(); - SolInputManager inputManager = solApplication.getInputManager(); - if (closeControl.isJustOff() || isTargetFar(hero)) { - inputManager.setScreen(solApplication, game.getScreens().mainGameScreen); - return; - } - - boolean station = target.getHull().config.getType() == HullConfig.Type.STATION; - shipsControl.setEnabled(station); - hireControl.setEnabled(station); - - InventoryScreen inventoryScreen = game.getScreens().inventoryScreen; - boolean sell = sellControl.isJustOff(); - boolean buy = buyControl.isJustOff(); - boolean sellShips = shipsControl.isJustOff(); - boolean hire = hireControl.isJustOff(); - if (sell || buy || sellShips || hire) { - inventoryScreen.setOperations(sell ? inventoryScreen.sellItems : buy ? inventoryScreen.buyItemsScreen : sellShips ? inventoryScreen.changeShipScreen : inventoryScreen.hireShipsScreen); - inputManager.setScreen(solApplication, game.getScreens().mainGameScreen); - inputManager.addScreen(solApplication, inventoryScreen); - } - } - - boolean isTargetFar(Hero hero) { - if (hero.isTranscendent() || target == null || target.getLife() <= 0) { - return true; - } - float dst = target.getPosition().dst(hero.getPosition()) - hero.getHull().config.getApproxRadius() - target.getHull().config.getApproxRadius(); - return MAX_TALK_DIST < dst; - } - - @Override - public void drawBackground(UiDrawer uiDrawer, SolApplication solApplication) { - uiDrawer.draw(background, SolColor.UI_BG); - } - - @Override - public boolean reactsToClickOutside() { - return true; - } - - @Override - public boolean isCursorOnBackground(SolInputManager.InputPointer inputPointer) { - return background.contains(inputPointer.x, inputPointer.y); - } - - public SolShip getTarget() { - return target; - } - - public void setTarget(SolShip target) { - this.target = target; - } -} 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/game/screens/ZoneNameAnnouncer.java b/engine/src/main/java/org/destinationsol/game/screens/ZoneNameAnnouncer.java index f4c57a33e..f0e11878a 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/ZoneNameAnnouncer.java +++ b/engine/src/main/java/org/destinationsol/game/screens/ZoneNameAnnouncer.java @@ -37,7 +37,7 @@ public class ZoneNameAnnouncer { private String zone; private String text; - ZoneNameAnnouncer() { + public ZoneNameAnnouncer() { displayDimensions = SolApplication.displayDimensions; } diff --git a/engine/src/main/java/org/destinationsol/game/ship/EmWave.java b/engine/src/main/java/org/destinationsol/game/ship/EmWave.java index 3ae4a960f..bda72d27f 100644 --- a/engine/src/main/java/org/destinationsol/game/ship/EmWave.java +++ b/engine/src/main/java/org/destinationsol/game/ship/EmWave.java @@ -93,7 +93,7 @@ public EmWaveConfig(float rechargeTime, SolItem chargeExample, float duration, A public static AbilityConfig load(JSONObject abNode, ItemManager itemManager, AbilityCommonConfig cc) { float rechargeTime = (float) abNode.getDouble("rechargeTime"); float duration = (float) abNode.getDouble("duration"); - SolItem chargeExample = itemManager.getExample("emWaveCharge"); + SolItem chargeExample = itemManager.parseItem("core:emWaveCharge").examples.get(0); return new EmWaveConfig(rechargeTime, chargeExample, duration, cc); } diff --git a/engine/src/main/java/org/destinationsol/game/ship/KnockBack.java b/engine/src/main/java/org/destinationsol/game/ship/KnockBack.java index 9e692bbe8..410604ea1 100644 --- a/engine/src/main/java/org/destinationsol/game/ship/KnockBack.java +++ b/engine/src/main/java/org/destinationsol/game/ship/KnockBack.java @@ -107,7 +107,7 @@ public KnockBackConfig(float rechargeTime, SolItem chargeExample, float force, A public static AbilityConfig load(JSONObject abNode, ItemManager itemManager, AbilityCommonConfig cc) { float rechargeTime = (float) abNode.getDouble("rechargeTime"); float force = (float) abNode.getDouble("force"); - SolItem chargeExample = itemManager.getExample("knockBackCharge"); + SolItem chargeExample = itemManager.parseItem("core:knockBackCharge").examples.get(0); return new KnockBackConfig(rechargeTime, chargeExample, force, cc); } diff --git a/engine/src/main/java/org/destinationsol/game/ship/SloMo.java b/engine/src/main/java/org/destinationsol/game/ship/SloMo.java index 64b9b539a..e5ab7b096 100644 --- a/engine/src/main/java/org/destinationsol/game/ship/SloMo.java +++ b/engine/src/main/java/org/destinationsol/game/ship/SloMo.java @@ -86,7 +86,7 @@ public SloMoConfig(float factor, float rechargeTime, SolItem chargeExample, Abil public static AbilityConfig load(JSONObject abNode, ItemManager itemManager, AbilityCommonConfig cc) { float factor = (float) abNode.getDouble("factor"); float rechargeTime = (float) abNode.getDouble("rechargeTime"); - SolItem chargeExample = itemManager.getExample("sloMoCharge"); + SolItem chargeExample = itemManager.parseItem("core:sloMoCharge").examples.get(0); return new SloMoConfig(factor, rechargeTime, chargeExample, cc); } diff --git a/engine/src/main/java/org/destinationsol/game/ship/Teleport.java b/engine/src/main/java/org/destinationsol/game/ship/Teleport.java index 28da06254..66e972746 100644 --- a/engine/src/main/java/org/destinationsol/game/ship/Teleport.java +++ b/engine/src/main/java/org/destinationsol/game/ship/Teleport.java @@ -126,7 +126,7 @@ public TeleportConfig(float angle, SolItem chargeExample, float rechargeTime, Ab public static AbilityConfig load(JSONObject abNode, ItemManager itemManager, AbilityCommonConfig cc) { float angle = (float) abNode.getDouble("angle"); - SolItem chargeExample = itemManager.getExample("teleportCharge"); + SolItem chargeExample = itemManager.parseItem("core:teleportCharge").examples.get(0); float rechargeTime = (float) abNode.getDouble("rechargeTime"); return new TeleportConfig(angle, chargeExample, rechargeTime, cc); } diff --git a/engine/src/main/java/org/destinationsol/game/ship/UnShield.java b/engine/src/main/java/org/destinationsol/game/ship/UnShield.java index a70cecf66..798ec55a8 100644 --- a/engine/src/main/java/org/destinationsol/game/ship/UnShield.java +++ b/engine/src/main/java/org/destinationsol/game/ship/UnShield.java @@ -107,7 +107,7 @@ public UnShieldConfig(float rechargeTime, SolItem chargeExample, float amount, A public static AbilityConfig load(JSONObject abNode, ItemManager itemManager, AbilityCommonConfig cc) { float rechargeTime = (float) abNode.getDouble("rechargeTime"); float amount = (float) abNode.getDouble("amount"); - SolItem chargeExample = itemManager.getExample("unShieldCharge"); + SolItem chargeExample = itemManager.parseItem("core:unShieldCharge").examples.get(0); return new UnShieldConfig(rechargeTime, chargeExample, amount, cc); } diff --git a/engine/src/main/java/org/destinationsol/ui/SolInputManager.java b/engine/src/main/java/org/destinationsol/ui/SolInputManager.java index 75b03aadf..c520f8d94 100644 --- a/engine/src/main/java/org/destinationsol/ui/SolInputManager.java +++ b/engine/src/main/java/org/destinationsol/ui/SolInputManager.java @@ -199,7 +199,8 @@ public void update(SolApplication solApplication) { // This keeps the mouse within the window, but only when playing the game with the mouse. // All other times the mouse can freely leave and return. - if (!mobile && solApplication.getOptions().controlType == GameOptions.ControlType.MIXED && game != null && getTopScreen() != game.getScreens().menuScreen) { + if (!mobile && solApplication.getOptions().controlType == GameOptions.ControlType.MIXED && game != null && + solApplication.getNuiManager().getTopScreen() != game.getScreens().menuScreen) { if (!Gdx.input.isCursorCatched() && !osIsLinux) { Gdx.input.setCursorCatched(true); } @@ -254,11 +255,6 @@ public void update(SolApplication solApplication) { screen.updateCustom(solApplication, inputPointers, clickedOutside); } - TutorialManager tutorialManager = game == null ? null : game.getTutMan(); - if (tutorialManager != null && tutorialManager.isFinished()) { - solApplication.finishGame(); - } - updateCursor(solApplication); addRemoveScreens(); updateWarnPerc(); @@ -301,14 +297,15 @@ private void updateCursor(SolApplication solApplication) { if (game == null || mouseOnUi || nuiManager.isMouseOnUi()) { currCursor = uiCursor; } else { - currCursor = game.getScreens().mainGameScreen.getShipControl().getInGameTex(); + currCursor = game.getScreens().oldMainGameScreen.getShipControl().getInGameTex(); if (currCursor == null) { currCursor = uiCursor; } } return; } - if (mousePrevPos.epsilonEquals(mousePos, 0) && game != null && getTopScreen() != game.getScreens().menuScreen) { + if (mousePrevPos.epsilonEquals(mousePos, 0) && game != null && + solApplication.getNuiManager().getTopScreen() != game.getScreens().menuScreen) { mouseIdleTime += Const.REAL_TIME_STEP; currCursor = mouseIdleTime < CURSOR_SHOW_TIME ? uiCursor : null; } else { @@ -364,12 +361,6 @@ public void draw(UiDrawer uiDrawer, SolApplication solApplication) { } } uiDrawer.setTextMode(null); - - SolGame game = solApplication.getGame(); - TutorialManager tutorialManager = game == null ? null : game.getTutMan(); - if (tutorialManager != null && getTopScreen() != game.getScreens().menuScreen) { - tutorialManager.draw(uiDrawer); - } } public void drawCursor(UiDrawer uiDrawer) { diff --git a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java index c50ec587f..6c913df3a 100644 --- a/engine/src/main/java/org/destinationsol/ui/TutorialManager.java +++ b/engine/src/main/java/org/destinationsol/ui/TutorialManager.java @@ -15,16 +15,17 @@ */ package org.destinationsol.ui; -import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.Gdx; import org.destinationsol.GameOptions; -import org.destinationsol.common.SolColor; import org.destinationsol.game.SolGame; 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.NUIManager; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.screens.TutorialScreen; import org.destinationsol.ui.nui.screens.UIShipControlsScreen; import org.destinationsol.ui.nui.widgets.UIWarnButton; @@ -34,32 +35,30 @@ import java.util.List; public class TutorialManager implements UpdateAwareSystem { - private final Rectangle background; + private final NUIManager nuiManager; + private final TutorialScreen tutorialScreen; private final ArrayList steps; private final GameScreens screens; private final GameOptions gameOptions; private final Provider game; - private final DisplayDimensions displayDimensions; private int stepIndex; @Inject - public TutorialManager(GameScreens screens, GameOptions gameOptions, Provider game, DisplayDimensions displayDimensions) { + public TutorialManager(GameScreens screens, GameOptions gameOptions, Provider game, NUIManager nuiManager) { this.screens = screens; this.gameOptions = gameOptions; this.game = game; - this.displayDimensions = displayDimensions; + this.nuiManager = nuiManager; + this.tutorialScreen = (TutorialScreen) nuiManager.createScreen("engine:tutorialScreen"); - float backgroundW = displayDimensions.getRatio() * .5f; - float backgroundH = .2f; - background = new Rectangle(displayDimensions.getRatio() / 2 - backgroundW / 2, 1 - backgroundH, backgroundW, backgroundH); steps = new ArrayList<>(); stepIndex = 0; } public void start() { boolean mobile = game.get().getSolApplication().isMobile(); - MainGameScreen main = screens.mainGameScreen; + MainGameScreen main = screens.oldMainGameScreen; boolean mouseCtrl = main.getShipControl() instanceof ShipMixedControl; org.destinationsol.ui.nui.screens.MainGameScreen nuiMain = game.get().getMainGameScreen(); SolUiControl shootCtrl = null; @@ -115,18 +114,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); + addScreenCloseStep("Close the map", screens.mapScreen.getCloseButton(), screens.mapScreen); } else { - addStep("Close the map\n(" + gameOptions.getKeyMapName() + " or " + gameOptions.getKeyCloseName() + " keys)", - screens.mapScreen.closeControl, true); + addScreenCloseStep("Close the map\n(" + gameOptions.getKeyMapName() + " or " + gameOptions.getKeyCloseName() + " keys)", + screens.mapScreen.getCloseButton(), screens.mapScreen); } UIWarnButton inventoryButton = nuiMain.getInventoryButton(); @@ -137,23 +136,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 +162,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); + addScreenCloseStep("Close the inventory\n(Touch the screen outside inventory)", screens.inventoryScreen.getCloseButton(), screens.inventoryScreen); } else { - addStep("Close the inventory (" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.closeControl, true); + addScreenCloseStep("Close the inventory (" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.getCloseButton(), screens.inventoryScreen); } if (mouseCtrl) { @@ -198,21 +196,21 @@ public void start() { } if (mouseCtrl || mobile) { - addStep("See what there is to buy", screens.talkScreen.buyControl, true); + addStep("See what there is to buy", screens.talkScreen.getBuyButton(), true); } else { - addStep("See what there is to buy\n(" + gameOptions.getKeyBuyMenuName() + " key)", screens.talkScreen.buyControl, true); + addStep("See what there is to buy\n(" + gameOptions.getKeyBuyMenuName() + " key)", screens.talkScreen.getBuyButton(), true); } 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); + addScreenCloseStep("Close the Buy screen\n(Touch the screen outside inventory)", screens.inventoryScreen.getCloseButton(), screens.inventoryScreen); } else { - addStep("Close the Buy screen\n(" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.closeControl, true); + addScreenCloseStep("Close the Buy screen\n(" + gameOptions.getKeyCloseName() + " key)", screens.inventoryScreen.getCloseButton(), screens.inventoryScreen); } if (mouseCtrl) { @@ -243,13 +241,19 @@ public void start() { addStep("Buy new ships, hire mercenaries\n" + shootKey2, nuiShootCtrl); addStep("Tutorial is complete and will exit now!\n" + shootKey2, nuiShootCtrl); } + steps.get(0).start(); + tutorialScreen.setTutorialText(steps.get(0).text); } 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); } @@ -266,28 +270,33 @@ private void addStep(Step step) { steps.add(step); } + private void addScreenCloseStep(String text, UIWarnButton ctrl, NUIScreenLayer uiScreen) { + steps.add(new NuiScreenCloseStep(text, ctrl, nuiManager, uiScreen)); + } + @Override public void update(SolGame game, float timeStep) { + if (nuiManager.getTopScreen() != tutorialScreen) { + if (nuiManager.hasScreen(tutorialScreen)) { + tutorialScreen.moveToTop(); + } else { + nuiManager.pushScreen(tutorialScreen); + } + } + Step step = steps.get(stepIndex); step.highlight(); if (step.canProgressToNextStep()) { stepIndex++; if (stepIndex < steps.size()) { steps.get(stepIndex).start(); + tutorialScreen.setTutorialText(steps.get(stepIndex).text); } - } - } - public void draw(UiDrawer uiDrawer) { - if (isFinished()) { - return; + if (isFinished()) { + game.getSolApplication().finishGame(); + } } - Step step = steps.get(stepIndex); - uiDrawer.draw(background, SolColor.UI_BG_LIGHT); - uiDrawer.drawLine(background.x, background.y, 0, background.width, SolColor.WHITE); - uiDrawer.drawLine(background.x + background.width, background.y, 90, background.height, SolColor.WHITE); - uiDrawer.drawLine(background.x, background.y, 90, background.height, SolColor.WHITE); - uiDrawer.drawString(step.text, displayDimensions.getRatio() / 2, background.y + background.height / 2, FontSize.TUT, true, SolColor.WHITE); } public boolean isFinished() { @@ -363,11 +372,30 @@ public boolean canProgressToNextStep() { } } + public static class NuiScreenCloseStep extends NuiStep { + private final NUIManager nuiManager; + private final NUIScreenLayer uiScreen; + + public NuiScreenCloseStep(String text, UIWarnButton closeButton, NUIManager nuiManager, NUIScreenLayer uiScreen) { + super(text, closeButton, true); + this.nuiManager = nuiManager; + this.uiScreen = uiScreen; + } + + @Override + public boolean canProgressToNextStep() { + if (super.canProgressToNextStep()) { + return true; + } + return !nuiManager.hasScreen(uiScreen); + } + } + public static class SelectEquippedItemStep extends Step { - InventoryScreen inventoryScreen; + org.destinationsol.ui.nui.screens.InventoryScreen inventoryScreen; SolGame game; - public SelectEquippedItemStep(String text, InventoryScreen inventoryScreen, SolGame game) { + public SelectEquippedItemStep(String text, org.destinationsol.ui.nui.screens.InventoryScreen inventoryScreen, SolGame game) { super(text, null, true); this.inventoryScreen = inventoryScreen; this.game = game; @@ -385,10 +413,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 1aa41e26b..4dfe29514 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 @@ -15,34 +15,86 @@ */ package org.destinationsol.ui.nui.screens; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.physics.box2d.Fixture; +import com.badlogic.gdx.physics.box2d.RayCastCallback; +import org.destinationsol.Const; import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; +import org.destinationsol.assets.Assets; +import org.destinationsol.common.SolColor; +import org.destinationsol.common.SolMath; import org.destinationsol.game.FactionManager; +import org.destinationsol.game.HardnessCalc; import org.destinationsol.game.Hero; +import org.destinationsol.game.SolCam; import org.destinationsol.game.SolGame; import org.destinationsol.game.SolObject; +import org.destinationsol.game.item.Gun; +import org.destinationsol.game.item.Shield; +import org.destinationsol.game.item.SolItem; +import org.destinationsol.game.planet.Planet; +import org.destinationsol.game.screens.BorderDrawer; import org.destinationsol.game.screens.GameScreens; -import org.destinationsol.game.screens.TalkScreen; +import org.destinationsol.game.screens.ZoneNameAnnouncer; import org.destinationsol.game.ship.SolShip; import org.destinationsol.ui.SolInputManager; +import org.destinationsol.ui.UiDrawer; +import org.destinationsol.ui.nui.NUIManager; import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.EmptyIfInvisibleContainer; +import org.destinationsol.ui.nui.widgets.UILabelledIcon; import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.destinationsol.ui.nui.widgets.UIWarnDrawer; +import org.destinationsol.world.generators.SolarSystemGenerator; import org.terasology.input.ButtonState; import org.terasology.input.Keyboard; import org.terasology.nui.AbstractWidget; +import org.terasology.nui.Canvas; +import org.terasology.nui.Color; +import org.terasology.nui.HorizontalAlign; +import org.terasology.nui.UITextureRegion; import org.terasology.nui.UIWidget; +import org.terasology.nui.VerticalAlign; import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.databinding.Binding; +import org.terasology.nui.databinding.DefaultBinding; +import org.terasology.nui.databinding.ReadOnlyBinding; import org.terasology.nui.events.NUIKeyEvent; +import org.terasology.nui.events.NUIMouseButtonEvent; +import org.terasology.nui.layouts.ColumnLayout; +import org.terasology.nui.layouts.FlowLayout; +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.UIIconBar; +import org.terasology.nui.widgets.UIImage; +import org.terasology.nui.widgets.UILabel; +import org.terasology.nui.widgets.UILoadBar; import javax.inject.Inject; import java.util.List; +import java.util.Locale; /** * The main HUD screen displayed when in-game. This screen is responsible for the menu buttons shown * on the right-hand side of the UI. Through it, the menu, map, current ship inventory, communications UI * and mercenaries UI can be accessed. + * It also displays status bars for weapons, ability cool-downs, health/shield percentages and HUD warnings. */ public class MainGameScreen extends NUIScreenLayer { + private static final String WHITE_TEXTURE_URN = "engine:uiWhiteTex"; + private static final String COMPASS_TEXTURE_URN = "engine:uiCompass"; + private static final String LIFE_TEXTURE_URN = "engine:iconLife"; + private static final String REPAIR_ITEM_TEXTURE_URN = "engine:iconRepairItem"; + private static final String WAIT_TEXTURE_URN = "engine:iconWait"; + private static final String INFINITY_TEXTURE_URN = "engine:iconInfinity"; + private static final String CONSOLE_SCREEN_URN = "engine:console"; + private final CollisionWarnDrawerRayCastCallback warnCallback = new CollisionWarnDrawerRayCastCallback(); + private UITextureRegion whiteTexture; + private TextureRegion compassTexture; private SolShip talkTarget; private UIWarnButton menuButton; private UIWarnButton mapButton; @@ -50,6 +102,16 @@ public class MainGameScreen extends NUIScreenLayer { private UIWarnButton talkButton; private UIWarnButton mercsButton; private ConsoleScreen consoleScreen; + private AbstractWidget shieldStats; + private AbstractWidget hullStats; + private AbstractWidget gun1Stats; + private AbstractWidget gun2Stats; + private AbstractWidget abilityStats; + private UILabelledIcon moneyIcon; + private FlowLayout warnDrawers; + private BorderDrawer borderDrawer; + private ZoneNameAnnouncer zoneNameAnnouncer; + private com.badlogic.gdx.graphics.Color compassTint; private final SolApplication solApplication; @@ -60,7 +122,11 @@ public MainGameScreen(SolApplication solApplication) { @Override public void initialise() { - consoleScreen = (ConsoleScreen) nuiManager.createScreen("engine:console"); + whiteTexture = Assets.getDSTexture(WHITE_TEXTURE_URN).getUiTexture(); + compassTexture = Assets.getAtlasRegion(COMPASS_TEXTURE_URN); + compassTint = SolColor.col(1, 0); + + consoleScreen = (ConsoleScreen) nuiManager.createScreen(CONSOLE_SCREEN_URN); GameOptions gameOptions = solApplication.getOptions(); @@ -83,6 +149,276 @@ public void initialise() { mercsButton = find("mercsButton", UIWarnButton.class); mercsButton.setKey(GDXInputUtil.GDXToNuiKey(gameOptions.getKeyMercenaryInteraction())); mercsButton.subscribe(this::onMercsButtonClicked); + + ColumnLayout statsBars = find("statsBars", ColumnLayout.class); + + shieldStats = createStatsRow("shield", new ReadOnlyBinding() { + @Override + public UITextureRegion get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + Shield shield = hero.getShield(); + if (shield != null) { + return Assets.getDSTexture(shield.getIcon(game).name).getUiTexture(); + } else { + return null; + } + } + }, + new ReadOnlyBinding() { + @Override + public Float get() { + Hero hero = solApplication.getGame().getHero(); + Shield heroShield = hero.getShield(); + if (heroShield != null) { + return heroShield.getLife() / heroShield.getMaxLife(); + } else { + return 0.0f; + } + } + }, new ReadOnlyBinding() { + @Override + public String get() { + Hero hero = solApplication.getGame().getHero(); + Shield heroShield = hero.getShield(); + if (heroShield != null) { + return (int) Math.floor(heroShield.getLife()) + "/" + (int) Math.floor(heroShield.getMaxLife()); + } else { + return ""; + } + } + }, new DefaultBinding<>(), null, new DefaultBinding<>(0.0f)); + statsBars.addWidget(shieldStats); + + hullStats = createStatsRow("health", new DefaultBinding<>(Assets.getDSTexture(LIFE_TEXTURE_URN).getUiTexture()), + new ReadOnlyBinding() { + @Override + public Float get() { + Hero hero = solApplication.getGame().getHero(); + if (hero.isNonTranscendent()) { + return hero.getLife() / hero.getHull().config.getMaxLife(); + } else { + // The HUD is hidden when the hero is transcendent, so the value here doesn't matter. + return 1.0f; + } + } + }, new ReadOnlyBinding() { + @Override + public String get() { + Hero hero = solApplication.getGame().getHero(); + if (hero.isNonTranscendent()) { + return (int) Math.floor(Math.max(0, hero.getLife())) + "/" + hero.getHull().config.getMaxLife(); + } else { + // The HUD is hidden when the hero is transcendent, so the value here doesn't matter. + return ""; + } + } + }, new DefaultBinding<>(), Assets.getDSTexture(REPAIR_ITEM_TEXTURE_URN).getUiTexture(), new ReadOnlyBinding() { + @Override + public Float get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + return (float) hero.getItemContainer().count(game.getItemMan().getRepairExample()); + } + }); + statsBars.addWidget(hullStats); + + gun1Stats = createStatsRow("gun1", createGunIconBinding(false), createGunValueBinding(false), + createGunValueLabelBinding(false), createGunBarIconBinding(false), + null, createGunClipValueBinding(false)); + statsBars.addWidget(gun1Stats); + + gun2Stats = createStatsRow("gun2", createGunIconBinding(true), createGunValueBinding(true), + createGunValueLabelBinding(true), createGunBarIconBinding(true), + null, createGunClipValueBinding(true)); + statsBars.addWidget(gun2Stats); + + abilityStats = createStatsRow("ability", new ReadOnlyBinding() { + @Override + public UITextureRegion get() { + Hero hero = solApplication.getGame().getHero(); + SolItem example = hero.getAbility().getConfig().getChargeExample(); + if (example != null) { + return Assets.getDSTexture(example.getIcon(solApplication.getGame()).name).getUiTexture(); + } + return null; + } + }, new ReadOnlyBinding() { + @Override + public Float get() { + Hero hero = solApplication.getGame().getHero(); + if (hero.getAbilityAwait() > 0) { + return 1.0f - hero.getAbilityAwait() / hero.getAbility().getConfig().getRechargeTime(); + } else { + return 1.0f; + } + } + }, new DefaultBinding<>(""), new ReadOnlyBinding() { + @Override + public UITextureRegion get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + return hero.getAbilityAwait() > 0 ? Assets.getDSTexture(WAIT_TEXTURE_URN).getUiTexture() : null; + } + }, null, new ReadOnlyBinding() { + @Override + public Float get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + SolItem example = hero.getAbility().getConfig().getChargeExample(); + if (example != null) { + return (float) hero.getItemContainer().count(example); + } + return 0.0f; + } + }); + statsBars.addWidget(abilityStats); + + moneyIcon = new UILabelledIcon("moneyIcon"); + moneyIcon.setSpacing(8); + moneyIcon.bindText(new ReadOnlyBinding() { + @Override + public String get() { + Hero hero = solApplication.getGame().getHero(); + return Integer.toString(Math.round(hero.getMoney())); + } + }); + statsBars.addWidget(moneyIcon); + + statsBars.bindVisible(new ReadOnlyBinding() { + @Override + public Boolean get() { + return solApplication.getGame().getHero().isNonTranscendent(); + } + }); + + Color warnColour = new Color(1.0f, 0.5f, 0.0f, 0.5f); + Color dangerColour = new Color(1.0f, 0.0f, 0.0f, 0.5f); + + warnDrawers = find("warnDrawers", FlowLayout.class); + addWarnDrawer("sunWarnDrawer", warnColour, "Sun Near", new ReadOnlyBinding() { + @Override + public Boolean get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + if (hero.isTranscendent()) { + return false; + } + Vector2 position = hero.getPosition(); + float toCenter = game.getPlanetManager().getNearestSystem(position).getPosition().dst(position); + return toCenter < SolarSystemGenerator.SUN_RADIUS; + } + }); + addWarnDrawer("damagedWarnDrawer", dangerColour, "Heavily Damaged", new ReadOnlyBinding() { + @Override + public Boolean get() { + Hero hero = solApplication.getGame().getHero(); + if (hero.isTranscendent()) { + return false; + } + float currentLife = hero.getLife(); + + // already dead + if (currentLife <= 0.0) { + return false; + } + + int maxLife = hero.getHull().config.getMaxLife(); + return currentLife < maxLife * .3f; + } + }); + addWarnDrawer("collisionWarnDrawer", warnColour, "Object Near", new ReadOnlyBinding() { + @Override + public Boolean get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + if (hero.isTranscendent()) { + return false; + } + Vector2 position = hero.getPosition(); + Vector2 velocity = hero.getVelocity(); + float acc = hero.getAcceleration(); + float speed = velocity.len(); + float velocityAngle = SolMath.angle(velocity); + if (acc <= 0 || speed < 2 * acc) { + return false; + } + // time = velocity/acceleration; + // speed = acceleration*time*time/2 = velocity*velocity/acceleration/2; + float breakWay = speed * speed / acc / 2; + breakWay += 2 * speed; + Vector2 finalPos = SolMath.getVec(0, 0); + SolMath.fromAl(finalPos, velocityAngle, breakWay); + finalPos.add(position); + warnCallback.show = false; + game.getObjectManager().getWorld().rayCast(warnCallback, position, finalPos); + SolMath.free(finalPos); + return warnCallback.show; + } + }); + addWarnDrawer("noShieldDrawer", warnColour, "No Shield", new ReadOnlyBinding() { + @Override + public Boolean get() { + Hero hero = solApplication.getGame().getHero(); + return hero.isNonTranscendent() && hero.getShield() == null; + } + }); + addWarnDrawer("noArmourDrawer", warnColour, "No Armor", new ReadOnlyBinding() { + @Override + public Boolean get() { + Hero hero = solApplication.getGame().getHero(); + return hero.isNonTranscendent() && hero.getArmor() == null; + } + }); + addWarnDrawer("enemyWarnDrawer", warnColour, "Dangerous Enemy", new ReadOnlyBinding() { + @Override + public Boolean get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + if (hero.isTranscendent()) { + return false; + } + + float heroCap = HardnessCalc.getShipDmgCap(hero.getShip()); + List objs = game.getObjectManager().getObjects(); + FactionManager fm = game.getFactionMan(); + SolCam cam = game.getContext().get(SolCam.class); + float viewDist = cam.getViewDistance(); + float dps = 0; + + for (SolObject o : objs) { + if (!(o instanceof SolShip)) { + continue; + } + + SolShip ship = (SolShip) o; + + if (viewDist < ship.getPosition().dst(hero.getPosition())) { + continue; + } + + if (!fm.areEnemies(hero.getShip(), ship)) { + continue; + } + + dps += HardnessCalc.getShipDps(ship); + + if (HardnessCalc.isDangerous(heroCap, dps)) { + return true; + } + } + + return false; + } + }); + + borderDrawer = new BorderDrawer(); + zoneNameAnnouncer = new ZoneNameAnnouncer(); + } + + @Override + public void onAdded() { + moneyIcon.setIcon(Assets.getDSTexture(solApplication.getGame().getItemMan().moneyIcon.name).getUiTexture()); } @Override @@ -90,14 +426,14 @@ public void update(float delta) { super.update(delta); SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - if (!solInputManager.isScreenOn(gameScreens.menuScreen) && - !solInputManager.isScreenOn(gameScreens.mapScreen)) { + if (!nuiManager.hasScreen(gameScreens.menuScreen) && + !nuiManager.hasScreen(gameScreens.mapScreen)) { ((AbstractWidget) contents).setVisible(true); } else { ((AbstractWidget) contents).setVisible(false); } - if (solInputManager.getTopScreen() != gameScreens.mainGameScreen) { + if (solInputManager.getTopScreen() != gameScreens.oldMainGameScreen) { // User is in an original UI menu, so disable the escape key toggling the pause menu. menuButton.setKey(Keyboard.Key.NONE); } else { @@ -109,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(); } @@ -156,6 +492,56 @@ public void update(float delta) { if (consoleScreen.isConsoleJustClosed()) { game.setPaused(false); } + + shieldStats.setVisible(hero.getShield() != null); + gun1Stats.setVisible(hero.getHull().getGun(false) != null); + gun2Stats.setVisible(hero.getHull().getGun(true) != null); + + Gun gun1 = hero.getHull().getGun(false); + if (gun1 != null) { + UITextureRegion gun1ClipIcon; + if (gun1.config.clipConf.infinite) { + gun1ClipIcon = Assets.getDSTexture(INFINITY_TEXTURE_URN).getUiTexture(); + } else { + gun1ClipIcon = Assets.getDSTexture(gun1.config.clipConf.icon.name).getUiTexture(); + } + // HACK: You can't bind to the icons of a UIIconBar, so we set them during an update instead. + gun1Stats.findAll(UIIconBar.class).iterator().next().setIcon(gun1ClipIcon); + } + + Gun gun2 = hero.getHull().getGun(true); + if (gun2 != null) { + UITextureRegion gun2ClipIcon; + if (gun2.config.clipConf.infinite) { + gun2ClipIcon = Assets.getDSTexture(INFINITY_TEXTURE_URN).getUiTexture(); + } else { + gun2ClipIcon = Assets.getDSTexture(gun2.config.clipConf.icon.name).getUiTexture(); + } + // HACK: You can't bind to the icons of a UIIconBar, so we set them during an update instead. + gun2Stats.findAll(UIIconBar.class).iterator().next().setIcon(gun2ClipIcon); + } + + SolItem example = hero.getAbility().getConfig().getChargeExample(); + if (example != null) { + UITextureRegion abilityIcon = Assets.getDSTexture(example.getIcon(solApplication.getGame()).name).getUiTexture(); + abilityStats.findAll(UIIconBar.class).iterator().next().setIcon(abilityIcon); + } + + zoneNameAnnouncer.update(solApplication.getGame(), solApplication.getGame().getContext()); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // Don't render the borders on-top of the map screen. + 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()); + drawHeightCompass(wrapper); + } + } } @Override @@ -185,9 +571,32 @@ public boolean onKeyEvent(NUIKeyEvent event) { return true; } + GameOptions gameOptions = solApplication.getOptions(); + // TODO: How to handle free camera movement on Android? (note: this has never been supported) + if (event.getKey() == GDXInputUtil.GDXToNuiKey(gameOptions.getKeyFreeCameraMovement())) { + SolCam.DIRECT_CAM_CONTROL = event.isDown(); + } + + SolGame solGame = solApplication.getGame(); + if (event.getState() == ButtonState.UP && event.getKey() == GDXInputUtil.GDXToNuiKey(gameOptions.getKeyPause())) { + solGame.setPaused(!solGame.isPaused()); + } + return super.onKeyEvent(event); } + @Override + public void onMouseButtonEvent(NUIMouseButtonEvent event) { + if (event.getState() == ButtonState.UP) { + NUIScreenLayer topScreen = nuiManager.getTopScreen(); + if (!solApplication.getInputManager().isMouseOnUi() && + topScreen != MainGameScreen.this && !(topScreen instanceof UIShipControlsScreen)) { + nuiManager.popScreen(); + event.consume(); + } + } + } + @Override public void onRemoved() { menuButton.unsubscribe(this::onMenuButtonClicked); @@ -237,18 +646,280 @@ public UIWarnButton getMercsButton() { return mercsButton; } + /** + * Creates and adds a new warn drawer with the specified properties and activation condition. + * @param id the id used for the drawer widget + * @param tint the tint used for the warning background + * @param text the text to be shown in the warning + * @param warnBinding the condition for the warning to be shown + * @return the {@link UIWarnDrawer} created + */ + public UIWarnDrawer addWarnDrawer(String id, Color tint, String text, Binding warnBinding) { + UIWarnDrawer warnDrawer = new UIWarnDrawer(id, whiteTexture, tint, new UILabel(text)); + warnDrawer.bindWarn(warnBinding); + warnDrawers.addWidget(new EmptyIfInvisibleContainer(warnDrawer), new RelativeLayoutHint()); + return warnDrawer; + } + + /** + * Adds the provided warn drawer to be displayed when the condition {@link UIWarnDrawer#isWarning()} is true. + * @param warnDrawer the warn-drawer instance to use + * @return the warn-drawer instance used. + */ + public UIWarnDrawer addWarnDrawer(UIWarnDrawer warnDrawer) { + warnDrawers.addWidget(new EmptyIfInvisibleContainer(warnDrawer), new RelativeLayoutHint()); + return warnDrawer; + } + + /** + * Returns true if a warn-drawer with the specified id already exists, otherwise false. + * @param id the id to search for + * @return true, if the drawer exists, otherwise false. + */ + public boolean hasWarnDrawer(String id) { + return warnDrawers.find(id, UIWarnDrawer.class) != null; + } + + /** + * Returns true if the specified warn-drawer already exists, otherwise false. + * @param warnDrawerToFind the drawer to search for + * @return true, if the drawer exists, otherwise false. + */ + public boolean hasWarnDrawer(UIWarnDrawer warnDrawerToFind) { + for (UIWidget warnDrawerContainer : warnDrawers) { + if (warnDrawerContainer instanceof EmptyIfInvisibleContainer) { + EmptyIfInvisibleContainer container = (EmptyIfInvisibleContainer) warnDrawerContainer; + if (container.iterator().hasNext() && container.iterator().next() == warnDrawerToFind) { + return true; + } + } + } + + return false; + } + + /** + * Removes the warn-drawer with the specified id from use. + * @param id the id of the warn-drawer to remove + */ + public void removeWarnDrawer(String id) { + UIWarnDrawer warnDrawer = warnDrawers.find(id, UIWarnDrawer.class); + if (warnDrawer != null) { + warnDrawers.removeWidget(warnDrawer); + } + } + + /** + * Removes the specified warn drawer from use. + * @param warnDrawer the warn-drawer instance to remove + */ + public void removeWarnDrawer(UIWarnDrawer warnDrawer) { + warnDrawers.removeWidget(warnDrawer); + } + + private void drawHeightCompass(NUIManager.LegacyUiDrawerWrapper drawerWrapper) { + SolGame game = solApplication.getGame(); + Planet np = game.getPlanetManager().getNearestPlanet(); + SolCam cam = solApplication.getGame().getCam(); + Vector2 camPos = cam.getPosition(); + if (np != null && np.getPosition().dst(camPos) < np.getFullHeight()) { + UiDrawer drawer = drawerWrapper.getUiDrawer(); + + float toPlanet = camPos.dst(np.getPosition()); + toPlanet -= np.getGroundHeight(); + if (Const.ATM_HEIGHT < toPlanet) { + return; + } + + float perc = toPlanet / Const.ATM_HEIGHT; + float sz = .08f; + float maxY = 1 - sz / 2; + float y = 1 - perc; + compassTint.a = SolMath.clamp(1.5f * y); + if (maxY < y) { + y = maxY; + } + float angle = np.getAngle() - cam.getAngle(); + drawer.draw(compassTexture, sz, sz, sz / 2, sz / 2, sz / 2, y, angle, compassTint); + } + } + + private AbstractWidget createStatsRow(String name, Binding statIcon, Binding statBinding, + Binding statBarTextBinding, Binding statBarIconBinding, + UITextureRegion refillIcon, Binding refillBinding) { + String iconId = name + "Icon"; + String statsBarTextId = name + "statsBarText"; + String refillExtraTextId = name + "refillExtraText"; + VerticalHint iconHeightHint = new VerticalHint() + .alignTopRelativeTo(iconId, VerticalAlign.TOP) + .alignBottomRelativeTo(iconId, VerticalAlign.BOTTOM); + + RelativeLayout relativeLayout = new RelativeLayout(); + UIImage icon = new UIImage(iconId, null); + icon.bindTexture(statIcon); + relativeLayout.addWidget(icon, new RelativeLayoutHint( + new HorizontalHint().alignLeft(), + new VerticalHint() + ).setUsingContentWidth(true).setUsingContentHeight(true)); + UILoadBar statsBar = new UILoadBar(); + statsBar.setAnimate(false); + statsBar.setFillTexture(Assets.getDSTexture("engine:buttonDown").getUiTexture()); + statsBar.bindValue(statBinding); + relativeLayout.addWidget(statsBar, new RelativeLayoutHint( + new HorizontalHint().alignLeftRelativeTo(iconId, HorizontalAlign.RIGHT, 8).alignRight(134), + iconHeightHint + )); + UILabelledIcon statsValueText = new UILabelledIcon(statsBarTextId, ""); + statsValueText.setFamily("centerAlignedLabel"); + statsValueText.setSpacing(0); + statsValueText.setIconAlign(HorizontalAlign.CENTER); + statsValueText.bindText(statBarTextBinding); + statsValueText.bindIcon(statBarIconBinding); + relativeLayout.addWidget(statsValueText, new RelativeLayoutHint( + new HorizontalHint().alignLeftRelativeTo(iconId, HorizontalAlign.RIGHT, 8).alignRight(134), + iconHeightHint + )); + + UIIconBar refillIconsBar = new UIIconBar(); + refillIconsBar.setMaxIcons(3); + refillIconsBar.setMaxValue(3); + refillIconsBar.setHalfIconMode(UIIconBar.HalfIconMode.NONE); + // NOTE: UIIconBar doesn't support icon bindings. + refillIconsBar.setIcon(refillIcon); + refillIconsBar.bindValue(refillBinding); + relativeLayout.addWidget(refillIconsBar, new RelativeLayoutHint( + new HorizontalHint() + .alignLeftRelativeTo(statsBarTextId, HorizontalAlign.RIGHT, 8) + .alignRightRelativeTo(refillExtraTextId, HorizontalAlign.LEFT), + iconHeightHint + )); + + UILabelledIcon refillExtrasText = new UILabelledIcon(refillExtraTextId, " "); + refillExtrasText.setFamily("topLeftAlignedLabel"); + refillExtrasText.setSpacing(0); + refillExtrasText.bindText(new ReadOnlyBinding() { + @Override + public String get() { + float value = refillBinding.get(); + if (value <= 3) { + return " "; + } + return "+" + String.format(Locale.ENGLISH, "%-2d", ((int)value - 3)); + } + }); + relativeLayout.addWidget(refillExtrasText, new RelativeLayoutHint( + new HorizontalHint().alignRight(), + iconHeightHint + ).setUsingContentWidth(true)); + + return new EmptyIfInvisibleContainer(relativeLayout); + } + + private ReadOnlyBinding createGunIconBinding(boolean isSecondary) { + return new ReadOnlyBinding() { + @Override + public UITextureRegion get() { + Hero hero = solApplication.getGame().getHero(); + Gun gun = hero.getHull().getGun(isSecondary); + if (gun != null) { + return Assets.getDSTexture(gun.getIcon(solApplication.getGame()).name).getUiTexture(); + } + return null; + } + }; + } + + private ReadOnlyBinding createGunClipValueBinding(boolean isSecondary) { + return new ReadOnlyBinding() { + @Override + public Float get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + Gun gun = hero.getHull().getGun(isSecondary); + if (gun == null) { + return 0.0f; + } + if (gun.config.clipConf.infinite) { + return 1.0f; + } + return (float) hero.getItemContainer().count(gun.config.clipConf.example); + } + }; + } + + private ReadOnlyBinding createGunValueBinding(boolean isSecondary) { + return new ReadOnlyBinding() { + @Override + public Float get() { + Hero hero = solApplication.getGame().getHero(); + Gun gun = hero.getHull().getGun(isSecondary); + if (gun == null) { + return 0.0f; + } + if (gun.reloadAwait > 0) { + return 1.0f - (gun.reloadAwait / gun.config.reloadTime); + } else { + return (float)gun.ammo / gun.config.clipConf.size; + } + } + }; + } + + private ReadOnlyBinding createGunValueLabelBinding(boolean isSecondary) { + return new ReadOnlyBinding() { + @Override + public String get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + Gun gun = hero.getHull().getGun(isSecondary); + if (gun == null) { + return ""; + } + if (gun.reloadAwait > 0) { + return ""; + } else { + return gun.ammo + "/" + gun.config.clipConf.size; + } + } + }; + } + + private ReadOnlyBinding createGunBarIconBinding(boolean isSecondary) { + return new ReadOnlyBinding() { + @Override + public UITextureRegion get() { + SolGame game = solApplication.getGame(); + Hero hero = game.getHero(); + Gun gun = hero.getHull().getGun(isSecondary); + if (gun == null) { + return null; + } + return gun.reloadAwait > 0 ? Assets.getDSTexture("engine:iconWait").getUiTexture() : null; + } + }; + } + + private void toggleScreen(NUIScreenLayer screen) { + if (nuiManager.hasScreen(screen)) { + nuiManager.removeScreen(screen); + return; + } + + while (!(nuiManager.getTopScreen() instanceof MainGameScreen) && !(nuiManager.getTopScreen() instanceof UIShipControlsScreen)) { + nuiManager.popScreen(); + } + solApplication.getInputManager().setScreen(solApplication, solApplication.getGame().getScreens().oldMainGameScreen); + nuiManager.pushScreen(screen); + } + private void onMenuButtonClicked(UIWidget widget) { - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - - solInputManager.setScreen(solApplication, gameScreens.menuScreen); + toggleScreen(gameScreens.menuScreen); } private void onMapButtonClicked(UIWidget widget) { - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - - solInputManager.setScreen(solApplication, gameScreens.mapScreen); + toggleScreen(gameScreens.mapScreen); } private void onItemsButtonClicked(UIWidget widget) { @@ -258,15 +929,10 @@ private void onItemsButtonClicked(UIWidget widget) { return; } - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = game.getScreens(); - - solInputManager.setScreen(solApplication, gameScreens.mainGameScreen); - if (!solInputManager.isScreenOn(gameScreens.inventoryScreen)) { - gameScreens.inventoryScreen.showInventory.setTarget(hero.getShip()); - gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.showInventory); - solInputManager.addScreen(solApplication, gameScreens.inventoryScreen); - } + gameScreens.inventoryScreen.getShowInventory().setTarget(hero.getShip()); + gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.getShowInventory()); + toggleScreen(gameScreens.inventoryScreen); } private void onTalkButtonClicked(UIWidget widget) { @@ -275,14 +941,9 @@ private void onTalkButtonClicked(UIWidget widget) { return; } - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = game.getScreens(); - - solInputManager.setScreen(solApplication, gameScreens.mainGameScreen); - if (!solInputManager.isScreenOn(gameScreens.talkScreen)) { - gameScreens.talkScreen.setTarget(talkTarget); - solInputManager.addScreen(solApplication, gameScreens.talkScreen); - } + gameScreens.talkScreen.setTarget(talkTarget); + toggleScreen(gameScreens.talkScreen); } private void onMercsButtonClicked(UIWidget widget) { @@ -292,14 +953,27 @@ private void onMercsButtonClicked(UIWidget widget) { return; } - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = game.getScreens(); + gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.getChooseMercenaryScreen()); + toggleScreen(gameScreens.inventoryScreen); + hero.getMercs().markAllAsSeen(); + } - solInputManager.setScreen(solApplication, gameScreens.mainGameScreen); - if (!solInputManager.isScreenOn(gameScreens.inventoryScreen)) { - gameScreens.inventoryScreen.setOperations(gameScreens.inventoryScreen.chooseMercenaryScreen); - solInputManager.addScreen(solApplication, gameScreens.inventoryScreen); - hero.getMercs().markAllAsSeen(); + private final class CollisionWarnDrawerRayCastCallback implements RayCastCallback { + private boolean show; + + //TODO code from era when hero was SolShip - does this still work? (what is it supposed to do?) + // TODO: Moved from the original MainGameScreen - still don't know what this does. + @Override + public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) { + if (fixture.getBody().getUserData() instanceof SolObject) { + SolObject o = (SolObject) fixture.getBody().getUserData(); + if (solApplication.getGame().getHero().getShip() == o) { + return -1; + } + show = true; + } + return 0; } } } 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/MenuScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MenuScreen.java new file mode 100644 index 000000000..3bd83857d --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MenuScreen.java @@ -0,0 +1,95 @@ +/* + * 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 org.destinationsol.SolApplication; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; +import org.terasology.nui.widgets.UIButton; + +import javax.inject.Inject; + +/** + * This is the game menu, accessible from anytime in-game by pressing the menu key (default "Escape"). + * The game menu allows you to configure volume options, trigger a respawn or exit to the main menu. + */ +public class MenuScreen extends NUIScreenLayer { + private final SolApplication solApplication; + + @Inject + public MenuScreen(SolApplication solApplication) { + this.solApplication = solApplication; + } + + @Override + public void initialise() { + UIButton canSellUsedItemsButton = find("canSellUsedItemsButton", UIButton.class); + canSellUsedItemsButton.setText("Can sell used items: " + (solApplication.getOptions().canSellEquippedItems ? "Yes" : "No")); + canSellUsedItemsButton.subscribe(button -> { + solApplication.getOptions().canSellEquippedItems = !solApplication.getOptions().canSellEquippedItems; + ((UIButton)button).setText("Can sell used items: " + (solApplication.getOptions().canSellEquippedItems ? "Yes" : "No")); + }); + + UIButton soundVolumeButton = find("soundVolumeButton", UIButton.class); + soundVolumeButton.setText("Sound Volume: " + solApplication.getOptions().sfxVolume.getName()); + soundVolumeButton.subscribe(button -> { + solApplication.getOptions().advanceSoundVolMul(); + ((UIButton)button).setText("Sound Volume: " + solApplication.getOptions().sfxVolume.getName()); + }); + + UIButton musicVolumeButton = find("musicVolumeButton", UIButton.class); + musicVolumeButton.setText("Music Volume: " + solApplication.getOptions().musicVolume.getName()); + musicVolumeButton.subscribe(button -> { + solApplication.getOptions().advanceMusicVolMul(); + ((UIButton)button).setText("Music Volume: " + solApplication.getOptions().musicVolume.getName()); + solApplication.getMusicManager().changeVolume(solApplication.getOptions()); + }); + + UIButton respawnButton = find("respawnButton", UIButton.class); + respawnButton.subscribe(button -> { + solApplication.getGame().respawn(); + nuiManager.removeScreen(this); + }); + + UIButton exitButton = find("exitButton", UIButton.class); + exitButton.subscribe(button -> { + solApplication.finishGame(); + }); + + KeyActivatedButton resumeButton = find("resumeButton", KeyActivatedButton.class); + resumeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyClose())); + resumeButton.subscribe(button -> { + nuiManager.removeScreen(this); + }); + } + + @Override + public void onAdded() { + solApplication.getGame().setPaused(true); + } + + @Override + public void onRemoved() { + solApplication.getGame().setPaused(false); + } + + @Override + protected boolean escapeCloses() { + return false; + } +} 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 new file mode 100644 index 000000000..f315077ae --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/TalkScreen.java @@ -0,0 +1,147 @@ +/* + * 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 org.destinationsol.SolApplication; +import org.destinationsol.game.Hero; +import org.destinationsol.game.ship.SolShip; +import org.destinationsol.game.ship.hulls.HullConfig; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.KeyActivatedButton; +import org.destinationsol.ui.nui.widgets.UIWarnButton; +import org.terasology.nui.backends.libgdx.GDXInputUtil; + +import javax.inject.Inject; + +/** + * The talk screen allows the player to perform actions at a station. + * At the moment, the player can buy and sell items from here, purchase new ships or hire mercenaries. + */ +public class TalkScreen extends NUIScreenLayer { + public static final float MAX_TALK_DIST = 1f; + private final SolApplication solApplication; + private UIWarnButton buyButton; + private KeyActivatedButton changeShipButton; + private KeyActivatedButton hireButton; + private SolShip target; + + @Inject + public TalkScreen(SolApplication solApplication) { + this.solApplication = solApplication; + } + + @Override + public void initialise() { + KeyActivatedButton sellButton = find("sellButton", KeyActivatedButton.class); + sellButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeySellMenu())); + sellButton.subscribe(button -> { + InventoryScreen inventoryScreen = solApplication.getGame().getScreens().inventoryScreen; + inventoryScreen.setOperations(inventoryScreen.getSellItems()); + nuiManager.removeScreen(this); + 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.getBuyItemsScreen()); + nuiManager.removeScreen(this); + 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.getChangeShipScreen()); + nuiManager.removeScreen(this); + 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.getHireShipsScreen()); + nuiManager.removeScreen(this); + nuiManager.pushScreen(inventoryScreen); + }); + + KeyActivatedButton closeButton = find("closeButton", KeyActivatedButton.class); + closeButton.setKey(GDXInputUtil.GDXToNuiKey(solApplication.getOptions().getKeyClose())); + closeButton.subscribe(button -> { + nuiManager.removeScreen(this); + }); + } + + @Override + public void onAdded() { + boolean isStation = target.getHull().config.getType() == HullConfig.Type.STATION; + changeShipButton.setEnabled(isStation); + hireButton.setEnabled(isStation); + } + + @Override + public void update(float delta) { + super.update(delta); + + if (isTargetFar(solApplication.getGame().getHero())) { + nuiManager.removeScreen(this); + } + } + + /** + * Returns the button pressed to open the buy items screen. + * + * This is exposed directly for use in the tutorial. + * @return the buy items button + */ + public UIWarnButton getBuyButton() { + return buyButton; + } + + /** + * Returns the current ship being talked to. + * @return the current ship being talked to + */ + public SolShip getTarget() { + return target; + } + + /** + * Assigns the ship to talk to + * @param target the ship to talk to + */ + public void setTarget(SolShip target) { + this.target = target; + } + + /** + * Returns true if the target is within communicating range. + * @return true, if the target is within communicating range, otherwise false + */ + public boolean isTargetFar(Hero hero) { + if (hero.isTranscendent() || target == null || target.getLife() <= 0) { + return true; + } + + float distance = target.getPosition().dst(hero.getPosition()) - hero.getHull().config.getApproxRadius() - target.getHull().config.getApproxRadius(); + + return (MAX_TALK_DIST < distance); + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/TutorialScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/TutorialScreen.java new file mode 100644 index 000000000..f1a012a65 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/TutorialScreen.java @@ -0,0 +1,82 @@ +/* + * Copyright 2022 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 org.destinationsol.game.SolGame; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.terasology.nui.widgets.UILabel; + +import javax.inject.Inject; + +/** + * This screen displays the message box shown during the tutorial to instruct the user. + * It is unusual in that it should always be rendered on-top of all other UI screens. + * See {@link #moveToTop()} and {@link org.destinationsol.ui.TutorialManager#update(SolGame, float)} for how this is done. + */ +public class TutorialScreen extends NUIScreenLayer { + private UILabel tutorialText; + private boolean isReplaceRemove; + + @Inject + public TutorialScreen() { + } + + @Override + public void initialise() { + tutorialText = find("tutorialText", UILabel.class); + } + + public String getTutorialText() { + return tutorialText.getText(); + } + + public void setTutorialText(String text) { + tutorialText.setText(text); + } + + @Override + public boolean isBlockingInput() { + return false; + } + + @Override + protected boolean escapeCloses() { + return false; + } + + public void moveToTop() { + isReplaceRemove = true; + nuiManager.removeScreen(this); + isReplaceRemove = false; + nuiManager.pushScreen(this); + } + + @Override + public void onRemoved() { + if (isReplaceRemove) { + return; + } + + // This screen is always on-top, so when other screens call popScreen, + // we should remove the screen underneath us, since this was likely the intended behaviour. + if (nuiManager.getScreens().size() > 1 && + !(nuiManager.getTopScreen() instanceof MainGameScreen) && + !(nuiManager.getTopScreen() instanceof UIShipControlsScreen)) { + nuiManager.popScreen(); + } + } +} 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 2d8c13bf0..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().mainGameScreen); + 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/java/org/destinationsol/ui/nui/widgets/UIWarnDrawer.java b/engine/src/main/java/org/destinationsol/ui/nui/widgets/UIWarnDrawer.java new file mode 100644 index 000000000..37f33f642 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/widgets/UIWarnDrawer.java @@ -0,0 +1,160 @@ +/* + * 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.widgets; + +import org.destinationsol.Const; +import org.destinationsol.common.SolMath; +import org.terasology.nui.Canvas; +import org.terasology.nui.Color; +import org.terasology.nui.LayoutConfig; +import org.terasology.nui.UITextureRegion; +import org.terasology.nui.UIWidget; +import org.terasology.nui.databinding.Binding; +import org.terasology.nui.databinding.DefaultBinding; +import org.terasology.nui.widgets.UISpace; + +/** + * An informational box that appears in the screen to alert the user to a particular circumstance that has occurred. + * The background, background tint, box content and trigger conditions are all configurable. + */ +public class UIWarnDrawer extends EmptyIfInvisibleContainer { + private static final float FADE_TIME = 1f; + @LayoutConfig + private UITextureRegion background; + @LayoutConfig + private Color tint; + private float alpha; + private Binding shouldWarn = new DefaultBinding<>(false); + + public UIWarnDrawer(String id, UITextureRegion background, Color tint) { + super(id, new UISpace()); + this.background = background; + this.tint = tint; + this.alpha = 0.0f; + } + + public UIWarnDrawer(String id, UITextureRegion background, Color tint, UIWidget content) { + super(id, content); + this.background = background; + this.tint = tint; + this.alpha = 0.0f; + } + + @Override + public void onDraw(Canvas canvas) { + canvas.setAlpha(alpha); + canvas.drawTexture(background, tint); + super.onDraw(canvas); + } + + @Override + public void update(float delta) { + if (isWarning()) { + alpha = 1; + } else { + alpha = SolMath.approach(alpha, 0, Const.REAL_TIME_STEP / FADE_TIME); + } + + super.update(delta); + } + + /** + * Returns the current background tint. + * @return the current background tint. + */ + public Color getTint() { + return tint; + } + + /** + * Sets the new background tint. + * @param tint the new background tint. + */ + public void setTint(Color tint) { + this.tint = tint; + } + + /** + * Returns the current background texture. + * @return the current background texture. + */ + public UITextureRegion getBackground() { + return background; + } + + /** + * Sets the new background texture. + * @param background the new background texture. + */ + public void setBackground(UITextureRegion background) { + this.background = background; + } + + /** + * Returns the current transparency of the widget. This is additive relative to the canvas. + * @return the current widget transparency. + */ + public float getAlpha() { + return alpha; + } + + /** + * Sets the new widget transparency, relative to the canvas. + * The assigned value may be overridden if the widget is currently warning. + * @param alpha the new widget transparency. + */ + public void setAlpha(float alpha) { + this.alpha = alpha; + } + + /** + * Returns if the widget is currently warning (full opacity). + * @return true, if the widget is currently warning, otherwise false. + */ + public boolean isWarning() { + return shouldWarn.get(); + } + + /** + * Sets whether the widget should currently be warning. + * @param shouldWarn true, if the widget should currently be warning, otherwise false. + */ + public void setWarn(boolean shouldWarn) { + this.shouldWarn.set(shouldWarn); + } + + /** + * Assigns a binding to the widget's warning value to determine when it should warn. + * @param shouldWarn the new warning binding. + */ + public void bindWarn(Binding shouldWarn) { + this.shouldWarn = shouldWarn; + } + + /** + * Returns if the widget is visible. + * NOTE: This overridden version also returns true if the widget alpha is zero or less. + */ + @Override + public boolean isVisible() { + if (!super.isVisible()) { + return false; + } + + return alpha > 0.0f; + } +} 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 b3b4d1619..c05e96ed0 100644 --- a/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin +++ b/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin @@ -10,8 +10,66 @@ }, "font": "engine:main#1" }, + "statsBars": { + "elements": { + "RelativeLayout": { + "fixed-height": 36 + }, + "UILabelledIcon": { + "fixed-height": 32, + "text-align-horizontal": "left", + "text-align-vertical": "center", + "font": "engine:main#0.75" + } + } + }, "controlsUIButton": { "font": "engine:main#0.95" + }, + "unrestrictedMenuBox": { + "elements": { + "UIBox": { + "background": "engine:background" + } + } + }, + "menuUIButton": { + "elements": { + "UIButton": { + "max-width": 640, + "max-height": 128 + } + }, + "font": "engine:main#1" + }, + "warnDrawers": { + "elements": { + "UIWarnDrawer": { + "min-width": 160, + "min-height": 96 + }, + "UILabel": { + "text-align-horizontal": "center", + "text-align-vertical": "middle" + } + }, + "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/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/skins/talkScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/talkScreen.skin new file mode 100644 index 000000000..087d482d2 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/skins/talkScreen.skin @@ -0,0 +1,23 @@ +{ + "inherit": "engine:mainGameScreen", + "families": { + "talkScreenButton": { + "elements": { + "UIButton": { + "max-width": 320, + "max-height": 256 + } + }, + "font": "engine:main#1" + }, + "talkScreenMenuBox": { + "max-width": 320, + "max-height": 800, + "elements": { + "UIBox": { + "background": "engine:background" + } + } + } + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/skins/tutorialScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/tutorialScreen.skin new file mode 100644 index 000000000..70394417a --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/skins/tutorialScreen.skin @@ -0,0 +1,16 @@ +{ + "inherit": "engine:mainGameScreen", + "families": { + "tutorialBox": { + "font": "engine:main#0.8", + "max-width": 512, + "min-height": 128, + "elements": { + "UIBox": { + "background": "engine:background", + "text-align-horizontal": "middle" + } + } + } + } +} \ No newline at end of file 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 diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_desktop.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_desktop.ui index 7e11eb81c..6ef46d1d9 100644 --- a/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_desktop.ui +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_desktop.ui @@ -4,6 +4,49 @@ "contents": { "type": "relativeLayout", "contents": [ + { + "type": "ColumnLayout", + "id": "statsBars", + "family": "statsBars", + "layoutInfo": { + "position-left": { + "offset": 16 + }, + "position-top": { + "offset": 16 + }, + "width": 288 + }, + "verticalSpacing": 0, + "fillVerticalSpace": false, + "contents": [ + ] + }, + { + "type": "FlowLayout", + "id": "warnDrawers", + "family": "warnDrawers", + "horizontalSpacing": 8, + "verticalSpacing": 8, + "contents": [ + ], + "layoutInfo": { + "position-left": { + "widget": "statsBars", + "target": "RIGHT" + }, + "position-right": { + "widget": "menuList", + "target": "LEFT" + }, + "position-top": { + "offset": 16 + }, + "position-bottom": { + "target": "MIDDLE" + } + } + }, { "type": "ColumnLayout", "id": "menuList", @@ -20,9 +63,9 @@ "family": "sideUIButton", "contents": [ { - "type": "UIWarnButton", - "text": "Menu", - "id": "menuButton" + "type": "UIWarnButton", + "text": "Menu", + "id": "menuButton" }, { "type": "UIWarnButton", diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_mobile.ui b/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_mobile.ui index 11ff594fc..62fd5900b 100644 --- a/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_mobile.ui +++ b/engine/src/main/resources/org/destinationsol/assets/ui/mainGameScreen_mobile.ui @@ -4,6 +4,50 @@ "contents": { "type": "relativeLayout", "contents": [ + { + "type": "ColumnLayout", + "id": "statsBars", + "family": "statsBars", + "layoutInfo": { + "position-left": { + "offset": 16 + }, + "position-right": { + "target": "CENTER" + }, + "position-top": { + "offset": 16 + } + }, + "column-widths": [0.6], + "verticalSpacing": 0, + "fillVerticalSpace": false, + "contents": [ + ] + }, + { + "type": "FlowLayout", + "id": "warnDrawers", + "family": "warnDrawers", + "horizontalSpacing": 8, + "verticalSpacing": 8, + "contents": [ + ], + "layoutInfo": { + "position-left": { + "widget": "statsBars", + "target": "RIGHT" + }, + "position-right": { + "widget": "rightMenuList", + "target": "LEFT" + }, + "position-top": {}, + "position-bottom": { + "target": "MIDDLE" + } + } + }, { "type": "ColumnLayout", "id": "leftMenuList", @@ -11,7 +55,7 @@ "use-content-width": true, "use-content-height": true, "position-vertical-center": { - "offset": -100 + "offset": 16 }, "position-left": {} }, @@ -20,9 +64,9 @@ "family": "sideUIButton", "contents": [ { - "type": "UIWarnButton", - "text": "Menu", - "id": "menuButton" + "type": "UIWarnButton", + "text": "Menu", + "id": "menuButton" }, { "type": "UIWarnButton", @@ -37,8 +81,9 @@ "layoutInfo": { "use-content-width": true, "use-content-height": true, - "position-vertical-center": { - "offset": -100 + "position-bottom": { + "widget": "leftMenuList", + "target": "BOTTOM" }, "position-right": {} }, 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/menuScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/menuScreen.ui new file mode 100644 index 000000000..c5893a061 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/menuScreen.ui @@ -0,0 +1,74 @@ +{ + "type": "MenuScreen", + "skin": "engine:mainGameScreen", + "contents": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UIBackingBox", + "family": "unrestrictedMenuBox", + "layoutInfo": { + "position-top": {}, + "position-bottom": {}, + "position-left": {}, + "position-right": {} + } + }, + { + "type": "ColumnLayout", + "id": "menuButtons", + "family": "menuUIButton", + "columns": 1, + "verticalSpacing": 10, + "contents": [ + { + "type": "UIButton", + "id": "canSellUsedItemsButton", + "text": "Can sell used items" + }, + { + "type": "UIButton", + "id": "soundVolumeButton", + "text": "Sound Volume" + }, + { + "type": "UIButton", + "id": "musicVolumeButton", + "text": "Music Volume" + }, + { + "type": "UIButton", + "id": "respawnButton", + "text": "Respawn" + }, + { + "type": "UIButton", + "id": "exitButton", + "text": "Exit" + }, + { + "type": "KeyActivatedButton", + "id": "resumeButton", + "text": "Resume" + } + ], + "layoutInfo": { + "position-horizontal-center": {}, + "position-bottom": { + "offset": 32 + }, + "position-top": { + "target": "MIDDLE", + "offset": -64 + }, + "position-left": { + "offset": 64 + }, + "position-right": { + "offset": 64 + } + } + } + ] + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/talkScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/talkScreen.ui new file mode 100644 index 000000000..6d7d8dcb5 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/talkScreen.ui @@ -0,0 +1,63 @@ +{ + "type": "TalkScreen", + "skin": "engine:talkScreen", + "contents": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UIBackingBox", + "family": "talkScreenMenuBox", + "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", + "id": "menuButtons", + "family": "talkScreenButton", + "columns": 1, + "verticalSpacing": 10, + "contents": [ + { + "type": "KeyActivatedButton", + "id": "sellButton", + "text": "Sell" + }, + { + "type": "UIWarnButton", + "id": "buyButton", + "text": "Buy" + }, + { + "type": "KeyActivatedButton", + "id": "changeShipButton", + "text": "Change Ship" + }, + { + "type": "KeyActivatedButton", + "id": "hireButton", + "text": "Hire" + }, + { + "type": "KeyActivatedButton", + "id": "closeButton", + "text": "Close" + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/engine/src/main/resources/org/destinationsol/assets/ui/tutorialScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/tutorialScreen.ui new file mode 100644 index 000000000..eabee7d77 --- /dev/null +++ b/engine/src/main/resources/org/destinationsol/assets/ui/tutorialScreen.ui @@ -0,0 +1,29 @@ +{ + "type": "TutorialScreen", + "skin": "engine:tutorialScreen", + "contents": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UIBox", + "id": "tutorialBox", + "family": "tutorialBox", + "content": { + "type": "UILabel", + "id": "tutorialText", + "text": "Tutorial content goes here..." + }, + "layoutInfo": { + "position-left": { + "offset": 128 + }, + "position-right": { + "offset": 128 + }, + "position-bottom": {}, + "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