#include "menu.h" #include #include #include #include #include #include #include #include "gui/GUI.h" #include "gui/panels.h" #include "gui/controls.h" #include "screens.h" #include "../coders/png.h" #include "../util/stringutil.h" #include "../files/engine_paths.h" #include "../files/WorldConverter.h" #include "../files/WorldFiles.h" #include "../world/World.h" #include "../world/Level.h" #include "../window/Events.h" #include "../window/Window.h" #include "../engine.h" #include "../settings.h" #include "../content/Content.h" #include "../content/ContentLUT.h" #include "../content/ContentPack.h" #include "gui/gui_util.h" #include "locale/langs.h" using glm::vec2; using glm::vec4; namespace fs = std::filesystem; using namespace gui; inline uint64_t randU64() { srand(time(NULL)); return rand() ^ (rand() << 8) ^ (rand() << 16) ^ (rand() << 24) ^ ((uint64_t)rand() << 32) ^ ((uint64_t)rand() << 40) ^ ((uint64_t)rand() << 56); } std::shared_ptr create_page( Engine* engine, std::string name, int width, float opacity, int interval) { PagesControl* menu = engine->getGUI()->getMenu(); Panel* panel = new Panel(vec2(width, 200), vec4(8.0f), interval); panel->color(vec4(0.0f, 0.0f, 0.0f, opacity)); std::shared_ptr ptr (panel); menu->add(name, ptr); return ptr; } Button* create_button(std::wstring text, glm::vec4 padding, glm::vec4 margin, gui::onaction action) { auto btn = new Button(langs::get(text, L"menu"), padding, margin); btn->listenAction(action); return btn; } void show_content_missing(Engine* engine, const Content* content, std::shared_ptr lut) { auto* gui = engine->getGUI(); auto* menu = gui->getMenu(); auto panel = create_page(engine, "missing-content", 500, 0.5f, 8); panel->add(new Label(langs::get(L"menu.missing-content"))); Panel* subpanel = new Panel(vec2(500, 100)); subpanel->color(vec4(0.0f, 0.0f, 0.0f, 0.5f)); for (auto& entry : lut->getMissingContent()) { Panel* hpanel = new Panel(vec2(500, 30)); hpanel->color(vec4(0.0f)); hpanel->orientation(Orientation::horizontal); Label* namelabel = new Label(util::str2wstr_utf8(entry.name)); namelabel->color(vec4(1.0f, 0.2f, 0.2f, 0.5f)); auto contentname = util::str2wstr_utf8(contenttype_name(entry.type)); Label* typelabel = new Label(L"["+contentname+L"]"); typelabel->color(vec4(0.5f)); hpanel->add(typelabel); hpanel->add(namelabel); subpanel->add(hpanel); } subpanel->maxLength(400); panel->add(subpanel); panel->add((new Button(langs::get(L"Back to Main Menu", L"menu"), vec4(8.0f))) ->listenAction([=](GUI*){ menu->back(); })); menu->set("missing-content"); } void show_convert_request( Engine* engine, const Content* content, std::shared_ptr lut, fs::path folder) { guiutil::confirm(engine->getGUI(), langs::get(L"world.convert-request"), [=]() { // TODO: add multithreading here auto converter = std::make_unique(folder, content, lut); while (converter->hasNext()) { converter->convertNext(); } converter->write(); }, L"", langs::get(L"Cancel")); } void create_languages_panel(Engine* engine, PagesControl* menu) { auto panel = create_page(engine, "languages", 400, 0.5f, 1); panel->scrollable(true); std::vector locales; for (auto& entry : langs::locales_info) { locales.push_back(entry.first); } std::sort(locales.begin(), locales.end()); for (std::string& name : locales) { auto& locale = langs::locales_info.at(name); std::string& fullName = locale.name; Button* button = new Button(util::str2wstr_utf8(fullName), vec4(10.f)); button->listenAction([=](GUI*) { engine->setLanguage(name); menu->back(); }); panel->add(button); } panel->add(guiutil::backButton(menu)); } void open_world(std::string name, Engine* engine) { auto paths = engine->getPaths(); auto folder = paths->getWorldsFolder()/fs::u8path(name); try { engine->loadWorldContent(folder); } catch (const contentpack_error& error) { // could not to find or read pack guiutil::alert(engine->getGUI(), langs::get(L"error.pack-not-found")+ L": "+util::str2wstr_utf8(error.getPackId())); return; } catch (const std::runtime_error& error) { guiutil::alert(engine->getGUI(), langs::get(L"Content Error", L"menu")+ L": "+util::str2wstr_utf8(error.what())); return; } paths->setWorldFolder(folder); auto& packs = engine->getContentPacks(); auto* content = engine->getContent(); auto& settings = engine->getSettings(); fs::create_directories(folder); std::shared_ptr lut (World::checkIndices(folder, content)); if (lut) { if (lut->hasMissingContent()) { show_content_missing(engine, content, lut); } else { show_convert_request(engine, content, lut, folder); } } else { try { Level* level = World::load(folder, settings, content, packs); engine->setScreen(std::make_shared(engine, level)); } catch (const world_load_error& error) { guiutil::alert(engine->getGUI(), langs::get(L"Error")+ L": "+util::str2wstr_utf8(error.what())); return; } } } Panel* create_worlds_panel(Engine* engine) { auto panel = new Panel(vec2(390, 200), vec4(5.0f)); panel->color(vec4(1.0f, 1.0f, 1.0f, 0.07f)); panel->maxLength(400); auto paths = engine->getPaths(); for (auto folder : paths->scanForWorlds()) { auto name = folder.filename().u8string(); auto namews = util::str2wstr_utf8(name); auto btn = std::make_shared(vec2(390, 46)); btn->color(vec4(1.0f, 1.0f, 1.0f, 0.1f)); btn->setHoverColor(vec4(1.0f, 1.0f, 1.0f, 0.17f)); auto label = std::make_shared