thedmd / imgui-node-editor

Node Editor built using Dear ImGui
MIT License
3.7k stars 545 forks source link

How to make all state (nodes, links, positions) serialization/desserialization using Blueprints-example2 ? #145

Open aabilityuk opened 2 years ago

aabilityuk commented 2 years ago

Hi, dear developers! I am strongly need the save/load functionality and i found some useful stuff in blueprints2-example (in the next branch), but what a pity it doesn't save the node links if they are not selected., i am just even try to select all links before i save the file:

ed::SelectLink(pin->m_Id, true);

but it doesn't help... Links are saved if i select all of them with Ctrl

Guys please help me to find a solution

thedmd commented 2 years ago

Node Editor keep track only position/size data of nodes, nothing more. Intent is to enable you as a user to write your own blueprint editor and examples are a guide to show how various task can be achieved.

Second blueprint-example aim to provide more complete experience. It is work in progress and document serialization does not work. Actually this is a playground in search for better API, and the work here is not complete.

Examples already show how to pull bits of data held by Node Editor so you can use them and save next to your own data. I'm not familiar with your own data structures, how you serialize it. I only assume you want to edit it using nodes.

I can help here only with issues in the scope of Node Editor itself. Please rephrase your question if it in fact related to editor and I failed to see that.

aabilityuk commented 2 years ago

@thedmd Thank you for a quick reply!!!

I'm not familiar with your own data structures, how you serialize it. I only assume you want to edit it using nodes.

I don't have my own data structures, i wish i could serialize a document with all states (nodes,links,positions) and desserialize it back using your example technics, but it's too complicated to dig in.

I can help here only with issues in the scope of Node Editor itself. Please rephrase your question if it in fact related to editor and I failed to see that.

I rephrased the question, and i don't mean that is the issue of Node Editor or you failed something i'am just trying to find the way how to solve my question.

If it possible could you help with a code example what should be changed in blueprints2 to be able to serialize/desserialize document state include "links"?

SadE54 commented 2 years ago

Just use a serialize lib like nhloman json. Using it , you could do whatever according your needs. Starting from the blueprint example, when saving serialize nodes/links arrays content and and fill nodes/links when deserializing. With nhloman json , using 'to_json' and 'from_json', you could serialize whatever you want from single type to complex structures easily.

aabilityuk commented 2 years ago

@SadE54 Thank you for reply! I added the nlohman json to the blueprint example project. Nhloman json , doesn't have methods 'to_json' and 'from_json', instead it has: to_bson, to_cbor, to_msgpack, to_ubjson...

And i don't know how to pass the s_Links and s_Nodes to nlohman json serialization and load it back... there is no default methods in nlohman to take the std::vector and std::vector.

Could you please explain how to pass these vectors to json serializer and desserialize it back?

SadE54 commented 2 years ago

here the doc part you need : https://github.com/nlohmann/json#arbitrary-types-conversions

aabilityuk commented 2 years ago

here the doc part you need :

I'm stuck with desserialization of "node.ID".

Here is serialization to json: j["Node_ID"] = node.ID.Get();

Here i am trying to desserialize: j.at("Node_ID").get_to(node.ID);

But it doesn't compile, it show there is no proper function arguments for this method... How can i desserialize the types like this?

thedmd commented 2 years ago

I'm stuck with desserialization of "node.ID".

All ID's (NodeId, PinId, LinkId) are non-zero values provided by the user. They are intptr_t so they can accommodate your pointer to your object. All of them are run-time in nature, they are not persistent unless you decide they are.

Examples generate ID's on the fly, while new nodes are spawned. In real life you usually already have means to identify an object you're trying to represent as a node. For example your object may have UUID or unique name assigned when created. While serializing your data you use that identifier instead of run-time ID. Deserialization should regenerate ID's. If you have control over data structures you are trying to represent as nodes, you can choose to add this ID there and serialize it together with your object, which make ID's persistent.

it doesn't compile

If you're using crude_json.h get_to is not implemented, only get.

aabilityuk commented 2 years ago

@thedmd

Thank you for detailed explanation!!! I am using the nlohman json and it also has a get method wich worked for my task!!! Could you clarify please a couple more questions:

  1. Node.State returns the json string like that: "{\"location\":{\"x\":-252,\"y\":220}}" and i could not parse it with nlohman json parse method, so if it possible how to disable the default node saving positions method (disabling the config.LoadNodeSettings and config.SaveNodeSettings doesn't help)? I want to implement my own;
  2. My friend help me to make serialization/desserialization of s_Nodes and s_Links vectors using nlohman json, but after desserialization i can't connect the pins to each other (when i am trying to connect the pins of the same Kind it shows: Incompatible pin kind), i guess it maybe cuz of i do not desserialize the Pin.Kind to inputs and outputs, but i don't know how to add this settings back to s_Nodes after desserialization, it takes only three arguments and there is no PinKind (id,name,PinType): s_Nodes.back().Outputs.emplace_back(GetNextId(), "Released", PinType::Flow);

Here is desserialization part for node inputs/outputs:

 if (n.contains("outputs"))
                {
                    for (auto& out : n.at("outputs"))
                    {
                        node.Outputs.emplace_back(out["Output_ID"], out["Output_Name"].get<std::string>().c_str(),out["Output_Type"]);
                    }
                }
                if (n.contains("inputs"))
                {
                    for (auto& in : n.at("inputs"))
                    {
                        node.Inputs.emplace_back(in["Input_ID"], in["Input_Name"].get<std::string>().c_str(), in["Input_Type"]);
                    }
                }

изображение

thedmd commented 2 years ago
  1. Node.State returns the json string like that: "{"location":{"x":-252,"y":220}}" and i could not parse it with nlohman json parse method, so if it possible how to disable the default node saving positions method (disabling the config.LoadNodeSettings and config.SaveNodeSettings doesn't help)? I want to implement my own;

This is odd, because this is valid json. I'm sure nlohman json is able to parse it and this is simply bug somewhere in your code. You can ignore simply callbacks, or use them to get notified when node data has changed so you can now it need to be save on your side.

  1. My friend help me to make serialization/desserialization of s_Nodes and s_Links vectors using nlohman json, but after desserialization i can't connect the pins to each other (when i am trying to connect the pins of the same Kind it shows: Incompatible pin kind), i guess it maybe cuz of i do not desserialize the Pin.Kind to inputs and outputs, but i don't know how to add this settings back to s_Nodes after desserialization, it takes only three arguments and there is no PinKind (id,name,PinType): s_Nodes.back().Outputs.emplace_back(GetNextId(), "Released", PinType::Flow);

You can extend code to serialize PinKind too.

In case you don't know how too do that, please seek help in C++ community that will help you learn. Github issues should stay about issues related to project itself.

aabilityuk commented 2 years ago

This is odd, because this is valid json. I'm sure nlohman json is able to parse it and this is simply bug somewhere in your code. You can ignore simply callbacks, or use them to get notified when node data has changed so you can now it need to be save on your side.

Ok, i will try to find the bugs in my code, but simply ignoring the callbacks doesn't help, it seems like somewhere else saving is done...

You can extend code to serialize PinKind too.

Ok, i will check it up!! Thank you.

moebiussurfing commented 2 years ago

sorry for off topic, can we use the Blueprints-example2 but using the main branch? (just by moving the example project)

thedmd commented 2 years ago

Copying example directly will not work. There are some changes to editor I made there while experimenting with new API to save/restore state and they are not ready for release. Example as a result have broken undo/redo which. In this state I leaved this branch last time. This is still work in progress.

I rebased blueprints2 example on master branch. It should be easier to use it.