diff --git a/core/story-manager/interfaces/i_story_manager.h b/core/story-manager/interfaces/i_story_manager.h index 7caae03..a25bf2e 100644 --- a/core/story-manager/interfaces/i_story_manager.h +++ b/core/story-manager/interfaces/i_story_manager.h @@ -32,7 +32,7 @@ class IStoryManager public: virtual ~IStoryManager() {} - virtual void OpenProject(const std::string &uuid) = 0; + virtual void OpenProject(const std::string &uuid, IStoryManager::ProjectType type) = 0; virtual void ImportProject(const std::string &fileName, int format) = 0; virtual void Log(const std::string &txt, bool critical = false) = 0; virtual void PlaySoundFile(const std::string &fileName) = 0; diff --git a/core/story-manager/interfaces/i_story_project.h b/core/story-manager/interfaces/i_story_project.h index 0f1ee29..4a91c84 100644 --- a/core/story-manager/interfaces/i_story_project.h +++ b/core/story-manager/interfaces/i_story_project.h @@ -9,7 +9,7 @@ class IStoryProject { public: - enum ProjectType + enum Type { PROJECT_TYPE_STORY = 0, PROJECT_TYPE_MODULE = 1, diff --git a/core/story-manager/lib/nodes_factory.h b/core/story-manager/lib/nodes_factory.h index 924dacc..37f1d7c 100644 --- a/core/story-manager/lib/nodes_factory.h +++ b/core/story-manager/lib/nodes_factory.h @@ -1,5 +1,10 @@ #pragma once +#include +#include +#include +#include + #include "json.hpp" // #include "media_node.h" #include "function_node.h" @@ -7,20 +12,34 @@ #include "operator_node.h" #include "print_node.h" #include "syscall_node.h" +#include "story_project.h" + +static const std::string OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec"; +static const std::string FunctionNodeUuid = "02745f38-9b11-49fe-94b1-b2a6b78249fb"; +static const std::string VariableNodeUuid = "020cca4e-9cdc-47e7-a6a5-53e4c9152ed0"; +static const std::string PrintNodeUuid = "02ee27bc-ff1d-4f94-b700-eab55052ad1c"; +static const std::string SyscallNodeUuid = "02225cff-4975-400e-8130-41524d8af773"; + +typedef std::shared_ptr (*GenericCreator)(const std::string &type); class NodesFactory { public: - NodesFactory() { + + NodesFactory(ILogger &log) + : m_log(log) + , m_rootPath("") + { // Register node types // registerNode("media-node"); - registerNode("operator-node"); - registerNode("function-node"); - registerNode("variable-node"); - registerNode("print-node"); - registerNode("syscall-node"); + registerNode(OperatorNodeUuid, nullptr); + registerNode(FunctionNodeUuid, nullptr); + registerNode(VariableNodeUuid, nullptr); + registerNode(PrintNodeUuid, nullptr); + registerNode(SyscallNodeUuid, nullptr); } + ~NodesFactory() = default; std::vector GetNodeTypes() const { @@ -38,12 +57,58 @@ public: } else { - auto n = i->second(type); + auto n = i->second.second(type); return n; } } + void SetModulesRootDirectory(const std::string &rootPath) { + m_rootPath = rootPath; + } + + void ScanModules() { + // This function should scan the rootPath for modules and register them + // For now, we just log the root path + std::cout << "Scanning modules in: " << m_rootPath << std::endl; + // Here you would implement the logic to scan the directory and register modules + + // For example, you could read JSON files in the directory and create nodes based on their content + // This is a placeholder for actual scanning logic + // Example: registerNode("custom-module-node"); + + // Loop through files in m_rootPath + // and register them as nodes if they match certain criteria + for (const auto& entry : std::filesystem::directory_iterator(m_rootPath)) + { + if (entry.is_regular_file() && entry.path().extension() == ".json") + { + // Load the JSON file and register a node based on its content + std::ifstream file(entry.path()); + nlohmann::json j; + file >> j; + + auto p = std::make_shared(m_log); + p->ParseStoryInformation(j); + + if (p->IsModule()) + { + registerNode(FunctionNodeUuid, p); + // For now, function node use only primitives nodes + // FIXME: in the future, allow function node to use other function nodes + // Need a list of required nodes to be registered + + // Maybe this algorithm: + // 1. load all function nodes + // 2. for each function node, check if it has a "requires" field + // 3. if it does, check if we have them + } + } + } + } + private: + ILogger &m_log; + std::string m_rootPath; template struct Factory { @@ -52,12 +117,13 @@ private: } }; - typedef std::shared_ptr (*GenericCreator)(const std::string &type); - typedef std::map Registry; + // UUID is the key, and the value is a function that creates the node + typedef std::map, GenericCreator>> Registry; Registry m_registry; template - void registerNode(const std::string& key) { - m_registry.insert(typename Registry::value_type(key, Factory::create_func)); + void registerNode(const std::string& uuid, std::shared_ptr moduleInfo = nullptr) { + info.creator = ; + m_registry.insert(typename Registry::value_type(uuid, std::make_pair::create_func>)); } }; diff --git a/core/story-manager/src/nodes/function_node.h b/core/story-manager/src/nodes/function_node.h index 6127a3b..4a16de1 100644 --- a/core/story-manager/src/nodes/function_node.h +++ b/core/story-manager/src/nodes/function_node.h @@ -13,7 +13,11 @@ public: virtual void Initialize() override; -private: + void SetContent(nlohmann::json &content) { + m_content = content; + } +private: + nlohmann::json m_content; }; diff --git a/core/story-manager/src/story_project.cpp b/core/story-manager/src/story_project.cpp index fc9f1e6..f484486 100644 --- a/core/story-manager/src/story_project.cpp +++ b/core/story-manager/src/story_project.cpp @@ -104,6 +104,23 @@ bool StoryProject::ParseStoryInformation(nlohmann::json &j) m_name = projectData["name"].get(); m_uuid = projectData["uuid"].get(); + m_uuid = projectData["description"].get(); + std::string typeString = projectData["type"].get(); + + if (typeString == "story") + { + m_projectType = IStoryProject::PROJECT_TYPE_STORY; + } + else if (typeString == "module") + { + m_projectType = IStoryProject::PROJECT_TYPE_MODULE; + } + else + { + m_log.Log("Unknown project type: " + typeString, true); + return false; + } + m_titleImage = projectData.value("title_image", ""); m_titleSound = projectData.value("title_sound", ""); diff --git a/core/story-manager/src/story_project.h b/core/story-manager/src/story_project.h index 45aa220..c3392c1 100644 --- a/core/story-manager/src/story_project.h +++ b/core/story-manager/src/story_project.h @@ -83,6 +83,8 @@ public: // Initialize with an existing project const bool IsInitialized() const { return m_initialized; } + const bool IsModule() const { return m_projectType == IStoryProject::PROJECT_TYPE_MODULE; } + const bool IsStory() const { return m_projectType == IStoryProject::PROJECT_TYPE_STORY; } bool ParseStoryInformation(nlohmann::json &j); @@ -117,9 +119,11 @@ private: std::string m_titleImage; std::string m_titleSound; std::string m_description; + + IStoryProject::Type m_projectType{IStoryProject::PROJECT_TYPE_STORY}; + uint32_t m_version; bool m_selected{false}; - IStoryProject::ProjectType m_type{IStoryProject::PROJECT_TYPE_STORY}; std::unordered_set m_usedLabels; // permet de ne pas générer un label qui existe déjà diff --git a/story-editor/src/node_editor/node_editor_window.cpp b/story-editor/src/node_editor/node_editor_window.cpp index c117fb4..071414b 100644 --- a/story-editor/src/node_editor/node_editor_window.cpp +++ b/story-editor/src/node_editor/node_editor_window.cpp @@ -26,10 +26,11 @@ if (!(x)) { \ #include "json.hpp" -NodeEditorWindow::NodeEditorWindow(IStoryManager &manager, NodesFactory &factory) - : WindowBase("Node editor") +NodeEditorWindow::NodeEditorWindow(IStoryManager &manager, NodesFactory &factory, IStoryManager::ProjectType type) + : WindowBase(type == IStoryManager::ProjectType::PROJECT_TYPE_STORY ? "Story editor" : "Module editor") , m_manager(manager) , m_nodesFactory(factory) + , m_editorType(type) { // registerNode("media-node"); @@ -379,26 +380,20 @@ void NodeEditorWindow::Draw() void NodeEditorWindow::ToolbarUI() { - auto& io = ImGui::GetIO(); - ImVec2 window_pos = ImGui::GetWindowPos(); - ImVec2 window_size = ImGui::GetWindowSize(); - ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoMove; - // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - // { - // const ImGuiViewport* viewport = ImGui::GetWindowViewport(); - // window_flags |= ImGuiWindowFlags_NoDocking; - // io.ConfigViewportsNoDecoration = true; - // ImGui::SetNextWindowViewport(viewport->ID); - // } - ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background - // ImGui::PushStyleColor(ImGuiCol_Button, m_StyleColors[BluePrintStyleColor_ToolButton]); - // ImGui::PushStyleColor(ImGuiCol_ButtonHovered, m_StyleColors[BluePrintStyleColor_ToolButtonHovered]); - // ImGui::PushStyleColor(ImGuiCol_ButtonActive, m_StyleColors[BluePrintStyleColor_ToolButtonActive]); - // ImGui::PushStyleColor(ImGuiCol_TexGlyphShadow, ImVec4(0.1, 0.1, 0.1, 0.8)); - // ImGui::PushStyleVar(ImGuiStyleVar_TexGlyphShadowOffset, ImVec2(2.0, 2.0)); + // auto& io = ImGui::GetIO(); + // ImVec2 window_pos = ImGui::GetWindowPos(); + // ImVec2 window_size = ImGui::GetWindowSize(); + // ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoMove; - ImGui::Begin("TOOLBAR", NULL, window_flags); - // ImGui::PopStyleVar(); + // ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background + + // ImGui::Begin("TOOLBAR", NULL, window_flags); + + + ImGui::SetCursorPos(ImVec2(10, 40)); + ImGui::BeginChild("ToolbarChild", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 1.5f), false, ImGuiWindowFlags_NoScrollbar); + + ImGui::PushID(m_editorType); // Draw call stack, each function is a button for (auto page : m_callStack) @@ -422,11 +417,17 @@ void NodeEditorWindow::ToolbarUI() ImGui::SameLine(); } - ImGui::End(); - // ImGui::PopStyleVar(); - // ImGui::PopStyleColor(4); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - { - io.ConfigViewportsNoDecoration = false; - } + ImGui::PopID(); + + // ImGui::End(); + + ImGui::EndChild(); // Fin de la ChildWindow de la barre d'outils + + ImGui::SetCursorPos(ImVec2(0, 0)); + + + // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + // { + // io.ConfigViewportsNoDecoration = false; + // } } diff --git a/story-editor/src/node_editor/node_editor_window.h b/story-editor/src/node_editor/node_editor_window.h index 7de3d52..ee168e2 100644 --- a/story-editor/src/node_editor/node_editor_window.h +++ b/story-editor/src/node_editor/node_editor_window.h @@ -25,8 +25,9 @@ namespace ed = ax::NodeEditor; class NodeEditorWindow : public WindowBase { -public: - NodeEditorWindow(IStoryManager &manager, NodesFactory &factory); +public: + + NodeEditorWindow(IStoryManager &manager, NodesFactory &factory, IStoryManager::ProjectType type = IStoryManager::ProjectType::PROJECT_TYPE_STORY); ~NodeEditorWindow(); virtual void Draw() override; @@ -40,6 +41,7 @@ public: private: IStoryManager &m_manager; NodesFactory &m_nodesFactory; + IStoryManager::ProjectType m_editorType{IStoryManager::ProjectType::PROJECT_TYPE_STORY}; bool m_loaded{false}; diff --git a/story-editor/src/windows/main_window.cpp b/story-editor/src/windows/main_window.cpp index 8299298..766bd67 100644 --- a/story-editor/src/windows/main_window.cpp +++ b/story-editor/src/windows/main_window.cpp @@ -30,6 +30,7 @@ MainWindow::MainWindow() , m_cpuWindow(*this) , m_resourcesWindow(*this) , m_nodeEditorWindow(*this, m_nodesFactory) + , m_moduleEditorWindow(*this, m_nodesFactory, NodeEditorWindow::EditorType::NODE_EDITOR_MODULE) , m_libraryWindow(*this, m_libraryManager) , m_variablesWindow(*this) , m_player(*this) @@ -582,6 +583,7 @@ bool MainWindow::Initialize() m_debuggerWindow.Initialize(); m_emulatorWindow.Initialize(); m_nodeEditorWindow.Initialize(); + m_moduleEditorWindow.Initialize(); m_PropertiesWindow.Initialize(); m_libraryWindow.Initialize(); @@ -835,7 +837,7 @@ void MainWindow::ProjectPropertiesPopup() } } -void MainWindow::SaveProject() +void MainWindow::SaveProject(IStoryManager::ProjectType type) { nlohmann::json model; m_story->Save(m_resources); @@ -844,7 +846,8 @@ void MainWindow::SaveProject() void MainWindow::OpenProject(const std::string &uuid) { - CloseProject(); + CloseProject(IStoryManager::ProjectType::PROJECT_TYPE_STORY); + m_story = m_libraryManager.GetStory(uuid); // DEBUG CODE !!!!!!!!!!!!! Permet si décommenter de forcer l'import, permet de tester plus facilement l'algo en ouvrant le projet @@ -875,6 +878,7 @@ void MainWindow::OpenProject(const std::string &uuid) } m_nodeEditorWindow.Enable(); + m_emulatorWindow.Enable(); m_consoleWindow.Enable(); m_debuggerWindow.Enable(); @@ -891,6 +895,70 @@ void MainWindow::OpenProject(const std::string &uuid) RefreshProjectInformation(); } +void MainWindow::OpenModule(const std::string &uuid) +{ + m_story = m_libraryManager.GetModule(uuid); + if (!m_story) + { + Log("Cannot find module: " + uuid); + } + else if (m_story->Load(m_resources, m_nodesFactory)) + { + Log("Open module success"); + m_moduleEditorWindow.Load(m_story); + } + else + { + Log("Open module error"); + } + + + m_moduleEditorWindow.Enable(); +} + + + +void MainWindow::CloseProject(IStoryManager::ProjectType type) +{ + // FIXME: not sure but if present, we lost some information in the library manager + + // if (m_story) + // { + // m_story->Clear(); + // m_story.reset(); + // } + + m_resources.Clear(); + + if (type == IStoryManager::ProjectType::PROJECT_TYPE_STORY) + { + m_nodeEditorWindow.Initialize(); + m_nodeEditorWindow.Disable(); + } + else if (type == IStoryManager::ProjectType::PROJECT_TYPE_MODULE) + { + m_moduleEditorWindow.Initialize(); + m_moduleEditorWindow.Disable(); + } + + // FIXME: si un des deux types de projets est encore ouvert, on ne va pas fermer + // le sautres fenêtres de preview + + m_emulatorWindow.ClearImage(); + m_consoleWindow.ClearLog(); + m_debuggerWindow.ClearErrors(); + m_debuggerWindow.SetScript(""); + + m_emulatorWindow.Disable(); + m_debuggerWindow.Disable(); + m_resourcesWindow.Disable(); + m_PropertiesWindow.Disable(); + m_variablesWindow.Disable(); + m_cpuWindow.Disable(); + + RefreshProjectInformation(); +} + void MainWindow::ImportProject(const std::string &filePathName, int format) { @@ -927,36 +995,6 @@ void MainWindow::RefreshProjectInformation() } -void MainWindow::CloseProject() -{ - // FIXME: not sure but if present, we lost some information in the library manager - - // if (m_story) - // { - // m_story->Clear(); - // m_story.reset(); - // } - - m_resources.Clear(); - - m_nodeEditorWindow.Initialize(); - m_emulatorWindow.ClearImage(); - m_consoleWindow.ClearLog(); - m_debuggerWindow.ClearErrors(); - m_debuggerWindow.SetScript(""); - - m_nodeEditorWindow.Disable(); - m_emulatorWindow.Disable(); - m_debuggerWindow.Disable(); - m_resourcesWindow.Disable(); - m_PropertiesWindow.Disable(); - m_variablesWindow.Disable(); - m_cpuWindow.Disable(); - - RefreshProjectInformation(); -} - - void MainWindow::DrawToolBar(float topPadding) { ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | @@ -1031,6 +1069,7 @@ void MainWindow::Loop() m_debuggerWindow.Draw(); m_resourcesWindow.Draw(); m_nodeEditorWindow.Draw(); + m_moduleEditorWindow.Draw(); m_variablesWindow.Draw(); m_cpuWindow.Draw(); diff --git a/story-editor/src/windows/main_window.h b/story-editor/src/windows/main_window.h index 9a6f764..2cfb42a 100644 --- a/story-editor/src/windows/main_window.h +++ b/story-editor/src/windows/main_window.h @@ -116,6 +116,8 @@ private: NodeEditorWindow m_nodeEditorWindow; + NodeEditorWindow m_moduleEditorWindow; + PropertiesWindow m_PropertiesWindow; LibraryWindow m_libraryWindow; @@ -134,7 +136,12 @@ private: WebServer m_webServer; // From IStoryManager (proxy to StoryProject class) - virtual void OpenProject(const std::string &uuid) override; + virtual void OpenProject(const std::string &uuid, IStoryManager::ProjectType type) override; + + void SaveProject(IStoryManager::ProjectType type); + void CloseProject(IStoryManager::ProjectType type); + + // From IStoryManager (proxy to StoryProject class) virtual void ImportProject(const std::string &filePathName, int format); virtual void PlaySoundFile(const std::string &fileName) override;; virtual std::string BuildFullAssetsPath(const std::string_view fileName) const override; @@ -185,8 +192,6 @@ private: bool ShowQuitConfirm(); void DrawToolBar(float topPadding); - void SaveProject(); - void CloseProject(); void DrawStatusBar(); void UpdateVmView();