remove flow libs, dependency on nodes lib
This commit is contained in:
parent
e418da1d3b
commit
803d1e17ec
18
imgui.ini
18
imgui.ini
@ -1,10 +1,24 @@
|
||||
[Window][Debug##Default]
|
||||
Pos=-3,-3
|
||||
ViewportPos=1277,2517
|
||||
ViewportId=0x9F5F46A1
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][viewport_container]
|
||||
Pos=0,0
|
||||
Size=1101,598
|
||||
Collapsed=0
|
||||
|
||||
[Window][Editor]
|
||||
Pos=8,27
|
||||
Size=1118,634
|
||||
Collapsed=0
|
||||
DockId=0x12F98E09,0
|
||||
|
||||
[Window][Main]
|
||||
Pos=0,19
|
||||
Size=1134,650
|
||||
Collapsed=0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x12F98E09 Window=0x1F1A625A Pos=2505,2927 Size=1118,634 CentralNode=1 Selected=0x9F27EDF6
|
||||
|
||||
|
@ -1,378 +0,0 @@
|
||||
#include "ImNodeFlow.h"
|
||||
|
||||
namespace ImFlow {
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// LINK
|
||||
|
||||
void Link::update() {
|
||||
ImVec2 start = m_left->pinPoint();
|
||||
ImVec2 end = m_right->pinPoint();
|
||||
float thickness = m_left->getStyle()->extra.link_thickness;
|
||||
bool mouseClickState = m_inf->getSingleUseClick();
|
||||
|
||||
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl) &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
||||
m_selected = false;
|
||||
|
||||
if (smart_bezier_collider(ImGui::GetMousePos(), start, end, 2.5)) {
|
||||
m_hovered = true;
|
||||
thickness = m_left->getStyle()->extra.link_hovered_thickness;
|
||||
if (mouseClickState) {
|
||||
m_inf->consumeSingleUseClick();
|
||||
m_selected = true;
|
||||
}
|
||||
} else {
|
||||
m_hovered = false;
|
||||
}
|
||||
|
||||
if (m_selected)
|
||||
smart_bezier(start, end, m_left->getStyle()->extra.outline_color,
|
||||
thickness +
|
||||
m_left->getStyle()->extra.link_selected_outline_thickness);
|
||||
smart_bezier(start, end, m_left->getStyle()->color, thickness);
|
||||
|
||||
if (m_selected && ImGui::IsKeyPressed(ImGuiKey_Delete, false))
|
||||
m_right->deleteLink();
|
||||
}
|
||||
|
||||
Link::~Link() { m_left->deleteLink(); }
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// BASE NODE
|
||||
|
||||
bool BaseNode::isHovered() {
|
||||
ImVec2 paddingTL = {m_style->padding.x, m_style->padding.y};
|
||||
ImVec2 paddingBR = {m_style->padding.z, m_style->padding.w};
|
||||
return ImGui::IsMouseHoveringRect(
|
||||
m_inf->grid2screen(m_pos - paddingTL),
|
||||
m_inf->grid2screen(m_pos + m_size + paddingBR));
|
||||
}
|
||||
|
||||
void BaseNode::update() {
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
ImGui::PushID(this);
|
||||
bool mouseClickState = m_inf->getSingleUseClick();
|
||||
ImVec2 offset = m_inf->grid2screen({0.f, 0.f});
|
||||
ImVec2 paddingTL = {m_style->padding.x, m_style->padding.y};
|
||||
ImVec2 paddingBR = {m_style->padding.z, m_style->padding.w};
|
||||
|
||||
draw_list->ChannelsSetCurrent(1); // Foreground
|
||||
ImGui::SetCursorScreenPos(offset + m_pos);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
// Header
|
||||
ImGui::BeginGroup();
|
||||
ImGui::TextColored(m_style->header_title_color, m_title.c_str());
|
||||
ImGui::Spacing();
|
||||
ImGui::EndGroup();
|
||||
float headerH = ImGui::GetItemRectSize().y;
|
||||
float titleW = ImGui::GetItemRectSize().x;
|
||||
|
||||
// Inputs
|
||||
ImGui::BeginGroup();
|
||||
for (auto &p : m_ins) {
|
||||
p->setPos(ImGui::GetCursorPos());
|
||||
p->update();
|
||||
}
|
||||
for (auto &p : m_dynamicIns) {
|
||||
if (p.first == 1) {
|
||||
p.second->setPos(ImGui::GetCursorPos());
|
||||
p.second->update();
|
||||
p.first = 0;
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Content
|
||||
ImGui::BeginGroup();
|
||||
draw();
|
||||
ImGui::Dummy(ImVec2(0.f, 0.f));
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
|
||||
// Outputs
|
||||
float maxW = 0.0f;
|
||||
for (auto &p : m_outs) {
|
||||
float w = p->calcWidth();
|
||||
if (w > maxW)
|
||||
maxW = w;
|
||||
}
|
||||
for (auto &p : m_dynamicOuts) {
|
||||
float w = p.second->calcWidth();
|
||||
if (w > maxW)
|
||||
maxW = w;
|
||||
}
|
||||
ImGui::BeginGroup();
|
||||
for (auto &p : m_outs) {
|
||||
// FIXME: This looks horrible
|
||||
if ((m_pos + ImVec2(titleW, 0) + m_inf->getGrid().scroll()).x <
|
||||
ImGui::GetCursorPos().x + ImGui::GetWindowPos().x + maxW)
|
||||
p->setPos(ImGui::GetCursorPos() + ImGui::GetWindowPos() +
|
||||
ImVec2(maxW - p->calcWidth(), 0.f));
|
||||
else
|
||||
p->setPos(ImVec2((m_pos + ImVec2(titleW - p->calcWidth(), 0) +
|
||||
m_inf->getGrid().scroll())
|
||||
.x,
|
||||
ImGui::GetCursorPos().y + ImGui::GetWindowPos().y));
|
||||
p->update();
|
||||
}
|
||||
for (auto &p : m_dynamicOuts) {
|
||||
// FIXME: This looks horrible
|
||||
if ((m_pos + ImVec2(titleW, 0) + m_inf->getGrid().scroll()).x <
|
||||
ImGui::GetCursorPos().x + ImGui::GetWindowPos().x + maxW)
|
||||
p.second->setPos(ImGui::GetCursorPos() + ImGui::GetWindowPos() +
|
||||
ImVec2(maxW - p.second->calcWidth(), 0.f));
|
||||
else
|
||||
p.second->setPos(
|
||||
ImVec2((m_pos + ImVec2(titleW - p.second->calcWidth(), 0) +
|
||||
m_inf->getGrid().scroll())
|
||||
.x,
|
||||
ImGui::GetCursorPos().y + ImGui::GetWindowPos().y));
|
||||
p.second->update();
|
||||
p.first -= 1;
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::EndGroup();
|
||||
m_size = ImGui::GetItemRectSize();
|
||||
ImVec2 headerSize = ImVec2(m_size.x + paddingBR.x, headerH);
|
||||
|
||||
// Background
|
||||
draw_list->ChannelsSetCurrent(0);
|
||||
draw_list->AddRectFilled(offset + m_pos - paddingTL,
|
||||
offset + m_pos + m_size + paddingBR, m_style->bg,
|
||||
m_style->radius);
|
||||
draw_list->AddRectFilled(offset + m_pos - paddingTL,
|
||||
offset + m_pos + headerSize, m_style->header_bg,
|
||||
m_style->radius, ImDrawFlags_RoundCornersTop);
|
||||
|
||||
ImU32 col = m_style->border_color;
|
||||
float thickness = m_style->border_thickness;
|
||||
ImVec2 ptl = paddingTL;
|
||||
ImVec2 pbr = paddingBR;
|
||||
if (m_selected) {
|
||||
col = m_style->border_selected_color;
|
||||
thickness = m_style->border_selected_thickness;
|
||||
}
|
||||
if (thickness < 0.f) {
|
||||
ptl.x -= thickness / 2;
|
||||
ptl.y -= thickness / 2;
|
||||
pbr.x -= thickness / 2;
|
||||
pbr.y -= thickness / 2;
|
||||
thickness *= -1.f;
|
||||
}
|
||||
draw_list->AddRect(offset + m_pos - ptl, offset + m_pos + m_size + pbr, col,
|
||||
m_style->radius, 0, thickness);
|
||||
|
||||
if (!ImGui::IsKeyDown(ImGuiKey_LeftCtrl) &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
|
||||
!m_inf->on_selected_node())
|
||||
selected(false);
|
||||
|
||||
if (isHovered()) {
|
||||
m_inf->hoveredNode(this);
|
||||
if (mouseClickState) {
|
||||
selected(true);
|
||||
m_inf->consumeSingleUseClick();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Delete) && !ImGui::IsAnyItemActive() &&
|
||||
isSelected())
|
||||
destroy();
|
||||
|
||||
bool onHeader = ImGui::IsMouseHoveringRect(offset + m_pos - paddingTL,
|
||||
offset + m_pos + headerSize);
|
||||
if (onHeader && mouseClickState) {
|
||||
m_inf->consumeSingleUseClick();
|
||||
m_dragged = true;
|
||||
m_inf->draggingNode(true);
|
||||
}
|
||||
if (m_dragged || (m_selected && m_inf->isNodeDragged())) {
|
||||
float step =
|
||||
m_inf->getStyle().grid_size / m_inf->getStyle().grid_subdivisions;
|
||||
m_posTarget += ImGui::GetIO().MouseDelta;
|
||||
// "Slam" The position
|
||||
m_pos.x = round(m_posTarget.x / step) * step;
|
||||
m_pos.y = round(m_posTarget.y / step) * step;
|
||||
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
m_dragged = false;
|
||||
m_inf->draggingNode(false);
|
||||
m_posTarget = m_pos;
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
||||
// Resolve output pins values
|
||||
for (auto &p : m_outs)
|
||||
p->resolve();
|
||||
for (auto &p : m_dynamicOuts)
|
||||
p.second->resolve();
|
||||
|
||||
// Deleting dead pins
|
||||
m_dynamicIns.erase(
|
||||
std::remove_if(m_dynamicIns.begin(), m_dynamicIns.end(),
|
||||
[](const std::pair<int, std::shared_ptr<Pin>> &p) {
|
||||
return p.first == 0;
|
||||
}),
|
||||
m_dynamicIns.end());
|
||||
m_dynamicOuts.erase(
|
||||
std::remove_if(m_dynamicOuts.begin(), m_dynamicOuts.end(),
|
||||
[](const std::pair<int, std::shared_ptr<Pin>> &p) {
|
||||
return p.first == 0;
|
||||
}),
|
||||
m_dynamicOuts.end());
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// HANDLER
|
||||
|
||||
int ImNodeFlow::m_instances = 0;
|
||||
|
||||
bool ImNodeFlow::on_selected_node() {
|
||||
return std::any_of(m_nodes.begin(), m_nodes.end(), [](const auto &n) {
|
||||
return n.second->isSelected() && n.second->isHovered();
|
||||
});
|
||||
}
|
||||
|
||||
bool ImNodeFlow::on_free_space() {
|
||||
return std::all_of(m_nodes.begin(), m_nodes.end(),
|
||||
[](const auto &n) { return !n.second->isHovered(); }) &&
|
||||
std::all_of(m_links.begin(), m_links.end(),
|
||||
[](const auto &l) { return !l.lock()->isHovered(); });
|
||||
}
|
||||
|
||||
ImVec2 ImNodeFlow::screen2grid(const ImVec2 &p) {
|
||||
if (ImGui::GetCurrentContext() == m_context.getRawContext())
|
||||
return p - m_context.scroll();
|
||||
else
|
||||
return p - m_context.origin() - m_context.scroll() * m_context.scale();
|
||||
}
|
||||
|
||||
ImVec2 ImNodeFlow::grid2screen(const ImVec2 &p) {
|
||||
if (ImGui::GetCurrentContext() == m_context.getRawContext())
|
||||
return p + m_context.scroll();
|
||||
else
|
||||
return p + m_context.origin() + m_context.scroll() * m_context.scale();
|
||||
}
|
||||
|
||||
void ImNodeFlow::addLink(std::shared_ptr<Link> &link) {
|
||||
m_links.push_back(link);
|
||||
}
|
||||
|
||||
void ImNodeFlow::update() {
|
||||
// Updating looping stuff
|
||||
m_hovering = nullptr;
|
||||
m_hoveredNode = nullptr;
|
||||
m_draggingNode = m_draggingNodeNext;
|
||||
m_singleUseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
|
||||
// Create child canvas
|
||||
m_context.begin();
|
||||
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
// Display grid
|
||||
ImVec2 win_pos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 canvas_sz = ImGui::GetWindowSize();
|
||||
for (float x = fmodf(m_context.scroll().x, m_style.grid_size);
|
||||
x < canvas_sz.x; x += m_style.grid_size)
|
||||
draw_list->AddLine(ImVec2(x, 0.0f) + win_pos,
|
||||
ImVec2(x, canvas_sz.y) + win_pos, m_style.colors.grid);
|
||||
for (float y = fmodf(m_context.scroll().y, m_style.grid_size);
|
||||
y < canvas_sz.y; y += m_style.grid_size)
|
||||
draw_list->AddLine(ImVec2(0.0f, y) + win_pos,
|
||||
ImVec2(canvas_sz.x, y) + win_pos, m_style.colors.grid);
|
||||
for (float x = fmodf(m_context.scroll().x,
|
||||
m_style.grid_size / m_style.grid_subdivisions);
|
||||
x < canvas_sz.x; x += m_style.grid_size / m_style.grid_subdivisions)
|
||||
draw_list->AddLine(ImVec2(x, 0.0f) + win_pos,
|
||||
ImVec2(x, canvas_sz.y) + win_pos,
|
||||
m_style.colors.subGrid);
|
||||
for (float y = fmodf(m_context.scroll().y,
|
||||
m_style.grid_size / m_style.grid_subdivisions);
|
||||
y < canvas_sz.y; y += m_style.grid_size / m_style.grid_subdivisions)
|
||||
draw_list->AddLine(ImVec2(0.0f, y) + win_pos,
|
||||
ImVec2(canvas_sz.x, y) + win_pos,
|
||||
m_style.colors.subGrid);
|
||||
|
||||
// Update and draw nodes
|
||||
// TODO: I don't like this
|
||||
draw_list->ChannelsSplit(2);
|
||||
for (auto &node : m_nodes) {
|
||||
node.second->update();
|
||||
}
|
||||
std::erase_if(m_nodes, [](const auto &n) { return n.second->toDestroy(); });
|
||||
draw_list->ChannelsMerge();
|
||||
for (auto &node : m_nodes) {
|
||||
node.second->updatePublicStatus();
|
||||
}
|
||||
|
||||
// Update and draw links
|
||||
for (auto &l : m_links) {
|
||||
if (!l.expired())
|
||||
l.lock()->update();
|
||||
}
|
||||
|
||||
// Links drop-off
|
||||
if (m_dragOut && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
if (!m_hovering) {
|
||||
if (on_free_space() && m_droppedLinkPopUp) {
|
||||
if (m_droppedLinkPupUpComboKey == ImGuiKey_None ||
|
||||
ImGui::IsKeyDown(m_droppedLinkPupUpComboKey)) {
|
||||
m_droppedLinkLeft = m_dragOut;
|
||||
ImGui::OpenPopup("DroppedLinkPopUp");
|
||||
}
|
||||
}
|
||||
} else
|
||||
m_dragOut->createLink(m_hovering);
|
||||
}
|
||||
|
||||
// Links drag-out
|
||||
if (!m_draggingNode && m_hovering && !m_dragOut &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
||||
m_dragOut = m_hovering;
|
||||
if (m_dragOut) {
|
||||
if (m_dragOut->getType() == PinType_Output)
|
||||
smart_bezier(m_dragOut->pinPoint(), ImGui::GetMousePos(),
|
||||
m_dragOut->getStyle()->color,
|
||||
m_dragOut->getStyle()->extra.link_dragged_thickness);
|
||||
else
|
||||
smart_bezier(ImGui::GetMousePos(), m_dragOut->pinPoint(),
|
||||
m_dragOut->getStyle()->color,
|
||||
m_dragOut->getStyle()->extra.link_dragged_thickness);
|
||||
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
m_dragOut = nullptr;
|
||||
}
|
||||
|
||||
// Right-click PopUp
|
||||
if (m_rightClickPopUp && ImGui::IsMouseClicked(ImGuiMouseButton_Right) &&
|
||||
ImGui::IsWindowHovered()) {
|
||||
m_hoveredNodeAux = m_hoveredNode;
|
||||
ImGui::OpenPopup("RightClickPopUp");
|
||||
}
|
||||
if (ImGui::BeginPopup("RightClickPopUp")) {
|
||||
m_rightClickPopUp(m_hoveredNodeAux);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Dropped Link PopUp
|
||||
if (ImGui::BeginPopup("DroppedLinkPopUp")) {
|
||||
m_droppedLinkPopUp(m_droppedLinkLeft);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Removing dead Links
|
||||
m_links.erase(
|
||||
std::remove_if(m_links.begin(), m_links.end(),
|
||||
[](const std::weak_ptr<Link> &l) { return l.expired(); }),
|
||||
m_links.end());
|
||||
|
||||
m_context.end();
|
||||
}
|
||||
} // namespace ImFlow
|
1318
lib/ImNodeFlow.h
1318
lib/ImNodeFlow.h
File diff suppressed because it is too large
Load Diff
@ -1,347 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ImNodeFlow.h"
|
||||
|
||||
namespace ImFlow
|
||||
{
|
||||
inline void smart_bezier(const ImVec2& p1, const ImVec2& p2, ImU32 color, float thickness)
|
||||
{
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
float distance = sqrt(pow((p2.x - p1.x), 2.f) + pow((p2.y - p1.y), 2.f));
|
||||
float delta = distance * 0.45f;
|
||||
if (p2.x < p1.x) delta += 0.2f * (p1.x - p2.x);
|
||||
// float vert = (p2.x < p1.x - 20.f) ? 0.062f * distance * (p2.y - p1.y) * 0.005f : 0.f;
|
||||
float vert = 0.f;
|
||||
ImVec2 p22 = p2 - ImVec2(delta, vert);
|
||||
if (p2.x < p1.x - 50.f) delta *= -1.f;
|
||||
ImVec2 p11 = p1 + ImVec2(delta, vert);
|
||||
dl->AddBezierCubic(p1, p11, p22, p2, color, thickness);
|
||||
}
|
||||
|
||||
inline bool smart_bezier_collider(const ImVec2& p, const ImVec2& p1, const ImVec2& p2, float radius)
|
||||
{
|
||||
float distance = sqrt(pow((p2.x - p1.x), 2.f) + pow((p2.y - p1.y), 2.f));
|
||||
float delta = distance * 0.45f;
|
||||
if (p2.x < p1.x) delta += 0.2f * (p1.x - p2.x);
|
||||
// float vert = (p2.x < p1.x - 20.f) ? 0.062f * distance * (p2.y - p1.y) * 0.005f : 0.f;
|
||||
float vert = 0.f;
|
||||
ImVec2 p22 = p2 - ImVec2(delta, vert);
|
||||
if (p2.x < p1.x - 50.f) delta *= -1.f;
|
||||
ImVec2 p11 = p1 + ImVec2(delta, vert);
|
||||
return ImProjectOnCubicBezier(p, p1, p11, p22, p2).Distance < radius;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// HANDLER
|
||||
|
||||
template<typename T, typename... Params>
|
||||
std::shared_ptr<T> ImNodeFlow::addNode(const ImVec2& pos, Params&&... args)
|
||||
{
|
||||
static_assert(std::is_base_of<BaseNode, T>::value, "Pushed type is not a subclass of BaseNode!");
|
||||
|
||||
std::shared_ptr<T> n = std::make_shared<T>(std::forward<Params>(args)...);
|
||||
n->setPos(pos);
|
||||
n->setHandler(this);
|
||||
if (!n->getStyle())
|
||||
n->setStyle(NodeStyle::cyan());
|
||||
|
||||
auto uid = reinterpret_cast<uintptr_t>(n.get());
|
||||
n->setUID(uid);
|
||||
m_nodes[uid] = n;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename T, typename... Params>
|
||||
std::shared_ptr<T> ImNodeFlow::placeNodeAt(const ImVec2& pos, Params&&... args)
|
||||
{
|
||||
return addNode<T>(screen2grid(pos), std::forward<Params>(args)...);
|
||||
}
|
||||
|
||||
template<typename T, typename... Params>
|
||||
std::shared_ptr<T> ImNodeFlow::placeNode(Params&&... args)
|
||||
{
|
||||
return placeNodeAt<T>(ImGui::GetMousePos(), std::forward<Params>(args)...);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// BASE NODE
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<InPin<T>> BaseNode::addIN(const std::string& name, T defReturn, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
return addIN_uid(name, name, defReturn, filter, std::move(style));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
std::shared_ptr<InPin<T>> BaseNode::addIN_uid(const U& uid, const std::string& name, T defReturn, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
auto p = std::make_shared<InPin<T>>(h, name, filter, this, defReturn, &m_inf, std::move(style));
|
||||
m_ins.emplace_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void BaseNode::dropIN(const U& uid)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
for (auto it = m_ins.begin(); it != m_ins.end(); it++)
|
||||
{
|
||||
if (it->get()->getUid() == h)
|
||||
{
|
||||
m_ins.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void BaseNode::dropIN(const char* uid)
|
||||
{
|
||||
dropIN<std::string>(uid);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& BaseNode::showIN(const std::string& name, T defReturn, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
return showIN_uid(name, name, defReturn, filter, std::move(style));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
const T& BaseNode::showIN_uid(const U& uid, const std::string& name, T defReturn, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
for (std::pair<int, std::shared_ptr<Pin>>& p : m_dynamicIns)
|
||||
{
|
||||
if (p.second->getUid() == h)
|
||||
{
|
||||
p.first = 1;
|
||||
return static_cast<InPin<T>*>(p.second.get())->val();
|
||||
}
|
||||
}
|
||||
|
||||
m_dynamicIns.emplace_back(std::make_pair(1, std::make_shared<InPin<T>>(h, name, filter, this, defReturn, &m_inf, std::move(style))));
|
||||
return static_cast<InPin<T>*>(m_dynamicIns.back().second.get())->val();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::shared_ptr<OutPin<T>> BaseNode::addOUT(const std::string& name, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
return addOUT_uid<T>(name, name, filter, std::move(style));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
std::shared_ptr<OutPin<T>> BaseNode::addOUT_uid(const U& uid, const std::string& name, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
auto p = std::make_shared<OutPin<T>>(h, name, filter, this, &m_inf, std::move(style));
|
||||
m_outs.emplace_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void BaseNode::dropOUT(const U& uid)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
for (auto it = m_outs.begin(); it != m_outs.end(); it++)
|
||||
{
|
||||
if (it->get()->getUid() == h)
|
||||
{
|
||||
m_outs.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void BaseNode::dropOUT(const char* uid)
|
||||
{
|
||||
dropOUT<std::string>(uid);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BaseNode::showOUT(const std::string& name, std::function<T()> behaviour, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
showOUT_uid<T>(name, name, std::move(behaviour), filter, std::move(style));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
void BaseNode::showOUT_uid(const U& uid, const std::string& name, std::function<T()> behaviour, ConnectionFilter filter, std::shared_ptr<PinStyle> style)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
for (std::pair<int, std::shared_ptr<Pin>>& p : m_dynamicOuts)
|
||||
{
|
||||
if (p.second->getUid() == h)
|
||||
{
|
||||
p.first = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_dynamicOuts.emplace_back(std::make_pair(2, std::make_shared<OutPin<T>>(h, name, filter, this, &m_inf, std::move(style))));
|
||||
static_cast<OutPin<T>*>(m_dynamicOuts.back().second.get())->behaviour(std::move(behaviour));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
const T& BaseNode::getInVal(const U& uid)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
auto it = std::find_if(m_ins.begin(), m_ins.end(), [&h](std::shared_ptr<Pin>& p)
|
||||
{ return p->getUid() == h; });
|
||||
assert(it != m_ins.end() && "Pin UID not found!");
|
||||
return static_cast<InPin<T>*>(it->get())->val();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& BaseNode::getInVal(const char* uid)
|
||||
{
|
||||
return getInVal<T, std::string>(uid);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Pin* BaseNode::inPin(const U& uid)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
auto it = std::find_if(m_ins.begin(), m_ins.end(), [&h](std::shared_ptr<Pin>& p)
|
||||
{ return p->getUid() == h; });
|
||||
assert(it != m_ins.end() && "Pin UID not found!");
|
||||
return it->get();
|
||||
}
|
||||
|
||||
inline Pin* BaseNode::inPin(const char* uid)
|
||||
{
|
||||
return inPin<std::string>(uid);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
Pin* BaseNode::outPin(const U& uid)
|
||||
{
|
||||
PinUID h = std::hash<U>{}(uid);
|
||||
auto it = std::find_if(m_outs.begin(), m_outs.end(), [&h](std::shared_ptr<Pin>& p)
|
||||
{ return p->getUid() == h; });
|
||||
assert(it != m_outs.end() && "Pin UID not found!");
|
||||
return it->get();
|
||||
}
|
||||
|
||||
inline Pin* BaseNode::outPin(const char* uid)
|
||||
{
|
||||
return outPin<std::string>(uid);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// PIN
|
||||
|
||||
inline void Pin::drawSocket()
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
ImVec2 tl = pinPoint() - ImVec2(m_style->socket_radius, m_style->socket_radius);
|
||||
ImVec2 br = pinPoint() + ImVec2(m_style->socket_radius, m_style->socket_radius);
|
||||
|
||||
if (isConnected())
|
||||
draw_list->AddCircleFilled(pinPoint(), m_style->socket_connected_radius, m_style->color, m_style->socket_shape);
|
||||
else
|
||||
{
|
||||
if (ImGui::IsItemHovered() || ImGui::IsMouseHoveringRect(tl, br))
|
||||
draw_list->AddCircle(pinPoint(), m_style->socket_hovered_radius, m_style->color, m_style->socket_shape, m_style->socket_thickness);
|
||||
else
|
||||
draw_list->AddCircle(pinPoint(), m_style->socket_radius, m_style->color, m_style->socket_shape, m_style->socket_thickness);
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(tl, br))
|
||||
(*m_inf)->hovering(this);
|
||||
}
|
||||
|
||||
inline void Pin::drawDecoration()
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
draw_list->AddRectFilled(m_pos - m_style->extra.padding, m_pos + m_size + m_style->extra.padding, m_style->extra.bg_hover_color, m_style->extra.bg_radius);
|
||||
else
|
||||
draw_list->AddRectFilled(m_pos - m_style->extra.padding, m_pos + m_size + m_style->extra.padding, m_style->extra.bg_color, m_style->extra.bg_radius);
|
||||
draw_list->AddRect(m_pos - m_style->extra.padding, m_pos + m_size + m_style->extra.padding, m_style->extra.border_color, m_style->extra.bg_radius, 0, m_style->extra.border_thickness);
|
||||
}
|
||||
|
||||
inline void Pin::update()
|
||||
{
|
||||
// Custom rendering
|
||||
if (m_renderer)
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
m_renderer(this);
|
||||
ImGui::EndGroup();
|
||||
m_size = ImGui::GetItemRectSize();
|
||||
if (ImGui::IsItemHovered())
|
||||
(*m_inf)->hovering(this);
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos(m_pos);
|
||||
ImGui::Text(m_name.c_str());
|
||||
m_size = ImGui::GetItemRectSize();
|
||||
|
||||
drawDecoration();
|
||||
drawSocket();
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
(*m_inf)->hovering(this);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// IN PIN
|
||||
|
||||
template<class T>
|
||||
const T& InPin<T>::val()
|
||||
{
|
||||
if(!m_link)
|
||||
return m_emptyVal;
|
||||
|
||||
return reinterpret_cast<OutPin<T>*>(m_link->left())->val();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void InPin<T>::createLink(Pin *other)
|
||||
{
|
||||
if (other == this || other->getType() == PinType_Input || (m_parent == other->getParent() && (m_filter & ConnectionFilter_SameNode) == 0))
|
||||
return;
|
||||
|
||||
if (!((m_filter & other->getFilter()) != 0 || m_filter == ConnectionFilter_None || other->getFilter() == ConnectionFilter_None)) // Check Filter
|
||||
return;
|
||||
|
||||
if (m_link && m_link->left() == other)
|
||||
{
|
||||
m_link.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
m_link = std::make_shared<Link>(other, this, (*m_inf));
|
||||
other->setLink(m_link);
|
||||
(*m_inf)->addLink(m_link);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// OUT PIN
|
||||
|
||||
template<class T>
|
||||
const T &OutPin<T>::val() { return m_val; }
|
||||
|
||||
template<class T>
|
||||
void OutPin<T>::createLink(ImFlow::Pin *other)
|
||||
{
|
||||
if (other == this || other->getType() == PinType_Output)
|
||||
return;
|
||||
|
||||
other->createLink(this);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void OutPin<T>::setLink(std::shared_ptr<Link>& link)
|
||||
{
|
||||
m_links.emplace_back(link);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void OutPin<T>::deleteLink()
|
||||
{
|
||||
m_links.erase(std::remove_if(m_links.begin(), m_links.end(),
|
||||
[](const std::weak_ptr<Link>& l) { return l.expired(); }), m_links.end());
|
||||
}
|
||||
}
|
28
main.cpp
28
main.cpp
@ -14,7 +14,7 @@
|
||||
#include "lib/backends/imgui_impl_opengl3.h"
|
||||
#include "lib/backends/imgui_impl_sdl2.h"
|
||||
#include "lib/imgui.h"
|
||||
#include "lib/nodes/load_image.h"
|
||||
#include "lib/imgui_internal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
@ -36,9 +36,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include "lib/ImNodeFlow.h"
|
||||
|
||||
static bool init = true;
|
||||
|
||||
// Main code
|
||||
@ -131,7 +128,6 @@ int main(int, char **) {
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
ImFlow::ImNodeFlow editor = ImFlow::ImNodeFlow("Nodes");
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
@ -172,6 +168,7 @@ int main(int, char **) {
|
||||
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
|
||||
ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
|
||||
#endif
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::Begin("Main", NULL,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
|
||||
@ -179,6 +176,7 @@ int main(int, char **) {
|
||||
ImGuiDockNodeFlags dockspace_flags =
|
||||
ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f));
|
||||
|
||||
if (init) {
|
||||
init = false;
|
||||
ImGui::DockBuilderRemoveNode(dockspace_id);
|
||||
@ -188,22 +186,12 @@ int main(int, char **) {
|
||||
ImGui::DockBuilderDockWindow("Editor", dockspace_id);
|
||||
ImGui::DockBuilderFinish(dockspace_id);
|
||||
}
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("Add")) {
|
||||
if (ImGui::MenuItem("Load image")) {
|
||||
editor.addNode<LoadImage>(ImVec2(10, 10));
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open")) {
|
||||
}
|
||||
if (ImGui::MenuItem("Preview")) {
|
||||
editor.addNode<PreviewImage>(ImVec2(10, 10));
|
||||
}
|
||||
if (ImGui::MenuItem("Simple Brightness")) {
|
||||
editor.addNode<SimpleBrightness>(ImVec2(10, 10));
|
||||
}
|
||||
if (ImGui::MenuItem("Contrast")) {
|
||||
editor.addNode<Contrast>(ImVec2(10, 10));
|
||||
}
|
||||
if (ImGui::MenuItem("Exposure")) {
|
||||
editor.addNode<Exposure>(ImVec2(10, 10));
|
||||
if (ImGui::MenuItem("Exit")) {
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -212,7 +200,7 @@ int main(int, char **) {
|
||||
|
||||
ImGui::Begin("Editor", NULL,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
|
||||
editor.update();
|
||||
// -- MAIN WINDOW HERE
|
||||
ImGui::End();
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
|
Loading…
Reference in New Issue
Block a user