nodes: Added primitive saving and loading mechanism
Not fully integrated yet. Also doesn't yet save any node settings, just nodes and links
This commit is contained in:
parent
cf67adfa42
commit
ee2b412a10
@ -37,6 +37,9 @@ namespace hex {
|
|||||||
void eraseLink(u32 id);
|
void eraseLink(u32 id);
|
||||||
void eraseNodes(const std::vector<int> &ids);
|
void eraseNodes(const std::vector<int> &ids);
|
||||||
void processNodes();
|
void processNodes();
|
||||||
|
|
||||||
|
std::string saveNodes();
|
||||||
|
void loadNodes(std::string_view data);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -160,7 +160,13 @@ namespace hex {
|
|||||||
|
|
||||||
template<hex::derived_from<dp::Node> T, typename ... Args>
|
template<hex::derived_from<dp::Node> T, typename ... Args>
|
||||||
static void add(std::string_view unlocalizedCategory, std::string_view unlocalizedName, Args&& ... args) {
|
static void add(std::string_view unlocalizedCategory, std::string_view unlocalizedName, Args&& ... args) {
|
||||||
add(Entry{ unlocalizedCategory.data(), unlocalizedName.data(), [args...]{ return new T(std::forward<Args>(args)...); } });
|
add(Entry{ unlocalizedCategory.data(), unlocalizedName.data(),
|
||||||
|
[args..., name = std::string(unlocalizedName)]{
|
||||||
|
auto node = new T(std::forward<Args>(args)...);
|
||||||
|
node->setUnlocalizedName(name);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addSeparator();
|
static void addSeparator();
|
||||||
|
@ -16,7 +16,7 @@ namespace hex::dp {
|
|||||||
In, Out
|
In, Out
|
||||||
};
|
};
|
||||||
|
|
||||||
Attribute(IOType ioType, Type type, std::string_view unlocalizedName) : m_id(SharedData::dataProcessorNodeIdCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(unlocalizedName) {
|
Attribute(IOType ioType, Type type, std::string_view unlocalizedName) : m_id(SharedData::dataProcessorAttrIdCounter++), m_ioType(ioType), m_type(type), m_unlocalizedName(unlocalizedName) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +26,8 @@ namespace hex::dp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||||
|
void setID(u32 id) { this->m_id = id; }
|
||||||
|
|
||||||
[[nodiscard]] IOType getIOType() const { return this->m_ioType; }
|
[[nodiscard]] IOType getIOType() const { return this->m_ioType; }
|
||||||
[[nodiscard]] Type getType() const { return this->m_type; }
|
[[nodiscard]] Type getType() const { return this->m_type; }
|
||||||
[[nodiscard]] std::string_view getUnlocalizedName() const { return this->m_unlocalizedName; }
|
[[nodiscard]] std::string_view getUnlocalizedName() const { return this->m_unlocalizedName; }
|
||||||
|
@ -4,9 +4,11 @@ namespace hex::dp {
|
|||||||
|
|
||||||
class Link {
|
class Link {
|
||||||
public:
|
public:
|
||||||
Link(u32 from, u32 to) : m_id(SharedData::dataProcessorNodeIdCounter++), m_from(from), m_to(to) { }
|
Link(u32 from, u32 to) : m_id(SharedData::dataProcessorLinkIdCounter++), m_from(from), m_to(to) { }
|
||||||
|
|
||||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||||
|
void setID(u32 id) { this->m_id = id; }
|
||||||
|
|
||||||
[[nodiscard]] u32 getFromID() const { return this->m_from; }
|
[[nodiscard]] u32 getFromID() const { return this->m_from; }
|
||||||
[[nodiscard]] u32 getToID() const { return this->m_to; }
|
[[nodiscard]] u32 getToID() const { return this->m_to; }
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ namespace hex::dp {
|
|||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
Node(std::string_view unlocalizedName, std::vector<Attribute> attributes) : m_id(SharedData::dataProcessorNodeIdCounter++), m_unlocalizedName(unlocalizedName), m_attributes(std::move(attributes)) {
|
Node(std::string_view unlocalizedTitle, std::vector<Attribute> attributes) : m_id(SharedData::dataProcessorNodeIdCounter++), m_unlocalizedTitle(unlocalizedTitle), m_attributes(std::move(attributes)) {
|
||||||
for (auto &attr : this->m_attributes)
|
for (auto &attr : this->m_attributes)
|
||||||
attr.setParentNode(this);
|
attr.setParentNode(this);
|
||||||
}
|
}
|
||||||
@ -17,7 +17,12 @@ namespace hex::dp {
|
|||||||
virtual ~Node() = default;
|
virtual ~Node() = default;
|
||||||
|
|
||||||
[[nodiscard]] u32 getID() const { return this->m_id; }
|
[[nodiscard]] u32 getID() const { return this->m_id; }
|
||||||
|
void setID(u32 id) { this->m_id = id; }
|
||||||
|
|
||||||
[[nodiscard]] std::string_view getUnlocalizedName() const { return this->m_unlocalizedName; }
|
[[nodiscard]] std::string_view getUnlocalizedName() const { return this->m_unlocalizedName; }
|
||||||
|
void setUnlocalizedName(std::string_view unlocalizedName) { this->m_unlocalizedName = unlocalizedName; }
|
||||||
|
|
||||||
|
[[nodiscard]] std::string_view getUnlocalizedTitle() const { return this->m_unlocalizedTitle; }
|
||||||
[[nodiscard]] std::vector<Attribute>& getAttributes() { return this->m_attributes; }
|
[[nodiscard]] std::vector<Attribute>& getAttributes() { return this->m_attributes; }
|
||||||
|
|
||||||
void setCurrentOverlay(prv::Overlay *overlay) {
|
void setCurrentOverlay(prv::Overlay *overlay) {
|
||||||
@ -40,7 +45,7 @@ namespace hex::dp {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
u32 m_id;
|
u32 m_id;
|
||||||
std::string m_unlocalizedName;
|
std::string m_unlocalizedTitle, m_unlocalizedName;
|
||||||
std::vector<Attribute> m_attributes;
|
std::vector<Attribute> m_attributes;
|
||||||
std::set<u32> m_processedInputs;
|
std::set<u32> m_processedInputs;
|
||||||
prv::Overlay *m_overlay = nullptr;
|
prv::Overlay *m_overlay = nullptr;
|
||||||
|
@ -71,6 +71,8 @@ namespace hex {
|
|||||||
|
|
||||||
static std::vector<ContentRegistry::DataProcessorNode::Entry> dataProcessorNodes;
|
static std::vector<ContentRegistry::DataProcessorNode::Entry> dataProcessorNodes;
|
||||||
static u32 dataProcessorNodeIdCounter;
|
static u32 dataProcessorNodeIdCounter;
|
||||||
|
static u32 dataProcessorLinkIdCounter;
|
||||||
|
static u32 dataProcessorAttrIdCounter;
|
||||||
|
|
||||||
static std::list<std::string> recentFilePaths;
|
static std::list<std::string> recentFilePaths;
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ namespace hex {
|
|||||||
|
|
||||||
std::vector<ContentRegistry::DataProcessorNode::Entry> SharedData::dataProcessorNodes;
|
std::vector<ContentRegistry::DataProcessorNode::Entry> SharedData::dataProcessorNodes;
|
||||||
u32 SharedData::dataProcessorNodeIdCounter = 1;
|
u32 SharedData::dataProcessorNodeIdCounter = 1;
|
||||||
|
u32 SharedData::dataProcessorLinkIdCounter = 1;
|
||||||
|
u32 SharedData::dataProcessorAttrIdCounter = 1;
|
||||||
|
|
||||||
std::list<std::string> SharedData::recentFilePaths;
|
std::list<std::string> SharedData::recentFilePaths;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
#include <imnodes.h>
|
#include <imnodes.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ namespace hex {
|
|||||||
imnodes::BeginNode(node->getID());
|
imnodes::BeginNode(node->getID());
|
||||||
|
|
||||||
imnodes::BeginNodeTitleBar();
|
imnodes::BeginNodeTitleBar();
|
||||||
ImGui::TextUnformatted(LangEntry(node->getUnlocalizedName()));
|
ImGui::TextUnformatted(LangEntry(node->getUnlocalizedTitle()));
|
||||||
imnodes::EndNodeTitleBar();
|
imnodes::EndNodeTitleBar();
|
||||||
|
|
||||||
node->drawNode();
|
node->drawNode();
|
||||||
@ -367,4 +368,123 @@ namespace hex {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ViewDataProcessor::saveNodes() {
|
||||||
|
using json = nlohmann::json;
|
||||||
|
json output;
|
||||||
|
|
||||||
|
output["nodes"] = json::object();
|
||||||
|
for (auto &node : this->m_nodes) {
|
||||||
|
auto id = node->getID();
|
||||||
|
auto &currNodeOutput = output["nodes"][std::to_string(id)];
|
||||||
|
auto pos = imnodes::GetNodeGridSpacePos(id);
|
||||||
|
|
||||||
|
currNodeOutput["type"] = node->getUnlocalizedName();
|
||||||
|
currNodeOutput["pos"] = { { "x", pos.x }, { "y", pos.y } };
|
||||||
|
currNodeOutput["attrs"] = json::array();
|
||||||
|
currNodeOutput["id"] = id;
|
||||||
|
|
||||||
|
u32 attrIndex = 0;
|
||||||
|
for (auto &attr : node->getAttributes()) {
|
||||||
|
currNodeOutput["attrs"][attrIndex] = attr.getID();
|
||||||
|
attrIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output["links"] = json::object();
|
||||||
|
for (auto &link : this->m_links) {
|
||||||
|
auto id = link.getID();
|
||||||
|
auto &currOutput = output["links"][std::to_string(id)];
|
||||||
|
|
||||||
|
currOutput["id"] = id;
|
||||||
|
currOutput["from"] = link.getFromID();
|
||||||
|
currOutput["to"] = link.getToID();
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewDataProcessor::loadNodes(std::string_view data) {
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
json input = json::parse(data);
|
||||||
|
|
||||||
|
u32 maxId = 0;
|
||||||
|
|
||||||
|
for (auto &node : this->m_nodes)
|
||||||
|
delete node;
|
||||||
|
|
||||||
|
this->m_nodes.clear();
|
||||||
|
this->m_endNodes.clear();
|
||||||
|
this->m_links.clear();
|
||||||
|
|
||||||
|
auto &nodeEntries = ContentRegistry::DataProcessorNode::getEntries();
|
||||||
|
for (auto &node : input["nodes"]) {
|
||||||
|
dp::Node *newNode = nullptr;
|
||||||
|
for (auto &entry : nodeEntries) {
|
||||||
|
if (entry.name == node["type"])
|
||||||
|
newNode = entry.creatorFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newNode == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u32 id = node["id"];
|
||||||
|
maxId = std::max(id, maxId);
|
||||||
|
|
||||||
|
newNode->setID(id);
|
||||||
|
|
||||||
|
bool hasOutput = false;
|
||||||
|
bool hasInput = false;
|
||||||
|
u32 attrIndex = 0;
|
||||||
|
for (auto &attr : newNode->getAttributes()) {
|
||||||
|
if (attr.getIOType() == dp::Attribute::IOType::Out)
|
||||||
|
hasOutput = true;
|
||||||
|
|
||||||
|
if (attr.getIOType() == dp::Attribute::IOType::In)
|
||||||
|
hasInput = true;
|
||||||
|
|
||||||
|
attr.setID(node["attrs"][attrIndex]);
|
||||||
|
attrIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasInput && !hasOutput)
|
||||||
|
this->m_endNodes.push_back(newNode);
|
||||||
|
|
||||||
|
this->m_nodes.push_back(newNode);
|
||||||
|
imnodes::SetNodeGridSpacePos(id, ImVec2(node["pos"]["x"], node["pos"]["y"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &link : input["links"]) {
|
||||||
|
dp::Link newLink(link["from"], link["to"]);
|
||||||
|
|
||||||
|
newLink.setID(link["id"]);
|
||||||
|
this->m_links.push_back(newLink);
|
||||||
|
|
||||||
|
dp::Attribute *fromAttr, *toAttr;
|
||||||
|
for (auto &node : this->m_nodes) {
|
||||||
|
for (auto &attribute : node->getAttributes()) {
|
||||||
|
if (attribute.getID() == newLink.getFromID())
|
||||||
|
fromAttr = &attribute;
|
||||||
|
else if (attribute.getID() == newLink.getToID())
|
||||||
|
toAttr = &attribute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fromAttr == nullptr || toAttr == nullptr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (fromAttr->getType() != toAttr->getType())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (fromAttr->getIOType() == toAttr->getIOType())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!toAttr->getConnectedAttributes().empty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
fromAttr->addConnectedAttribute(newLink.getID(), toAttr);
|
||||||
|
toAttr->addConnectedAttribute(newLink.getID(), fromAttr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user