From 198c38f0b114d9c2059b201a872e2ef1ee102b93 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Feb 2024 16:33:54 +0100 Subject: [PATCH] Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. --- docs/CHANGELOG.txt | 2 ++ imgui.h | 3 ++- imgui_demo.cpp | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c393981c..7b481dbc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: drawn too low, particularly visible with tables that have no scrolling. (#6917) - ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars, where in some situations the rounded section wouldn't follow regular tesselation rules. +- Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), + PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. ----------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 615e3403..9c04e4f9 100644 --- a/imgui.h +++ b/imgui.h @@ -2765,7 +2765,8 @@ struct ImDrawList IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); // Stateful path API, add points then finish with PathFillConvex() or PathStroke() - // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. + // - Important: filled shapes must always use clockwise winding order! The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. + // so e.g. 'PathArcTo(center, radius, PI * -0.5f, PI)' is ok, whereas 'PathArcTo(center, radius, PI, PI * -0.5f)' won't have correct anti-aliasing when followed by PathFillConvex(). inline void PathClear() { _Path.Size = 0; } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3a7a818a..96021502 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8030,6 +8030,9 @@ static void ShowExampleAppCustomRendering(bool* p_open) const float rounding = sz / 5.0f; const int circle_segments = circle_segments_override ? circle_segments_override_v : 0; const int curve_segments = curve_segments_override ? curve_segments_override_v : 0; + const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves + const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) }; + float x = p.x + 4.0f; float y = p.y + 4.0f; for (int n = 0; n < 2; n++) @@ -8048,17 +8051,23 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!) draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line + // Path + draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f); + draw_list->PathStroke(col, ImDrawFlags_None, th); + x += sz + spacing; + // Quadratic Bezier Curve (3 control points) - ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing; + draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments); + x += sz + spacing; // Cubic Bezier Curve (4 control points) - ImVec2 cp4[4] = { ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz) }; - draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments); + draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments); x = p.x + 4; y += sz + spacing; } + + // Filled shapes draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides); x += sz + spacing; // N-gon draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments); x += sz + spacing; // Circle draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, sz * 0.3f, col, -0.3f, circle_segments); x += sz + spacing;// Ellipse @@ -8070,9 +8079,27 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine) + + // Path + draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f); + draw_list->PathFillConvex(col); + x += sz + spacing; + + // Quadratic Bezier Curve (3 control points) + draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y)); + draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments); + draw_list->PathFillConvex(col); + x += sz + spacing; + + // Cubic Bezier Curve (4 control points): this is concave so not drawing it yet + //draw_list->PathLineTo(ImVec2(x + cp4[0].x, y + cp4[0].y)); + //draw_list->PathBezierCubicCurveTo(ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), curve_segments); + //draw_list->PathFillConvex(col); + //x += sz + spacing; + draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255)); - ImGui::Dummy(ImVec2((sz + spacing) * 11.2f, (sz + spacing) * 3.0f)); + ImGui::Dummy(ImVec2((sz + spacing) * 12.2f, (sz + spacing) * 3.0f)); ImGui::PopItemWidth(); ImGui::EndTabItem(); }