(WIP) Library Manager

This commit is contained in:
Anthony 2024-01-15 11:56:07 +01:00
parent ce26db3aaa
commit 4bcb8e4490
13 changed files with 505 additions and 103 deletions

2
.gitignore vendored
View file

@ -67,3 +67,5 @@ build-story-editor-Desktop-Debug/
docs/.vitepress/cache/ docs/.vitepress/cache/
docs/.vitepress/dist/ docs/.vitepress/dist/
software/.cache/

26
.vscode/launch.json vendored
View file

@ -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"
]
} }
] ]
} }

70
software/common/tlv.h Normal file
View file

@ -0,0 +1,70 @@
#ifndef TLV_H
#define TLV_H
#include <stdint.h>
#define TLV_ARRAY_TYPE 0xAB
#define TLV_OBJECT_TYPE 0xE7
#define TLV_STRING_TYPE 0x3D
#define TLV_INTEGER 0x77
#define TLV_REAL 0xB8
#include <iostream>
#include <fstream>
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<const char*>(&m_objectType), sizeof(m_objectType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
}
void add_string(const char *s, uint16_t size)
{
m_file.write(reinterpret_cast<const char*>(&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<const char*>(&m_integerType), sizeof(m_integerType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
m_file.write(reinterpret_cast<const char*>(&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<const char*>(&m_arrayType), sizeof(m_arrayType));
m_file.write(reinterpret_cast<const char*>(&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

View file

@ -0,0 +1,106 @@
#include "library_manager.h"
#include "tlv.h"
#include <filesystem>
#include <regex>
#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<StoryProject>();
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);
}

View file

@ -0,0 +1,30 @@
#ifndef LIBRARYMANAGER_H
#define LIBRARYMANAGER_H
#include <string>
#include <vector>
#include <memory>
#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<std::shared_ptr<StoryProject>>::const_iterator begin() const { return m_projectsList.begin(); }
std::vector<std::shared_ptr<StoryProject>>::const_iterator end() const { return m_projectsList.end(); }
void Save();
void Scan();
private:
std::string m_library_path;
std::vector<std::shared_ptr<StoryProject>> m_projectsList;
};
#endif // LIBRARYMANAGER_H

View file

@ -24,74 +24,12 @@ void StoryProject::New(const std::string &uuid, const std::string &file_path)
Initialize(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<const char*>(&m_objectType), sizeof(m_objectType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
}
void add_string(const char *s, uint16_t size)
{
m_file.write(reinterpret_cast<const char*>(&m_stringType), sizeof(m_stringType));
m_file.write(reinterpret_cast<const char*>(&size), sizeof(size));
m_file.write(s, size);
}
void add_object(uint16_t entries)
{
m_file.write(reinterpret_cast<const char*>(&m_arrayType), sizeof(m_arrayType));
m_file.write(reinterpret_cast<const char*>(&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<uint8_t> &m_program) void StoryProject::SaveStory(const std::vector<uint8_t> &m_program)
{ {
std::ofstream o(m_working_dir / "story.c32", std::ios::out | std::ios::binary); std::ofstream o(m_working_dir / "story.c32", std::ios::out | std::ios::binary);
o.write(reinterpret_cast<const char*>(m_program.data()), m_program.size()); o.write(reinterpret_cast<const char*>(m_program.data()), m_program.size());
o.close(); 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) 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); std::filesystem::path p(file_path);
m_working_dir= p.parent_path().generic_string(); 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)) if (!std::filesystem::is_directory(m_working_dir))
{ {
std::filesystem::create_directories(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; 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<std::string>();
m_uuid = projectData["uuid"].get<std::string>();
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) 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(); // m_nodes.clear();
manager.Clear(); manager.Clear();
if (j.contains("project")) if (ParseStoryInformation(j))
{ {
nlohmann::json projectData = j["project"];
m_name = projectData["name"].get<std::string>();
m_uuid = projectData["uuid"].get<std::string>();
m_titleImage = projectData.value("title_image", "");
m_titleSound = projectData.value("title_sound", "");
if (j.contains("resources")) if (j.contains("resources"))
{ {
nlohmann::json resourcesData = j["resources"]; nlohmann::json resourcesData = j["resources"];

View file

@ -41,6 +41,7 @@ struct StoryNode
// "sound": 0 // "sound": 0
}; };
struct StoryProject struct StoryProject
{ {
@ -74,6 +75,8 @@ public:
std::string GetWorkingDir() const; std::string GetWorkingDir() const;
std::string GetName() const { return m_name; } std::string GetName() const { return m_name; }
std::string GetUuid() const { return m_uuid; } 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; std::string BuildFullAssetsPath(const std::string &fileName) const;
@ -101,17 +104,20 @@ public:
void SaveStory(const std::vector<uint8_t> &m_program); void SaveStory(const std::vector<uint8_t> &m_program);
bool ParseStoryInformation(nlohmann::json &j);
private: private:
// Project properties and location // Project properties and location
std::string m_name; /// human readable name std::string m_name; /// human readable name
std::string m_uuid; std::string m_uuid;
std::string m_titleImage;
std::string m_titleSound;
std::string m_description;
int m_version;
std::filesystem::path m_assetsPath; std::filesystem::path m_assetsPath;
bool m_initialized{false}; 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::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 std::string m_story_file_path; /// JSON project file

View file

@ -101,6 +101,9 @@ set(SRCS
src/node_editor_window.cpp src/node_editor_window.cpp
src/node_editor_window.h src/node_editor_window.h
src/library_window.cpp
src/library_window.h
src/media_node.h src/media_node.h
src/media_node.cpp src/media_node.cpp
@ -148,8 +151,11 @@ set(SRCS
../software/chip32/chip32_assembler.cpp ../software/chip32/chip32_assembler.cpp
../software/chip32/chip32_vm.c ../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/miniaudio.h
../software/library/uuid.h ../software/library/uuid.h
../software/library/resource.h ../software/library/resource.h
@ -157,6 +163,8 @@ set(SRCS
../software/library/story_project.cpp ../software/library/story_project.cpp
../software/library/story_project.h ../software/library/story_project.h
../software/library/thread_safe_queue.h ../software/library/thread_safe_queue.h
../software/library/library_manager.h
../software/library/library_manager.cpp
) )
if(WIN32) if(WIN32)
@ -174,6 +182,8 @@ if(WIN32)
else() else()
add_executable(${STORY_EDITOR_PROJECT} add_executable(${STORY_EDITOR_PROJECT}
${SRCS} ${SRCS}
) )
endif() endif()
@ -187,6 +197,7 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
../software/library/ ../software/library/
../software/chip32/ ../software/chip32/
../software/common
) )
add_definitions(-DIMGUI_USE_WCHAR32 -DVERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DVERSION_MINOR=${PROJECT_VERSION_MINOR} -DVERSION_PATCH=${PROJECT_VERSION_PATCH}) add_definitions(-DIMGUI_USE_WCHAR32 -DVERSION_MAJOR=${PROJECT_VERSION_MAJOR} -DVERSION_MINOR=${PROJECT_VERSION_MINOR} -DVERSION_PATCH=${PROJECT_VERSION_PATCH})

View file

@ -3,7 +3,6 @@
#include <string> #include <string>
#include <vector>
#include <memory> #include <memory>
#include <list> #include <list>
@ -15,6 +14,7 @@ class IStoryManager
public: public:
virtual ~IStoryManager() {} virtual ~IStoryManager() {}
virtual void OpenProject(const std::string &filename) = 0;
virtual void Log(const std::string &txt, bool critical = false) = 0; virtual void Log(const std::string &txt, bool critical = false) = 0;
virtual void PlaySoundFile(const std::string &fileName) = 0; virtual void PlaySoundFile(const std::string &fileName) = 0;
virtual std::string BuildFullAssetsPath(const std::string &fileName) const = 0; virtual std::string BuildFullAssetsPath(const std::string &fileName) const = 0;

View file

@ -0,0 +1,159 @@
#include "library_window.h"
#include "gui.h"
#include "ImGuiFileDialog.h"
#include <filesystem>
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();
}

View file

@ -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;
};

View file

@ -1,6 +1,5 @@
#include "main_window.h" #include "main_window.h"
#include <filesystem> #include <filesystem>
#include <random>
#include <SDL.h> #include <SDL.h>
#include "platform_folders.h" #include "platform_folders.h"
#include "uuid.h" #include "uuid.h"
@ -19,17 +18,14 @@
#include "IconsMaterialDesignIcons.h" #include "IconsMaterialDesignIcons.h"
#include "ImGuiFileDialog.h" #include "ImGuiFileDialog.h"
static std::string gVersion;
MainWindow::MainWindow() MainWindow::MainWindow()
: m_emulatorWindow(*this) : m_emulatorWindow(*this)
, m_resourcesWindow(*this) , m_resourcesWindow(*this)
, m_nodeEditorWindow(*this) , m_nodeEditorWindow(*this)
, m_libraryWindow(*this, m_libraryManager)
, m_player(*this) , m_player(*this)
{ {
gVersion = std::to_string(VERSION_MAJOR) + '.' + std::to_string(VERSION_MINOR) + '.' + std::to_string(VERSION_PATCH);
// VM Initialize // VM Initialize
m_chip32_ctx.stack_size = 512; m_chip32_ctx.stack_size = 512;
@ -51,7 +47,7 @@ MainWindow::MainWindow()
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
SaveParams();
} }
@ -270,7 +266,7 @@ void MainWindow::DrawMainMenuBar()
{ {
showNewProject = true; showNewProject = true;
} }
/*
if (ImGui::MenuItem("Open project")) if (ImGui::MenuItem("Open project"))
{ {
showOpenProject = true; showOpenProject = true;
@ -279,17 +275,22 @@ void MainWindow::DrawMainMenuBar()
if (ImGui::BeginMenu("Open Recent")) if (ImGui::BeginMenu("Open Recent"))
{ {
for (auto &e : m_recentProjects) for (auto &e : m_recentProjects)
{
if (e.size() > 0)
{ {
if (ImGui::MenuItem(e.c_str())) if (ImGui::MenuItem(e.c_str()))
{ {
OpenProject(e); OpenProject(e);
} }
} }
}
ImGui::EndMenu(); 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::BeginDisabled();
ImGui::Separator(); ImGui::Separator();
@ -308,7 +309,7 @@ void MainWindow::DrawMainMenuBar()
showParameters = true; showParameters = true;
} }
if (!m_story.IsInitialized()) if (!init)
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenu(); ImGui::EndMenu();
@ -359,7 +360,7 @@ void MainWindow::DrawMainMenuBar()
if (ImGui::BeginPopupModal("AboutPopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) 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::Text("http://www.openstoryteller.org");
ImGui::Separator(); ImGui::Separator();
ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Platform"); 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); ImGuiFileDialog::Instance()->OpenDialog("ChooseDirDialog", "Choose File", nullptr, ".", 1, nullptr, ImGuiFileDialogFlags_Modal);
} }
// display // display
if (ImGuiFileDialog::Instance()->Display("ChooseDirDialog")) if (ImGuiFileDialog::Instance()->Display("ChooseDirDialog"))
{ {
@ -681,8 +681,7 @@ void MainWindow::SaveProject()
void MainWindow::OpenProject(const std::string &filename) void MainWindow::OpenProject(const std::string &filename)
{ {
m_story.Initialize(filename); CloseProject();
nlohmann::json model; nlohmann::json model;
if (m_story.Load(filename, model, m_resources)) if (m_story.Load(filename, model, m_resources))
@ -720,7 +719,7 @@ void MainWindow::OpenProject(const std::string &filename)
void MainWindow::RefreshProjectInformation() 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); m_gui.SetWindowTitle(fullText);
} }
@ -738,7 +737,6 @@ void MainWindow::CloseProject()
m_nodeEditorWindow.Disable(); m_nodeEditorWindow.Disable();
m_emulatorWindow.Disable(); m_emulatorWindow.Disable();
m_consoleWindow.Disable();
m_editorWindow.Disable(); m_editorWindow.Disable();
m_resourcesWindow.Disable(); m_resourcesWindow.Disable();
m_PropertiesWindow.Disable(); m_PropertiesWindow.Disable();
@ -768,14 +766,20 @@ void MainWindow::Loop()
// ------------ Draw all windows // ------------ Draw all windows
m_libraryWindow.Draw();
if (m_libraryManager.IsInitialized())
{
m_consoleWindow.Draw(); m_consoleWindow.Draw();
m_emulatorWindow.Draw(); m_emulatorWindow.Draw();
m_editorWindow.Draw(); m_editorWindow.Draw();
m_resourcesWindow.Draw(); m_resourcesWindow.Draw();
m_nodeEditorWindow.Draw(); m_nodeEditorWindow.Draw();
m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode()); m_PropertiesWindow.SetSelectedNode(m_nodeEditorWindow.GetSelectedNode());
m_PropertiesWindow.Draw(); m_PropertiesWindow.Draw();
}
NewProjectPopup(); NewProjectPopup();
OpenProjectDialog(); OpenProjectDialog();
@ -798,6 +802,7 @@ void MainWindow::Loop()
m_gui.Destroy(); m_gui.Destroy();
} }
void MainWindow::Log(const std::string &txt, bool critical) void MainWindow::Log(const std::string &txt, bool critical)
{ {
m_consoleWindow.AddLog(txt, critical ? 1 : 0); m_consoleWindow.AddLog(txt, critical ? 1 : 0);
@ -1007,6 +1012,7 @@ void MainWindow::SaveParams()
nlohmann::json recents(m_recentProjects); nlohmann::json recents(m_recentProjects);
j["recents"] = recents; j["recents"] = recents;
j["library_path"] = m_libraryManager.LibraryPath();
std::string loc = pf::getConfigHome() + "/ost_settings.json"; std::string loc = pf::getConfigHome() + "/ost_settings.json";
std::ofstream o(loc); std::ofstream o(loc);
@ -1032,6 +1038,14 @@ void MainWindow::LoadParams()
m_recentProjects.push_back(element); 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) catch(std::exception &e)
{ {

View file

@ -19,6 +19,8 @@
#include "i_story_manager.h" #include "i_story_manager.h"
#include "thread_safe_queue.h" #include "thread_safe_queue.h"
#include "audio_player.h" #include "audio_player.h"
#include "library_manager.h"
#include "library_window.h"
struct DebugContext struct DebugContext
{ {
@ -110,6 +112,8 @@ private:
ResourceManager m_resources; ResourceManager m_resources;
LibraryManager m_libraryManager;
Gui m_gui; Gui m_gui;
EmulatorWindow m_emulatorWindow; EmulatorWindow m_emulatorWindow;
ConsoleWindow m_consoleWindow; ConsoleWindow m_consoleWindow;
@ -121,6 +125,8 @@ private:
PropertiesWindow m_PropertiesWindow; PropertiesWindow m_PropertiesWindow;
LibraryWindow m_libraryWindow;
AudioPlayer m_player; AudioPlayer m_player;
struct VmEvent struct VmEvent
@ -132,6 +138,7 @@ private:
// From IStoryManager (proxy to StoryProject class) // 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 Log(const std::string &txt, bool critical = false) override;
virtual void PlaySoundFile(const std::string &fileName) override;; virtual void PlaySoundFile(const std::string &fileName) override;;
virtual std::string BuildFullAssetsPath(const std::string &fileName) const override; virtual std::string BuildFullAssetsPath(const std::string &fileName) const override;
@ -162,7 +169,6 @@ private:
void NewProjectPopup(); void NewProjectPopup();
void SaveProject(); void SaveProject();
void OpenProject(const std::string &filename);
void CloseProject(); void CloseProject();
void OpenProjectDialog(); void OpenProjectDialog();
void DrawStatusBar(); void DrawStatusBar();