From 5bccbba8cf173df28919d5697b1d633afb25b66a Mon Sep 17 00:00:00 2001 From: External Host Date: Tue, 26 May 2026 17:04:53 -0700 Subject: [PATCH] gradient beizer force --- include/ImNodeFlow.h | 13 +++++++++++++ src/ImNodeFlow.cpp | 3 ++- src/ImNodeFlow.inl | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/ImNodeFlow.h b/include/ImNodeFlow.h index 3fd17cd..e92fb39 100644 --- a/include/ImNodeFlow.h +++ b/include/ImNodeFlow.h @@ -34,6 +34,17 @@ namespace ImFlow */ inline static void smart_bezier(const ImVec2& p1, const ImVec2& p2, ImU32 color, float thickness); + /** + * @brief
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
Collider checker for smart_bezier * @details Projects the point "p" orthogonally onto the bezier curve and @@ -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; }; diff --git a/src/ImNodeFlow.cpp b/src/ImNodeFlow.cpp index 2f49467..8b1a3f6 100644 --- a/src/ImNodeFlow.cpp +++ b/src/ImNodeFlow.cpp @@ -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(); diff --git a/src/ImNodeFlow.inl b/src/ImNodeFlow.inl index 7546123..effb701 100644 --- a/src/ImNodeFlow.inl +++ b/src/ImNodeFlow.inl @@ -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));