mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Create separated core (WIP) GUI agnostic, new sub pages for functions
This commit is contained in:
parent
f0ffb62867
commit
f538148a9a
32 changed files with 519 additions and 321 deletions
10
core/README.md
Normal file
10
core/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# StoryTeller core files
|
||||||
|
|
||||||
|
GUI agnostic implementation of the editor engine.
|
||||||
|
|
||||||
|
Directories:
|
||||||
|
- interfaces: contains only pure virtual C++ interface classes
|
||||||
|
- lib: shared static classes utilities
|
||||||
|
- src: core implementation (private files)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7,4 +7,5 @@ class ILogger
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void Log(const std::string &txt, bool critical = false) = 0;
|
virtual void Log(const std::string &txt, bool critical = false) = 0;
|
||||||
|
virtual ~ILogger() {}
|
||||||
};
|
};
|
||||||
|
|
@ -49,10 +49,6 @@ public:
|
||||||
// Node interaction
|
// Node interaction
|
||||||
virtual void BuildNodes(bool compileonly) = 0;
|
virtual void BuildNodes(bool compileonly) = 0;
|
||||||
virtual void BuildCode(bool compileonly) = 0;
|
virtual void BuildCode(bool compileonly) = 0;
|
||||||
virtual std::shared_ptr<BaseNode> CreateNode(const std::string &type) = 0;
|
|
||||||
virtual void DeleteNode(const std::string &id) = 0;
|
|
||||||
virtual void DeleteLink(std::shared_ptr<Connection> c) = 0;
|
|
||||||
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0;
|
|
||||||
virtual void LoadBinaryStory(const std::string &filename) = 0;
|
virtual void LoadBinaryStory(const std::string &filename) = 0;
|
||||||
virtual void ToggleBreakpoint(int line) = 0;
|
virtual void ToggleBreakpoint(int line) = 0;
|
||||||
virtual uint32_t GetRegister(int reg) = 0;
|
virtual uint32_t GetRegister(int reg) = 0;
|
||||||
12
core/interfaces/i_story_page.h
Normal file
12
core/interfaces/i_story_page.h
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
class IStoryPage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IStoryPage() {}
|
||||||
|
|
||||||
|
virtual void GetNodeConnections(std::list<std::shared_ptr<Connection>> &c, const std::string &nodeId) = 0;
|
||||||
|
};
|
||||||
|
|
@ -3,15 +3,16 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "story_options.h"
|
||||||
|
|
||||||
class IStoryProject
|
class IStoryProject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IStoryProject() {};
|
virtual ~IStoryProject() {};
|
||||||
|
|
||||||
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0;
|
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) = 0;
|
||||||
virtual int OutputsCount(const std::string &nodeId) = 0;
|
virtual int OutputsCount(const std::string &nodeId) = 0;
|
||||||
virtual std::string ImageExtension(const std::string &filename) const = 0;
|
virtual StoryOptions GetOptions() = 0;
|
||||||
virtual std::string SoundExtension(const std::string &filename) const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
56
core/lib/resource.cpp
Normal file
56
core/lib/resource.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
#include "sys_lib.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Resource::ImageExtension(const std::string &filename, Resource::ImageFormat prefered_format)
|
||||||
|
{
|
||||||
|
std::string ext = SysLib::GetFileExtension(filename);
|
||||||
|
if (prefered_format == Resource::ImageFormat::IMG_FORMAT_QOIF)
|
||||||
|
{
|
||||||
|
return "qoi";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Resource::SoundExtension(const std::string &filename, Resource::SoundFormat prefered_format)
|
||||||
|
{
|
||||||
|
std::string ext = SysLib::GetFileExtension(filename);
|
||||||
|
if (prefered_format == Resource::SoundFormat::SND_FORMAT_QOAF)
|
||||||
|
{
|
||||||
|
return "qoa";
|
||||||
|
}
|
||||||
|
else if (prefered_format == Resource::SoundFormat::SND_FORMAT_WAV)
|
||||||
|
{
|
||||||
|
return "wav";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,8 @@ struct Resource
|
||||||
|
|
||||||
static std::string ImageFormatToString(ImageFormat format);
|
static std::string ImageFormatToString(ImageFormat format);
|
||||||
static std::string SoundFormatToString(SoundFormat format);
|
static std::string SoundFormatToString(SoundFormat format);
|
||||||
|
static std::string ImageExtension(const std::string &filename, Resource::ImageFormat prefered_format);
|
||||||
|
static std::string SoundExtension(const std::string &filename, Resource::SoundFormat prefered_format);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Itérateur pour parcourir les éléments filtrés
|
// Itérateur pour parcourir les éléments filtrés
|
||||||
|
|
@ -82,12 +84,4 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class IResource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~IResource() {}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // RESOURCE_H
|
#endif // RESOURCE_H
|
||||||
11
core/lib/story_options.h
Normal file
11
core/lib/story_options.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
struct StoryOptions
|
||||||
|
{
|
||||||
|
Resource::ImageFormat image_format{Resource::IMG_SAME_FORMAT};
|
||||||
|
Resource::SoundFormat sound_format{Resource::SND_SAME_FORMAT};
|
||||||
|
int display_w{320};
|
||||||
|
int display_h{240};
|
||||||
|
};
|
||||||
|
|
@ -21,7 +21,6 @@ std::string SysLib::ToUpper(const std::string &input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::string SysLib::GetFileExtension(const std::string &fileName)
|
std::string SysLib::GetFileExtension(const std::string &fileName)
|
||||||
{
|
{
|
||||||
auto idx = fileName.find_last_of(".");
|
auto idx = fileName.find_last_of(".");
|
||||||
|
|
@ -80,7 +79,6 @@ std::string SysLib::RemoveFileExtension(const std::string &filename)
|
||||||
return filename.substr(0, dotPos);
|
return filename.substr(0, dotPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string SysLib::Normalize(const std::string &input)
|
std::string SysLib::Normalize(const std::string &input)
|
||||||
{
|
{
|
||||||
std::string valid_file = input;
|
std::string valid_file = input;
|
||||||
|
|
@ -6,7 +6,6 @@ class SysLib
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
static std::string GetFileExtension(const std::string &FileName);
|
static std::string GetFileExtension(const std::string &FileName);
|
||||||
static std::string GetFileName(const std::string &path);
|
static std::string GetFileName(const std::string &path);
|
||||||
static std::string RemoveFileExtension(const std::string &FileName);
|
static std::string RemoveFileExtension(const std::string &FileName);
|
||||||
|
|
@ -6,7 +6,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include "i_story_project.h"
|
#include "i_story_page.h"
|
||||||
|
#include "story_options.h"
|
||||||
|
|
||||||
class BaseNode
|
class BaseNode
|
||||||
{
|
{
|
||||||
|
|
@ -23,8 +24,8 @@ public:
|
||||||
static std::string GetEntryLabel(const std::string &id);
|
static std::string GetEntryLabel(const std::string &id);
|
||||||
|
|
||||||
virtual void Initialize() = 0;
|
virtual void Initialize() = 0;
|
||||||
virtual std::string Build(IStoryProject &story, int nb_out_conns) = 0;
|
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) = 0;
|
||||||
virtual std::string GenerateConstants(IStoryProject &story, int nb_out_conns) = 0;
|
virtual std::string GenerateConstants(IStoryPage &page, const StoryOptions &options, int nb_out_conns) = 0;
|
||||||
|
|
||||||
void SetPosition(float x, float y);
|
void SetPosition(float x, float y);
|
||||||
|
|
||||||
9
core/src/compiler.cpp
Normal file
9
core/src/compiler.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::string Compiler::FileToConstant(const std::string &FileName, const std::string &extension)
|
||||||
|
{
|
||||||
|
std::string f = SysLib::RemoveFileExtension(FileName);
|
||||||
|
return "$" + FileName + " DC8 \"" + FileName + "\", 8\r\n";
|
||||||
|
}
|
||||||
15
core/src/compiler.h
Normal file
15
core/src/compiler.h
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sys_lib.h"
|
||||||
|
|
||||||
|
class Compiler
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Compiler() = default;
|
||||||
|
~Compiler() = default;
|
||||||
|
|
||||||
|
static std::string FileToConstant(const std::string &FileName, const std::string &extension);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -27,12 +27,12 @@ void FunctionNode::Initialize()
|
||||||
// m_sound = j["sound"].get<std::string>();
|
// m_sound = j["sound"].get<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FunctionNode::Build(IStoryProject &story, int nb_out_conns)
|
std::string FunctionNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
{
|
{
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FunctionNode::GenerateConstants(IStoryProject &story, int nb_out_conns)
|
std::string FunctionNode::GenerateConstants(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@ public:
|
||||||
FunctionNode(const std::string &type);
|
FunctionNode(const std::string &type);
|
||||||
|
|
||||||
virtual void Initialize() override;
|
virtual void Initialize() override;
|
||||||
virtual std::string Build(IStoryProject &story, int nb_out_conns) override;
|
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||||
virtual std::string GenerateConstants(IStoryProject &story, int nb_out_conns) override;
|
virtual std::string GenerateConstants(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||||
|
|
||||||
void StoreInternalData();
|
void StoreInternalData();
|
||||||
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "story_project.h"
|
#include "story_project.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "sys_lib.h"
|
#include "sys_lib.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
static std::string ChoiceLabel(const std::string &id)
|
static std::string ChoiceLabel(const std::string &id)
|
||||||
{
|
{
|
||||||
|
|
@ -33,17 +34,17 @@ void MediaNode::Initialize()
|
||||||
m_sound = j["sound"].get<std::string>();
|
m_sound = j["sound"].get<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MediaNode::GenerateConstants(IStoryProject &story, int nb_out_conns)
|
std::string MediaNode::GenerateConstants(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
|
|
||||||
if (m_image.size() > 0)
|
if (m_image.size() > 0)
|
||||||
{
|
{
|
||||||
s = StoryProject::FileToConstant(m_image, story.ImageExtension(m_image));
|
s = Compiler::FileToConstant(m_image, Resource::ImageExtension(m_image, options.image_format));
|
||||||
}
|
}
|
||||||
if (m_sound.size() > 0)
|
if (m_sound.size() > 0)
|
||||||
{
|
{
|
||||||
s += StoryProject::FileToConstant(m_sound, story.SoundExtension(m_sound)); // FIXME: Generate the extension setup in user option of output format
|
s += Compiler::FileToConstant(m_sound, Resource::SoundExtension(m_sound, options.sound_format)); // FIXME: Generate the extension setup in user option of output format
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate choice table if needed (out ports > 1)
|
// Generate choice table if needed (out ports > 1)
|
||||||
|
|
@ -53,7 +54,8 @@ std::string MediaNode::GenerateConstants(IStoryProject &story, int nb_out_conns)
|
||||||
<< " DC32, "
|
<< " DC32, "
|
||||||
<< nb_out_conns << ", ";
|
<< nb_out_conns << ", ";
|
||||||
|
|
||||||
std::list<std::shared_ptr<Connection>> conns = story.GetNodeConnections(GetId());
|
std::list<std::shared_ptr<Connection>> conns;
|
||||||
|
page.GetNodeConnections(conns, GetId());
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto & c : conns)
|
for (auto & c : conns)
|
||||||
{
|
{
|
||||||
|
|
@ -100,7 +102,7 @@ std::string_view MediaNode::GetSound() const
|
||||||
return m_sound;
|
return m_sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MediaNode::Build(IStoryProject &story, int nb_out_conns)
|
std::string MediaNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
|
|
@ -148,8 +150,8 @@ std::string MediaNode::Build(IStoryProject &story, int nb_out_conns)
|
||||||
}
|
}
|
||||||
else if (nb_out_conns == 1) // it is a transition node
|
else if (nb_out_conns == 1) // it is a transition node
|
||||||
{
|
{
|
||||||
std::list<std::shared_ptr<Connection>> conns = story.GetNodeConnections(GetId());
|
std::list<std::shared_ptr<Connection>> conns;
|
||||||
|
page.GetNodeConnections(conns, GetId());
|
||||||
|
|
||||||
for (auto c : conns)
|
for (auto c : conns)
|
||||||
{
|
{
|
||||||
|
|
@ -12,8 +12,8 @@ public:
|
||||||
MediaNode(const std::string &type);
|
MediaNode(const std::string &type);
|
||||||
|
|
||||||
virtual void Initialize() override;
|
virtual void Initialize() override;
|
||||||
virtual std::string Build(IStoryProject &story, int nb_out_conns) override;
|
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||||
virtual std::string GenerateConstants(IStoryProject &story, int nb_out_conns) override;
|
virtual std::string GenerateConstants(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||||
|
|
||||||
void SetImage(const std::string &image);
|
void SetImage(const std::string &image);
|
||||||
std::string_view GetImage() const;
|
std::string_view GetImage() const;
|
||||||
4
core/src/story_page.cpp
Normal file
4
core/src/story_page.cpp
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
#include "story_page.h"
|
||||||
|
|
||||||
|
|
||||||
181
core/src/story_page.h
Normal file
181
core/src/story_page.h
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "i_story_page.h"
|
||||||
|
#include "base_node.h"
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
class StoryPage : public IStoryPage
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
StoryPage(const std::string &uuid)
|
||||||
|
: m_uuid(uuid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~StoryPage() {
|
||||||
|
m_links.clear();
|
||||||
|
m_nodes.clear();
|
||||||
|
std::cout << "StoryPage destructor" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view Uuid() const { return m_uuid; }
|
||||||
|
|
||||||
|
void AddNode(std::shared_ptr<BaseNode> node) {
|
||||||
|
m_nodes.push_back(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddLink(std::shared_ptr<Connection> link) {
|
||||||
|
m_links.push_back(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintStats() const {
|
||||||
|
std::cout << "Nodes: " << m_nodes.size() << ", links: " << m_links.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::list<std::shared_ptr<BaseNode>>::iterator, std::list<std::shared_ptr<BaseNode>>::iterator> Nodes() {
|
||||||
|
return std::make_pair(m_nodes.begin(), m_nodes.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator> Links() {
|
||||||
|
return std::make_pair(m_links.begin(), m_links.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
m_links.clear();
|
||||||
|
m_nodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Build(std::stringstream &code, const StoryOptions &options)
|
||||||
|
{
|
||||||
|
// First generate all constants
|
||||||
|
for (const auto & n : m_nodes)
|
||||||
|
{
|
||||||
|
code << n->GenerateConstants(*this, options, OutputsCount(n->GetId())) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto & n : m_nodes)
|
||||||
|
{
|
||||||
|
code << n->Build(*this, options, OutputsCount(n->GetId())) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void GetNodeConnections(std::list<std::shared_ptr<Connection>> &c, const std::string &nodeId) override
|
||||||
|
{
|
||||||
|
for (const auto & l : m_links)
|
||||||
|
{
|
||||||
|
if (l->outNodeId == nodeId)
|
||||||
|
{
|
||||||
|
c.push_back(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FindFirstNode() const
|
||||||
|
{
|
||||||
|
std::string id;
|
||||||
|
|
||||||
|
// First node is the one without connection on its input port
|
||||||
|
|
||||||
|
for (const auto & n : m_nodes)
|
||||||
|
{
|
||||||
|
bool foundConnection = false;
|
||||||
|
|
||||||
|
for (const auto& l : m_links)
|
||||||
|
{
|
||||||
|
if (l->inNodeId == n->GetId())
|
||||||
|
{
|
||||||
|
foundConnection = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundConnection)
|
||||||
|
{
|
||||||
|
id = n->GetId();
|
||||||
|
std::cout << "First node is: " + id << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OutputsCount(const std::string &nodeId) const
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (const auto & l : m_links)
|
||||||
|
{
|
||||||
|
if (l->outNodeId == nodeId)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nlohmann::json ToJson() const
|
||||||
|
{
|
||||||
|
nlohmann::json model;
|
||||||
|
model["uuid"] = m_uuid;
|
||||||
|
|
||||||
|
nlohmann::json nodes = nlohmann::json::array();
|
||||||
|
for (const auto & n : m_nodes)
|
||||||
|
{
|
||||||
|
nodes.push_back(n->ToJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
model["nodes"] = nodes;
|
||||||
|
|
||||||
|
// Save links
|
||||||
|
nlohmann::json connections = nlohmann::json::array();
|
||||||
|
for (const auto& cnx : m_links)
|
||||||
|
{
|
||||||
|
nlohmann::json c(*cnx);
|
||||||
|
connections.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
model["connections"] = connections;
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteLink(std::shared_ptr<Connection> c)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(m_links.begin(),
|
||||||
|
m_links.end(),
|
||||||
|
[&c](std::shared_ptr<Connection> const &cnx) {
|
||||||
|
return *cnx == *c;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( it != m_links.end() )
|
||||||
|
{
|
||||||
|
it->reset();
|
||||||
|
m_links.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteNode(const std::string &id)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto it = std::find_if(m_nodes.begin(),
|
||||||
|
m_nodes.end(),
|
||||||
|
[&id](std::shared_ptr<BaseNode> const &n) { return n->GetId() == id; });
|
||||||
|
|
||||||
|
if ( it != m_nodes.end() )
|
||||||
|
{
|
||||||
|
it->reset();
|
||||||
|
m_nodes.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_uuid;
|
||||||
|
std::string m_name;
|
||||||
|
std::list<std::shared_ptr<Connection>> m_links;
|
||||||
|
std::list<std::shared_ptr<BaseNode>> m_nodes;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -56,7 +56,7 @@ void StoryProject::CopyToDevice(const std::string &outputDir)
|
||||||
std::filesystem::copy(BinaryFileName(), destRootDir, std::filesystem::copy_options::overwrite_existing);
|
std::filesystem::copy(BinaryFileName(), destRootDir, std::filesystem::copy_options::overwrite_existing);
|
||||||
|
|
||||||
// Convert resources (if necessary) and copy them to destination assets
|
// Convert resources (if necessary) and copy them to destination assets
|
||||||
manager.ConvertResources(AssetsPath(), destAssetsDir, m_imageFormat, m_soundFormat);
|
manager.ConvertResources(AssetsPath(), destAssetsDir, m_storyOptions.image_format, m_storyOptions.sound_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,29 +109,22 @@ bool StoryProject::ParseStoryInformation(nlohmann::json &j)
|
||||||
|
|
||||||
void StoryProject::ModelToJson(nlohmann::json &model)
|
void StoryProject::ModelToJson(nlohmann::json &model)
|
||||||
{
|
{
|
||||||
nlohmann::json nodes = nlohmann::json::array();
|
for (const auto & p : m_pages)
|
||||||
for (const auto & n : m_nodes)
|
|
||||||
{
|
{
|
||||||
nodes.push_back(n->ToJson());
|
nlohmann::json page = p->ToJson();
|
||||||
|
model.push_back(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
model["nodes"] = nodes;
|
|
||||||
|
|
||||||
// Save links
|
|
||||||
nlohmann::json connections = nlohmann::json::array();
|
|
||||||
for (const auto& cnx : m_links)
|
|
||||||
{
|
|
||||||
nlohmann::json c(*cnx);
|
|
||||||
connections.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
model["connections"] = connections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<StoryPage> StoryProject::CreatePage(const std::string &uuid)
|
||||||
std::shared_ptr<BaseNode> StoryProject::CreateNode(const std::string &type)
|
|
||||||
{
|
{
|
||||||
|
auto newPage = std::make_shared<StoryPage>(uuid);
|
||||||
|
m_pages.push_back(newPage);
|
||||||
|
return newPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BaseNode> StoryProject::CreateNode(const std::string_view &page_uuid, const std::string &type)
|
||||||
|
{
|
||||||
typename Registry::const_iterator i = m_registry.find(type);
|
typename Registry::const_iterator i = m_registry.find(type);
|
||||||
if (i == m_registry.end()) {
|
if (i == m_registry.end()) {
|
||||||
throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
|
throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
|
||||||
|
|
@ -140,88 +133,132 @@ std::shared_ptr<BaseNode> StoryProject::CreateNode(const std::string &type)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto n = i->second(type);
|
auto n = i->second(type);
|
||||||
m_nodes.push_back(n);
|
|
||||||
|
for (auto & p : m_pages)
|
||||||
|
{
|
||||||
|
if (p->Uuid() == page_uuid)
|
||||||
|
{
|
||||||
|
p->AddNode(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryProject::AddConnection(std::shared_ptr<Connection> c)
|
void StoryProject::AddConnection(const std::string_view &page_uuid, std::shared_ptr<Connection> c)
|
||||||
{
|
|
||||||
m_links.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoryProject::DeleteNode(const std::string &id)
|
|
||||||
{
|
{
|
||||||
auto it = std::find_if(m_nodes.begin(),
|
for (const auto & p : m_pages)
|
||||||
m_nodes.end(),
|
|
||||||
[&id](std::shared_ptr<BaseNode> const &n) { return n->GetId() == id; });
|
|
||||||
|
|
||||||
if ( it != m_nodes.end() )
|
|
||||||
{
|
{
|
||||||
it->reset();
|
if (p->Uuid() == page_uuid)
|
||||||
m_nodes.erase(it);
|
{
|
||||||
|
p->AddLink(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryProject::DeleteLink(std::shared_ptr<Connection> c)
|
void StoryProject::DeleteNode(const std::string_view &page_uuid, const std::string &id)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(m_links.begin(),
|
for (const auto & p : m_pages)
|
||||||
m_links.end(),
|
|
||||||
[&c](std::shared_ptr<Connection> const &cnx) {
|
|
||||||
return *cnx == *c;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( it != m_links.end() )
|
|
||||||
{
|
{
|
||||||
it->reset();
|
if (p->Uuid() == page_uuid)
|
||||||
m_links.erase(it);
|
{
|
||||||
|
p->DeleteNode(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StoryProject::DeleteLink(const std::string_view &page_uuid, std::shared_ptr<Connection> c)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (const auto & p : m_pages)
|
||||||
|
{
|
||||||
|
if (p->Uuid() == page_uuid)
|
||||||
|
{
|
||||||
|
p->DeleteLink(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::list<std::shared_ptr<BaseNode>>::iterator, std::list<std::shared_ptr<BaseNode>>::iterator> StoryProject::Nodes(const std::string_view &page_uuid)
|
||||||
|
{
|
||||||
|
for (const auto & p : m_pages)
|
||||||
|
{
|
||||||
|
if (p->Uuid() == page_uuid)
|
||||||
|
{
|
||||||
|
return p->Nodes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::pair<std::list<std::shared_ptr<BaseNode>>::iterator, std::list<std::shared_ptr<BaseNode>>::iterator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator> StoryProject::Links(const std::string_view &page_uuid)
|
||||||
|
{
|
||||||
|
for (const auto & p : m_pages)
|
||||||
|
{
|
||||||
|
if (p->Uuid() == page_uuid)
|
||||||
|
{
|
||||||
|
return p->Links();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator>();
|
||||||
|
}
|
||||||
|
|
||||||
bool StoryProject::ModelFromJson(const nlohmann::json &model)
|
bool StoryProject::ModelFromJson(const nlohmann::json &model)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
nlohmann::json nodesJsonArray = model["nodes"];
|
nlohmann::json pagesJsonArray = model["pages"];
|
||||||
|
m_pages.clear();
|
||||||
|
|
||||||
m_nodes.clear();
|
for (auto& pageModel : pagesJsonArray)
|
||||||
m_links.clear();
|
|
||||||
|
|
||||||
for (auto& element : nodesJsonArray) {
|
|
||||||
|
|
||||||
std::string type = element["type"].get<std::string>();
|
|
||||||
|
|
||||||
auto n = CreateNode(type);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
n->FromJson(element);
|
|
||||||
n->Initialize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::logic_error(std::string("No registered model with name ") + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::cout << model.dump(4) << std::endl;
|
|
||||||
|
|
||||||
// Ici on reste flexible sur les connexions, cela permet de créer éventuellement des
|
|
||||||
// projets sans fils (bon, l'élément devrait quand même exister dans le JSON)
|
|
||||||
if (model.contains("connections"))
|
|
||||||
{
|
{
|
||||||
nlohmann::json connectionJsonArray = model["connections"];
|
// 1. Create the page in memory
|
||||||
|
auto p = std::make_shared<StoryPage>(pageModel["uuid"].get<std::string>());
|
||||||
|
m_pages.push_back(p);
|
||||||
|
|
||||||
// key: node UUID, value: output counts
|
// 2. Load the nodes
|
||||||
std::map<std::string, int> outputCounts;
|
nlohmann::json nodesJsonArray = pageModel["nodes"];
|
||||||
|
for (auto& element : nodesJsonArray) {
|
||||||
|
|
||||||
|
std::string type = element["type"].get<std::string>();
|
||||||
|
|
||||||
for (auto& connection : connectionJsonArray)
|
auto n = CreateNode(p->Uuid(), type);
|
||||||
{
|
if (n)
|
||||||
m_links.push_back(std::make_shared<Connection>(connection.get<Connection>()));
|
{
|
||||||
|
n->FromJson(element);
|
||||||
|
n->Initialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::logic_error(std::string("No registered model with name ") + type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Load the connections
|
||||||
|
// std::cout << model.dump(4) << std::endl;
|
||||||
|
|
||||||
|
// Ici on reste flexible sur les connexions, cela permet de créer éventuellement des
|
||||||
|
// projets sans fils (bon, l'élément devrait quand même exister dans le JSON)
|
||||||
|
if (pageModel.contains("connections"))
|
||||||
|
{
|
||||||
|
nlohmann::json connectionJsonArray = pageModel["connections"];
|
||||||
|
|
||||||
|
// key: node UUID, value: output counts
|
||||||
|
std::map<std::string, int> outputCounts;
|
||||||
|
|
||||||
|
for (auto& connection : connectionJsonArray)
|
||||||
|
{
|
||||||
|
p->AddLink(std::make_shared<Connection>(connection.get<Connection>()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "From model, loded nodes: " << m_nodes.size() << ", links: " << m_links.size() << std::endl;
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
catch(nlohmann::json::exception &e)
|
catch(nlohmann::json::exception &e)
|
||||||
|
|
@ -266,97 +303,37 @@ bool StoryProject::GetAssemblyLine(uint32_t pointer_counter, uint32_t &line)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StoryProject::OutputsCount(const std::string &nodeId)
|
|
||||||
{
|
|
||||||
int count = 0;
|
|
||||||
for (const auto & l : m_links)
|
|
||||||
{
|
|
||||||
if (l->outNodeId == nodeId)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StoryProject::ImageExtension(const std::string &filename) const
|
|
||||||
{
|
|
||||||
std::string ext = SysLib::GetFileExtension(filename);
|
|
||||||
if (m_imageFormat == Resource::ImageFormat::IMG_FORMAT_QOIF)
|
|
||||||
{
|
|
||||||
return "qoi";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string StoryProject::SoundExtension(const std::string &filename) const
|
|
||||||
{
|
|
||||||
std::string ext = SysLib::GetFileExtension(filename);
|
|
||||||
if (m_soundFormat == Resource::SoundFormat::SND_FORMAT_QOAF)
|
|
||||||
{
|
|
||||||
return "qoa";
|
|
||||||
}
|
|
||||||
else if (m_soundFormat == Resource::SoundFormat::SND_FORMAT_WAV)
|
|
||||||
{
|
|
||||||
return "wav";
|
|
||||||
}
|
|
||||||
|
|
||||||
return ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<std::shared_ptr<Connection>> StoryProject::GetNodeConnections(const std::string &nodeId)
|
std::list<std::shared_ptr<Connection>> StoryProject::GetNodeConnections(const std::string &nodeId)
|
||||||
{
|
{
|
||||||
std::list<std::shared_ptr<Connection>> c;
|
std::list<std::shared_ptr<Connection>> c;
|
||||||
|
|
||||||
for (const auto & l : m_links)
|
for (const auto &p : m_pages)
|
||||||
{
|
{
|
||||||
if (l->outNodeId == nodeId)
|
p->GetNodeConnections(c, nodeId);
|
||||||
{
|
|
||||||
c.push_back(l);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int StoryProject::OutputsCount(const std::string &nodeId)
|
||||||
std::string StoryProject::FindFirstNode() const
|
|
||||||
{
|
{
|
||||||
std::string id;
|
for (const auto &p : m_pages)
|
||||||
|
|
||||||
// First node is the one without connection on its input port
|
|
||||||
|
|
||||||
for (const auto & n : m_nodes)
|
|
||||||
{
|
{
|
||||||
bool foundConnection = false;
|
return p->OutputsCount(nodeId);
|
||||||
|
|
||||||
for (const auto& l : m_links)
|
|
||||||
{
|
|
||||||
if (l->inNodeId == n->GetId())
|
|
||||||
{
|
|
||||||
foundConnection = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!foundConnection)
|
|
||||||
{
|
|
||||||
id = n->GetId();
|
|
||||||
std::cout << "First node is: " + id << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool StoryProject::GenerateScript(std::string &codeStr)
|
bool StoryProject::GenerateScript(std::string &codeStr)
|
||||||
{
|
{
|
||||||
std::stringstream code;
|
std::stringstream code;
|
||||||
std::stringstream chip32;
|
std::stringstream chip32;
|
||||||
|
std::string firstNode;
|
||||||
|
|
||||||
std::string firstNode = FindFirstNode();
|
for (const auto & p : m_pages)
|
||||||
|
{
|
||||||
|
firstNode = p->FindFirstNode();
|
||||||
|
}
|
||||||
|
|
||||||
if (firstNode == "")
|
if (firstNode == "")
|
||||||
{
|
{
|
||||||
|
|
@ -365,16 +342,11 @@ bool StoryProject::GenerateScript(std::string &codeStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
code << "\tjump " << BaseNode::GetEntryLabel(firstNode) << "\r\n";
|
code << "\tjump " << BaseNode::GetEntryLabel(firstNode) << "\r\n";
|
||||||
|
|
||||||
// First generate all constants
|
// On build toutes les pages
|
||||||
for (const auto & n : m_nodes)
|
for (const auto & p : m_pages)
|
||||||
{
|
{
|
||||||
code << n->GenerateConstants(*this, OutputsCount(n->GetId())) << "\n";
|
p->Build(code, m_storyOptions);
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto & n : m_nodes)
|
|
||||||
{
|
|
||||||
code << n->Build(*this, OutputsCount(n->GetId())) << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
codeStr = code.str();
|
codeStr = code.str();
|
||||||
|
|
@ -448,9 +420,9 @@ bool StoryProject::Load(ResourceManager &manager)
|
||||||
manager.Add(rData);
|
manager.Add(rData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j.contains("nodegraph"))
|
if (j.contains("pages"))
|
||||||
{
|
{
|
||||||
ModelFromJson(j["nodegraph"]);
|
ModelFromJson(j["pages"]);
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -487,7 +459,7 @@ void StoryProject::Save(ResourceManager &manager)
|
||||||
|
|
||||||
nlohmann::json model;
|
nlohmann::json model;
|
||||||
ModelToJson(model);
|
ModelToJson(model);
|
||||||
j["nodegraph"] = model;
|
j["pages"] = model;
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -533,8 +505,6 @@ void StoryProject::Clear()
|
||||||
m_working_dir = "";
|
m_working_dir = "";
|
||||||
m_project_file_path = "";
|
m_project_file_path = "";
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
m_nodes.clear();
|
|
||||||
m_links.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -550,18 +520,18 @@ void StoryProject::SetTitleSound(const std::string &titleSound)
|
||||||
|
|
||||||
void StoryProject::SetImageFormat(Resource::ImageFormat format)
|
void StoryProject::SetImageFormat(Resource::ImageFormat format)
|
||||||
{
|
{
|
||||||
m_imageFormat = format;
|
m_storyOptions.image_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryProject::SetSoundFormat(Resource::SoundFormat format)
|
void StoryProject::SetSoundFormat(Resource::SoundFormat format)
|
||||||
{
|
{
|
||||||
m_soundFormat = format;
|
m_storyOptions.sound_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StoryProject::SetDisplayFormat(int w, int h)
|
void StoryProject::SetDisplayFormat(int w, int h)
|
||||||
{
|
{
|
||||||
m_display_w = w;
|
m_storyOptions.display_w = w;
|
||||||
m_display_h = h;
|
m_storyOptions.display_h = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StoryProject::GetProjectFilePath() const
|
std::string StoryProject::GetProjectFilePath() const
|
||||||
|
|
@ -579,11 +549,6 @@ std::string StoryProject::BuildFullAssetsPath(const std::string_view fileName) c
|
||||||
return (AssetsPath() / fileName).generic_string();
|
return (AssetsPath() / fileName).generic_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StoryProject::FileToConstant(const std::string &FileName, const std::string &extension)
|
|
||||||
{
|
|
||||||
std::string f = SysLib::RemoveFileExtension(FileName);
|
|
||||||
return "$" + FileName + " DC8 \"" + FileName + "\", 8\r\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
#include "base_node.h"
|
#include "base_node.h"
|
||||||
#include "i_story_project.h"
|
#include "i_story_project.h"
|
||||||
#include "chip32_assembler.h"
|
#include "chip32_assembler.h"
|
||||||
|
#include "story_page.h"
|
||||||
|
#include "story_options.h"
|
||||||
|
|
||||||
// FIXME : Structure très Lunii style, à utiliser pour la conversion peut-être ...
|
// FIXME : Structure très Lunii style, à utiliser pour la conversion peut-être ...
|
||||||
struct StoryNode
|
struct StoryNode
|
||||||
|
|
@ -45,6 +47,7 @@ struct StoryNode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct StoryProject : public IStoryProject
|
struct StoryProject : public IStoryProject
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -78,29 +81,17 @@ public:
|
||||||
|
|
||||||
bool CopyProgramTo(uint8_t *memory, uint32_t size);
|
bool CopyProgramTo(uint8_t *memory, uint32_t size);
|
||||||
|
|
||||||
// returns >= 0 on success
|
// returns >= 0 on success
|
||||||
bool GetAssemblyLine(uint32_t pointer_counter, uint32_t &line);
|
bool GetAssemblyLine(uint32_t pointer_counter, uint32_t &line);
|
||||||
|
|
||||||
void CreateTree();
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
std::pair<std::list<std::shared_ptr<BaseNode>>::iterator, std::list<std::shared_ptr<BaseNode>>::iterator> Nodes() {
|
|
||||||
return std::make_pair(m_nodes.begin(), m_nodes.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator> Links() {
|
|
||||||
return std::make_pair(m_links.begin(), m_links.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Select(bool selected) { m_selected = selected; }
|
void Select(bool selected) { m_selected = selected; }
|
||||||
bool IsSelected() const { return m_selected; }
|
bool IsSelected() const { return m_selected; }
|
||||||
|
|
||||||
void SetImageFormat(Resource::ImageFormat format);
|
void SetImageFormat(Resource::ImageFormat format);
|
||||||
void SetSoundFormat(Resource::SoundFormat 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 SetDisplayFormat(int w, int h);
|
||||||
void SetName(const std::string &name) { m_name = name; }
|
void SetName(const std::string &name) { m_name = name; }
|
||||||
void SetUuid(const std::string &uuid) { m_uuid = uuid; }
|
void SetUuid(const std::string &uuid) { m_uuid = uuid; }
|
||||||
|
|
@ -114,8 +105,6 @@ public:
|
||||||
|
|
||||||
std::string BuildFullAssetsPath(const std::string_view fileName) const;
|
std::string BuildFullAssetsPath(const std::string_view fileName) const;
|
||||||
|
|
||||||
static std::string FileToConstant(const std::string &FileName, const std::string &extension);
|
|
||||||
|
|
||||||
std::filesystem::path AssetsPath() const { return m_assetsPath; }
|
std::filesystem::path AssetsPath() const { return m_assetsPath; }
|
||||||
|
|
||||||
void SetTitleImage(const std::string &titleImage);
|
void SetTitleImage(const std::string &titleImage);
|
||||||
|
|
@ -131,15 +120,17 @@ public:
|
||||||
|
|
||||||
// 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) override;
|
||||||
std::string FindFirstNode() const;
|
|
||||||
virtual int OutputsCount(const std::string &nodeId) override;
|
virtual int OutputsCount(const std::string &nodeId) override;
|
||||||
virtual std::string ImageExtension(const std::string &filename) const override;
|
virtual StoryOptions GetOptions() override { return m_storyOptions; }
|
||||||
virtual std::string SoundExtension(const std::string &filename) const override;
|
|
||||||
|
|
||||||
std::shared_ptr<BaseNode> CreateNode(const std::string& type);
|
// Node interaction
|
||||||
void AddConnection(std::shared_ptr<Connection> c);
|
std::shared_ptr<StoryPage> CreatePage(const std::string &uuid);
|
||||||
void DeleteNode(const std::string &id);
|
std::shared_ptr<BaseNode> CreateNode(const std::string_view &page, const std::string &type);
|
||||||
void DeleteLink(std::shared_ptr<Connection> c);
|
void AddConnection(const std::string_view &page, std::shared_ptr<Connection> c);
|
||||||
|
void DeleteNode(const std::string_view &page, const std::string &id);
|
||||||
|
void DeleteLink(const std::string_view &page, std::shared_ptr<Connection> c);
|
||||||
|
std::pair<std::list<std::shared_ptr<BaseNode>>::iterator, std::list<std::shared_ptr<BaseNode>>::iterator> Nodes(const std::string_view &page_uuid);
|
||||||
|
std::pair<std::list<std::shared_ptr<Connection>>::iterator, std::list<std::shared_ptr<Connection>>::iterator> Links(const std::string_view &page_uuid);
|
||||||
|
|
||||||
std::vector<std::string> GetNodeTypes() const {
|
std::vector<std::string> GetNodeTypes() const {
|
||||||
std::vector<std::string> l;
|
std::vector<std::string> l;
|
||||||
|
|
@ -164,21 +155,15 @@ private:
|
||||||
Chip32::Assembler m_assembler;
|
Chip32::Assembler m_assembler;
|
||||||
std::vector<uint8_t> m_program;
|
std::vector<uint8_t> m_program;
|
||||||
|
|
||||||
// Model in memory
|
std::list<std::shared_ptr<StoryPage>> m_pages;
|
||||||
std::list<std::shared_ptr<Connection>> m_links;
|
|
||||||
std::list<std::shared_ptr<BaseNode>> m_nodes;
|
StoryOptions m_storyOptions;
|
||||||
|
|
||||||
bool m_initialized{false};
|
bool m_initialized{false};
|
||||||
|
|
||||||
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::filesystem::path m_project_file_path; /// JSON project file
|
std::filesystem::path m_project_file_path; /// JSON project file
|
||||||
|
|
||||||
int m_display_w{320};
|
|
||||||
int m_display_h{240};
|
|
||||||
|
|
||||||
Resource::ImageFormat m_imageFormat{Resource::IMG_SAME_FORMAT};
|
|
||||||
Resource::SoundFormat m_soundFormat{Resource::SND_SAME_FORMAT};
|
|
||||||
|
|
||||||
template<class NodeType>
|
template<class NodeType>
|
||||||
struct Factory {
|
struct Factory {
|
||||||
static std::shared_ptr<BaseNode> create_func(const std::string &type) {
|
static std::shared_ptr<BaseNode> create_func(const std::string &type) {
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -187,15 +187,6 @@ set(SRCS
|
||||||
src/platform_folders.cpp
|
src/platform_folders.cpp
|
||||||
src/platform_folders.h
|
src/platform_folders.h
|
||||||
|
|
||||||
src/node_engine/base_node.h
|
|
||||||
src/node_engine/base_node.cpp
|
|
||||||
src/node_engine/media_node.h
|
|
||||||
src/node_engine/media_node.cpp
|
|
||||||
src/node_engine/function_node.h
|
|
||||||
src/node_engine/function_node.cpp
|
|
||||||
src/node_engine/connection.cpp
|
|
||||||
src/node_engine/connection.h
|
|
||||||
|
|
||||||
src/node_editor/media_node_widget.h
|
src/node_editor/media_node_widget.h
|
||||||
src/node_editor/media_node_widget.cpp
|
src/node_editor/media_node_widget.cpp
|
||||||
src/node_editor/base_node_widget.h
|
src/node_editor/base_node_widget.h
|
||||||
|
|
@ -223,15 +214,12 @@ set(SRCS
|
||||||
src/media_converter.cpp
|
src/media_converter.cpp
|
||||||
src/media_converter.h
|
src/media_converter.h
|
||||||
|
|
||||||
src/i_story_manager.h
|
|
||||||
|
|
||||||
src/miniz.c
|
src/miniz.c
|
||||||
src/zip.cpp
|
src/zip.cpp
|
||||||
|
|
||||||
src/importers/pack_archive.cpp
|
src/importers/pack_archive.cpp
|
||||||
src/importers/ni_parser.c
|
src/importers/ni_parser.c
|
||||||
|
|
||||||
|
|
||||||
libs/ImGuiColorTextEdit/TextEditor.cpp
|
libs/ImGuiColorTextEdit/TextEditor.cpp
|
||||||
libs/ImGuiColorTextEdit/TextEditor.h
|
libs/ImGuiColorTextEdit/TextEditor.h
|
||||||
libs/imgui-node-editor/imgui_node_editor.cpp
|
libs/imgui-node-editor/imgui_node_editor.cpp
|
||||||
|
|
@ -257,17 +245,25 @@ set(SRCS
|
||||||
../shared/miniaudio.h
|
../shared/miniaudio.h
|
||||||
../shared/stb_vorbis.c
|
../shared/stb_vorbis.c
|
||||||
../shared/uuid.h
|
../shared/uuid.h
|
||||||
../shared/resource.h
|
|
||||||
../shared/resource.cpp
|
|
||||||
../shared/resource_manager.h
|
../shared/resource_manager.h
|
||||||
../shared/resource_manager.cpp
|
../shared/resource_manager.cpp
|
||||||
../shared/story_project.cpp
|
|
||||||
../shared/story_project.h
|
|
||||||
../shared/thread_safe_queue.h
|
../shared/thread_safe_queue.h
|
||||||
../shared/library_manager.h
|
../shared/library_manager.h
|
||||||
../shared/library_manager.cpp
|
../shared/library_manager.cpp
|
||||||
../shared/sys_lib.cpp
|
|
||||||
../shared/sys_lib.h
|
# Core engine files
|
||||||
|
|
||||||
|
../core/src/compiler.cpp
|
||||||
|
../core/src/story_project.cpp
|
||||||
|
../core/src/story_page.cpp
|
||||||
|
../core/src/base_node.cpp
|
||||||
|
../core/src/media_node.cpp
|
||||||
|
../core/src/function_node.cpp
|
||||||
|
../core/src/connection.cpp
|
||||||
|
|
||||||
|
../core/lib/sys_lib.cpp
|
||||||
|
../core/lib/resource.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|
@ -307,7 +303,9 @@ target_include_directories(${STORY_EDITOR_PROJECT} PUBLIC
|
||||||
../firmware/library
|
../firmware/library
|
||||||
../firmware/chip32
|
../firmware/chip32
|
||||||
../shared
|
../shared
|
||||||
|
../core/src
|
||||||
|
../core/lib
|
||||||
|
../core/interfaces
|
||||||
)
|
)
|
||||||
|
|
||||||
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})
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,8 @@ bool PackArchive::ConvertJsonStudioToOst(const std::string &basePath, const std:
|
||||||
StoryProject proj(m_log);
|
StoryProject proj(m_log);
|
||||||
ResourceManager res(m_log);
|
ResourceManager res(m_log);
|
||||||
|
|
||||||
|
std::shared_ptr<StoryPage> page = proj.CreatePage("main");
|
||||||
|
|
||||||
if (j.contains("title"))
|
if (j.contains("title"))
|
||||||
{
|
{
|
||||||
proj.New(uuid, outputDir);
|
proj.New(uuid, outputDir);
|
||||||
|
|
@ -414,7 +416,7 @@ bool PackArchive::ConvertJsonStudioToOst(const std::string &basePath, const std:
|
||||||
|
|
||||||
for (const auto & n : j["stageNodes"])
|
for (const auto & n : j["stageNodes"])
|
||||||
{
|
{
|
||||||
auto node = proj.CreateNode("media-node");
|
auto node = proj.CreateNode("main", "media-node");
|
||||||
|
|
||||||
if (node)
|
if (node)
|
||||||
{
|
{
|
||||||
|
|
@ -452,7 +454,7 @@ bool PackArchive::ConvertJsonStudioToOst(const std::string &basePath, const std:
|
||||||
c->inPortIndex = 0;
|
c->inPortIndex = 0;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
proj.AddConnection(c);
|
page->AddLink(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -360,6 +360,7 @@ float MainWindow::DrawMainMenuBar()
|
||||||
if (m_story)
|
if (m_story)
|
||||||
{
|
{
|
||||||
SaveProject();
|
SaveProject();
|
||||||
|
m_libraryManager.Scan(); // Add new project to library
|
||||||
OpenProject(m_story->GetUuid());
|
OpenProject(m_story->GetUuid());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1005,11 +1006,6 @@ void MainWindow::DeleteResource(FilterIterator &it)
|
||||||
return m_resources.Delete(it);
|
return m_resources.Delete(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<BaseNode> MainWindow::CreateNode(const std::string &type)
|
|
||||||
{
|
|
||||||
return m_story->CreateNode(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::LoadBinaryStory(const std::string &filename)
|
void MainWindow::LoadBinaryStory(const std::string &filename)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(filename.c_str(), "rb");
|
FILE *fp = fopen(filename.c_str(), "rb");
|
||||||
|
|
@ -1072,7 +1068,8 @@ void MainWindow::Build(bool compileonly)
|
||||||
if (!compileonly)
|
if (!compileonly)
|
||||||
{
|
{
|
||||||
// 3. Convert all media to desired type format
|
// 3. Convert all media to desired type format
|
||||||
m_resources.ConvertResources(m_story->AssetsPath(), "", m_story->GetImageFormat(), m_story->GetSoundFormat()); // pas de répertoire de destination
|
auto options = m_story->GetOptions();
|
||||||
|
m_resources.ConvertResources(m_story->AssetsPath(), "", options.image_format, options.sound_format); // pas de répertoire de destination
|
||||||
}
|
}
|
||||||
|
|
||||||
Chip32::Assembler::Error err;
|
Chip32::Assembler::Error err;
|
||||||
|
|
@ -1109,20 +1106,6 @@ void MainWindow::BuildCode(bool compileonly)
|
||||||
Build(compileonly);
|
Build(compileonly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::DeleteNode(const std::string &id)
|
|
||||||
{
|
|
||||||
m_story->DeleteNode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::DeleteLink(std::shared_ptr<Connection> c)
|
|
||||||
{
|
|
||||||
m_story->DeleteLink(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::list<std::shared_ptr<Connection>> MainWindow::GetNodeConnections(const std::string &nodeId)
|
|
||||||
{
|
|
||||||
return m_story->GetNodeConnections(nodeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::UpdateVmView()
|
void MainWindow::UpdateVmView()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -137,12 +137,9 @@ private:
|
||||||
virtual std::pair<FilterIterator, FilterIterator> Resources() override;
|
virtual std::pair<FilterIterator, FilterIterator> Resources() override;
|
||||||
virtual void DeleteResource(FilterIterator &it) override;
|
virtual void DeleteResource(FilterIterator &it) override;
|
||||||
|
|
||||||
virtual std::shared_ptr<BaseNode> CreateNode(const std::string &type) override;
|
|
||||||
virtual void BuildNodes(bool compileonly) override;
|
virtual void BuildNodes(bool compileonly) override;
|
||||||
virtual void BuildCode(bool compileonly) override;
|
virtual void BuildCode(bool compileonly) override;
|
||||||
virtual void DeleteNode(const std::string &id) override;
|
|
||||||
virtual void DeleteLink(std::shared_ptr<Connection> c) override;
|
|
||||||
virtual std::list<std::shared_ptr<Connection>> GetNodeConnections(const std::string &nodeId) override;
|
|
||||||
virtual void LoadBinaryStory(const std::string &filename) override;
|
virtual void LoadBinaryStory(const std::string &filename) override;
|
||||||
virtual void ToggleBreakpoint(int line) override;
|
virtual void ToggleBreakpoint(int line) override;
|
||||||
virtual uint32_t GetRegister(int reg) override;
|
virtual uint32_t GetRegister(int reg) override;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ void NodeEditorWindow::Initialize()
|
||||||
m_callStack.clear();
|
m_callStack.clear();
|
||||||
|
|
||||||
m_currentPage = std::make_shared<NodeEditorPage>(gMainUuid, "Main");
|
m_currentPage = std::make_shared<NodeEditorPage>(gMainUuid, "Main");
|
||||||
m_pages.emplace_back(m_currentPage);
|
m_pages.push_back(m_currentPage);
|
||||||
|
m_callStack.push_back(m_currentPage);
|
||||||
|
|
||||||
m_currentPage->Select();
|
m_currentPage->Select();
|
||||||
}
|
}
|
||||||
|
|
@ -70,9 +71,9 @@ void NodeEditorWindow::LoadPage(const std::string &uuid, const std::string &name
|
||||||
|
|
||||||
if (m_currentPage->Uuid() != uuid)
|
if (m_currentPage->Uuid() != uuid)
|
||||||
{
|
{
|
||||||
m_callStack.push_back(m_currentPage); // save where we are
|
|
||||||
m_currentPage = page;
|
m_currentPage = page;
|
||||||
m_currentPage->Select();
|
m_currentPage->Select();
|
||||||
|
m_callStack.push_back(m_currentPage); // show current page in call stack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +98,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
||||||
BaseNodeWidget::InitId();
|
BaseNodeWidget::InitId();
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
auto [node_begin, node_end] = m_story->Nodes();
|
auto [node_begin, node_end] = m_story->Nodes(m_currentPage->Uuid());
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
|
@ -117,7 +118,7 @@ void NodeEditorWindow::Load(std::shared_ptr<StoryProject> story)
|
||||||
|
|
||||||
std::cout << "Created " << ++i << " node" << std::endl;
|
std::cout << "Created " << ++i << " node" << std::endl;
|
||||||
}
|
}
|
||||||
auto [link_begin, link_end] = m_story->Links();
|
auto [link_begin, link_end] = m_story->Links(m_currentPage->Uuid());
|
||||||
|
|
||||||
for (auto it = link_begin; it != link_end; ++it)
|
for (auto it = link_begin; it != link_end; ++it)
|
||||||
{
|
{
|
||||||
|
|
@ -203,6 +204,8 @@ std::shared_ptr<BaseNodeWidget> NodeEditorWindow::GetSelectedNode()
|
||||||
|
|
||||||
void NodeEditorWindow::Draw()
|
void NodeEditorWindow::Draw()
|
||||||
{
|
{
|
||||||
|
// Check if we need to load a new page
|
||||||
|
// Typically if we are in a function and we want to open a new one
|
||||||
if (!m_newPageUuid.empty())
|
if (!m_newPageUuid.empty())
|
||||||
{
|
{
|
||||||
LoadPage(m_newPageUuid, m_newPageName);
|
LoadPage(m_newPageUuid, m_newPageName);
|
||||||
|
|
@ -251,7 +254,7 @@ void NodeEditorWindow::Draw()
|
||||||
{
|
{
|
||||||
if (FillConnection(c, endId))
|
if (FillConnection(c, endId))
|
||||||
{
|
{
|
||||||
m_story->AddConnection(c);
|
m_story->AddConnection(m_currentPage->Uuid(), c);
|
||||||
|
|
||||||
CreateLink(c, startId, endId);
|
CreateLink(c, startId, endId);
|
||||||
|
|
||||||
|
|
@ -282,7 +285,7 @@ void NodeEditorWindow::Draw()
|
||||||
if (m_currentPage->GetNode(nodeId, node))
|
if (m_currentPage->GetNode(nodeId, node))
|
||||||
{
|
{
|
||||||
// First delete model, then current entry
|
// First delete model, then current entry
|
||||||
m_manager.DeleteNode(node->Base()->GetId());
|
m_story->DeleteNode(m_currentPage->Uuid(), node->Base()->GetId());
|
||||||
m_currentPage->DeleteNode(nodeId);
|
m_currentPage->DeleteNode(nodeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +301,7 @@ void NodeEditorWindow::Draw()
|
||||||
std::shared_ptr<Connection> model;
|
std::shared_ptr<Connection> model;
|
||||||
if (m_currentPage->GetModel(deletedLinkId, model))
|
if (m_currentPage->GetModel(deletedLinkId, model))
|
||||||
{
|
{
|
||||||
m_manager.DeleteLink(model);
|
m_story->DeleteLink(m_currentPage->Uuid(), model);
|
||||||
m_currentPage->EraseLink(deletedLinkId);
|
m_currentPage->EraseLink(deletedLinkId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,7 +331,7 @@ void NodeEditorWindow::Draw()
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem(type.c_str()))
|
if (ImGui::MenuItem(type.c_str()))
|
||||||
{
|
{
|
||||||
base = m_manager.CreateNode(type);
|
base = m_story->CreateNode(m_currentPage->Uuid(), type);
|
||||||
if (base)
|
if (base)
|
||||||
{
|
{
|
||||||
auto n = CreateNodeWidget(type, m_manager, base);
|
auto n = CreateNodeWidget(type, m_manager, base);
|
||||||
|
|
@ -390,12 +393,17 @@ void NodeEditorWindow::ToolbarUI()
|
||||||
{
|
{
|
||||||
if (ImGui::Button(page->Name().data()))
|
if (ImGui::Button(page->Name().data()))
|
||||||
{
|
{
|
||||||
// Erase all pages after this iterator
|
if (page->Uuid() != m_currentPage->Uuid())
|
||||||
auto it = std::find(m_callStack.begin(), m_callStack.end(), page);
|
{
|
||||||
m_callStack.erase(it, m_callStack.end());
|
|
||||||
|
// Erase all pages after this iterator
|
||||||
|
auto it = std::find(m_callStack.begin(), m_callStack.end(), page);
|
||||||
|
m_callStack.erase(it, m_callStack.end());
|
||||||
|
|
||||||
LoadPage(page->Uuid().data(), page->Name().data());
|
LoadPage(page->Uuid().data(), page->Name().data());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Text(">");
|
ImGui::Text(">");
|
||||||
|
|
|
||||||
BIN
story-editor/story-editor
Executable file
BIN
story-editor/story-editor
Executable file
Binary file not shown.
Loading…
Reference in a new issue