diff --git a/src/frontend/gui/GUI.cpp b/src/frontend/gui/GUI.cpp index f28ad67d..b0831077 100644 --- a/src/frontend/gui/GUI.cpp +++ b/src/frontend/gui/GUI.cpp @@ -22,6 +22,9 @@ GUI::GUI() { uicamera = new Camera(vec3(), Window::height); uicamera->perspective = false; uicamera->flipped = true; + + menu = new PagesControl(); + container->add(menu); } GUI::~GUI() { @@ -29,6 +32,10 @@ GUI::~GUI() { delete container; } +PagesControl* GUI::getMenu() { + return menu; +} + void GUI::act(float delta) { container->size(vec2(Window::width, Window::height)); container->act(delta); @@ -94,6 +101,7 @@ void GUI::act(float delta) { } void GUI::draw(Batch2D* batch, Assets* assets) { + menu->setCoord((Window::size() - menu->size()) / 2.0f); uicamera->fov = Window::height; Shader* uishader = assets->getShader("ui"); diff --git a/src/frontend/gui/GUI.h b/src/frontend/gui/GUI.h index b17af47f..3d4adc6b 100644 --- a/src/frontend/gui/GUI.h +++ b/src/frontend/gui/GUI.h @@ -46,6 +46,7 @@ class Camera; namespace gui { class UINode; class Container; + class PagesControl; class GUI { Container* container; @@ -55,10 +56,13 @@ namespace gui { std::unordered_map> storage; Camera* uicamera; + PagesControl* menu; public: GUI(); ~GUI(); + PagesControl* getMenu(); + std::shared_ptr getFocused() const; bool isFocusCaught() const; diff --git a/src/frontend/gui/panels.cpp b/src/frontend/gui/panels.cpp index 6488b6be..8959b492 100644 --- a/src/frontend/gui/panels.cpp +++ b/src/frontend/gui/panels.cpp @@ -183,10 +183,18 @@ void Panel::lock(){ PagesControl::PagesControl() : Container(vec2(), vec2(1)){ } +bool PagesControl::has(std::string name) { + return pages.find(name) != pages.end(); +} + void PagesControl::add(std::string name, std::shared_ptr panel) { pages[name] = Page{panel}; } +void PagesControl::add(std::string name, UINode* panel) { + add(name, shared_ptr(panel)); +} + void PagesControl::set(std::string name, bool history) { auto found = pages.find(name); if (found == pages.end()) { diff --git a/src/frontend/gui/panels.h b/src/frontend/gui/panels.h index 174180c7..a44c605b 100644 --- a/src/frontend/gui/panels.h +++ b/src/frontend/gui/panels.h @@ -61,6 +61,10 @@ namespace gui { struct Page { std::shared_ptr panel = nullptr; + + ~Page() { + panel = nullptr; + } }; class PagesControl : public Container { @@ -72,8 +76,10 @@ namespace gui { public: PagesControl(); + bool has(std::string name); void set(std::string name, bool history=true); void add(std::string name, std::shared_ptr panel); + void add(std::string name, UINode* panel); void back(); void clearHistory(); void reset(); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 0d0b04cb..d22eacae 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -46,14 +46,12 @@ inline Label* create_label(gui::wstringsupplier supplier) { } HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), gui(engine->getGUI()) { + auto menu = gui->getMenu(); batch = new Batch2D(1024); uicamera = new Camera(vec3(), 1); uicamera->perspective = false; uicamera->flipped = true; - auto pagesptr = gui->get("pages"); - PagesControl* pages = (PagesControl*)(pagesptr.get()); - Panel* panel = new Panel(vec2(250, 200), vec4(5.0f), 1.0f); debugPanel = shared_ptr(panel); panel->listenInterval(1.0f, [this]() { @@ -117,37 +115,13 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en panel->add(shared_ptr(sub)); } panel->refresh(); - - panel = new Panel(vec2(350, 200)); - auto pauseMenu = shared_ptr(panel); - panel->color(vec4(0.0f)); - { - Button* button = new Button(L"Continue", vec4(10.0f)); - button->listenAction([=](GUI*){ - pages->reset(); - pause = false; - }); - panel->add(shared_ptr(button)); - } - panel->add((new Button(L"Settings", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->set("settings"); - })); - { - Button* button = new Button(L"Save and Quit to Menu", vec4(10.f)); - button->listenAction([this, engine](GUI*){ - engine->setScreen(shared_ptr(new MenuScreen(engine))); - }); - panel->add(shared_ptr(button)); - } - - pages->reset(); - pages->add("pause", pauseMenu); + menu->reset(); + gui->add(this->debugPanel); } HudRenderer::~HudRenderer() { gui->remove(debugPanel); - //gui->remove(gui->get("pages")); delete batch; delete uicamera; } @@ -224,7 +198,7 @@ void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { tint.r *= 1.2f; tint.g *= 1.2f; tint.b *= 1.2f; - if (Events::jclicked(GLFW_MOUSE_BUTTON_LEFT)) { + if (Events::jclicked(mousecode::BUTTON_1)) { player->choosenBlock = i+1; } } else { @@ -240,16 +214,19 @@ void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) { } void HudRenderer::update() { - PagesControl* pages = (PagesControl*)(gui->get("pages").get()); + auto menu = gui->getMenu(); + if (pause && menu->current().panel == nullptr) { + pause = false; + } if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) { if (pause) { pause = false; - pages->reset(); + menu->reset(); } else if (inventoryOpen) { inventoryOpen = false; } else { pause = true; - pages->set("pause"); + menu->set("pause"); } } if (Events::jactive(BIND_HUD_INVENTORY)) { @@ -265,10 +242,8 @@ void HudRenderer::draw(const GfxContext& ctx){ const Viewport& viewport = ctx.getViewport(); const uint width = viewport.getWidth(); const uint height = viewport.getHeight(); - auto pages = gui->get("pages"); debugPanel->visible(level->player->debug); - pages->setCoord((viewport.size() - pages->size()) / 2.0f); uicamera->fov = height; diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 22cb092f..75280e41 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -25,274 +25,34 @@ #include "hud.h" #include "gui/GUI.h" #include "gui/panels.h" -#include "gui/controls.h" #include "../engine.h" -#include "../files/engine_files.h" #include "../util/stringutil.h" #include "../core_defs.h" +#include "menu.h" + using std::string; using std::wstring; using glm::vec3; using glm::vec4; using std::shared_ptr; -using std::filesystem::path; -using std::filesystem::u8path; -using std::filesystem::directory_iterator; -using namespace gui; - -shared_ptr create_main_menu_panel(Engine* engine, PagesControl* pages) { - Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); - shared_ptr panelptr(panel); - panel->color(vec4(0.0f)); - - panel->add((new Button(L"New World", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->set("new-world"); - })); - - Panel* worldsPanel = new Panel(vec2(390, 200), vec4(5.0f)); - worldsPanel->color(vec4(0.1f)); - path worldsFolder = enginefs::get_worlds_folder(); - if (std::filesystem::is_directory(worldsFolder)) { - for (auto const& entry : directory_iterator(worldsFolder)) { - string name = entry.path().filename().string(); - Button* button = new Button(util::str2wstr_utf8(name), - vec4(10.0f, 8.0f, 10.0f, 8.0f)); - button->color(vec4(0.5f)); - button->listenAction([engine, panel, name](GUI*) { - EngineSettings& settings = engine->getSettings(); - - auto folder = enginefs::get_worlds_folder()/u8path(name); - World* world = new World(name, folder, 42, settings); - auto screen = new LevelScreen(engine, world->load(settings)); - engine->setScreen(shared_ptr(screen)); - }); - worldsPanel->add(button); - } - } - panel->add(worldsPanel); - - panel->add((new Button(L"Settings", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->set("settings"); - })); - - panel->add((new Button(L"Quit", vec4(10.f)))->listenAction([](GUI*) { - Window::setShouldClose(true); - })); - panel->refresh(); - return panelptr; -} - -shared_ptr create_new_world_panel(Engine* engine, PagesControl* pages) { - Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); - shared_ptr panelptr(panel); - panel->color(vec4(0.0f)); - - TextBox* worldNameInput; - { - Label* label = new Label(L"World Name"); - panel->add(label); - - TextBox* input = new TextBox(L"New World", vec4(6.0f)); - panel->add(input); - worldNameInput = input; - } - - TextBox* seedInput; - { - Label* label = new Label(L"Seed"); - panel->add(shared_ptr(label)); - - uint64_t randseed = rand() ^ (rand() << 8) ^ - (rand() << 16) ^ (rand() << 24) ^ - ((uint64_t)rand() << 32) ^ - ((uint64_t)rand() << 40) ^ - ((uint64_t)rand() << 56); - - seedInput = new TextBox(std::to_wstring(randseed), vec4(6.0f)); - panel->add(seedInput); - } - - { - Button* button = new Button(L"Create World", vec4(10.0f)); - button->margin(vec4(0, 20, 0, 0)); - vec4 basecolor = worldNameInput->color(); - button->listenAction([=](GUI*) { - wstring name = worldNameInput->text(); - string nameutf8 = util::wstr2str_utf8(name); - - // Basic validation - if (!util::is_valid_filename(name) || - enginefs::is_world_name_used(nameutf8)) { - // blink red two times - panel->listenInterval(0.1f, [worldNameInput, basecolor]() { - static bool flag = true; - if (flag) { - worldNameInput->color(vec4(0.3f, 0.0f, 0.0f, 0.5f)); - } else { - worldNameInput->color(basecolor); - } - flag = !flag; - }, 4); - return; - } - - wstring seedstr = seedInput->text(); - uint64_t seed; - if (util::is_integer(seedstr)) { - try { - seed = std::stoull(seedstr); - } catch (const std::out_of_range& err) { - std::hash hash; - seed = hash(seedstr); - } - } else { - std::hash hash; - seed = hash(seedstr); - } - std::cout << "world seed: " << seed << std::endl; - - EngineSettings& settings = engine->getSettings(); - - auto folder = enginefs::get_worlds_folder()/u8path(nameutf8); - std::filesystem::create_directories(folder); - World* world = new World(nameutf8, folder, seed, settings); - auto screen = new LevelScreen(engine, world->load(settings)); - engine->setScreen(shared_ptr(screen)); - }); - panel->add(button); - } - - panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->back(); - })); - panel->refresh(); - return panelptr; -} - -Panel* create_controls_panel(Engine* engine, PagesControl* pages) { - Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); - panel->color(vec4(0.0f)); - - for (auto& entry : Events::bindings){ - string bindname = entry.first; - - Panel* subpanel = new Panel(vec2(400, 45), vec4(5.0f), 1.0f); - subpanel->color(vec4(0.0f)); - subpanel->orientation(Orientation::horizontal); - - InputBindBox* bindbox = new InputBindBox(entry.second); - subpanel->add(bindbox); - Label* label = new Label(util::str2wstr_utf8(bindname)); - label->margin(vec4(6.0f)); - subpanel->add(label); - panel->add(subpanel); - } - - panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->back(); - })); - panel->refresh(); - return panel; -} - -shared_ptr create_settings_panel(Engine* engine, PagesControl* pages) { - Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 1.0f); - panel->color(vec4(0.0f)); - - shared_ptr panelptr(panel); - - /* Load Distance setting track bar */{ - panel->add((new Label(L""))->textSupplier([=]() { - return L"Load Distance: " + - std::to_wstring(engine->getSettings().chunks.loadDistance); - })); - - TrackBar* trackbar = new TrackBar(3, 66, 10, 1, 3); - trackbar->supplier([=]() { - return engine->getSettings().chunks.loadDistance; - }); - trackbar->consumer([=](double value) { - engine->getSettings().chunks.loadDistance = value; - }); - panel->add(trackbar); - } - - /* Fog Curve setting track bar */{ - panel->add((new Label(L""))->textSupplier([=]() { - std::wstringstream ss; - ss << std::fixed << std::setprecision(1); - ss << engine->getSettings().graphics.fogCurve; - return L"Fog Curve: " + ss.str(); - })); - - TrackBar* trackbar = new TrackBar(1.0, 6.0, 1.0, 0.1, 2); - trackbar->supplier([=]() { - return engine->getSettings().graphics.fogCurve; - }); - trackbar->consumer([=](double value) { - engine->getSettings().graphics.fogCurve = value; - }); - panel->add(trackbar); - } - - { - Panel* checkpanel = new Panel(vec2(400, 32), vec4(5.0f), 1.0f); - checkpanel->color(vec4(0.0f)); - checkpanel->orientation(Orientation::horizontal); - - CheckBox* checkbox = new CheckBox(); - checkbox->margin(vec4(0.0f, 0.0f, 5.0f, 0.0f)); - checkbox->supplier([=]() { - return engine->getSettings().display.swapInterval != 0; - }); - checkbox->consumer([=](bool checked) { - engine->getSettings().display.swapInterval = checked; - }); - checkpanel->add(checkbox); - checkpanel->add(new Label(L"V-Sync")); - - panel->add(checkpanel); - } - - panel->add((new Button(L"Controls", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->set("controls"); - })); - - panel->add((new Button(L"Back", vec4(10.f)))->listenAction([=](GUI* gui) { - pages->back(); - })); - panel->refresh(); - return panelptr; -} MenuScreen::MenuScreen(Engine* engine_) : Screen(engine_) { - GUI* gui = engine->getGUI(); + auto menu = engine->getGUI()->getMenu(); - auto pagesptr = gui->get("pages"); - PagesControl* pages; - if (pagesptr == nullptr) { - pages = new PagesControl(); - auto newWorldPanel = create_new_world_panel(engine, pages); + // Create pages if not created yet + if (!menu->has("new-world")) + menu->add("new-world", create_new_world_panel(engine, menu)); + if (!menu->has("settings")) + menu->add("settings", create_settings_panel(engine, menu)); + if (!menu->has("controls")) + menu->add("controls", create_controls_panel(engine, menu)); + if (!menu->has("pause")) + menu->add("pause", create_pause_panel(engine, menu)); - auto settingsPanel = shared_ptr(create_settings_panel(engine, pages)); - auto controlsPanel = shared_ptr(create_controls_panel(engine, pages)); - - pages->add("new-world", newWorldPanel); - pages->add("settings", settingsPanel); - pages->add("controls", controlsPanel); - - this->pages = shared_ptr(pages); - gui->add(this->pages); - gui->store("pages", this->pages); - } else { - this->pages = pagesptr; - pages = (PagesControl*)(pagesptr.get()); - pages->reset(); - } - auto mainMenuPanel = create_main_menu_panel(engine, pages); - pages->add("main", mainMenuPanel); - pages->set("main"); + menu->add("main", create_main_menu_panel(engine, menu)); + menu->reset(); + menu->set("main"); batch = new Batch2D(1024); uicamera = new Camera(vec3(), Window::height); @@ -309,8 +69,6 @@ void MenuScreen::update(float delta) { } void MenuScreen::draw(float delta) { - pages->setCoord((Window::size() - pages->size()) / 2.0f); - Window::clear(); Window::setBgColor(vec3(0.2f, 0.2f, 0.2f)); diff --git a/src/frontend/screens.h b/src/frontend/screens.h index c29299c8..2ea6c3e9 100644 --- a/src/frontend/screens.h +++ b/src/frontend/screens.h @@ -12,10 +12,6 @@ class Engine; class Camera; class Batch2D; -namespace gui { - class UINode; -} - /* Screen is a mainloop state */ class Screen { protected: @@ -28,7 +24,6 @@ public: }; class MenuScreen : public Screen { - std::shared_ptr pages; Batch2D* batch; Camera* uicamera; public: