diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/frontend/StarTitleScreen.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/frontend/StarTitleScreen.cpp')
-rw-r--r-- | source/frontend/StarTitleScreen.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/source/frontend/StarTitleScreen.cpp b/source/frontend/StarTitleScreen.cpp new file mode 100644 index 0000000..84790f0 --- /dev/null +++ b/source/frontend/StarTitleScreen.cpp @@ -0,0 +1,435 @@ +#include "StarTitleScreen.hpp" +#include "StarEncode.hpp" +#include "StarGuiReader.hpp" +#include "StarRoot.hpp" +#include "StarJsonExtra.hpp" +#include "StarPlayer.hpp" +#include "StarGuiContext.hpp" +#include "StarPaneManager.hpp" +#include "StarButtonWidget.hpp" +#include "StarCharSelection.hpp" +#include "StarCharCreation.hpp" +#include "StarTextBoxWidget.hpp" +#include "StarOptionsMenu.hpp" +#include "StarModsMenu.hpp" +#include "StarAssets.hpp" +#include "StarCelestialDatabase.hpp" +#include "StarEnvironmentPainter.hpp" + +namespace Star { + +TitleScreen::TitleScreen(PlayerStoragePtr playerStorage, MixerPtr mixer) + : m_playerStorage(playerStorage), m_skipMultiPlayerConnection(false), m_mixer(mixer) { + m_titleState = TitleState::Quit; + + auto assets = Root::singleton().assets(); + + m_guiContext = GuiContext::singletonPtr(); + + m_celestialDatabase = make_shared<CelestialMasterDatabase>(); + auto randomWorld = m_celestialDatabase->findRandomWorld(10, 50, [this](CelestialCoordinate const& coordinate) { + return is<TerrestrialWorldParameters>(m_celestialDatabase->parameters(coordinate)->visitableParameters()); + }).take(); + SkyParameters skyParameters(randomWorld, m_celestialDatabase); + m_skyBackdrop = make_shared<Sky>(skyParameters, true); + + m_musicTrack = make_shared<AmbientNoisesDescription>(assets->json("/interface/windowconfig/title.config:music").toObject(), "/"); + + initMainMenu(); + initCharSelectionMenu(); + initCharCreationMenu(); + initMultiPlayerMenu(); + initOptionsMenu(); + initModsMenu(); + + resetState(); +} + +void TitleScreen::renderInit(RendererPtr renderer) { + m_renderer = move(renderer); + m_environmentPainter = make_shared<EnvironmentPainter>(m_renderer); +} + +void TitleScreen::render() { + auto assets = Root::singleton().assets(); + + float pixelRatio = m_guiContext->interfaceScale(); + Vec2F screenSize = Vec2F(m_guiContext->windowSize()); + auto skyRenderData = m_skyBackdrop->renderData(); + m_environmentPainter->renderStars(pixelRatio, screenSize, skyRenderData); + m_environmentPainter->renderDebrisFields(pixelRatio, screenSize, skyRenderData); + m_environmentPainter->renderBackOrbiters(pixelRatio, screenSize, skyRenderData); + m_environmentPainter->renderPlanetHorizon(pixelRatio, screenSize, skyRenderData); + m_environmentPainter->renderFrontOrbiters(pixelRatio, screenSize, skyRenderData); + m_environmentPainter->renderSky(screenSize, skyRenderData); + + m_renderer->flush(); + + auto skyBackdropDarken = jsonToColor(assets->json("/interface/windowconfig/title.config:skyBackdropDarken")); + m_renderer->render(renderFlatRect(RectF(0, 0, windowWidth(), windowHeight()), skyBackdropDarken.toRgba(), 0.0f)); + + m_renderer->flush(); + + for (auto backdropImage : assets->json("/interface/windowconfig/title.config:backdropImages").toArray()) { + Vec2F offset = jsonToVec2F(backdropImage.get(0)) * interfaceScale(); + String image = backdropImage.getString(1); + float scale = backdropImage.getFloat(2); + Vec2F imageSize = Vec2F(m_guiContext->textureSize(image)) * interfaceScale() * scale; + + Vec2F lowerLeft = Vec2F(windowWidth() / 2.0f, windowHeight()); + lowerLeft[0] -= imageSize[0] / 2; + lowerLeft[1] -= imageSize[1]; + lowerLeft += offset; + RectF screenCoords(lowerLeft, lowerLeft + imageSize); + m_guiContext->drawQuad(image, screenCoords); + } + + m_renderer->flush(); + + m_paneManager.render(); + renderCursor(); + + m_renderer->flush(); +} + +bool TitleScreen::handleInputEvent(InputEvent const& event) { + if (auto mouseMove = event.ptr<MouseMoveEvent>()) + m_cursorScreenPos = mouseMove->mousePosition; + + if (event.is<KeyDownEvent>()) { + if (GuiContext::singleton().actions(event).contains(InterfaceAction::TitleBack)) { + back(); + return true; + } + } + + return m_paneManager.sendInputEvent(event); +} + +void TitleScreen::update() { + for (auto p : m_rightAnchoredButtons) + p.first->setPosition(Vec2I(m_guiContext->windowWidth() / m_guiContext->interfaceScale(), 0) + p.second); + m_mainMenu->determineSizeFromChildren(); + + m_skyBackdrop->update(); + m_environmentPainter->update(); + + m_paneManager.update(); + + if (!finishedState()) { + if (auto audioSample = m_musicTrackManager.updateAmbient(m_musicTrack, m_skyBackdrop->isDayTime())) { + audioSample->setMixerGroup(MixerGroup::Music); + m_mixer->play(audioSample); + } + } +} + +bool TitleScreen::textInputActive() const { + return m_paneManager.keyboardCapturedForTextInput(); +} + +TitleState TitleScreen::currentState() const { + return m_titleState; +} + +bool TitleScreen::finishedState() const { + switch (m_titleState) { + case TitleState::StartSinglePlayer: + case TitleState::StartMultiPlayer: + case TitleState::Quit: + return true; + default: + return false; + } +} + +void TitleScreen::resetState() { + switchState(TitleState::Main); +} + +void TitleScreen::goToMultiPlayerSelectCharacter(bool skipConnection) { + m_skipMultiPlayerConnection = skipConnection; + switchState(TitleState::MultiPlayerSelectCharacter); +} + +void TitleScreen::stopMusic() { + m_musicTrackManager.cancelAll(); +} + +PlayerPtr TitleScreen::currentlySelectedPlayer() const { + return m_mainAppPlayer; +} + +String TitleScreen::multiPlayerAddress() const { + return m_connectionAddress; +} + +void TitleScreen::setMultiPlayerAddress(String address) { + m_multiPlayerMenu->fetchChild<TextBoxWidget>("address")->setText(address); + m_connectionAddress = move(address); +} + +String TitleScreen::multiPlayerPort() const { + return m_connectionPort; +} + +void TitleScreen::setMultiPlayerPort(String port) { + m_multiPlayerMenu->fetchChild<TextBoxWidget>("port")->setText(port); + m_connectionPort = move(port); +} + +String TitleScreen::multiPlayerAccount() const { + return m_account; +} + +void TitleScreen::setMultiPlayerAccount(String account) { + m_multiPlayerMenu->fetchChild<TextBoxWidget>("account")->setText(account); + m_account = move(account); +} + +String TitleScreen::multiPlayerPassword() const { + return m_password; +} + +void TitleScreen::setMultiPlayerPassword(String password) { + m_multiPlayerMenu->fetchChild<TextBoxWidget>("password")->setText(password); + m_password = move(password); +} + +void TitleScreen::initMainMenu() { + m_mainMenu = make_shared<Pane>(); + auto backMenu = make_shared<Pane>(); + + auto assets = Root::singleton().assets(); + + StringMap<WidgetCallbackFunc> buttonCallbacks; + buttonCallbacks["singleplayer"] = [=](Widget*) { switchState(TitleState::SinglePlayerSelectCharacter); }; + buttonCallbacks["multiplayer"] = [=](Widget*) { switchState(TitleState::MultiPlayerSelectCharacter); }; + buttonCallbacks["options"] = [=](Widget*) { switchState(TitleState::Options); }; + buttonCallbacks["quit"] = [=](Widget*) { switchState(TitleState::Quit); }; + buttonCallbacks["back"] = [=](Widget*) { back(); }; + buttonCallbacks["mods"] = [=](Widget*) { switchState(TitleState::Mods); }; + + for (auto buttonConfig : assets->json("/interface/windowconfig/title.config:mainMenuButtons").toArray()) { + String key = buttonConfig.getString("key"); + String image = buttonConfig.getString("button"); + String imageHover = buttonConfig.getString("hover"); + Vec2I offset = jsonToVec2I(buttonConfig.get("offset")); + WidgetCallbackFunc callback = buttonCallbacks.get(key); + bool rightAnchored = buttonConfig.getBool("rightAnchored", false); + + auto button = make_shared<ButtonWidget>(callback, image, imageHover, "", ""); + button->setPosition(offset); + + if (rightAnchored) + m_rightAnchoredButtons.append({button, offset}); + + if (key == "back") + backMenu->addChild(key, button); + else + m_mainMenu->addChild(key, button); + } + + m_mainMenu->setAnchor(PaneAnchor::BottomLeft); + m_mainMenu->lockPosition(); + + backMenu->determineSizeFromChildren(); + backMenu->setAnchor(PaneAnchor::BottomLeft); + backMenu->lockPosition(); + + m_paneManager.registerPane("mainMenu", PaneLayer::Hud, m_mainMenu); + m_paneManager.registerPane("backMenu", PaneLayer::Hud, backMenu); +} + +void TitleScreen::initCharSelectionMenu() { + auto deleteDialog = make_shared<Pane>(); + + GuiReader reader; + + reader.registerCallback("delete", [=](Widget*) { deleteDialog->dismiss(); }); + reader.registerCallback("cancel", [=](Widget*) { deleteDialog->dismiss(); }); + + reader.construct(Root::singleton().assets()->json("/interface/windowconfig/deletedialog.config"), deleteDialog.get()); + + auto charSelectionMenu = make_shared<CharSelectionPane>(m_playerStorage, [=]() { + if (m_titleState == TitleState::SinglePlayerSelectCharacter) + switchState(TitleState::SinglePlayerCreateCharacter); + else if (m_titleState == TitleState::MultiPlayerSelectCharacter) + switchState(TitleState::MultiPlayerCreateCharacter); + }, [=](PlayerPtr mainPlayer) { + m_mainAppPlayer = mainPlayer; + m_playerStorage->moveToFront(m_mainAppPlayer->uuid()); + if (m_titleState == TitleState::SinglePlayerSelectCharacter) { + switchState(TitleState::StartSinglePlayer); + } else if (m_titleState == TitleState::MultiPlayerSelectCharacter) { + if (m_skipMultiPlayerConnection) + switchState(TitleState::StartMultiPlayer); + else + switchState(TitleState::MultiPlayerConnect); + } + }, [=](Uuid playerUuid) { + auto deleteDialog = m_paneManager.registeredPane("deleteDialog"); + deleteDialog->fetchChild<ButtonWidget>("delete")->setCallback([=](Widget*) { + m_playerStorage->deletePlayer(playerUuid); + deleteDialog->dismiss(); + }); + m_paneManager.displayRegisteredPane("deleteDialog"); + }); + charSelectionMenu->setAnchor(PaneAnchor::Center); + charSelectionMenu->lockPosition(); + + m_paneManager.registerPane("deleteDialog", PaneLayer::ModalWindow, deleteDialog, [=](PanePtr const&) { + charSelectionMenu->updateCharacterPlates(); + }); + m_paneManager.registerPane("charSelectionMenu", PaneLayer::Hud, charSelectionMenu); +} + +void TitleScreen::initCharCreationMenu() { + auto charCreationMenu = make_shared<CharCreationPane>([=](PlayerPtr newPlayer) { + if (newPlayer) { + m_mainAppPlayer = newPlayer; + m_playerStorage->savePlayer(m_mainAppPlayer); + m_playerStorage->moveToFront(m_mainAppPlayer->uuid()); + } + back(); + }); + charCreationMenu->setAnchor(PaneAnchor::Center); + charCreationMenu->lockPosition(); + + m_paneManager.registerPane("charCreationMenu", PaneLayer::Hud, charCreationMenu); +} + +void TitleScreen::initMultiPlayerMenu() { + m_multiPlayerMenu = make_shared<Pane>(); + + GuiReader reader; + + reader.registerCallback("address", [=](Widget* obj) { + m_connectionAddress = convert<TextBoxWidget>(obj)->getText().trim(); + }); + + reader.registerCallback("port", [=](Widget* obj) { + m_connectionPort = convert<TextBoxWidget>(obj)->getText().trim(); + }); + + reader.registerCallback("account", [=](Widget* obj) { + m_account = convert<TextBoxWidget>(obj)->getText().trim(); + }); + + reader.registerCallback("password", [=](Widget* obj) { + m_password = convert<TextBoxWidget>(obj)->getText().trim(); + }); + + reader.registerCallback("connect", [=](Widget*) { + switchState(TitleState::StartMultiPlayer); + }); + + auto assets = Root::singleton().assets(); + reader.construct(assets->json("/interface/windowconfig/multiplayer.config"), m_multiPlayerMenu.get()); + + m_paneManager.registerPane("multiplayerMenu", PaneLayer::Hud, m_multiPlayerMenu); +} + +void TitleScreen::initOptionsMenu() { + auto optionsMenu = make_shared<OptionsMenu>(&m_paneManager); + optionsMenu->setAnchor(PaneAnchor::Center); + optionsMenu->lockPosition(); + + m_paneManager.registerPane("optionsMenu", PaneLayer::Hud, optionsMenu, [this](PanePtr const&) { + back(); + }); +} + +void TitleScreen::initModsMenu() { + auto modsMenu = make_shared<ModsMenu>(); + modsMenu->setAnchor(PaneAnchor::Center); + modsMenu->lockPosition(); + + m_paneManager.registerPane("modsMenu", PaneLayer::Hud, modsMenu, [this](PanePtr const&) { + back(); + }); +} + +void TitleScreen::switchState(TitleState titleState) { + if (m_titleState == titleState) + return; + + m_paneManager.dismissAllPanes(); + m_titleState = titleState; + + // Clear the 'skip multi player connection' flag if we leave the multi player + // menus + if (m_titleState < TitleState::MultiPlayerSelectCharacter || m_titleState > TitleState::MultiPlayerConnect) + m_skipMultiPlayerConnection = false; + + if (titleState == TitleState::Main) { + m_paneManager.displayRegisteredPane("mainMenu"); + } else { + m_paneManager.displayRegisteredPane("backMenu"); + + if (titleState == TitleState::Options) { + m_paneManager.displayRegisteredPane("optionsMenu"); + } if (titleState == TitleState::Mods) { + m_paneManager.displayRegisteredPane("modsMenu"); + } else if (titleState == TitleState::SinglePlayerSelectCharacter) { + m_paneManager.displayRegisteredPane("charSelectionMenu"); + } else if (titleState == TitleState::SinglePlayerCreateCharacter) { + m_paneManager.displayRegisteredPane("charCreationMenu"); + } else if (titleState == TitleState::MultiPlayerSelectCharacter) { + m_paneManager.displayRegisteredPane("charSelectionMenu"); + } else if (titleState == TitleState::MultiPlayerCreateCharacter) { + m_paneManager.displayRegisteredPane("charCreationMenu"); + } else if (titleState == TitleState::MultiPlayerConnect) { + m_paneManager.displayRegisteredPane("multiplayerMenu"); + if (auto addressWidget = m_multiPlayerMenu->fetchChild("address")) + addressWidget->focus(); + } + } + + if (titleState == TitleState::Quit) + m_musicTrackManager.cancelAll(); +} + +void TitleScreen::back() { + if (m_titleState == TitleState::Options) + switchState(TitleState::Main); + else if (m_titleState == TitleState::Mods) + switchState(TitleState::Main); + else if (m_titleState == TitleState::SinglePlayerSelectCharacter) + switchState(TitleState::Main); + else if (m_titleState == TitleState::SinglePlayerCreateCharacter) + switchState(TitleState::SinglePlayerSelectCharacter); + else if (m_titleState == TitleState::MultiPlayerSelectCharacter) + switchState(TitleState::Main); + else if (m_titleState == TitleState::MultiPlayerCreateCharacter) + switchState(TitleState::MultiPlayerSelectCharacter); + else if (m_titleState == TitleState::MultiPlayerConnect) + switchState(TitleState::MultiPlayerSelectCharacter); +} + +void TitleScreen::renderCursor() { + auto assets = Root::singleton().assets(); + + m_cursor.update(WorldTimestep); + Vec2I cursorPos = m_cursorScreenPos; + Vec2I cursorSize = m_cursor.size(); + Vec2I cursorOffset = m_cursor.offset(); + + cursorPos[0] -= cursorOffset[0] * interfaceScale(); + cursorPos[1] -= (cursorSize[1] - cursorOffset[1]) * interfaceScale(); + m_guiContext->drawDrawable(m_cursor.drawable(), Vec2F(cursorPos), interfaceScale()); +} + +float TitleScreen::interfaceScale() const { + return m_guiContext->interfaceScale(); +} + +unsigned TitleScreen::windowHeight() const { + return m_guiContext->windowHeight(); +} + +unsigned TitleScreen::windowWidth() const { + return m_guiContext->windowWidth(); +} + +} |