From 32af745eb9eb7acb4e9a27a929dee3c28e822c96 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 20 Apr 2025 13:09:08 +0300 Subject: [PATCH 1/7] feat: translated textbox hints support --- src/graphics/ui/gui_xml.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 151d1239..80512bc5 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -434,6 +434,11 @@ static std::shared_ptr read_text_box( auto placeholder = util::str2wstr_utf8(element.attr("placeholder", "").getText()); auto hint = util::str2wstr_utf8(element.attr("hint", "").getText()); + if (!hint.empty() && hint[0] == '@') { + hint = langs::get( + hint.substr(1), util::str2wstr_utf8(reader.getContext()) + ); + } auto text = parse_inner_text(element, reader.getContext()); auto textbox = std::make_shared( reader.getGUI(), placeholder, glm::vec4(0.0f) From 05ddffb5c9902e237c73cdea55d4ac1e303c6a8e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 20 Apr 2025 13:10:26 +0300 Subject: [PATCH 2/7] fix stack traces --- res/layouts/code_editor.xml | 6 +++--- res/layouts/code_editor.xml.lua | 13 +++++++------ res/layouts/console.xml.lua | 6 ++++++ res/modules/internal/scripts_registry.lua | 5 ++++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/res/layouts/code_editor.xml b/res/layouts/code_editor.xml index 906ff070..4336ee4f 100644 --- a/res/layouts/code_editor.xml +++ b/res/layouts/code_editor.xml @@ -1,14 +1,14 @@ - - + diff --git a/res/layouts/code_editor.xml.lua b/res/layouts/code_editor.xml.lua index e936aa71..6cb9ce68 100644 --- a/res/layouts/code_editor.xml.lua +++ b/res/layouts/code_editor.xml.lua @@ -1,5 +1,5 @@ local writeables = {} -local registry = require "core:internal/scripts_registry" +local registry local filenames local current_file = { @@ -163,7 +163,6 @@ end events.on("core:open_traceback", function(traceback_b64) local traceback = bjson.frombytes(base64.decode(traceback_b64)) - modes:set('debug') clear_traceback() @@ -257,14 +256,16 @@ function build_files_list(filenames, selected) end function on_open(mode) + registry = require "core:internal/scripts_registry" + local files_list = document.filesList - filenames = registry.filenames - table.sort(filenames) - build_files_list(filenames) - document.editorContainer:setInterval(200, refresh_file_title) clear_traceback() clear_output() + + filenames = registry.filenames + table.sort(filenames) + build_files_list(filenames) end diff --git a/res/layouts/console.xml.lua b/res/layouts/console.xml.lua index 10cad2ba..3617c08a 100644 --- a/res/layouts/console.xml.lua +++ b/res/layouts/console.xml.lua @@ -3,6 +3,12 @@ console_mode = "console" history = session.get_entry("commands_history") history_pointer = #history +events.on("core:open_traceback", function() + if modes then + modes:set('debug') + end +end) + function setup_variables() local pid = hud.get_player() local x,y,z = player.get_pos(pid) diff --git a/res/modules/internal/scripts_registry.lua b/res/modules/internal/scripts_registry.lua index de685224..8933c971 100644 --- a/res/modules/internal/scripts_registry.lua +++ b/res/modules/internal/scripts_registry.lua @@ -1,4 +1,7 @@ -local export = {} +local export = { + filenames = {}, + classification = {} +} local function collect_components(dirname, dest) if file.isdir(dirname) then From fe2a40b06e5c56f9b690c564b13d15629dedaffa Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 21 Apr 2025 21:51:55 +0300 Subject: [PATCH 3/7] reduce 'debug build' opacity --- src/frontend/menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 62cf6959..e46888df 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -26,7 +26,7 @@ void menus::create_version_label(gui::GUI& gui) { auto text = ENGINE_VERSION_STRING + " debug build"; gui.add(guiutil::create( gui, - "" )); From 3498af6be9e29196a6a2ba3fb9867cebbe21b2f6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 21 Apr 2025 21:53:27 +0300 Subject: [PATCH 4/7] cleanup --- res/layouts/pages/main.xml | 2 +- res/texts/ru_RU.txt | 2 +- src/graphics/ui/gui_xml.cpp | 8 ++++---- src/util/listutil.cpp | 18 ------------------ src/util/listutil.hpp | 2 -- 5 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 src/util/listutil.cpp diff --git a/res/layouts/pages/main.xml b/res/layouts/pages/main.xml index a3960666..b1fab2c9 100644 --- a/res/layouts/pages/main.xml +++ b/res/layouts/pages/main.xml @@ -2,6 +2,6 @@ - + diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index 65db4507..1836981d 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -24,6 +24,7 @@ Save=Сохранить Grant %{0} pack modification permission?=Выдать разрешение на модификацию пака %{0}? Error at line %{0}=Ошибка на строке %{0} Run=Запустить +Filter=Фильтр editor.info.tooltip=CTRL+S - Сохранить\nCTRL+R - Запустить\nCTRL+Z - Отменить\nCTRL+Y - Повторить devtools.traceback=Стек вызовов (от последнего) @@ -58,7 +59,6 @@ menu.Quit=Выход menu.Save and Quit to Menu=Сохранить и Выйти в Меню menu.Settings=Настройки menu.Reset settings=Сбросить настройки -menu.Contents Menu=Меню контентпаков menu.Open data folder=Открыть папку данных menu.Open content folder=Открыть папку [content] diff --git a/src/graphics/ui/gui_xml.cpp b/src/graphics/ui/gui_xml.cpp index 80512bc5..d76b76b7 100644 --- a/src/graphics/ui/gui_xml.cpp +++ b/src/graphics/ui/gui_xml.cpp @@ -619,7 +619,7 @@ static slotcallback read_slot_func( }; } -static void readSlot( +static void read_slot( InventoryView* view, UiXmlReader& reader, const xml::xmlelement& element ) { int index = element.attr("index", "0").asInt(); @@ -649,7 +649,7 @@ static void readSlot( view->add(slot); } -static void readSlotsGrid( +static void read_slots_grid( InventoryView* view, const UiXmlReader& reader, const xml::xmlelement& element @@ -726,9 +726,9 @@ static std::shared_ptr read_inventory( for (auto& sub : element.getElements()) { if (sub->getTag() == "slot") { - readSlot(view.get(), reader, *sub); + read_slot(view.get(), reader, *sub); } else if (sub->getTag() == "slots-grid") { - readSlotsGrid(view.get(), reader, *sub); + read_slots_grid(view.get(), reader, *sub); } } return view; diff --git a/src/util/listutil.cpp b/src/util/listutil.cpp deleted file mode 100644 index 97d24aa6..00000000 --- a/src/util/listutil.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "listutil.hpp" - -#include - -#include "stringutil.hpp" - -std::string util::to_string(const std::vector& vec) { - std::stringstream ss; - ss << "["; - for (size_t i = 0; i < vec.size(); i++) { - ss << util::quote(vec[1]); - if (i < vec.size() - 1) { - ss << ", "; - } - } - ss << "]"; - return ss.str(); -} diff --git a/src/util/listutil.hpp b/src/util/listutil.hpp index 9f2afe0c..609c1669 100644 --- a/src/util/listutil.hpp +++ b/src/util/listutil.hpp @@ -33,6 +33,4 @@ namespace util { a.reserve(a.size() + b.size()); a.insert(a.end(), b.begin(), b.end()); } - - std::string to_string(const std::vector& vec); } From 1bdb5c314522ccef17ded2732d0ff7eb0052ab9c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 22 Apr 2025 19:30:25 +0300 Subject: [PATCH 5/7] add dv::to_value for std::vector --- src/data/dv_util.hpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/data/dv_util.hpp b/src/data/dv_util.hpp index e016edb0..3f09ffde 100644 --- a/src/data/dv_util.hpp +++ b/src/data/dv_util.hpp @@ -6,7 +6,7 @@ namespace dv { template - inline dv::value to_value(glm::vec vec) { + dv::value to_value(const glm::vec& vec) { auto list = dv::list(); for (size_t i = 0; i < n; i++) { list.add(vec[i]); @@ -15,7 +15,7 @@ namespace dv { } template - inline dv::value to_value(glm::mat mat) { + dv::value to_value(const glm::mat& mat) { auto list = dv::list(); for (size_t i = 0; i < n; i++) { for (size_t j = 0; j < m; j++) { @@ -25,6 +25,15 @@ namespace dv { return list; } + template + dv::value to_value(const std::vector& vec) { + auto values = dv::list(); + for (const auto& value : vec) { + values.add(value); + } + return values; + } + template void get_vec(const dv::value& list, glm::vec& vec) { for (size_t i = 0; i < n; i++) { @@ -68,11 +77,24 @@ namespace dv { if (!map.has(key)) { return; } - auto& list = map[key]; + auto& arr = map[key]; for (size_t y = 0; y < n; y++) { for (size_t x = 0; x < m; x++) { - mat[y][x] = list[y * m + x].asNumber(); + mat[y][x] = arr[y * m + x].asNumber(); } } } + + template + void get(const dv::value& map, const std::string& key, std::vector& vec) { + if (!map.has(key)) { + return; + } + const auto& arr = map[key]; + for (size_t i = 0; i < arr.size(); i++) { + T value; + arr.at(i).get(value); + vec.emplace_back(std::move(value)); + } + } } From 61643746669df4eeca7c231ff55bbd6b853f7c0c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 22 Apr 2025 21:46:10 +0300 Subject: [PATCH 6/7] feat: projects & replace builtins.list with 'base_packs' project property --- res/project.toml | 3 +++ src/content/ContentControl.cpp | 8 ++++++-- src/content/ContentControl.hpp | 6 +++++- src/devtools/Project.cpp | 17 +++++++++++++++++ src/devtools/Project.hpp | 15 +++++++++++++++ src/engine/Engine.cpp | 28 +++++++++++++++++++++++----- src/engine/Engine.hpp | 4 ++++ src/io/engine_paths.cpp | 6 ++++++ src/io/engine_paths.hpp | 3 +++ src/util/command_line.cpp | 13 +++++++------ 10 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 res/project.toml create mode 100644 src/devtools/Project.cpp create mode 100644 src/devtools/Project.hpp diff --git a/res/project.toml b/res/project.toml new file mode 100644 index 00000000..c30e72dd --- /dev/null +++ b/res/project.toml @@ -0,0 +1,3 @@ +# default project +name = "default" +base_packs = ["base"] diff --git a/src/content/ContentControl.cpp b/src/content/ContentControl.cpp index 37d68294..c0ed582d 100644 --- a/src/content/ContentControl.cpp +++ b/src/content/ContentControl.cpp @@ -8,6 +8,7 @@ #include "ContentLoader.hpp" #include "PacksManager.hpp" #include "objects/rigging.hpp" +#include "devtools/Project.hpp" #include "logic/scripting/scripting.hpp" #include "core_defs.hpp" @@ -16,12 +17,15 @@ static void load_configs(Input& input, const io::path& root) { } ContentControl::ContentControl( - EnginePaths& paths, Input& input, std::function postContent + const Project& project, + EnginePaths& paths, + Input& input, + std::function postContent ) : paths(paths), input(input), postContent(std::move(postContent)), - basePacks(io::read_list("res:config/builtins.list")), + basePacks(project.basePacks), manager(std::make_unique()) { manager->setSources({ "world:content", diff --git a/src/content/ContentControl.hpp b/src/content/ContentControl.hpp index db08fa5a..4c52ec10 100644 --- a/src/content/ContentControl.hpp +++ b/src/content/ContentControl.hpp @@ -11,6 +11,7 @@ class Content; class PacksManager; class EnginePaths; class Input; +struct Project; namespace io { class path; @@ -19,7 +20,10 @@ namespace io { class ContentControl { public: ContentControl( - EnginePaths& paths, Input& input, std::function postContent + const Project& project, + EnginePaths& paths, + Input& input, + std::function postContent ); ~ContentControl(); diff --git a/src/devtools/Project.cpp b/src/devtools/Project.cpp new file mode 100644 index 00000000..c1d382ee --- /dev/null +++ b/src/devtools/Project.cpp @@ -0,0 +1,17 @@ +#include "Project.hpp" + +#include "data/dv_util.hpp" + +dv::value Project::serialize() const { + return dv::object({ + {"name", name}, + {"title", title}, + {"base_packs", dv::to_value(basePacks)}, + }); +} + +void Project::deserialize(const dv::value& src) { + src.at("name").get(name); + src.at("title").get(title); + dv::get(src, "base_packs", basePacks); +} diff --git a/src/devtools/Project.hpp b/src/devtools/Project.hpp new file mode 100644 index 00000000..857b58f1 --- /dev/null +++ b/src/devtools/Project.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "interfaces/Serializable.hpp" + +struct Project : Serializable { + std::string name; + std::string title; + std::vector basePacks; + + dv::value serialize() const override; + void deserialize(const dv::value& src) override; +}; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index fb53978a..63db4490 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -13,6 +13,7 @@ #include "coders/toml.hpp" #include "coders/commons.hpp" #include "devtools/Editor.hpp" +#include "devtools/Project.hpp" #include "content/ContentControl.hpp" #include "core_defs.hpp" #include "io/io.hpp" @@ -74,17 +75,24 @@ Engine& Engine::getInstance() { void Engine::initialize(CoreParameters coreParameters) { params = std::move(coreParameters); settingsHandler = std::make_unique(settings); - editor = std::make_unique(*this); - cmd = std::make_unique(); - network = network::Network::create(settings.network); logger.info() << "engine version: " << ENGINE_VERSION_STRING; if (params.headless) { logger.info() << "headless mode is enabled"; } + if (params.projectFolder.empty()) { + params.projectFolder = params.resFolder; + } paths.setResourcesFolder(params.resFolder); paths.setUserFilesFolder(params.userFolder); + paths.setProjectFolder(params.projectFolder); paths.prepare(); + loadProject(); + + editor = std::make_unique(*this); + cmd = std::make_unique(); + network = network::Network::create(settings.network); + if (!params.scriptFile.empty()) { paths.setScriptFolder(params.scriptFile.parent_path()); } @@ -92,9 +100,12 @@ void Engine::initialize(CoreParameters coreParameters) { controller = std::make_unique(*this); if (!params.headless) { - std::string title = "VoxelCore v" + + std::string title = project->title; + if (title.empty()) { + title = "VoxelCore v" + std::to_string(ENGINE_VERSION_MAJOR) + "." + std::to_string(ENGINE_VERSION_MINOR); + } if (ENGINE_DEBUG_BUILD) { title += " [debug]"; } @@ -135,7 +146,7 @@ void Engine::initialize(CoreParameters coreParameters) { langs::locale_by_envlocale(platform::detect_locale()) ); } - content = std::make_unique(paths, *input, [this]() { + content = std::make_unique(*project, paths, *input, [this]() { editor->loadTools(); langs::setup(langs::get_current(), paths.resPaths.collectRoots()); if (!isHeadless()) { @@ -325,6 +336,13 @@ void Engine::loadAssets() { gui->onAssetsLoad(assets.get()); } +void Engine::loadProject() { + io::path projectFile = "project:project.toml"; + project = std::make_unique(); + project->deserialize(io::read_object(projectFile)); + logger.info() << "loaded project " << util::quote(project->name); +} + void Engine::setScreen(std::shared_ptr screen) { // reset audio channels (stop all sources) audio::reset_channel(audio::get_channel_index("regular")); diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 5e854ae3..8f8683da 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -20,6 +20,7 @@ class Screen; class ContentControl; class EngineController; class Input; +struct Project; namespace gui { class GUI; @@ -48,6 +49,7 @@ struct CoreParameters { std::filesystem::path resFolder = "res"; std::filesystem::path userFolder = "."; std::filesystem::path scriptFile; + std::filesystem::path projectFolder; }; using OnWorldOpen = std::function, int64_t)>; @@ -57,6 +59,7 @@ class Engine : public util::ObjectsKeeper { EngineSettings settings; EnginePaths paths; + std::unique_ptr project; std::unique_ptr settingsHandler; std::unique_ptr assets; std::shared_ptr screen; @@ -78,6 +81,7 @@ class Engine : public util::ObjectsKeeper { void saveSettings(); void updateHotkeys(); void loadAssets(); + void loadProject(); public: Engine(); ~Engine(); diff --git a/src/io/engine_paths.cpp b/src/io/engine_paths.cpp index bc98e8a9..cb2d11e9 100644 --- a/src/io/engine_paths.cpp +++ b/src/io/engine_paths.cpp @@ -46,6 +46,7 @@ void EnginePaths::prepare() { } logger.info() << "resources folder: " << fs::canonical(resourcesFolder).u8string(); logger.info() << "user files folder: " << fs::canonical(userFilesFolder).u8string(); + logger.info() << "project folder: " << fs::canonical(projectFolder).u8string(); if (!io::is_directory(CONTENT_FOLDER)) { io::create_directories(CONTENT_FOLDER); @@ -142,6 +143,11 @@ void EnginePaths::setScriptFolder(std::filesystem::path folder) { this->scriptFolder = std::move(folder); } +void EnginePaths::setProjectFolder(std::filesystem::path folder) { + io::set_device("project", std::make_shared(folder)); + this->projectFolder = std::move(folder); +} + void EnginePaths::setCurrentWorldFolder(io::path folder) { this->currentWorldFolder = std::move(folder); io::create_subdevice("world", "user", currentWorldFolder); diff --git a/src/io/engine_paths.hpp b/src/io/engine_paths.hpp index 1b6739b8..8b9b7f8e 100644 --- a/src/io/engine_paths.hpp +++ b/src/io/engine_paths.hpp @@ -56,6 +56,8 @@ public: void setScriptFolder(std::filesystem::path folder); + void setProjectFolder(std::filesystem::path folder); + io::path getWorldFolderByName(const std::string& name); io::path getWorldsFolder() const; @@ -80,6 +82,7 @@ public: private: std::filesystem::path userFilesFolder {"."}; std::filesystem::path resourcesFolder {"res"}; + std::filesystem::path projectFolder = resourcesFolder; io::path currentWorldFolder; std::optional scriptFolder; std::vector entryPoints; diff --git a/src/util/command_line.cpp b/src/util/command_line.cpp index ee0ace92..b6ef091b 100644 --- a/src/util/command_line.cpp +++ b/src/util/command_line.cpp @@ -12,18 +12,19 @@ static bool perform_keyword( util::ArgsReader& reader, const std::string& keyword, CoreParameters& params ) { if (keyword == "--res") { - auto token = reader.next(); - params.resFolder = token; + params.resFolder = reader.next(); } else if (keyword == "--dir") { - auto token = reader.next(); - params.userFolder = token; + params.userFolder = reader.next(); + } else if (keyword == "--project") { + params.projectFolder = reader.next(); } else if (keyword == "--help" || keyword == "-h") { std::cout << "VoxelCore v" << ENGINE_VERSION_STRING << "\n\n"; std::cout << "command-line arguments:\n"; - std::cout << " --help - show help\n"; - std::cout << " --version - print engine version\n"; + std::cout << " --help - display this help\n"; + std::cout << " --version - display engine version\n"; std::cout << " --res - set resources directory\n"; std::cout << " --dir - set userfiles directory\n"; + std::cout << " --project - set project directory\n"; std::cout << " --headless - run in headless mode\n"; std::cout << " --test - test script file\n"; std::cout << " --script - main script file\n"; From 41754582cda1f0383b8ea95d391a6eed59f79f91 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 22 Apr 2025 21:46:51 +0300 Subject: [PATCH 7/7] remove res/config/builtins.list --- res/config/builtins.list | 1 - 1 file changed, 1 deletion(-) delete mode 100644 res/config/builtins.list diff --git a/res/config/builtins.list b/res/config/builtins.list deleted file mode 100644 index df967b96..00000000 --- a/res/config/builtins.list +++ /dev/null @@ -1 +0,0 @@ -base