1#include "Base/NodeEditor/NodeEditor.h"
2#include "Base/ImGuiShapes.h"
3#include "Base/UIFontManager.h"
5#include "Application.h"
14void SeUIDSeed(
int seed)
24 data[
"type"] =
"Link";
25 data[
"from"] = from->id;
34 data[
"thickness"] = thickness;
38NodeEditorLink::NodeEditorLink(
int id)
46 color.x = data[
"color"][
"r"];
47 color.y = data[
"color"][
"g"];
48 color.z = data[
"color"][
"b"];
49 color.w = data[
"color"][
"a"];
50 thickness = data[
"thickness"];
60 data[
"userData"] =
static_cast<uint32_t
>(userData);
61 data[
"color"] = color;
70 color = data[
"color"];
71 userData = data[
"userData"].
get<uint32_t>();
74void NodeEditorPin::Begin()
76 ImGuiNodeEditor::PinKind pinKind = type == NodeEditorPinType::Input ? ImGuiNodeEditor::PinKind::Input : ImGuiNodeEditor::PinKind::Output;
77 ImGuiNodeEditor::BeginPin(
id, pinKind);
80void NodeEditorPin::End()
82 ImGuiNodeEditor::EndPin();
92 if (lnk->from->parent->id == lnk->to->parent->id)
97 if (lnk->from->type == lnk->to->type)
102 return parent->OnLink(
this, lnk);
109 if (link->from->id ==
id)
120bool NodeEditorPin::IsLinked()
125NodeEditorPin::NodeEditorPin(NodeEditorPinType type,
int id)
126 :type(type), id(id), link(nullptr)
131void NodeEditorPin::Render()
133 if (type == NodeEditorPinType::Output)
142 ImGui::DrawFilledCircle(10, color);
147 ImGui::DrawCircle(10, color);
150 ImGui::Dummy(ImVec2(20, 20));
153 if(type== NodeEditorPinType::Input)
159NodeEditorPin::~NodeEditorPin()
163void NodeEditorPin::Unlink()
176std::vector<NodeEditorPin *> NodeEditorNode::GetPins()
178 std::vector<NodeEditorPin *> pins;
181 std::make_move_iterator(inputPins.begin()),
182 std::make_move_iterator(inputPins.end())
186 std::make_move_iterator(outputPins.begin()),
187 std::make_move_iterator(outputPins.end())
197void NodeEditorNode::OnDelete()
201void NodeEditorNode::Render()
204 ImGuiNodeEditor::BeginNode(
id);
206 ImGuiNodeEditor::EndNode();
210NodeEditorNode::NodeEditorNode(
int id)
214 nodePosition = ImVec2(0, 0);
217NodeEditorNode::~NodeEditorNode()
221void NodeEditorNode::DrawHeader(std::string text)
223 ImVec2 pos = ImGui::GetCursorPos();
224 ImGui::SetCursorPos(ImVec2(pos.x - ImGuiNodeEditor::GetStyle().NodePadding.x, pos.y - ImGuiNodeEditor::GetStyle().NodePadding.y));
225 ImVec2 start = ImGuiNodeEditor::GetNodeSize(_id);
226 ImGui::DrawFilledRect(ImVec2(start.x, 60), headerColor, 13);
227 ImGui::SetCursorPos(ImVec2(pos.x + ImGuiNodeEditor::GetStyle().NodePadding.x, pos.y + ImGuiNodeEditor::GetStyle().NodePadding.x));
228 ImGui::PushFont(GetUIFont(
"OpenSans-Bold"));
229 ImGui::Text(text.c_str());
238 headerColor = data[
"headerColor"];
244 inputPins[pns[
"index"]]->Load(pns);
249 outputPins[pns[
"index"]]->Load(pns);
254 nodePosition = ImVec2(data[
"posX"], data[
"posY"]);
259 std::cout <<
"Failed to load node position!\n";
262 reqNodePosLoad =
true;
270 data[
"headerColor"] = headerColor;
274 for (
int i = 0; i < inputPins.size(); i++)
276 tmp2 = inputPins[i]->Save();
281 data[
"inputPins"] = tmp;
284 for (
int i = 0; i < outputPins.size(); i++)
286 tmp2 = outputPins[i]->Save();
291 data[
"posX"] = nodePosition.x;
292 data[
"posY"] = nodePosition.y;
293 data[
"outputPins"] = tmp;
297void NodeEditorNode::Setup()
313 data[
"type"] =
"NodeEditorData";
314 data[
"serializer"] =
"Node Serializer v2.0";
317 for (
auto &it : nodes)
319 if(it.second->name !=
"Output")
321 tmp.
push_back(it.second->SaveInternal());
328 for (
auto &it : links)
334 data[
"uidSeed"] = GenerateUID();
340 if (!config.insNodeFunc)
342 throw std::runtime_error(
"Node Instantiate Function Not Found!");
346 SeUIDSeed(data[
"uidSeed"]);
351 nd->LoadInternal(ndata);
359 ImGuiNodeEditor::PinId fromId, toId;
360 fromId = (int)ldata[
"from"];
361 toId = (int)ldata[
"to"];
362 lnk->from = pins[fromId.Get()];
363 lnk->to = pins[toId.Get()];
364 lnk->from->Link(lnk);
366 links[lnk->_id.Get()] = lnk;
370void NodeEditor::Render()
372 bool windowFocused = ImGui::IsWindowFocused();
373 ImGuiNodeEditor::SetCurrentEditor(context);
374 ImGuiNodeEditor::Begin(name.c_str());
375 ImGuiNodeEditor::EnableShortcuts(windowFocused);
377 for (
auto &it : nodes)
382 outputNode->Render();
384 for (
auto &it : links)
386 ImGuiNodeEditor::Link(it.second->id, it.second->from->id, it.second->to->id, it.second->color, it.second->thickness);
389 if (ImGuiNodeEditor::BeginCreate())
391 ImGuiNodeEditor::PinId iPid, oPid;
393 if (ImGuiNodeEditor::QueryNewLink(&iPid, &oPid))
397 if (ImGuiNodeEditor::AcceptNewItem())
400 link->from = pins[iPid.Get()];
401 link->to = pins[oPid.Get()];
402 bool lnkFrm = link->from->ValidateLink(link);
403 bool lnkTo = link->to->ValidateLink(link);
407 link->from->Link(link);
408 link->to->Link(link);
409 links[link->_id.Get()] = link;
410 ImGuiNodeEditor::Link(link->id, link->from->id, link->to->id);
421 DeleteLink(pin->link);
431 DeleteLink(pin->link);
436 ImGuiNodeEditor::PinId nPid;
438 if (config.makeNodeFunc && ImGuiNodeEditor::QueryNewNode(&nPid))
440 if (ImGuiNodeEditor::AcceptNewItem())
446 DeleteLink(pin->link);
451 config.makeNodeFunc();
457 ImGuiNodeEditor::EndCreate();
459 if (ImGuiNodeEditor::BeginDelete())
461 ImGuiNodeEditor::NodeId nId;
463 if (ImGuiNodeEditor::QueryDeletedNode(&nId))
465 if (nId && ImGuiNodeEditor::AcceptDeletedItem())
467 if (!(outputNode && nId == outputNode->_id))
477 ImGuiNodeEditor::LinkId lId;
479 if (ImGuiNodeEditor::QueryDeletedLink(&lId))
481 if (lId && ImGuiNodeEditor::AcceptDeletedItem())
490 ImGuiNodeEditor::EndDelete();
491 ImGuiNodeEditor::NodeId sNode;
492 ImGuiNodeEditor::GetSelectedNodes(&sNode, 1);
494 if (ImGui::IsWindowFocused())
496 GLFWwindow *wind = Application::Get()->GetWindow()->GetNativeWindow();
498 if (glfwGetKey(wind, GLFW_KEY_RIGHT_SHIFT) || glfwGetKey(wind, GLFW_KEY_LEFT_SHIFT))
500 if (glfwGetKey(wind, GLFW_KEY_D) && sNode)
502 if (!(sNode.Get() == outputNode->_id.Get()))
504 NodeEditorNode *node = (config.insNodeFunc(nodes[sNode.Get()]->Save()));
505 ImVec2 prePos = ImGuiNodeEditor::GetNodePosition(sNode);
506 ImGuiNodeEditor::SetNodePosition(node->_id, ImVec2(prePos.x + 10, prePos.y + 10));
507 ImGuiNodeEditor::DeselectNode(sNode);
514 for(
auto &it : nodes)
516 if(it.second->reqNodePosLoad)
518 ImGuiNodeEditor::SetNodePosition(it.second->_id, it.second->nodePosition);
519 it.second->reqNodePosLoad =
false;
524 it.second->nodePosition = ImGuiNodeEditor::GetNodePosition(it.second->_id);
528 if (config.updateFunc)
533 ImGuiNodeEditor::End();
534 ImGuiNodeEditor::SetCurrentEditor(
nullptr);
539 link->from->link =
nullptr;
540 link->to->link =
nullptr;
541 links.erase(links.find(link->_id.Get()));
547 nodes[node->_id.Get()] = node;
549 for (
auto &it : node->GetPins())
551 pins[it->_id.Get()] = it;
556 if (nodes.size() > 2 && nodes.find(lastNodeId.Get()) != nodes.end() && !node->reqNodePosLoad)
559 node->nodePosition = lastNode->nodePosition;
560 node->reqNodePosLoad =
true;
563 lastNodeId = node->_id;
569 ImGuiNodeEditor::Config iconfig;
570 iconfig.SettingsFile = config.saveFile.c_str();
571 context = ImGuiNodeEditor::CreateEditor(&iconfig);
578 if (nodes.find(node->_id.Get()) != nodes.end())
581 using namespace std::chrono_literals;
582 std::this_thread::sleep_for(500ms);
585 std::vector<NodeEditorPin *> mPins = node->GetPins();
591 links.erase(links.find(pin->link->_id.Get()));
592 pin->other->Unlink();
596 pins.erase(pins.find(pin->_id.Get()));
600 nodes.erase(nodes.find(node->_id.Get()));
607NodeEditor::~NodeEditor()
609 ImGuiNodeEditor::DestroyEditor(context);
612void NodeEditor::Reset()
616 std::unordered_map<uintptr_t, NodeEditorNode *> nodesc = nodes;
618 for (
auto &it : nodesc)
620 DeleteNode(it.second);
625 for (
auto &it : node->GetPins())
627 pins[it->_id.Get()] = it;
637 for (
auto &it : node->GetPins())
639 pins[it->_id.Get()] = it;
646NodeEditorConfig::NodeEditorConfig(std::string saveFile)
651NodeInputParam::NodeInputParam()
655NodeInputParam::NodeInputParam(
float *pos,
float *texCoord,
float *minPos,
float *maxPos)
void clear() noexcept
clears the contents
void push_back(basic_json &&val)
add an object to an array
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
a class to store JSON values
basic_json<> json
default JSON class