From 4bcb8e44903c1595a00002787c9cf118f8c0830d Mon Sep 17 00:00:00 2001 From: Anthony Date: Mon, 15 Jan 2024 11:56:07 +0100 Subject: [PATCH] (WIP) Library Manager --- .gitignore | 2 + .vscode/launch.json | 26 +++++ software/common/tlv.h | 70 ++++++++++++ software/library/library_manager.cpp | 106 ++++++++++++++++++ software/library/library_manager.h | 30 +++++ software/library/story_project.cpp | 94 ++++------------ software/library/story_project.h | 12 +- story-editor/CMakeLists.txt | 15 ++- story-editor/src/i_story_manager.h | 2 +- story-editor/src/library_window.cpp | 159 +++++++++++++++++++++++++++ story-editor/src/library_window.h | 20 ++++ story-editor/src/main_window.cpp | 64 ++++++----- story-editor/src/main_window.h | 8 +- 13 files changed, 505 insertions(+), 103 deletions(-) create mode 100644 software/common/tlv.h create mode 100644 software/library/library_manager.cpp create mode 100644 software/library/library_manager.h create mode 100644 story-editor/src/library_window.cpp create mode 100644 story-editor/src/library_window.h diff --git a/.gitignore b/.gitignore index 0346237..f65b305 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,5 @@ build-story-editor-Desktop-Debug/ docs/.vitepress/cache/ docs/.vitepress/dist/ + +software/.cache/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 7936ddd..dfe57fc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,6 +23,32 @@ } ] + }, + { + "name": "Black Magic Probe", + "cwd": "${workspaceRoot}", + "executable": "${workspaceRoot}/software/build/RaspberryPico/open-story-teller.elf", + "request": "launch", + "type": "cortex-debug", + "showDevDebugOutput": "raw", + "BMPGDBSerialPort": "/dev/ttyACM0", + "servertype": "bmp", + "interface": "swd", + "gdbPath": "gdb-multiarch", + "svdFile": "${workspaceRoot}/software/platform/raspberry-pico-w/rp2040.svd", + // "device": "STM32L431VC", + "runToMain": true, + "preRestartCommands": [ + "cd ${workspaceRoot}/software/build/RaspberryPico", + "file open-story-teller.elf", + // "target extended-remote /dev/ttyACM0", + "set mem inaccessible-by-default off", + "enable breakpoint", + "monitor reset", + "monitor swdp_scan", + "attach 1", + "load" + ] } ] } \ No newline at end of file diff --git a/software/common/tlv.h b/software/common/tlv.h new file mode 100644 index 0000000..14b4659 --- /dev/null +++ b/software/common/tlv.h @@ -0,0 +1,70 @@ +#ifndef TLV_H +#define TLV_H + +#include + +#define TLV_ARRAY_TYPE 0xAB +#define TLV_OBJECT_TYPE 0xE7 +#define TLV_STRING_TYPE 0x3D +#define TLV_INTEGER 0x77 +#define TLV_REAL 0xB8 + +#include +#include + +class Tlv +{ +public: + explicit Tlv(const std::string &filename) + { + m_file = std::ofstream(filename, std::ios::out | std::ios::binary); + } + + ~Tlv() { + m_file.close(); + } + + void add_array(uint16_t size) + { + m_file.write(reinterpret_cast(&m_objectType), sizeof(m_objectType)); + m_file.write(reinterpret_cast(&size), sizeof(size)); + } + + void add_string(const char *s, uint16_t size) + { + m_file.write(reinterpret_cast(&m_stringType), sizeof(m_stringType)); + + m_file.write(s, size); + } + + void add_integer(uint32_t value) + { + static const uint16_t size = 4; + m_file.write(reinterpret_cast(&m_integerType), sizeof(m_integerType)); + m_file.write(reinterpret_cast(&size), sizeof(size)); + m_file.write(reinterpret_cast(&value), sizeof(value)); + } + + void add_string(const std::string &s) + { + add_string(s.c_str(), s.size()); + } + + void add_object(uint16_t entries) + { + m_file.write(reinterpret_cast(&m_arrayType), sizeof(m_arrayType)); + m_file.write(reinterpret_cast(&entries), sizeof(entries)); + } + +private: + std::ofstream m_file; + + uint8_t m_arrayType = TLV_ARRAY_TYPE; + uint8_t m_objectType = TLV_OBJECT_TYPE; + uint8_t m_stringType = TLV_STRING_TYPE; + uint8_t m_integerType = TLV_INTEGER; + +}; + + +#endif // TLV_H diff --git a/software/library/library_manager.cpp b/software/library/library_manager.cpp new file mode 100644 index 0000000..235b72f --- /dev/null +++ b/software/library/library_manager.cpp @@ -0,0 +1,106 @@ +#include "library_manager.h" +#include "tlv.h" +#include +#include +#include "json.hpp" +#include "story_project.h" + +LibraryManager::LibraryManager() {} + +void LibraryManager::Initialize(const std::string &library_path) +{ + m_library_path = library_path; + Scan(); +} + +bool IsUUIDV4(const std::string& input) { + // Le motif regex pour un UUID V4 + std::regex uuidRegex("^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$",std::regex_constants::icase); + + // Vérifier si la chaîne correspond au motif UUID V4 + return std::regex_match(input, uuidRegex); +} + +void LibraryManager::Scan() +{ + std::filesystem::path directoryPath(m_library_path); + if (std::filesystem::exists(directoryPath) && std::filesystem::is_directory(directoryPath)) + { + m_projectsList.clear(); + for (const auto& entry : std::filesystem::directory_iterator(directoryPath)) + { + if (std::filesystem::is_directory(entry.path())) + { + // Si c'est un sous-répertoire, récursivement scanner le contenu + std::string uuid = entry.path().filename(); + if (IsUUIDV4(uuid)) + { + std::cout << "Found story directory" << std::endl; + // Look for a story.json file in this directory + auto p = entry.path() / "project.json"; + if (std::filesystem::exists(p)) + { + // okay, open it + auto proj = std::make_shared(); + try { + std::ifstream f(p); + nlohmann::json j = nlohmann::json::parse(f); + + if (proj->ParseStoryInformation(j)) + { + // Valid project file, add it to the list + m_projectsList.push_back(proj); + } + } + catch(std::exception &e) + { + std::cout << e.what() << std::endl; + } + } + } + } + } + } +} + +void LibraryManager::Save() +{ + auto p = std::filesystem::path(m_library_path) / "index.ost"; + Tlv tlv(p.string()); + + tlv.add_object(1); + tlv.add_string(GetVersion()); + + tlv.add_array(m_projectsList.size()); + for (auto &p : m_projectsList) + { + tlv.add_object(6); + tlv.add_string(p->GetUuid()); + tlv.add_string(p->GetTitleImage()); + tlv.add_string(p->GetTitleSound()); + tlv.add_string(p->GetName()); + tlv.add_string(p->GetDescription()); + tlv.add_integer(p->GetVersion()); + } + + /* + + + // Title image + std::string image = RemoveFileExtension(m_titleImage) + ".qoi"; + tlv.add_string(image.c_str(), image.size()); + + std::string sound = RemoveFileExtension(m_titleSound) + ".wav"; + tlv.add_string(sound.c_str(), sound.size()); // title sound +*/ +} + +bool LibraryManager::IsInitialized() const +{ + return m_library_path.size() > 0; +} + +std::string LibraryManager::GetVersion() +{ + return std::to_string(VERSION_MAJOR) + '.' + std::to_string(VERSION_MINOR) + '.' + std::to_string(VERSION_PATCH); +} diff --git a/software/library/library_manager.h b/software/library/library_manager.h new file mode 100644 index 0000000..4d72f84 --- /dev/null +++ b/software/library/library_manager.h @@ -0,0 +1,30 @@ +#ifndef LIBRARYMANAGER_H +#define LIBRARYMANAGER_H + +#include +#include +#include +#include "story_project.h" + +class LibraryManager +{ +public: + LibraryManager(); + + void Initialize(const std::string &library_path); + bool IsInitialized() const; + + std::string LibraryPath() const { return m_library_path; } + static std::string GetVersion(); + + std::vector>::const_iterator begin() const { return m_projectsList.begin(); } + std::vector>::const_iterator end() const { return m_projectsList.end(); } + + void Save(); + void Scan(); +private: + std::string m_library_path; + std::vector> m_projectsList; +}; + +#endif // LIBRARYMANAGER_H diff --git a/software/library/story_project.cpp b/software/library/story_project.cpp index 09756e6..3b34fde 100644 --- a/software/library/story_project.cpp +++ b/software/library/story_project.cpp @@ -24,74 +24,12 @@ void StoryProject::New(const std::string &uuid, const std::string &file_path) Initialize(file_path); } -#define TLV_ARRAY_TYPE 0xAB -#define TLV_OBJECT_TYPE 0xE7 -#define TLV_STRING_TYPE 0x3D -#define TLV_INTEGER 0x77 -#define TLV_REAL 0xB8 - -class Tlv -{ -public: - explicit Tlv(const std::string &filename) - { - m_file = std::ofstream(filename, std::ios::out | std::ios::binary); - } - - ~Tlv() { - m_file.close(); - } - - void add_array(uint16_t size) - { - m_file.write(reinterpret_cast(&m_objectType), sizeof(m_objectType)); - m_file.write(reinterpret_cast(&size), sizeof(size)); - } - - void add_string(const char *s, uint16_t size) - { - m_file.write(reinterpret_cast(&m_stringType), sizeof(m_stringType)); - m_file.write(reinterpret_cast(&size), sizeof(size)); - m_file.write(s, size); - } - - void add_object(uint16_t entries) - { - m_file.write(reinterpret_cast(&m_arrayType), sizeof(m_arrayType)); - m_file.write(reinterpret_cast(&entries), sizeof(entries)); - } - -private: - std::ofstream m_file; - - uint8_t m_arrayType = TLV_ARRAY_TYPE; - uint8_t m_objectType = TLV_OBJECT_TYPE; - uint8_t m_stringType = TLV_STRING_TYPE; - -}; - - void StoryProject::SaveStory(const std::vector &m_program) { std::ofstream o(m_working_dir / "story.c32", std::ios::out | std::ios::binary); o.write(reinterpret_cast(m_program.data()), m_program.size()); o.close(); - - auto p = m_working_dir / "index.ost"; - Tlv tlv(p.string()); - - tlv.add_array(1); - - tlv.add_object(3); - tlv.add_string(m_uuid.c_str(), m_uuid.size()); // uuid - - // Title image - std::string image = RemoveFileExtension(m_titleImage) + ".qoi"; - tlv.add_string(image.c_str(), image.size()); - - std::string sound = RemoveFileExtension(m_titleSound) + ".wav"; - tlv.add_string(sound.c_str(), sound.size()); // title sound } void StoryProject::Initialize(const std::string &file_path) @@ -100,7 +38,7 @@ void StoryProject::Initialize(const std::string &file_path) std::filesystem::path p(file_path); m_working_dir= p.parent_path().generic_string(); - // Frist try to create the working directory + // First try to create the working directory if (!std::filesystem::is_directory(m_working_dir)) { std::filesystem::create_directories(m_working_dir); @@ -112,6 +50,27 @@ void StoryProject::Initialize(const std::string &file_path) m_initialized = true; } + +bool StoryProject::ParseStoryInformation(nlohmann::json &j) +{ + bool success = false; + + if (j.contains("project")) + { + nlohmann::json projectData = j["project"]; + + m_name = projectData["name"].get(); + m_uuid = projectData["uuid"].get(); + m_titleImage = projectData.value("title_image", ""); + m_titleSound = projectData.value("title_sound", ""); + + success = true; + } + + return success; +} + + bool StoryProject::Load(const std::string &file_path, nlohmann::json &model, ResourceManager &manager) { @@ -130,15 +89,8 @@ bool StoryProject::Load(const std::string &file_path, nlohmann::json &model, Res // m_nodes.clear(); manager.Clear(); - if (j.contains("project")) + if (ParseStoryInformation(j)) { - nlohmann::json projectData = j["project"]; - - m_name = projectData["name"].get(); - m_uuid = projectData["uuid"].get(); - m_titleImage = projectData.value("title_image", ""); - m_titleSound = projectData.value("title_sound", ""); - if (j.contains("resources")) { nlohmann::json resourcesData = j["resources"]; diff --git a/software/library/story_project.h b/software/library/story_project.h index 2e1b6dd..57aba21 100644 --- a/software/library/story_project.h +++ b/software/library/story_project.h @@ -41,6 +41,7 @@ struct StoryNode // "sound": 0 }; + struct StoryProject { @@ -74,6 +75,8 @@ public: std::string GetWorkingDir() const; std::string GetName() const { return m_name; } std::string GetUuid() const { return m_uuid; } + std::string GetDescription() const { return m_description; } + int GetVersion() const { return m_version; } std::string BuildFullAssetsPath(const std::string &fileName) const; @@ -101,17 +104,20 @@ public: void SaveStory(const std::vector &m_program); + bool ParseStoryInformation(nlohmann::json &j); private: // Project properties and location std::string m_name; /// human readable name std::string m_uuid; + std::string m_titleImage; + std::string m_titleSound; + std::string m_description; + int m_version; + std::filesystem::path m_assetsPath; bool m_initialized{false}; - std::string m_titleImage; - std::string m_titleSound; - std::filesystem::path m_working_dir; /// Temporary folder based on the uuid, where the archive is unzipped std::string m_story_file_path; /// JSON project file diff --git a/story-editor/CMakeLists.txt b/story-editor/CMakeLists.txt index c5f7329..b319a53 100644 --- a/story-editor/CMakeLists.txt +++ b/story-editor/CMakeLists.txt @@ -101,6 +101,9 @@ set(SRCS src/node_editor_window.cpp src/node_editor_window.h + src/library_window.cpp + src/library_window.h + src/media_node.h src/media_node.cpp @@ -148,8 +151,11 @@ set(SRCS ../software/chip32/chip32_assembler.cpp ../software/chip32/chip32_vm.c - ../software/library/audio_player.cpp - ../software/library/audio_player.h + + ../software/common/audio_player.cpp + ../software/common/audio_player.h + ../software/common/tlv.h + ../software/library/miniaudio.h ../software/library/uuid.h ../software/library/resource.h @@ -157,6 +163,8 @@ set(SRCS ../software/library/story_project.cpp ../software/library/story_project.h ../software/library/thread_safe_queue.h + ../software/library/library_manager.h + ../software/library/library_manager.cpp ) if(WIN32) @@ -174,6 +182,8 @@ if(WIN32) else() add_executable(${STORY_EDITOR_PROJECT} ${SRCS} + + ) endif() @@ -187,6 +197,7 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC ../software/library/ ../software/chip32/ + ../software/common ) add_definitions(-DIMGUI_USE_WCHAR32 -DVERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DVERSION_MINOR=${PROJECT_VERSION_MINOR} -DVERSION_PATCH=${PROJECT_VERSION_PATCH}) diff --git a/story-editor/src/i_story_manager.h b/story-editor/src/i_story_manager.h index d198e1a..3e69960 100644 --- a/story-editor/src/i_story_manager.h +++ b/story-editor/src/i_story_manager.h @@ -3,7 +3,6 @@ #include -#include #include #include @@ -15,6 +14,7 @@ class IStoryManager public: virtual ~IStoryManager() {} + virtual void OpenProject(const std::string &filename) = 0; virtual void Log(const std::string &txt, bool critical = false) = 0; virtual void PlaySoundFile(const std::string &fileName) = 0; virtual std::string BuildFullAssetsPath(const std::string &fileName) const = 0; diff --git a/story-editor/src/library_window.cpp b/story-editor/src/library_window.cpp new file mode 100644 index 0000000..e92622c --- /dev/null +++ b/story-editor/src/library_window.cpp @@ -0,0 +1,159 @@ +#include "library_window.h" +#include "gui.h" +#include "ImGuiFileDialog.h" +#include + +LibraryWindow::LibraryWindow(IStoryManager &project, LibraryManager &library) + : WindowBase("Library Manager") + , m_storyManager(project) + , m_libraryManager(library) +{ + +} + +void LibraryWindow::Initialize() +{ + + + +} + +static bool canValidateDialog = false; +inline void InfosPane(const char *vFilter, IGFDUserDatas vUserDatas, bool *vCantContinue) // if vCantContinue is false, the user cant validate the dialog +{ + ImGui::TextColored(ImVec4(0, 1, 1, 1), "Infos Pane"); + ImGui::Text("Selected Filter : %s", vFilter); + ImGui::Checkbox("if not checked you cant validate the dialog", &canValidateDialog); + if (vCantContinue) + *vCantContinue = canValidateDialog; +} + + +void LibraryWindow::Draw() +{ +// if (!IsVisible()) +// { +// return; +// } + + + WindowBase::BeginDraw(); + ImGui::SetWindowSize(ImVec2(626, 744), ImGuiCond_FirstUseEver); + + if (ImGui::Button("Select directory")) + { + ImGuiFileDialog::Instance()->OpenDialog("ChooseLibraryDirDialog", "Choose a library directory", nullptr, ".", 1, nullptr, ImGuiFileDialogFlags_Modal); + } + + ImGui::SameLine(); + + if (!m_libraryManager.IsInitialized()) + { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255,0,0,255)); + ImGui::Text("No any library directory set. Please select one where stories will be located."); + ImGui::PopStyleColor(); + } + else + { + ImGui::Text("Library path: %s", m_libraryManager.LibraryPath().c_str()); + } + + if (ImGui::Button("Scan library")) + { + m_libraryManager.Scan(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Import story")) + { + ImGuiFileDialog::Instance()->OpenDialogWithPane("ImportStoryDlgKey", "Import story", "", "", InfosPane); + } + + if (m_libraryManager.IsInitialized()) + { + static ImGuiTableFlags tableFlags = + ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable + | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti + | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody + | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY + | ImGuiTableFlags_SizingFixedFit; + + if (ImGui::BeginTable("library_table", 2, tableFlags)) + { + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); + + ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed); + + ImGui::TableHeadersRow(); + + for (auto &p : m_libraryManager) + { + ImGui::TableNextColumn(); + ImGui::Text("%s", p->GetName().c_str()); + + ImGui::TableNextColumn(); + + if (ImGui::SmallButton("Load")) + { + auto filename = std::filesystem::path(m_libraryManager.LibraryPath()) / p->GetUuid() / std::filesystem::path("project.json"); + m_storyManager.OpenProject(filename); + } + + ImGui::SameLine(); + + if (ImGui::SmallButton("Remove")) + { + + } + } + + ImGui::EndTable(); + } + } + + + // ---------------- ADD EXISTING STORY TELLER STORY + if (ImGuiFileDialog::Instance()->Display("ImportStoryDlgKey")) + { + if (ImGuiFileDialog::Instance()->IsOk()) + { + std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); + std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath(); + std::string filter = ImGuiFileDialog::Instance()->GetCurrentFilter(); + // here convert from string because a string was passed as a userDatas, but it can be what you want + // std::string userDatas; + // if (ImGuiFileDialog::Instance()->GetUserDatas()) + // userDatas = std::string((const char*)ImGuiFileDialog::Instance()->GetUserDatas()); + // auto selection = ImGuiFileDialog::Instance()->GetSelection(); // multiselection + + // action + } + // close + ImGuiFileDialog::Instance()->Close(); + } + + + // ---------------- CHOOSE LIBRARY DIR + if (ImGuiFileDialog::Instance()->Display("ChooseLibraryDirDialog")) + { + // action if OK + if (ImGuiFileDialog::Instance()->IsOk()) + { + std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); + std::string projdir = ImGuiFileDialog::Instance()->GetCurrentPath(); + + if (std::filesystem::is_directory(projdir)) + { + m_libraryManager.Initialize(projdir); + } + } + + // close + ImGuiFileDialog::Instance()->Close(); + } + + + WindowBase::EndDraw(); +} + diff --git a/story-editor/src/library_window.h b/story-editor/src/library_window.h new file mode 100644 index 0000000..0101a3f --- /dev/null +++ b/story-editor/src/library_window.h @@ -0,0 +1,20 @@ +#pragma once + +#include "window_base.h" +#include "library_manager.h" +#include "i_story_manager.h" + +class LibraryWindow : public WindowBase +{ +public: + LibraryWindow(IStoryManager &project, LibraryManager &library); + + void Initialize(); + virtual void Draw() override; + +private: + IStoryManager &m_storyManager; + LibraryManager &m_libraryManager; + +}; + diff --git a/story-editor/src/main_window.cpp b/story-editor/src/main_window.cpp index 7b06634..1bc6066 100644 --- a/story-editor/src/main_window.cpp +++ b/story-editor/src/main_window.cpp @@ -1,6 +1,5 @@ #include "main_window.h" #include -#include #include #include "platform_folders.h" #include "uuid.h" @@ -19,17 +18,14 @@ #include "IconsMaterialDesignIcons.h" #include "ImGuiFileDialog.h" -static std::string gVersion; - MainWindow::MainWindow() : m_emulatorWindow(*this) , m_resourcesWindow(*this) , m_nodeEditorWindow(*this) + , m_libraryWindow(*this, m_libraryManager) , m_player(*this) + { - - gVersion = std::to_string(VERSION_MAJOR) + '.' + std::to_string(VERSION_MINOR) + '.' + std::to_string(VERSION_PATCH); - // VM Initialize m_chip32_ctx.stack_size = 512; @@ -51,7 +47,7 @@ MainWindow::MainWindow() MainWindow::~MainWindow() { - + SaveParams(); } @@ -270,7 +266,7 @@ void MainWindow::DrawMainMenuBar() { showNewProject = true; } - +/* if (ImGui::MenuItem("Open project")) { showOpenProject = true; @@ -280,16 +276,21 @@ void MainWindow::DrawMainMenuBar() { for (auto &e : m_recentProjects) { - if (ImGui::MenuItem(e.c_str())) + if (e.size() > 0) { - OpenProject(e); + if (ImGui::MenuItem(e.c_str())) + { + OpenProject(e); + } } } ImGui::EndMenu(); } +*/ - if (!m_story.IsInitialized()) + bool init = m_story.IsInitialized(); // local copy because CloseProject() changes the status between BeginDisabled/EndDisabled + if (!init) ImGui::BeginDisabled(); ImGui::Separator(); @@ -308,7 +309,7 @@ void MainWindow::DrawMainMenuBar() showParameters = true; } - if (!m_story.IsInitialized()) + if (!init) ImGui::EndDisabled(); ImGui::EndMenu(); @@ -359,7 +360,7 @@ void MainWindow::DrawMainMenuBar() if (ImGui::BeginPopupModal("AboutPopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::Text("Story Editor - v%s", gVersion.c_str()); + ImGui::Text("Story Editor - v%s", LibraryManager::GetVersion().c_str()); ImGui::Text("http://www.openstoryteller.org"); ImGui::Separator(); ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Platform"); @@ -505,7 +506,6 @@ void MainWindow::ProjectPropertiesPopup() ImGuiFileDialog::Instance()->OpenDialog("ChooseDirDialog", "Choose File", nullptr, ".", 1, nullptr, ImGuiFileDialogFlags_Modal); } - // display if (ImGuiFileDialog::Instance()->Display("ChooseDirDialog")) { @@ -681,8 +681,7 @@ void MainWindow::SaveProject() void MainWindow::OpenProject(const std::string &filename) { - m_story.Initialize(filename); - + CloseProject(); nlohmann::json model; if (m_story.Load(filename, model, m_resources)) @@ -720,7 +719,7 @@ void MainWindow::OpenProject(const std::string &filename) void MainWindow::RefreshProjectInformation() { - std::string fullText = "Story Editor " + gVersion + " - " + m_story.GetProjectFilePath(); + std::string fullText = "Story Editor " + LibraryManager::GetVersion() + " - " + m_story.GetProjectFilePath(); m_gui.SetWindowTitle(fullText); } @@ -738,7 +737,6 @@ void MainWindow::CloseProject() m_nodeEditorWindow.Disable(); m_emulatorWindow.Disable(); - m_consoleWindow.Disable(); m_editorWindow.Disable(); m_resourcesWindow.Disable(); m_PropertiesWindow.Disable(); @@ -768,14 +766,20 @@ void MainWindow::Loop() // ------------ Draw all windows - m_consoleWindow.Draw(); - m_emulatorWindow.Draw(); - m_editorWindow.Draw(); - m_resourcesWindow.Draw(); - m_nodeEditorWindow.Draw(); + m_libraryWindow.Draw(); - m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode()); - m_PropertiesWindow.Draw(); + if (m_libraryManager.IsInitialized()) + { + m_consoleWindow.Draw(); + m_emulatorWindow.Draw(); + m_editorWindow.Draw(); + m_resourcesWindow.Draw(); + m_nodeEditorWindow.Draw(); + + + m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode()); + m_PropertiesWindow.Draw(); + } NewProjectPopup(); OpenProjectDialog(); @@ -798,6 +802,7 @@ void MainWindow::Loop() m_gui.Destroy(); } + void MainWindow::Log(const std::string &txt, bool critical) { m_consoleWindow.AddLog(txt, critical ? 1 : 0); @@ -1007,6 +1012,7 @@ void MainWindow::SaveParams() nlohmann::json recents(m_recentProjects); j["recents"] = recents; + j["library_path"] = m_libraryManager.LibraryPath(); std::string loc = pf::getConfigHome() + "/ost_settings.json"; std::ofstream o(loc); @@ -1032,6 +1038,14 @@ void MainWindow::LoadParams() m_recentProjects.push_back(element); } } + + nlohmann::json library_path = j["library_path"]; + + if (std::filesystem::exists(library_path)) + { + m_libraryManager.Initialize(library_path); + } + } catch(std::exception &e) { diff --git a/story-editor/src/main_window.h b/story-editor/src/main_window.h index 8bee88e..882f1f8 100644 --- a/story-editor/src/main_window.h +++ b/story-editor/src/main_window.h @@ -19,6 +19,8 @@ #include "i_story_manager.h" #include "thread_safe_queue.h" #include "audio_player.h" +#include "library_manager.h" +#include "library_window.h" struct DebugContext { @@ -110,6 +112,8 @@ private: ResourceManager m_resources; + LibraryManager m_libraryManager; + Gui m_gui; EmulatorWindow m_emulatorWindow; ConsoleWindow m_consoleWindow; @@ -121,6 +125,8 @@ private: PropertiesWindow m_PropertiesWindow; + LibraryWindow m_libraryWindow; + AudioPlayer m_player; struct VmEvent @@ -132,6 +138,7 @@ private: // From IStoryManager (proxy to StoryProject class) + virtual void OpenProject(const std::string &filename) override; virtual void Log(const std::string &txt, bool critical = false) override; virtual void PlaySoundFile(const std::string &fileName) override;; virtual std::string BuildFullAssetsPath(const std::string &fileName) const override; @@ -162,7 +169,6 @@ private: void NewProjectPopup(); void SaveProject(); - void OpenProject(const std::string &filename); void CloseProject(); void OpenProjectDialog(); void DrawStatusBar();