[Add] Implement screen manager state machine.

This commit is contained in:
Ritchie Cunningham 2025-09-28 00:09:26 +01:00
parent 5cbcfeb54e
commit b1bdb86b76
3 changed files with 90 additions and 44 deletions

View File

@ -9,73 +9,105 @@
#include "ui/desktop.h" #include "ui/desktop.h"
#include "ui/ui_window.h" #include "ui/ui_window.h"
GameState::GameState(void) = default; void GameState::_init_desktop(void) {
_desktop = std::make_unique<Desktop>();
auto term = std::make_unique<Terminal>(_network.get());
auto term_window = std::make_unique<UIWindow>("Terminal", 100, 100, 800, 500);
term_window->set_content(std::move(term));
_desktop->add_window(std::move(term_window));
}
GameState::GameState(void) : _current_screen(Screen::MAIN_MENU) {}
GameState::~GameState(void) = default; GameState::~GameState(void) = default;
void GameState::init(void) { void GameState::init(void) {
/* Create and connect the network client. */ /* Create and connect the network client. */
_network = std::make_unique<ClientNetwork>(); _network = std::make_unique<ClientNetwork>();
if(_network->connect("127.0.0.1", 1337)) {
/* TODO: handle connection success message. */ /* TODO: For now, connect immediately, later, trigger by menu option. */
} else { if(!_network->connect("127.0.0.1", 1337)) {
/* TODO: handle connection failure. */ /* TODO: Handle connection failure. */
} }
_current_screen = Screen::DESKTOP;
/* Create the desktop. */ _init_desktop();
_desktop = std::make_unique<Desktop>();
/*
* Create initial terminal window.
*/
auto term = std::make_unique<Terminal>(_network.get()); /* Pass network connection. */
auto term_window = std::make_unique<UIWindow>("Terminal", 100, 100, 800, 500);
term_window->set_content(std::move(term));
_desktop->add_window(std::move(term_window));
} }
void GameState::handle_event(SDL_Event* event) { void GameState::handle_event(SDL_Event* event) {
if(_desktop) { switch(_current_screen) {
_desktop->handle_event(event); case Screen::MAIN_MENU:
/* TODO: */
break;
case Screen::BOOTING:
/* TODO: */
break;
case Screen::DESKTOP:
if(_desktop) {
_desktop->handle_event(event);
}
break;
} }
} }
void GameState::update(void) { void GameState::update(void) {
std::string server_msg; switch(_current_screen) {
while(_network->poll_message(server_msg)) { case Screen::MAIN_MENU:
UIWindow* focused_window = _desktop->get_focused_window(); /* TODO: */
if(!focused_window) continue; break;
case Screen::BOOTING:
/* TODO: */
break;
case Screen::DESKTOP:
std::string server_msg;
while(_network->poll_message(server_msg)) {
UIWindow* focused_window = _desktop->get_focused_window();
if(!focused_window)
continue;
Terminal* terminal = focused_window->get_content(); Terminal* terminal = focused_window->get_content();
if(!terminal) continue; if(!terminal)
continue;
/* Server sends "output\nprompt", split them. */ /* Server sends "output\nprompt", split them. */
size_t last_newline = server_msg.find_last_of("\n"); size_t last_newline = server_msg.find_last_of('\n');
if(last_newline != std::string::npos) { if(last_newline != std::string::npos) {
std::string prompt = server_msg.substr(last_newline+1); std::string prompt = server_msg.substr(last_newline+1);
terminal->set_prompt(prompt); terminal->set_prompt(prompt);
std::string output = server_msg.substr(0, last_newline); std::string output = server_msg.substr(0, last_newline);
if(!output.empty()) { if(!output.empty()) {
/* split the multiline output and push each line to history. */ /* Split multiline output and push each line to history. */
std::stringstream ss(output); std::stringstream ss(output);
std::string line; std::string line;
while(std::getline(ss, line, '\n')) { while(std::getline(ss, line, '\n')) {
terminal->add_history(line); terminal->add_history(line);
}
}
} else {
terminal->add_history(server_msg);
} }
} }
} else { if(_desktop) {
terminal->add_history(server_msg); _desktop->update();
} }
} break;
if(_desktop) {
_desktop->update();
} }
} }
void GameState::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, void GameState::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
int screen_height, bool show_cursor) { int screen_height, bool show_cursor) {
if(_desktop) { switch(_current_screen) {
_desktop->render(shape_renderer, txt_renderer, screen_height, show_cursor); case Screen::MAIN_MENU:
/* TODO: */
break;
case Screen::BOOTING:
/* TODO: */
break;
case Screen::DESKTOP:
if(_desktop) {
_desktop->render(shape_renderer, txt_renderer, screen_height, show_cursor);
}
break;
} }
} }

View File

@ -8,6 +8,12 @@ class ShapeRenderer;
class TextRenderer; class TextRenderer;
union SDL_Event; union SDL_Event;
enum class Screen {
MAIN_MENU,
BOOTING,
DESKTOP
};
class GameState { class GameState {
public: public:
GameState(void); GameState(void);
@ -22,4 +28,7 @@ public:
private: private:
std::unique_ptr<ClientNetwork> _network; std::unique_ptr<ClientNetwork> _network;
std::unique_ptr<Desktop> _desktop; std::unique_ptr<Desktop> _desktop;
Screen _current_screen;
void _init_desktop(void);
}; };

View File

@ -17,6 +17,11 @@ Desktop::~Desktop(void) {}
void Desktop::add_window(std::unique_ptr<UIWindow> window) { void Desktop::add_window(std::unique_ptr<UIWindow> window) {
_windows.push_back(std::move(window)); _windows.push_back(std::move(window));
/* I'm sick of reaching for my mouse to focus the terminal.. Stop that! */
if(_windows.size() == 1) {
_focused_window = _windows.back().get();
_focused_window->set_focused(true);
}
} }
void Desktop::handle_event(SDL_Event* event) { void Desktop::handle_event(SDL_Event* event) {