Module save/load
Some checks are pending
Build-StoryEditor / build_linux (push) Waiting to run
Build-StoryEditor / build_win32 (push) Waiting to run
Deploy-Documentation / deploy (push) Waiting to run

This commit is contained in:
anthony@rabine.fr 2025-07-27 16:09:48 +02:00
parent 8aec974f89
commit 65094d88a3
10 changed files with 426 additions and 250 deletions

View file

@ -19,12 +19,6 @@ public:
virtual std::string GetName() const = 0; virtual std::string GetName() const = 0;
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0;
virtual int OutputsCount(const std::string &nodeId) = 0;
virtual StoryOptions GetOptions() = 0;
/* Retourne true si la resource existe déjà et que le code a déjà été généré */
virtual bool UseResource(const std::string &label) = 0;
}; };

View file

@ -14,6 +14,7 @@
#include "print_node.h" #include "print_node.h"
#include "syscall_node.h" #include "syscall_node.h"
#include "story_project.h" #include "story_project.h"
#include "story_primitive.h"
static const std::string OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec"; static const std::string OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec";
static const std::string CallFunctionNodeUuid = "02745f38-9b11-49fe-94b1-b2a6b78249fb"; static const std::string CallFunctionNodeUuid = "02745f38-9b11-49fe-94b1-b2a6b78249fb";
@ -35,18 +36,24 @@ public:
{ {
// Register node types // Register node types
// registerNode<MediaNode>("media-node"); // registerNode<MediaNode>("media-node");
registerNode<OperatorNode>(OperatorNodeUuid, nullptr); registerNode<OperatorNode>(OperatorNodeUuid, std::make_shared<StoryPrimitive>("Operator"));
registerNode<CallFunctionNode>(CallFunctionNodeUuid, nullptr); registerNode<CallFunctionNode>(CallFunctionNodeUuid, std::make_shared<StoryPrimitive>("Call function"));
registerNode<VariableNode>(VariableNodeUuid, nullptr); registerNode<VariableNode>(VariableNodeUuid, std::make_shared<StoryPrimitive>("Variable"));
registerNode<PrintNode>(PrintNodeUuid, nullptr); registerNode<PrintNode>(PrintNodeUuid, std::make_shared<StoryPrimitive>("Print"));
registerNode<SyscallNode>(SyscallNodeUuid, nullptr); registerNode<SyscallNode>(SyscallNodeUuid, std::make_shared<StoryPrimitive>("System call"));
} }
~NodesFactory() = default; ~NodesFactory() = default;
std::vector<std::string> GetNodeTypes() const { struct NodeInfo {
std::vector<std::string> l; std::string uuid;
for(auto const& imap: m_registry) l.push_back(imap.first); std::string name;
};
// key: uuid, value: node name
std::vector<NodeInfo> LitOfNodes() const {
std::vector<NodeInfo> l;
for(auto const& imap: m_registry) l.push_back(NodeInfo{imap.first, imap.second.first->GetName() });
return l; return l;
} }
@ -78,7 +85,12 @@ public:
// We have a module here, get the name // We have a module here, get the name
if (n.second.first->GetName() == name) if (n.second.first->GetName() == name)
{ {
module = n.second.first; auto p = dynamic_cast<StoryProject*>(n.second.first.get());
if (p == nullptr)
{
throw std::runtime_error("Node is not a StoryProject");
}
module = p->shared_from_this();
} }
} }
} }
@ -87,34 +99,71 @@ public:
return module; return module;
} }
void SaveAllModules(ResourceManager &manager)
{
for (const auto &entry : m_registry)
{
// Uniquement les modules custom (ici ModuleNodeUuid)
if (entry.first == ModuleNodeUuid)
{
// Get the module from the registry
auto module = std::dynamic_pointer_cast<StoryProject>(entry.second.first);
if (module)
{
module->Save(manager);
}
}
}
}
// Creates a new empty module (StoryProject) and registers it as a module node.
std::shared_ptr<StoryProject> NewModule(const std::string& moduleName = "Untitled Module") {
// Create a new StoryProject with the given name
auto module = std::make_shared<StoryProject>(m_log);
module->New(Uuid().String(), m_rootPath);
module->SetName(moduleName);
module->SetTitleImage("");
module->SetTitleSound("");
module->SetDisplayFormat(320, 240);
module->SetImageFormat(Resource::ImageFormat::IMG_SAME_FORMAT);
module->SetSoundFormat(Resource::SoundFormat::SND_SAME_FORMAT);
module->SetDescription("");
module->SetProjectType(IStoryProject::PROJECT_TYPE_MODULE);
// Register as module node if not already in registry
registerNode<ModuleNode>(ModuleNodeUuid, module);
return module;
}
void SetModulesRootDirectory(const std::string &rootPath) { void SetModulesRootDirectory(const std::string &rootPath) {
m_rootPath = rootPath; m_rootPath = rootPath;
} }
void ScanModules() { 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; 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<CustomModuleNode>("custom-module-node");
// Loop through files in m_rootPath // Loop through files in m_rootPath
// and register them as nodes if they match certain criteria // and register them as nodes if they match certain criteria
for (const auto& entry : std::filesystem::directory_iterator(m_rootPath)) for (const auto& entry : std::filesystem::directory_iterator(m_rootPath))
{ {
if (entry.is_regular_file() && entry.path().extension() == ".json") // Enter directory and look for .json files
if (entry.is_directory())
{ {
std::cout << "Scanning directory: " << entry.path() << std::endl;
for (const auto& subEntry : std::filesystem::directory_iterator(entry.path()))
{
if (subEntry.is_regular_file() && subEntry.path().extension() == ".json")
{
std::cout << "Found module file: " << subEntry.path() << std::endl;
// Load the JSON file and register a node based on its content // Load the JSON file and register a node based on its content
std::ifstream file(entry.path()); std::ifstream file(subEntry.path());
nlohmann::json j; nlohmann::json j;
file >> j; file >> j;
auto p = std::make_shared<StoryProject>(m_log); auto p = std::make_shared<StoryProject>(m_log);
p->ParseStoryInformation(j); p->ParseStoryInformation(j);
if (p->IsModule()) if (p->IsModule())
{ {
registerNode<ModuleNode>(ModuleNodeUuid, p); registerNode<ModuleNode>(ModuleNodeUuid, p);
@ -127,6 +176,12 @@ public:
// 2. for each function node, check if it has a "requires" field // 2. for each function node, check if it has a "requires" field
// 3. if it does, check if we have them // 3. if it does, check if we have them
} }
else
{
std::cout << "Skipping non-module project: " << p->GetName() << std::endl;
}
}
}
} }
} }
} }
@ -143,11 +198,11 @@ private:
}; };
// UUID is the key, and the value is a function that creates the node // UUID is the key, and the value is a function that creates the node
typedef std::map<std::string, std::pair<std::shared_ptr<StoryProject>, GenericCreator>> Registry; typedef std::map<std::string, std::pair<std::shared_ptr<IStoryProject>, GenericCreator>> Registry;
Registry m_registry; Registry m_registry;
template<class Derived> template<class Derived>
void registerNode(const std::string& uuid, std::shared_ptr<StoryProject> moduleInfo) { void registerNode(const std::string& uuid, std::shared_ptr<IStoryProject> moduleInfo) {
m_registry.insert(std::make_pair(uuid, std::make_pair(moduleInfo, Factory<Derived>::create_func))); m_registry.insert(std::make_pair(uuid, std::make_pair(moduleInfo, Factory<Derived>::create_func)));
} }
}; };

View file

@ -0,0 +1,25 @@
#pragma once
#include "i_story_project.h"
class StoryPrimitive : public IStoryProject
{
public:
StoryPrimitive(const std::string &name)
: m_name(name)
{
}
virtual ~StoryPrimitive() {};
virtual std::string GetName() const
{
return m_name;
}
private:
std::string m_name;
};

View file

@ -558,8 +558,18 @@ bool StoryProject::Load(ResourceManager &manager, NodesFactory &factory)
void StoryProject::Save(ResourceManager &manager) void StoryProject::Save(ResourceManager &manager)
{ {
try
{
nlohmann::json j; nlohmann::json j;
j["project"] = { {"name", m_name}, {"uuid", m_uuid}, { "title_image", m_titleImage }, { "title_sound", m_titleSound } }; j["project"] = {
{"name", m_name},
{"uuid", m_uuid},
{ "title_image", m_titleImage },
{ "title_sound", m_titleSound },
{"description", m_description},
{"type", (m_projectType == IStoryProject::PROJECT_TYPE_STORY) ? "story" : "module"},
{"version", m_version}
};
{ {
nlohmann::json resourcesData; nlohmann::json resourcesData;
@ -617,6 +627,11 @@ void StoryProject::Save(ResourceManager &manager)
std::ofstream o(m_project_file_path); std::ofstream o(m_project_file_path);
o << std::setw(4) << j << std::endl; o << std::setw(4) << j << std::endl;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
} }

View file

@ -19,7 +19,7 @@
class NodesFactory; class NodesFactory;
struct StoryProject : public IStoryProject struct StoryProject : public std::enable_shared_from_this<StoryProject>, public IStoryProject
{ {
public: public:
@ -30,6 +30,10 @@ public:
return &m_selected; return &m_selected;
} }
// std::shared_ptr<StoryProject> shared_from_this() {
// return shared_from_this();
// }
std::string MainUuid() const { std::string MainUuid() const {
return "490745ab-df4d-476d-ae27-027e94b8ee0a"; return "490745ab-df4d-476d-ae27-027e94b8ee0a";
} }
@ -86,14 +90,15 @@ public:
const bool IsInitialized() const { return m_initialized; } const bool IsInitialized() const { return m_initialized; }
const bool IsModule() const { return m_projectType == IStoryProject::PROJECT_TYPE_MODULE; } const bool IsModule() const { return m_projectType == IStoryProject::PROJECT_TYPE_MODULE; }
const bool IsStory() const { return m_projectType == IStoryProject::PROJECT_TYPE_STORY; } const bool IsStory() const { return m_projectType == IStoryProject::PROJECT_TYPE_STORY; }
void SetProjectType(IStoryProject::Type type) { m_projectType = type; }
bool ParseStoryInformation(nlohmann::json &j); bool ParseStoryInformation(nlohmann::json &j);
// From IStoryProject // From IStoryProject
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) override; virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId);
virtual int OutputsCount(const std::string &nodeId) override; virtual int OutputsCount(const std::string &nodeId);
virtual StoryOptions GetOptions() override { return m_storyOptions; } StoryOptions GetOptions() { return m_storyOptions; }
virtual bool UseResource(const std::string &label) override; virtual bool UseResource(const std::string &label);
// Node interaction // Node interaction
std::shared_ptr<StoryPage> CreatePage(const std::string &uuid); std::shared_ptr<StoryPage> CreatePage(const std::string &uuid);

View file

@ -4,13 +4,13 @@ Size=1220,694
Collapsed=0 Collapsed=0
[Window][Debug##Default] [Window][Debug##Default]
Pos=60,60 Pos=106,62
Size=400,400 Size=400,400
Collapsed=0 Collapsed=0
[Window][Library Manager] [Window][Library Manager]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
@ -21,20 +21,20 @@ Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
[Window][Emulator] [Window][Emulator]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,5 DockId=0x00000003,5
[Window][Code viewer] [Window][Code viewer]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,4 DockId=0x00000003,4
[Window][Resources] [Window][Resources]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,1 DockId=0x00000003,1
@ -56,20 +56,20 @@ Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
[Window][CPU] [Window][CPU]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,2 DockId=0x00000003,2
[Window][RAM view] [Window][RAM view]
Pos=796,26 Pos=643,26
Size=484,268 Size=637,268
Collapsed=0 Collapsed=0
DockId=0x00000003,3 DockId=0x00000003,3
[Window][Properties] [Window][Properties]
Pos=796,296 Pos=643,296
Size=484,169 Size=637,169
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
@ -79,8 +79,8 @@ Size=60,694
Collapsed=0 Collapsed=0
[Window][QuitConfirm] [Window][QuitConfirm]
Pos=479,312 Pos=508,312
Size=321,96 Size=264,96
Collapsed=0 Collapsed=0
[Window][ProjectPropertiesPopup] [Window][ProjectPropertiesPopup]
@ -90,13 +90,13 @@ Collapsed=0
[Window][Module editor] [Window][Module editor]
Pos=60,26 Pos=60,26
Size=734,439 Size=581,439
Collapsed=0 Collapsed=0
DockId=0x00000001,1 DockId=0x00000001,1
[Window][Story editor] [Window][Story editor]
Pos=60,26 Pos=60,26
Size=734,439 Size=581,439
Collapsed=0 Collapsed=0
DockId=0x00000001,0 DockId=0x00000001,0
@ -122,9 +122,9 @@ Column 2 Width=124
[Docking][Data] [Docking][Data]
DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=Y DockSpace ID=0x08BD597D Window=0x1BBC0F80 Pos=60,26 Size=1220,694 Split=Y
DockNode ID=0x00000007 Parent=0x08BD597D SizeRef=1220,439 Split=X DockNode ID=0x00000007 Parent=0x08BD597D SizeRef=1220,439 Split=X
DockNode ID=0x00000001 Parent=0x00000007 SizeRef=734,694 CentralNode=1 Selected=0x93ADCAAB DockNode ID=0x00000001 Parent=0x00000007 SizeRef=581,694 CentralNode=1 Selected=0x54E37131
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=484,694 Split=Y Selected=0x52EB28B5 DockNode ID=0x00000002 Parent=0x00000007 SizeRef=637,694 Split=Y Selected=0x52EB28B5
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=718,268 Selected=0x4B07C626 DockNode ID=0x00000003 Parent=0x00000002 SizeRef=718,268 Selected=0x63869CAF
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=718,169 Selected=0x8C72BEA8 DockNode ID=0x00000006 Parent=0x00000002 SizeRef=718,169 Selected=0x8C72BEA8
DockNode ID=0x00000008 Parent=0x08BD597D SizeRef=1220,253 Split=X Selected=0xEA83D666 DockNode ID=0x00000008 Parent=0x08BD597D SizeRef=1220,253 Split=X Selected=0xEA83D666
DockNode ID=0x00000004 Parent=0x00000008 SizeRef=610,192 Selected=0xEA83D666 DockNode ID=0x00000004 Parent=0x00000008 SizeRef=610,192 Selected=0xEA83D666

View file

@ -34,28 +34,47 @@ NodeEditorWindow::NodeEditorWindow(IStoryManager &manager, NodesFactory &factory
, m_editorType(type) , m_editorType(type)
{ {
// g OperatorNodeUuid = "0226fdac-8f7a-47d7-8584-b23aceb712ec";
// static const std::string CallFunctionNodeUuid = "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";
// static const std::string ModuleNodeUuid = "02e4c728-ef72-4003-b7c8-2bee8834a47e";
// registerNode<MediaNodeWidget>("media-node"); // registerNode<MediaNodeWidget>("media-node");
registerNode<OperatorNodeWidget>("operator-node"); registerNode<OperatorNodeWidget>(OperatorNodeUuid);
registerNode<CallFunctionNodeWidget>("call-function-node"); registerNode<CallFunctionNodeWidget>(CallFunctionNodeUuid);
registerNode<ModuleNodeWidget>("module-node"); // registerNode<ModuleNodeWidget>("module-node");
registerNode<VariableNodeWidget>("variable-node"); registerNode<VariableNodeWidget>(VariableNodeUuid);
registerNode<PrintNodeWidget>("print-node"); registerNode<PrintNodeWidget>(PrintNodeUuid);
registerNode<SyscallNodeWidget>("syscall-node"); registerNode<SyscallNodeWidget>(SyscallNodeUuid);
} }
NodeEditorWindow::~NodeEditorWindow() NodeEditorWindow::~NodeEditorWindow()
{ {
m_pages.clear(); Clear();
m_story.reset();
} }
void NodeEditorWindow::Clear()
{
m_pages.clear();
m_story.reset();
m_callStack.clear();
}
void NodeEditorWindow::Initialize() void NodeEditorWindow::Initialize()
{ {
m_pages.clear(); Clear();
m_callStack.clear(); }
void NodeEditorWindow::InitializeProject()
{
// Always ensure a main page exists (this matches StoryProject::New)
if (!m_story->GetPage(m_story->MainUuid()))
{
m_story->CreatePage(m_story->MainUuid());
}
m_currentPage = std::make_shared<NodeEditorPage>(m_story->MainUuid(), "Main"); m_currentPage = std::make_shared<NodeEditorPage>(m_story->MainUuid(), "Main");
m_pages.push_back(m_currentPage); m_pages.push_back(m_currentPage);
m_callStack.push_back(m_currentPage); m_callStack.push_back(m_currentPage);
@ -108,7 +127,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
try { try {
BaseNodeWidget::InitId(); BaseNodeWidget::InitId();
Initialize(); InitializeProject();
auto [node_begin, node_end] = m_story->Nodes(m_currentPage->Uuid()); auto [node_begin, node_end] = m_story->Nodes(m_currentPage->Uuid());
@ -204,6 +223,11 @@ bool NodeEditorWindow::FillConnection(std::shared_ptr<Connection> c, ed::PinId p
std::shared_ptr<BaseNodeWidget> NodeEditorWindow::GetSelectedNode() std::shared_ptr<BaseNodeWidget> NodeEditorWindow::GetSelectedNode()
{ {
if (!m_currentPage)
{
return nullptr; // No current page, nothing to select
}
std::shared_ptr<BaseNodeWidget> selected; std::shared_ptr<BaseNodeWidget> selected;
m_currentPage->Select(); m_currentPage->Select();
@ -225,6 +249,9 @@ void NodeEditorWindow::Draw()
} }
if (WindowBase::BeginDraw()) if (WindowBase::BeginDraw())
{
if (m_currentPage)
{ {
m_currentPage->Select(); m_currentPage->Select();
@ -232,7 +259,6 @@ void NodeEditorWindow::Draw()
ed::Begin(m_currentPage->Uuid().data(), ImVec2(0.0, 0.0f)); ed::Begin(m_currentPage->Uuid().data(), ImVec2(0.0, 0.0f));
// Draw our nodes // Draw our nodes
m_currentPage->Draw(); m_currentPage->Draw();
@ -339,17 +365,17 @@ void NodeEditorWindow::Draw()
{ {
auto newNodePostion = openPopupPosition; auto newNodePostion = openPopupPosition;
std::shared_ptr<BaseNode> base; std::shared_ptr<BaseNode> base;
auto nodeTypes = m_nodesFactory.GetNodeTypes(); auto nodeTypes = m_nodesFactory.LitOfNodes();
for (auto &type : nodeTypes) for (auto &type : nodeTypes)
{ {
if (ImGui::MenuItem(type.c_str())) if (ImGui::MenuItem(type.name.c_str()))
{ {
base = m_nodesFactory.CreateNode(type); base = m_nodesFactory.CreateNode(type.uuid);
if (base) if (base)
{ {
m_story->AddNode(m_currentPage->Uuid(), base); m_story->AddNode(m_currentPage->Uuid(), base);
auto n = CreateNodeWidget(type, m_manager, base); auto n = CreateNodeWidget(type.uuid, m_manager, base);
if (n) if (n)
{ {
n->Base()->SetPosition(newNodePostion.x, newNodePostion.y); n->Base()->SetPosition(newNodePostion.x, newNodePostion.y);
@ -374,6 +400,17 @@ void NodeEditorWindow::Draw()
ed::End(); ed::End();
ed::SetCurrentEditor(nullptr); ed::SetCurrentEditor(nullptr);
}
else
{
// Set background color to light gray
// ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.7f, 0.7f, 0.7f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::Text("Please load or create a project.");
ImGui::PopStyleColor(1); // Pop both colors
}
} }

View file

@ -33,6 +33,9 @@ public:
virtual void Draw() override; virtual void Draw() override;
void Initialize(); void Initialize();
void InitializeProject();
void NewProject();
void Clear();
void Load(std::shared_ptr<StoryProject> story); void Load(std::shared_ptr<StoryProject> story);
void SaveNodePositions(); void SaveNodePositions();
void OpenFunction(const std::string &uuid, const std::string &name); void OpenFunction(const std::string &uuid, const std::string &name);

View file

@ -52,6 +52,7 @@ MainWindow::MainWindow()
m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(chip32_ctx_t *, uint8_t)>::callback); m_chip32_ctx.syscall = static_cast<syscall_t>(Callback<uint8_t(chip32_ctx_t *, uint8_t)>::callback);
CloseProject(); CloseProject();
CloseModule();
// define style for all directories // define style for all directories
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeDir, "", ImVec4(0.5f, 1.0f, 0.9f, 0.9f), ICON_MDI_FOLDER); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeDir, "", ImVec4(0.5f, 1.0f, 0.9f, 0.9f), ICON_MDI_FOLDER);
@ -459,9 +460,18 @@ float MainWindow::DrawMainMenuBar()
OpenProject(m_story->GetUuid()); OpenProject(m_story->GetUuid());
} }
} }
if (ImGui::MenuItem("New module")) if (ImGui::MenuItem("New module"))
{ {
// Current module project
CloseModule();
showNewProject = true; showNewProject = true;
NewModule();
}
if (ImGui::MenuItem("Save module"))
{
SaveModule();
} }
/* /*
@ -492,6 +502,8 @@ float MainWindow::DrawMainMenuBar()
SaveProject(); SaveProject();
} }
if (ImGui::MenuItem("Close project")) if (ImGui::MenuItem("Close project"))
{ {
CloseProject(); CloseProject();
@ -502,6 +514,11 @@ float MainWindow::DrawMainMenuBar()
showParameters = true; showParameters = true;
} }
if (ImGui::MenuItem("Close module"))
{
CloseModule();
}
if (!init) if (!init)
ImGui::EndDisabled(); ImGui::EndDisabled();
@ -575,6 +592,8 @@ bool MainWindow::Initialize()
bool success = false; bool success = false;
LoadParams(); LoadParams();
m_nodesFactory.ScanModules();
// GUI Init // GUI Init
if (m_gui.Initialize()) if (m_gui.Initialize())
{ {
@ -896,6 +915,21 @@ void MainWindow::OpenProject(const std::string &uuid)
RefreshProjectInformation(); RefreshProjectInformation();
} }
void MainWindow::NewModule()
{
auto module = m_nodesFactory.NewModule();
m_moduleEditorWindow.Load(module);
m_moduleEditorWindow.Enable();
}
void MainWindow::SaveModule()
{
m_nodesFactory.SaveAllModules(m_resources);;
Log("Modules saved");
}
void MainWindow::OpenModule(const std::string &uuid) void MainWindow::OpenModule(const std::string &uuid)
{ {
m_module = m_nodesFactory.GetModule(uuid); m_module = m_nodesFactory.GetModule(uuid);
@ -930,7 +964,7 @@ void MainWindow::CloseProject()
// } // }
m_resources.Clear(); m_resources.Clear();
m_nodeEditorWindow.Initialize(); m_nodeEditorWindow.Clear();
m_nodeEditorWindow.Disable(); m_nodeEditorWindow.Disable();
m_emulatorWindow.ClearImage(); m_emulatorWindow.ClearImage();
@ -951,7 +985,7 @@ void MainWindow::CloseProject()
void MainWindow::CloseModule() void MainWindow::CloseModule()
{ {
m_moduleEditorWindow.Initialize(); m_moduleEditorWindow.Clear();
m_moduleEditorWindow.Disable(); m_moduleEditorWindow.Disable();
} }
@ -1337,6 +1371,12 @@ void MainWindow::SaveParams()
void MainWindow::LoadParams() void MainWindow::LoadParams()
{ {
try { try {
// Modules directory
std::filesystem::path dlDir = std::filesystem::path(pf::getConfigHome()) / "ost_modules";
std::filesystem::create_directories(dlDir);
m_nodesFactory.SetModulesRootDirectory(dlDir.string());
std::string loc = pf::getConfigHome() + "/ost_settings.json"; std::string loc = pf::getConfigHome() + "/ost_settings.json";
// read a JSON file // read a JSON file
std::ifstream i(loc); std::ifstream i(loc);
@ -1365,6 +1405,6 @@ void MainWindow::LoadParams()
} }
catch(std::exception &e) catch(std::exception &e)
{ {
Log(e.what(), true);
} }
} }

View file

@ -142,6 +142,8 @@ private:
void CloseProject(); void CloseProject();
void OpenModule(const std::string &uuid); void OpenModule(const std::string &uuid);
void NewModule();
void SaveModule();
void CloseModule(); void CloseModule();
// From IStoryManager (proxy to StoryProject class) // From IStoryManager (proxy to StoryProject class)