diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index ec333f60c..8cd6a54ba 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -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/screens/GameScreens.java b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java index cda4b9a3d..c7303c0ae 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java +++ b/engine/src/main/java/org/destinationsol/game/screens/GameScreens.java @@ -19,6 +19,7 @@ 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 javax.inject.Inject; @@ -46,7 +47,7 @@ public GameScreens(SolApplication cmp, Context context) { mainGameScreen = (org.destinationsol.ui.nui.screens.MainGameScreen) cmp.getNuiManager().createScreen(NUI_MAIN_GAME_SCREEN_MOBILE_URI); } mapScreen = new MapScreen(rightPaneLayout, cmp.isMobile(), cmp.getOptions()); - menuScreen = new MenuScreen(layouts.menuLayout, cmp.getOptions()); + menuScreen = (MenuScreen) cmp.getNuiManager().createScreen("engine:menuScreen"); inventoryScreen = new InventoryScreen(cmp.getOptions()); talkScreen = new TalkScreen(layouts.menuLayout, cmp.getOptions()); waypointCreationScreen = new WaypointCreationScreen(layouts.menuLayout, cmp.getOptions(), mapScreen); 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 d8b861745..87030ace3 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java @@ -122,7 +122,7 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi 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)); } 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 a0f9e084c..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().oldMainGameScreen); - game.setPaused(false); - } - if (exitControl.isJustOff()) { - solApplication.finishGame(); - } - if (closeControl.isJustOff()) { - game.setPaused(false); - im.setScreen(solApplication, game.getScreens().oldMainGameScreen); - } - 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/ui/SolInputManager.java b/engine/src/main/java/org/destinationsol/ui/SolInputManager.java index 9a3e2f678..813ad01d2 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); } @@ -308,7 +309,8 @@ private void updateCursor(SolApplication solApplication) { } 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 { @@ -367,7 +369,8 @@ public void draw(UiDrawer uiDrawer, SolApplication solApplication) { SolGame game = solApplication.getGame(); TutorialManager tutorialManager = game == null ? null : game.getTutMan(); - if (tutorialManager != null && getTopScreen() != game.getScreens().menuScreen) { + if (tutorialManager != null && + solApplication.getNuiManager().getTopScreen() != game.getScreens().menuScreen) { tutorialManager.draw(uiDrawer); } } 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 4e62a52ba..678ac4b89 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MainGameScreen.java @@ -427,7 +427,7 @@ public void update(float delta) { super.update(delta); SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - if (!solInputManager.isScreenOn(gameScreens.menuScreen) && + if (!nuiManager.hasScreen(gameScreens.menuScreen) && !solInputManager.isScreenOn(gameScreens.mapScreen)) { ((AbstractWidget) contents).setVisible(true); } else { @@ -901,10 +901,9 @@ public UITextureRegion get() { } private void onMenuButtonClicked(UIWidget widget) { - SolInputManager solInputManager = solApplication.getInputManager(); GameScreens gameScreens = solApplication.getGame().getScreens(); - solInputManager.setScreen(solApplication, gameScreens.menuScreen); + nuiManager.pushScreen(gameScreens.menuScreen); } private void onMapButtonClicked(UIWidget widget) { 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/resources/org/destinationsol/assets/skins/mainGameScreen.skin b/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin index 5035d8223..ef98162fc 100644 --- a/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin +++ b/engine/src/main/resources/org/destinationsol/assets/skins/mainGameScreen.skin @@ -26,6 +26,22 @@ "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": { 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