Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions include/ImNodeFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ namespace ImFlow
*/
inline static void smart_bezier(const ImVec2& p1, const ImVec2& p2, ImU32 color, float thickness);

/**
* @brief <BR>Draw a sensible bezier whose color blends from one end to the other
* @param p1 Starting point
* @param p2 Ending point
* @param color1 Color at the starting point
* @param color2 Color at the ending point
* @param thickness Thickness of the curve
* @param blend Tightness of the color transition. 1 = linear, >1 concentrates it toward the middle, <1 spreads it
*/
inline static void smart_bezier_gradient(const ImVec2& p1, const ImVec2& p2, ImU32 color1, ImU32 color2, float thickness, float blend = 1.f);

/**
* @brief <BR>Collider checker for smart_bezier
* @details Projects the point "p" orthogonally onto the bezier curve and
Expand Down Expand Up @@ -261,6 +272,8 @@ namespace ImFlow
float grid_size = 50.f;
/// @brief Sub-grid divisions for Node snapping
float grid_subdivisions = 5.f;
/// @brief Tightness of gradient links. 1 = linear, >1 concentrates the color transition toward the middle, <1 spreads it out
float link_gradient_blend = 1.f;
/// @brief ImNodeFlow colors
InfColors colors;
};
Expand Down
3 changes: 2 additions & 1 deletion src/ImNodeFlow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace ImFlow {
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);
smart_bezier_gradient(start, end, m_left->getStyle()->color, m_right->getStyle()->color, thickness,
m_inf->getStyle().link_gradient_blend);

if (m_selected && ImGui::IsKeyPressed(ImGuiKey_Delete, false))
m_right->deleteLink();
Expand Down
37 changes: 37 additions & 0 deletions src/ImNodeFlow.inl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,43 @@ namespace ImFlow
dl->AddBezierCubic(p1, p11, p22, p2, color, thickness);
}

inline void smart_bezier_gradient(const ImVec2& p1, const ImVec2& p2, ImU32 color1, ImU32 color2, float thickness, float blend)
{
if (color1 == color2)
{
smart_bezier(p1, p2, color1, thickness);
return;
}

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 = 0.f;
ImVec2 p22 = p2 - ImVec2(delta, vert);
if (p2.x < p1.x - 50.f) delta *= -1.f;
ImVec2 p11 = p1 + ImVec2(delta, vert);

const int segments = 32;
ImVec4 c1 = ImGui::ColorConvertU32ToFloat4(color1);
ImVec4 c2 = ImGui::ColorConvertU32ToFloat4(color2);
ImVec2 prev = p1;
for (int i = 1; i <= segments; ++i)
{
float t = (float)i / (float)segments;
float u = 1.f - t;
ImVec2 pt(u*u*u*p1.x + 3*u*u*t*p11.x + 3*u*t*t*p22.x + t*t*t*p2.x,
u*u*u*p1.y + 3*u*u*t*p11.y + 3*u*t*t*p22.y + t*t*t*p2.y);
float tm = ((float)i - 0.5f) / (float)segments;
if (blend != 1.f) // symmetric contrast curve around the midpoint
tm = (tm < 0.5f) ? 0.5f * powf(2.f * tm, blend)
: 1.f - 0.5f * powf(2.f * (1.f - tm), blend);
ImU32 col = ImGui::ColorConvertFloat4ToU32(ImLerp(c1, c2, tm));
dl->AddLine(prev, pt, col, thickness);
prev = pt;
}
}

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));
Expand Down