From 9accbbeea792f8b0b46d40281859456ea27fd851 Mon Sep 17 00:00:00 2001 From: "anthony@rabine.fr" Date: Tue, 14 May 2024 11:05:17 +0200 Subject: [PATCH] Fix project loading duplicate nodes, formats moved --- docs/editor-dev.md | 28 +++++++++++++ shared/library_manager.cpp | 5 ++- shared/resource.cpp | 29 +++++++++++++ shared/resource.h | 8 ++++ shared/resource_manager.cpp | 41 ++++++++++++++----- shared/resource_manager.h | 15 ++++--- shared/story_project.cpp | 14 ++++--- shared/story_project.h | 18 ++++---- story-editor/CMakeLists.txt | 2 + story-editor/README.md | 20 --------- story-editor/src/importers/pack_archive.cpp | 25 +++++------ story-editor/src/importers/pack_archive.h | 1 + .../src/node_editor/base_node_widget.cpp | 11 ++++- .../src/node_editor/node_editor_window.cpp | 10 +++++ .../src/node_editor/node_editor_window.h | 1 + story-editor/src/node_engine/media_node.cpp | 3 +- 16 files changed, 164 insertions(+), 67 deletions(-) create mode 100644 shared/resource.cpp delete mode 100644 story-editor/README.md diff --git a/docs/editor-dev.md b/docs/editor-dev.md index 4b9c124..1d6988e 100644 --- a/docs/editor-dev.md +++ b/docs/editor-dev.md @@ -17,10 +17,36 @@ You'll need: - A C++ compiler - CMake build utility +Here is a list of packages for Ubuntu-like systems: + +``` +sudo apt install cmake mesa-utils mesa-common-dev ninja-build libxext-dev +``` + ## How to build Open the CMakeLists.txt with your favorite IDE (ie, QtCreator, Visual Studio Code) or build from the command line. +## How to generate a Windows executable and setup executable on Ubuntu + +The build system uses a Docker environment image for reproductible builds. + +Run `build_win32.sh` script. + +Output file is located here: `story-editor/build-win32/Open-Story-Editor-1.0.0-win64.exe` + +## Linux build + +``` +cd story-editor +mkdir build +cd build +cmake .. +make -j4 +make package +``` + + # Architecture ![arch](./images/story-editor-architecture.png) @@ -28,3 +54,5 @@ Open the CMakeLists.txt with your favorite IDE (ie, QtCreator, Visual Studio Cod + + diff --git a/shared/library_manager.cpp b/shared/library_manager.cpp index cb9fdfa..54a21c2 100644 --- a/shared/library_manager.cpp +++ b/shared/library_manager.cpp @@ -85,8 +85,8 @@ std::shared_ptr LibraryManager::NewProject() story->New(uuid, m_library_path); story->SetDisplayFormat(320, 240); - story->SetImageFormat(StoryProject::IMG_FORMAT_QOIF); - story->SetSoundFormat(StoryProject::SND_FORMAT_WAV); + story->SetImageFormat(Resource::IMG_FORMAT_QOIF); + story->SetSoundFormat(Resource::SND_FORMAT_WAV); story->SetName("New project"); return story; } @@ -171,6 +171,7 @@ void LibraryManager::CopyToDevice(const std::string &outputDir) { if (p->IsSelected()) { + std::cout << "Copying " << p->GetName() << std::endl; p->CopyToDevice(outputDir); } } diff --git a/shared/resource.cpp b/shared/resource.cpp new file mode 100644 index 0000000..d2499d9 --- /dev/null +++ b/shared/resource.cpp @@ -0,0 +1,29 @@ + +#include "resource.h" + +std::string Resource::ImageFormatToString(ImageFormat format) +{ + std::string text = "SAME"; + switch (format) + { + case IMG_FORMAT_QOIF: + text = "QOIF"; + break; + } + return text; +} + +std::string Resource::SoundFormatToString(SoundFormat format) +{ + std::string text = "SAME"; + switch (format) + { + case SND_FORMAT_WAV: + text = "WAV"; + break; + case SND_FORMAT_QOAF: + text = "QOAF"; + break; + } + return text; +} diff --git a/shared/resource.h b/shared/resource.h index 34cfc31..bbde7ab 100644 --- a/shared/resource.h +++ b/shared/resource.h @@ -6,9 +6,14 @@ #include #include #include +#include + struct Resource { + enum ImageFormat { IMG_SAME_FORMAT, IMG_FORMAT_QOIF, IMG_FORMAT_COUNT }; + enum SoundFormat { SND_SAME_FORMAT, SND_FORMAT_WAV, SND_FORMAT_QOAF, SND_FORMAT_COUNT }; + std::string file; std::string description; std::string format; @@ -17,6 +22,9 @@ struct Resource ~Resource() { // std::cout << "Res deleted" << std::endl; } + + static std::string ImageFormatToString(ImageFormat format); + static std::string SoundFormatToString(SoundFormat format); }; // Itérateur pour parcourir les éléments filtrés diff --git a/shared/resource_manager.cpp b/shared/resource_manager.cpp index 77ed83c..0842dc9 100644 --- a/shared/resource_manager.cpp +++ b/shared/resource_manager.cpp @@ -5,10 +5,7 @@ #include "resource_manager.h" #include "media_converter.h" #include "sys_lib.h" -struct Media { - std::string type; - std::string format; -}; + static const std::unordered_map mediaTypes { {".mp3", {"sound", "MP3"}}, @@ -22,6 +19,7 @@ static const std::unordered_map mediaTypes { }; + std::string ResourceManager::ExtentionInfo(std::string extension, int info_type) { std::string lowerExtension = extension; @@ -36,7 +34,7 @@ std::string ResourceManager::ExtentionInfo(std::string extension, int info_type) } } -void ResourceManager::ConvertResources(const std::filesystem::path &assetsPath, const std::filesystem::path &destAssetsPath) +void ResourceManager::ConvertResources(const std::filesystem::path &assetsPath, const std::filesystem::path &destAssetsPath, Resource::ImageFormat imageFormat, Resource::SoundFormat soundFormat) { auto [b, e] = Items(); for (auto it = b; it != e; ++it) @@ -49,18 +47,39 @@ void ResourceManager::ConvertResources(const std::filesystem::path &assetsPath, { if ((*it)->format == "PNG") { - outputfile += ".qoi"; // FIXME: prendre la config en cours désirée - retCode = MediaConverter::ImageToQoi(inputfile.generic_string(), outputfile.generic_string()); + if (imageFormat == Resource::IMG_FORMAT_QOIF) + { + outputfile += ".qoi"; // FIXME: prendre la config en cours désirée + retCode = MediaConverter::ImageToQoi(inputfile.generic_string(), outputfile.generic_string()); + } + else + { + outputfile += ".png"; + } } else if ((*it)->format == "MP3") { - outputfile += ".wav"; // FIXME: prendre la config en cours désirée - retCode = MediaConverter::Mp3ToWav(inputfile.generic_string(), outputfile.generic_string()); + if (soundFormat == Resource::SND_FORMAT_WAV) + { + outputfile += ".wav"; // FIXME: prendre la config en cours désirée + retCode = MediaConverter::Mp3ToWav(inputfile.generic_string(), outputfile.generic_string()); + } + else + { + outputfile += ".mp3"; + } } else if ((*it)->format == "OGG") { - outputfile += ".wav"; // FIXME: prendre la config en cours désirée - retCode = MediaConverter::OggToWav(inputfile.generic_string(), outputfile.generic_string()); + if (soundFormat == Resource::SND_FORMAT_WAV) + { + outputfile += ".wav"; // FIXME: prendre la config en cours désirée + retCode = MediaConverter::OggToWav(inputfile.generic_string(), outputfile.generic_string()); + } + else + { + outputfile += ".ogg"; + } } else { diff --git a/shared/resource_manager.h b/shared/resource_manager.h index ffd9541..413ee79 100644 --- a/shared/resource_manager.h +++ b/shared/resource_manager.h @@ -11,21 +11,25 @@ #include "resource.h" #include "i_logger.h" +struct Media { + std::string type; + std::string format; +}; + + + class ResourceManager { -public: - - +public: ResourceManager() : m_images(filter("image")) , m_sounds(filter("sound")) { - } static std::string ExtentionInfo(std::string extension, int info_type); - void ConvertResources(const std::filesystem::path &assetsPath, const std::filesystem::path &destAssetsPath); + void ConvertResources(const std::filesystem::path &assetsPath, const std::filesystem::path &destAssetsPath, Resource::ImageFormat imageFormat, Resource::SoundFormat soundFormat); ~ResourceManager() { @@ -48,7 +52,6 @@ public: UpdateIterators(); } - // Fonction pour créer un itérateur de début et de fin pour les éléments filtrés std::pair filter(const std::string &type) const { auto begin = std::begin(m_items); diff --git a/shared/story_project.cpp b/shared/story_project.cpp index eabbcfc..a711c3b 100644 --- a/shared/story_project.cpp +++ b/shared/story_project.cpp @@ -52,7 +52,7 @@ void StoryProject::CopyToDevice(const std::string &outputDir) std::filesystem::copy(BinaryFileName(), destRootDir, std::filesystem::copy_options::overwrite_existing); // Convert resources (if necessary) and copy them to destination assets - manager.ConvertResources(AssetsPath(), destAssetsDir); + manager.ConvertResources(AssetsPath(), destAssetsDir, m_imageFormat, m_soundFormat); } } @@ -136,7 +136,9 @@ std::shared_ptr StoryProject::CreateNode(const std::string &type) } else { - return i->second(type); + auto n = i->second(type); + m_nodes.push_back(n); + return n; } } @@ -191,7 +193,6 @@ bool StoryProject::ModelFromJson(const nlohmann::json &model) if (n) { n->FromJson(element); - m_nodes.push_back(n); } else { @@ -215,12 +216,15 @@ bool StoryProject::ModelFromJson(const nlohmann::json &model) m_links.push_back(std::make_shared(connection.get())); } } + + std::cout << "From model, loded nodes: " << m_nodes.size() << ", links: " << m_links.size() << std::endl; success = true; } catch(nlohmann::json::exception &e) { std::cout << "(NodeEditorWindow::Load) " << e.what() << std::endl; } + return success; } @@ -517,12 +521,12 @@ void StoryProject::SetTitleSound(const std::string &titleSound) -void StoryProject::SetImageFormat(ImageFormat format) +void StoryProject::SetImageFormat(Resource::ImageFormat format) { m_imageFormat = format; } -void StoryProject::SetSoundFormat(SoundFormat format) +void StoryProject::SetSoundFormat(Resource::SoundFormat format) { m_soundFormat = format; } diff --git a/shared/story_project.h b/shared/story_project.h index bc29f2a..2779bd1 100644 --- a/shared/story_project.h +++ b/shared/story_project.h @@ -49,8 +49,7 @@ struct StoryProject : public IStoryProject { public: - enum ImageFormat { IMG_SAME_FORMAT, IMG_FORMAT_QOIF, IMG_FORMAT_COUNT }; - enum SoundFormat { SND_SAME_FORMAT, SND_FORMAT_WAV, SND_FORMAT_QOAF, SND_FORMAT_COUNT }; + StoryProject(ILogger &log); ~StoryProject(); @@ -98,8 +97,12 @@ public: void Select(bool selected) { m_selected = selected; } bool IsSelected() const { return m_selected; } - void SetImageFormat(ImageFormat format); - void SetSoundFormat(SoundFormat format); + void SetImageFormat(Resource::ImageFormat format); + void SetSoundFormat(Resource::SoundFormat format); + + Resource::ImageFormat GetImageFormat() const { return m_imageFormat; } + Resource::SoundFormat GetSoundFormat() const { return m_soundFormat; } + void SetDisplayFormat(int w, int h); void SetName(const std::string &name) { m_name = name; } void SetUuid(const std::string &uuid) { m_uuid = uuid; } @@ -167,9 +170,8 @@ private: int m_display_w{320}; int m_display_h{240}; - ImageFormat m_imageFormat{IMG_SAME_FORMAT}; - SoundFormat m_soundFormat{SND_FORMAT_WAV}; - + Resource::ImageFormat m_imageFormat{Resource::IMG_SAME_FORMAT}; + Resource::SoundFormat m_soundFormat{Resource::SND_SAME_FORMAT}; template struct Factory { @@ -187,8 +189,6 @@ private: m_registry.insert(typename Registry::value_type(key, Factory::create_func)); } - - }; #endif // STORY_PROJECT_H diff --git a/story-editor/CMakeLists.txt b/story-editor/CMakeLists.txt index ba5e314..a8d1175 100644 --- a/story-editor/CMakeLists.txt +++ b/story-editor/CMakeLists.txt @@ -232,6 +232,8 @@ set(SRCS ../shared/miniaudio.h ../shared/stb_vorbis.c ../shared/uuid.h + ../shared/resource.h + ../shared/resource.cpp ../shared/resource_manager.h ../shared/resource_manager.cpp ../shared/story_project.cpp diff --git a/story-editor/README.md b/story-editor/README.md deleted file mode 100644 index dbd8ed4..0000000 --- a/story-editor/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Story Editor - -## How to generate a Windows executable and setup executable on Ubuntu - -The build system uses a Docker environment image for reproductible builds. - -Run `build_win32.sh` script. - -Output file is located here: `story-editor/build-win32/Open-Story-Editor-1.0.0-win64.exe` - -## Linux build - -``` -cd story-editor -mkdir build -cd build -cmake .. -make -j4 -make package -``` diff --git a/story-editor/src/importers/pack_archive.cpp b/story-editor/src/importers/pack_archive.cpp index f7407fb..b90678f 100644 --- a/story-editor/src/importers/pack_archive.cpp +++ b/story-editor/src/importers/pack_archive.cpp @@ -373,12 +373,8 @@ std::string PackArchive::OpenImage(const std::string &fileName) return f; } -bool PackArchive::ImportStudioFormat(const std::string &fileName, const std::string &outputDir) -{ - auto uuid = Uuid().String(); - std::string basePath = outputDir + "/" + uuid; - Unzip(fileName, basePath); - +bool PackArchive::ConvertJsonStudioToOst(const std::string &basePath, const std::string &uuid, const std::string &outputDir) +{ try { @@ -436,12 +432,7 @@ bool PackArchive::ImportStudioFormat(const std::string &fileName, const std::str stageActionLink[n["okTransition"]["actionNode"]] = node_uuid; } -/* - "okTransition":{ - "actionNode":"19d7328f-d0d2-4443-a7a2-25270dafe52c", - "optionIndex":0 - }, - */ + } for (const auto & n : j["actionNodes"]) @@ -478,6 +469,16 @@ bool PackArchive::ImportStudioFormat(const std::string &fileName, const std::str m_log.Log(std::string("Import failure: ") + e.what()); } + return true; // FIXME +} + +bool PackArchive::ImportStudioFormat(const std::string &fileName, const std::string &outputDir) +{ + auto uuid = Uuid().String(); + std::string basePath = outputDir + "/" + uuid; + Unzip(fileName, basePath); + + ConvertJsonStudioToOst(basePath, uuid, outputDir); return false; } diff --git a/story-editor/src/importers/pack_archive.h b/story-editor/src/importers/pack_archive.h index a7783ec..fcc1a33 100644 --- a/story-editor/src/importers/pack_archive.h +++ b/story-editor/src/importers/pack_archive.h @@ -32,6 +32,7 @@ public: void Previous(); void Unzip(const std::string &filePath, const std::string &parent_dest_dir); void DecipherAll(const std::string &packFileName, const std::string &parent_dest_dir); + bool ConvertJsonStudioToOst(const std::string &basePath, const std::string &uuid, const std::string &outputDir); std::string HexDump(const char *desc, const void *addr, int len); private: diff --git a/story-editor/src/node_editor/base_node_widget.cpp b/story-editor/src/node_editor/base_node_widget.cpp index 54b7794..427fd95 100644 --- a/story-editor/src/node_editor/base_node_widget.cpp +++ b/story-editor/src/node_editor/base_node_widget.cpp @@ -10,11 +10,12 @@ BaseNodeWidget::BaseNodeWidget(IStoryManager &manager, std::shared_ptr(GetNextId(), ""); // ImGui internal ID + std::cout << " --> Created node widget: " << (int)m_node->ID.Get() << std::endl; } BaseNodeWidget::~BaseNodeWidget() { - std::cout << "Deleted node widget" << std::endl; + std::cout << " <-- Deleted node widget: " << (int)m_node->ID.Get() << std::endl; } void BaseNodeWidget::AddInput() @@ -71,6 +72,14 @@ void BaseNodeWidget::FrameStart() ed::SetNodePosition(m_node->ID, ImVec2(m_base->GetX(), m_base->GetY())); } } + else + { + // Si ce n'est pas la première frame, on synchronise la position du noeud avec l'objet + if (m_base) + { + m_base->SetPosition(GetX(), GetY()); + } + } m_firstFrame = false; } diff --git a/story-editor/src/node_editor/node_editor_window.cpp b/story-editor/src/node_editor/node_editor_window.cpp index d30a6ce..b82f462 100644 --- a/story-editor/src/node_editor/node_editor_window.cpp +++ b/story-editor/src/node_editor/node_editor_window.cpp @@ -106,6 +106,8 @@ void NodeEditorWindow::Load(std::shared_ptr story) auto [node_begin, node_end] = m_story->Nodes(); + int i = 0; + for (auto it = node_begin; it != node_end; ++it) { auto n = CreateNodeWidget((*it)->GetType(), m_manager, (*it)); @@ -119,6 +121,8 @@ void NodeEditorWindow::Load(std::shared_ptr story) { throw std::logic_error(std::string("No registered model with name ") + (*it)->GetType()); } + + std::cout << "Created " << ++i << " node" << std::endl; } auto [link_begin, link_end] = m_story->Links(); @@ -136,9 +140,15 @@ void NodeEditorWindow::Load(std::shared_ptr story) std::cout << "(NodeEditorWindow::Load) " << e.what() << std::endl; } } + + std::cout << "Loaded " << m_nodes.size() << " nodes, " << m_links.size() << " links" << std::endl; } +void NodeEditorWindow::SaveNodePositions() +{ + +} void NodeEditorWindow::CreateLink(std::shared_ptr model, ed::PinId inId, ed::PinId outId) { diff --git a/story-editor/src/node_editor/node_editor_window.h b/story-editor/src/node_editor/node_editor_window.h index d3c3912..d1ea2b0 100644 --- a/story-editor/src/node_editor/node_editor_window.h +++ b/story-editor/src/node_editor/node_editor_window.h @@ -54,6 +54,7 @@ public: void Initialize(); void Clear(); void Load(std::shared_ptr story); + void SaveNodePositions(); std::shared_ptr GetSelectedNode(); diff --git a/story-editor/src/node_engine/media_node.cpp b/story-editor/src/node_engine/media_node.cpp index 0bf2bb4..69132c3 100644 --- a/story-editor/src/node_engine/media_node.cpp +++ b/story-editor/src/node_engine/media_node.cpp @@ -13,7 +13,8 @@ static std::string ChoiceLabel(const std::string &id) MediaNode::MediaNode(const std::string &type) : BaseNode(type) { - + nlohmann::json j{ {"image", ""}, {"sound", ""}}; + SetInternalData(j); }