diff --git a/implot.h b/implot.h index 2c995a80..9307a069 100644 --- a/implot.h +++ b/implot.h @@ -138,13 +138,18 @@ enum ImAxis_ { // Plotting properties. These provide syntactic sugar for creating ImPlotSpecs from (ImPlotProp,value) pairs. See ImPlotSpec documentation. enum ImPlotProp_ { ImPlotProp_LineColor, // line color (applies to lines, bar edges); IMPLOT_AUTO_COL will use next Colormap color or current item color + ImPlotProp_LineColors, // array of colors for each line; if nullptr, use LineColor for all lines ImPlotProp_LineWeight, // line weight in pixels (applies to lines, bar edges, marker edges) ImPlotProp_FillColor, // fill color (applies to shaded regions, bar faces); IMPLOT_AUTO_COL will use next Colormap color or current item color - ImPlotProp_FillAlpha, // alpha multiplier (applies to FillColor and MarkerFillColor) + ImPlotProp_FillColors, // array of colors for each fill; if nullptr, use FillColor for all fills + ImPlotProp_FillAlpha, // alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors) ImPlotProp_Marker, // marker type; specify ImPlotMarker_Auto to use the next unused marker ImPlotProp_MarkerSize, // size of markers (radius) *in pixels* + ImPlotProp_MarkerSizes, // array of sizes for each marker; if nullptr, use MarkerSize for all markers ImPlotProp_MarkerLineColor, // marker edge color; IMPLOT_AUTO_COL will use LineColor + ImPlotProp_MarkerLineColors, // array of colors for each marker edge; if nullptr, use MarkerLineColor for all markers ImPlotProp_MarkerFillColor, // marker face color; IMPLOT_AUTO_COL will use LineColor + ImPlotProp_MarkerFillColors, // array of colors for each marker face; if nullptr, use MarkerFillColor for all markers ImPlotProp_Size, // size of error bar whiskers (width or height), and digital bars (height) *in pixels* ImPlotProp_Offset, // data index offset ImPlotProp_Stride, // data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX @@ -509,13 +514,18 @@ enum ImPlotBin_ { // }); struct ImPlotSpec { ImVec4 LineColor = IMPLOT_AUTO_COL; // line color (applies to lines, bar edges); IMPLOT_AUTO_COL will use next Colormap color or current item color + ImU32* LineColors = nullptr; // array of colors for each line; if nullptr, use LineColor for all lines float LineWeight = 1.0f; // line weight in pixels (applies to lines, bar edges, marker edges) ImVec4 FillColor = IMPLOT_AUTO_COL; // fill color (applies to shaded regions, bar faces); IMPLOT_AUTO_COL will use next Colormap color or current item color - float FillAlpha = 1.0f; // alpha multiplier (applies to FillColor and MarkerFillColor) + ImU32* FillColors = nullptr; // array of colors for each fill; if nullptr, use FillColor for all fills + float FillAlpha = 1.0f; // alpha multiplier (applies to FillColor, FillColors, MarkerFillColor, and MarkerFillColors) ImPlotMarker Marker = ImPlotMarker_None; // marker type; specify ImPlotMarker_Auto to use the next unused marker float MarkerSize = 4; // size of markers (radius) *in pixels* + float* MarkerSizes = nullptr; // array of sizes for each marker; if nullptr, use MarkerSize for all markers ImVec4 MarkerLineColor = IMPLOT_AUTO_COL; // marker edge color; IMPLOT_AUTO_COL will use LineColor + ImU32* MarkerLineColors = nullptr; // array of colors for each marker edge; if nullptr, use MarkerLineColor for all markers ImVec4 MarkerFillColor = IMPLOT_AUTO_COL; // marker face color; IMPLOT_AUTO_COL will use LineColor + ImU32* MarkerFillColors = nullptr; // array of colors for each marker face; if nullptr, use MarkerFillColor for all markers float Size = 4; // size of error bar whiskers (width or height), and digital bars (height) *in pixels* int Offset = 0; // data index offset int Stride = IMPLOT_AUTO; // data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX @@ -559,6 +569,27 @@ struct ImPlotSpec { IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from scalar value!"); } + // Set a property from a pointer value. + void SetProp(ImPlotProp prop, ImU32* v) { + switch (prop) { + case ImPlotProp_LineColors : LineColors = v; return; + case ImPlotProp_FillColors : FillColors = v; return; + case ImPlotProp_MarkerLineColors : MarkerLineColors = v; return; + case ImPlotProp_MarkerFillColors : MarkerFillColors = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from pointer value!"); + } + + // Set a property from a float pointer value. + void SetProp(ImPlotProp prop, float* v) { + switch (prop) { + case ImPlotProp_MarkerSizes : MarkerSizes = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlotProp which cannot be set from float pointer value!"); + } + // Set a property from an ImVec4 value. void SetProp(ImPlotProp prop, const ImVec4& v) { switch (prop) { diff --git a/implot_demo.cpp b/implot_demo.cpp index 96005ffc..b1381093 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -1142,6 +1142,327 @@ void Demo_NaNValues() { //----------------------------------------------------------------------------- +void Demo_PerIndexColors() { + // Colorful Lines + static float xs1[1001], ys1[1001]; + static ImU32 colors1[1001]; + for (int i = 0; i < 1001; ++i) { + xs1[i] = i * 0.001f; + ys1[i] = 0.5f + 0.5f * sinf(50 * (xs1[i] + (float)ImGui::GetTime() / 10)); + // Rainbow colors for f(x) + float hue = (float)i / 1000.0f; + colors1[i] = ImColor::HSV(hue, 0.8f, 0.9f); + } + static double xs2[20], ys2[20]; + static ImU32 colors2[20]; + for (int i = 0; i < 20; ++i) { + xs2[i] = i * 1/19.0f; + ys2[i] = xs2[i] * xs2[i]; + // Colormap colors for g(x) + float t = i / 19.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2[i] = ImGui::GetColorU32(color); + } + if (ImPlot::BeginPlot("Colorful Lines")) { + ImPlot::SetupAxes("x","y"); + ImPlot::PlotLine("f(x)", xs1, ys1, 1001, { + ImPlotProp_LineColors, colors1 + }); + ImPlot::PlotLine("g(x)", xs2, ys2, 20, { + ImPlotProp_Marker, ImPlotMarker_Circle, + ImPlotProp_Flags, ImPlotLineFlags_Segments, + ImPlotProp_LineColors, colors2, + ImPlotProp_MarkerFillColors, colors2, + ImPlotProp_MarkerLineColors, colors2 + }); + ImPlot::EndPlot(); + } + + // Colorful Shaded Plots + static float xs_shaded[1001], ys_shaded[1001], ys1_shaded[1001], ys2_shaded[1001], ys3_shaded[1001], ys4_shaded[1001]; + static ImU32 colors_shaded1[1001], colors_shaded2[1001]; + srand(0); + for (int i = 0; i < 1001; ++i) { + xs_shaded[i] = i * 0.001f; + ys_shaded[i] = 0.25f + 0.25f * sinf(25 * xs_shaded[i]) * sinf(5 * xs_shaded[i]) + RandomRange(-0.01f, 0.01f); + ys1_shaded[i] = ys_shaded[i] + RandomRange(0.1f, 0.12f); + ys2_shaded[i] = ys_shaded[i] - RandomRange(0.1f, 0.12f); + ys3_shaded[i] = 0.75f + 0.2f * sinf(25 * xs_shaded[i]); + ys4_shaded[i] = 0.75f + 0.1f * cosf(25 * xs_shaded[i]); + + // Rainbow colors for Uncertain Data + float hue = i / 1000.0f; + colors_shaded1[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Overlapping + float t = i / 1000.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_shaded2[i] = ImGui::GetColorU32(color); + } + static ImPlotSpec spec_shaded(ImPlotProp_FillAlpha, 0.25f); + + if (ImPlot::BeginPlot("Colorful Shaded Plots")) { + ImPlot::SetupLegend(ImPlotLocation_NorthWest, ImPlotLegendFlags_Reverse); + ImPlot::PlotShaded("Uncertain Data", xs_shaded, ys1_shaded, ys2_shaded, 1001, { + ImPlotProp_FillColors, colors_shaded1, + ImPlotProp_FillAlpha, spec_shaded.FillAlpha + }); + ImPlot::PlotLine("Uncertain Data", xs_shaded, ys_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded1 + }); + ImPlot::PlotShaded("Overlapping", xs_shaded, ys3_shaded, ys4_shaded, 1001, { + ImPlotProp_FillColors, colors_shaded2, + ImPlotProp_FillAlpha, spec_shaded.FillAlpha + }); + ImPlot::PlotLine("Overlapping", xs_shaded, ys3_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded2 + }); + ImPlot::PlotLine("Overlapping", xs_shaded, ys4_shaded, 1001, { + ImPlotProp_LineColors, colors_shaded2 + }); + ImPlot::EndPlot(); + } + + // Colorful Scatter + srand(0); + static float xs_scatter1[100], ys_scatter1[100]; + static ImU32 colors_scatter1_fill[100], colors_scatter1_line[100]; + static float sizes_scatter1[100]; + for (int i = 0; i < 100; ++i) { + xs_scatter1[i] = i * 0.01f; + ys_scatter1[i] = xs_scatter1[i] + 0.1f * ((float)rand() / (float)RAND_MAX); + // Rainbow hue colors + float hue = i / 99.0f; + colors_scatter1_fill[i] = ImColor::HSV(hue, 0.8f, 0.9f); + colors_scatter1_line[i] = ImColor::HSV(hue, 0.9f, 0.7f); + // Random sizes between 2 and 6 + sizes_scatter1[i] = 2.0f + 4.0f * ((float)rand() / (float)RAND_MAX); + } + static float xs_scatter2[50], ys_scatter2[50]; + static ImU32 colors_scatter2[50]; + static float sizes_scatter2[50]; + for (int i = 0; i < 50; i++) { + xs_scatter2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX); + ys_scatter2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX); + // Colormap colors (Viridis) + float t = i / 49.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_scatter2[i] = ImGui::GetColorU32(color); + // Random sizes between 2 and 6 + sizes_scatter2[i] = 2.0f + 4.0f * ((float)rand() / (float)RAND_MAX); + } + + if (ImPlot::BeginPlot("Colorful Scatter", ImVec2(-1,0))) { + ImPlot::PlotScatter("Data 1", xs_scatter1, ys_scatter1, 100, { + ImPlotProp_MarkerFillColors, colors_scatter1_fill, + ImPlotProp_MarkerLineColors, colors_scatter1_line, + ImPlotProp_MarkerSizes, sizes_scatter1 + }); + ImPlot::PlotScatter("Data 2", xs_scatter2, ys_scatter2, 50, { + ImPlotProp_Marker, ImPlotMarker_Square, + ImPlotProp_MarkerFillColors, colors_scatter2, + ImPlotProp_MarkerLineColors, colors_scatter2, + ImPlotProp_MarkerSizes, sizes_scatter2, + ImPlotProp_FillAlpha, 0.5f + }); + ImPlot::EndPlot(); + } + + // Colorful Bubbles + srand(0); + static float xs_bubble[20], ys1_bubble[20], ys2_bubble[20], szs1_bubble[20], szs2_bubble[20]; + static ImU32 colors1_bubble[20], colors2_bubble[20]; + for (int i = 0; i < 20; ++i) { + xs_bubble[i] = i * 0.1f; + ys1_bubble[i] = (float)rand() / (float)RAND_MAX; + ys2_bubble[i] = (float)rand() / (float)RAND_MAX; + + szs1_bubble[i] = 0.02f + 0.08f * ((float)rand() / (float)RAND_MAX); + szs2_bubble[i] = 0.02f + 0.08f * ((float)rand() / (float)RAND_MAX); + + // Rainbow colors for Data 1 + float hue = i / 19.0f; + colors1_bubble[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Data 2 + float t = i / 19.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_bubble[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Bubbles", ImVec2(-1,0), ImPlotFlags_Equal)) { + ImPlot::PlotBubbles("Data 1", xs_bubble, ys1_bubble, szs1_bubble, 20, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_FillColors, colors1_bubble, + ImPlotProp_LineColors, colors1_bubble + }); + ImPlot::PlotBubbles("Data 2", xs_bubble, ys2_bubble, szs2_bubble, 20, { + ImPlotProp_FillAlpha, 0.5f, + ImPlotProp_LineColor, ImVec4(0,0,0,0.0), + ImPlotProp_FillColors, colors2_bubble + }); + + ImPlot::EndPlot(); + } + + // Colorful Stairstep + static float ys1_stairs[21], ys2_stairs[21]; + static ImU32 colors1_stairs[21], colors2_stairs[21]; + for (int i = 0; i < 21; ++i) { + ys1_stairs[i] = 0.75f + 0.2f * sinf(10 * i * 0.05f); + ys2_stairs[i] = 0.25f + 0.2f * sinf(10 * i * 0.05f); + + // Rainbow colors for Post Step + float hue = i / 20.0f; + colors1_stairs[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Pre Step + float t = i / 20.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_stairs[i] = ImGui::GetColorU32(color); + } + static ImPlotStairsFlags flags_stairs = 0; + CHECKBOX_FLAG(flags_stairs, ImPlotStairsFlags_Shaded); + + if (ImPlot::BeginPlot("Colorful Stairstep Plot")) { + ImPlot::SetupAxes("x","f(x)"); + ImPlot::SetupAxesLimits(0,1,0,1); + ImPlot::PlotLine("##1", ys1_stairs, 21, 0.05f, 0, { + ImPlotProp_LineColor, ImVec4(0.5f,0.5f,0.5f,1.0f) + }); + ImPlot::PlotLine("##2", ys2_stairs, 21, 0.05f, 0, { + ImPlotProp_LineColor, ImVec4(0.5f,0.5f,0.5f,1.0f) + }); + + ImPlot::PlotStairs("Post Step (default)", ys1_stairs, 21, 0.05f, 0, { + ImPlotProp_Flags, flags_stairs, + ImPlotProp_FillAlpha, 0.25f, + ImPlotProp_Marker, ImPlotMarker_Auto, + ImPlotProp_LineColors, colors1_stairs, + ImPlotProp_FillColors, colors1_stairs, + ImPlotProp_MarkerFillColors, colors1_stairs, + ImPlotProp_MarkerLineColors, colors1_stairs + }); + + ImPlot::PlotStairs("Pre Step", ys2_stairs, 21, 0.05f, 0, { + ImPlotProp_Flags, flags_stairs | ImPlotStairsFlags_PreStep, + ImPlotProp_FillAlpha, 0.25f, + ImPlotProp_Marker, ImPlotMarker_Auto, + ImPlotProp_LineColors, colors2_stairs, + ImPlotProp_FillColors, colors2_stairs, + ImPlotProp_MarkerFillColors, colors2_stairs, + ImPlotProp_MarkerLineColors, colors2_stairs + }); + + ImPlot::EndPlot(); + } + + // Colorful Bar Plots + static ImS8 data_bars[10] = {1,2,3,4,5,6,7,8,9,10}; + static ImU32 colors_bars_v[10], colors_bars_h[10]; + for (int i = 0; i < 10; ++i) { + // Rainbow colors for Vertical + float hue = i / 9.0f; + colors_bars_v[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Horizontal + float t = i / 9.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors_bars_h[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Bar Plot")) { + ImPlot::PlotBars("Vertical", data_bars, 10, 0.7, 1, { + ImPlotProp_FillColors, colors_bars_v, + ImPlotProp_LineColors, colors_bars_v + }); + ImPlot::PlotBars("Horizontal", data_bars, 10, 0.4, 1, { + ImPlotProp_Flags, ImPlotBarsFlags_Horizontal, + ImPlotProp_FillColors, colors_bars_h, + ImPlotProp_LineColors, colors_bars_h + }); + ImPlot::EndPlot(); + } + + // Colorful Stem Plots + static double xs_stems[51], ys1_stems[51], ys2_stems[51]; + static ImU32 colors1_stems[51], colors2_stems[51]; + for (int i = 0; i < 51; ++i) { + xs_stems[i] = i * 0.02; + ys1_stems[i] = 1.0 + 0.5 * sin(25*xs_stems[i])*cos(2*xs_stems[i]); + ys2_stems[i] = 0.5 + 0.25 * sin(10*xs_stems[i]) * sin(xs_stems[i]); + + // Rainbow colors for Stems 1 + float hue = i / 50.0f; + colors1_stems[i] = ImColor::HSV(hue, 0.8f, 0.9f); + + // Colormap colors for Stems 2 + float t = i / 50.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Viridis); + colors2_stems[i] = ImGui::GetColorU32(color); + } + + if (ImPlot::BeginPlot("Colorful Stem Plots")) { + ImPlot::SetupAxisLimits(ImAxis_X1,0,1.0); + ImPlot::SetupAxisLimits(ImAxis_Y1,0,1.6); + ImPlot::PlotStems("Stems 1", xs_stems, ys1_stems, 51, 0, { + ImPlotProp_LineColors, colors1_stems, + ImPlotProp_MarkerFillColors, colors1_stems, + ImPlotProp_MarkerLineColors, colors1_stems + }); + ImPlot::PlotStems("Stems 2", xs_stems, ys2_stems, 51, 0, { + ImPlotProp_Marker, ImPlotMarker_Circle, + ImPlotProp_LineColors, colors2_stems, + ImPlotProp_MarkerFillColors, colors2_stems, + ImPlotProp_MarkerLineColors, colors2_stems + }); + ImPlot::EndPlot(); + } + + // Colorful Infinite Lines + if (ImPlot::BeginPlot("Colorful Infinite Lines", ImVec2(-1,0))) { + ImPlot::SetupAxes("x","y"); + ImPlot::SetupAxesLimits(0, 10, -1, 10); + + // 1. Constant color infinite lines + static double vals1[5] = {1.0, 2.5, 4.0, 5.5, 7.0}; + ImPlot::PlotInfLines("Const Color", vals1, 5, { + ImPlotProp_LineColor, ImVec4(0.0f, 0.7f, 1.0f, 1.0f), + }); + + // 2. Per-line rainbow colors (horizontal) + static double vals2[8]; + static ImU32 colors_infline_rainbow[8]; + for (int i = 0; i < 8; ++i) { + vals2[i] = 1.0 + i * 1.0; + float t = i / 7.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Jet); + colors_infline_rainbow[i] = ImGui::GetColorU32(color); + } + ImPlot::PlotInfLines("Rainbow Horizontal", vals2, 8, { + ImPlotProp_LineColors, colors_infline_rainbow, + ImPlotProp_Flags, ImPlotInfLinesFlags_Horizontal + }); + + // 3. Per-line colormap colors (vertical) + static double vals3[6]; + static ImU32 colors_infline_viridis[6]; + for (int i = 0; i < 6; ++i) { + vals3[i] = 1.5 + i * 1.5; + float t = i / 5.0f; + ImVec4 color = ImPlot::SampleColormap(t, ImPlotColormap_Plasma); + colors_infline_viridis[i] = ImGui::GetColorU32(color); + } + ImPlot::PlotInfLines("Plasma Vertical", vals3, 6, { + ImPlotProp_LineColors, colors_infline_viridis, + }); + + ImPlot::EndPlot(); + } +} + +//----------------------------------------------------------------------------- + void Demo_LogScale() { IMGUI_DEMO_MARKER("Axes/Log Scale"); static double xs[1001], ys1[1001], ys2[1001], ys3[1001]; @@ -2507,6 +2828,7 @@ void ShowDemoWindow(bool* p_open) { DemoHeader("Images", Demo_Images); DemoHeader("Markers and Text", Demo_MarkersAndText); DemoHeader("NaN Values", Demo_NaNValues); + DemoHeader("Per-Index Colors", Demo_PerIndexColors); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Subplots")) { diff --git a/implot_items.cpp b/implot_items.cpp index 4df2ea9e..c329d4e3 100644 --- a/implot_items.cpp +++ b/implot_items.cpp @@ -684,6 +684,61 @@ struct GetterError { typedef ImPlotPointError value_type; }; +//----------------------------------------------------------------------------- +// [SECTION] Color Getters +//----------------------------------------------------------------------------- + +struct GetterConstColor { + GetterConstColor(ImU32 color, float alpha = 1.0f) { + ImU32 col = color; + if (alpha < 1.0f) { + ImVec4 col_vec = ImGui::ColorConvertU32ToFloat4(col); + col_vec.w *= alpha; + col = ImGui::GetColorU32(col_vec); + } + Color = col; + } + template IMPLOT_INLINE ImU32 operator[](I) const { return Color; } + ImU32 Color; +}; + +struct GetterIdxColor { + GetterIdxColor(const ImU32* data, int count, float alpha = 1.0f) : Data(data), Count(count), Alpha(alpha) { } + template IMPLOT_INLINE ImU32 operator[](I idx) const { + IM_ASSERT(idx >= 0 && idx < Count); + ImU32 col = Data[idx]; + if (Alpha < 1.0f) { + ImVec4 col_vec = ImGui::ColorConvertU32ToFloat4(col); + col_vec.w *= Alpha; + col = ImGui::GetColorU32(col_vec); + } + return col; + } + const ImU32* Data; + const int Count; + const float Alpha; +}; + +//----------------------------------------------------------------------------- +// [SECTION] Size Getters +//----------------------------------------------------------------------------- + +struct GetterConstSize { + GetterConstSize(float size) : Size(size) { } + template IMPLOT_INLINE float operator[](I) const { return Size; } + float Size; +}; + +struct GetterIdxSize { + GetterIdxSize(const float* data, int count) : Data(data), Count(count) { } + template IMPLOT_INLINE float operator[](I idx) const { + IM_ASSERT(idx >= 0 && idx < Count); + return Data[idx]; + } + const float* Data; + const int Count; +}; + //----------------------------------------------------------------------------- // [SECTION] Fitters //----------------------------------------------------------------------------- @@ -918,12 +973,12 @@ struct RendererBase { const int VtxConsumed; }; -template +template struct RendererLineStrip : RendererBase { - RendererLineStrip(const _Getter& getter, ImU32 col, float weight) : + RendererLineStrip(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -937,24 +992,25 @@ struct RendererLineStrip : RendererBase { P1 = P2; return false; } - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineStripSkip : RendererBase { - RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight) : + RendererLineStripSkip(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -969,25 +1025,26 @@ struct RendererLineStripSkip : RendererBase { P1 = P2; return false; } - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); if (!ImNan(P2.x) && !ImNan(P2.y)) P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineSegments1 : RendererBase { - RendererLineSegments1(const _Getter& getter, ImU32 col, float weight) : + RendererLineSegments1(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count / 2, 6, 4), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { } void Init(ImDrawList& draw_list) const { @@ -998,23 +1055,24 @@ struct RendererLineSegments1 : RendererBase { ImVec2 P2 = this->Transformer(Getter[prim*2+1]); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) return false; - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim*2]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererLineSegments2 : RendererBase { - RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, float weight) : + RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, float weight) : RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) {} void Init(ImDrawList& draw_list) const { @@ -1025,24 +1083,25 @@ struct RendererLineSegments2 : RendererBase { ImVec2 P2 = this->Transformer(Getter2[prim]); if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) return false; - PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); + ImU32 col = GetterColor[prim]; + PrimLine(draw_list,P1,P2,HalfWeight,col,UV0,UV1); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 UV0; mutable ImVec2 UV1; }; -template +template struct RendererBarsFillV : RendererBase { - RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width) : + RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double width) : RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWidth(width/2) {} void Init(ImDrawList& draw_list) const { @@ -1064,23 +1123,24 @@ struct RendererBarsFillV : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectFill(draw_list,PMin,PMax,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list,PMin,PMax,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfWidth; mutable ImVec2 UV; }; -template +template struct RendererBarsFillH : RendererBase { - RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height) : + RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double height) : RendererBase(ImMin(getter1.Count, getter2.Count), 6, 4), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfHeight(height/2) {} void Init(ImDrawList& draw_list) const { @@ -1102,23 +1162,24 @@ struct RendererBarsFillH : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectFill(draw_list,PMin,PMax,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list,PMin,PMax,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfHeight; mutable ImVec2 UV; }; -template +template struct RendererBarsLineV : RendererBase { - RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width, float weight) : + RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double width, float weight) : RendererBase(ImMin(getter1.Count, getter2.Count), 24, 8), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfWidth(width/2), Weight(weight) {} @@ -1141,24 +1202,25 @@ struct RendererBarsLineV : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectLine(draw_list,PMin,PMax,Weight,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfWidth; const float Weight; mutable ImVec2 UV; }; -template +template struct RendererBarsLineH : RendererBase { - RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height, float weight) : + RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color, double height, float weight) : RendererBase(ImMin(getter1.Count, getter2.Count), 24, 8), Getter1(getter1), Getter2(getter2), - Col(col), + GetterColor(getter_color), HalfHeight(height/2), Weight(weight) {} @@ -1181,24 +1243,25 @@ struct RendererBarsLineH : RendererBase { ImVec2 PMax = ImMax(P1, P2); if (!cull_rect.Overlaps(ImRect(PMin, PMax))) return false; - PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); + ImU32 col = GetterColor[prim]; + PrimRectLine(draw_list,PMin,PMax,Weight,col,UV); return true; } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; const double HalfHeight; const float Weight; mutable ImVec2 UV; }; -template +template struct RendererStairsPre : RendererBase { - RendererStairsPre(const _Getter& getter, ImU32 col, float weight) : + RendererStairsPre(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 12, 8), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight)*0.5f) { P1 = this->Transformer(Getter[0]); @@ -1212,24 +1275,25 @@ struct RendererStairsPre : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), Col, UV); - PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), col, UV); + PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPost : RendererBase { - RendererStairsPost(const _Getter& getter, ImU32 col, float weight) : + RendererStairsPost(const _Getter& getter, const _GetterColor& getter_color, float weight) : RendererBase(getter.Count - 1, 12, 8), Getter(getter), - Col(col), + GetterColor(getter_color), HalfWeight(ImMax(1.0f,weight) * 0.5f) { P1 = this->Transformer(Getter[0]); @@ -1243,24 +1307,25 @@ struct RendererStairsPost : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, UV); - PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), col, UV); + PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; mutable float HalfWeight; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPreShaded : RendererBase { - RendererStairsPreShaded(const _Getter& getter, ImU32 col) : + RendererStairsPreShaded(const _Getter& getter, const _GetterColor& getter_color) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col) + GetterColor(getter_color) { P1 = this->Transformer(Getter[0]); Y0 = this->Transformer(ImPlotPoint(0,0)).y; @@ -1276,23 +1341,24 @@ struct RendererStairsPreShaded : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, PMin, PMax, Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, PMin, PMax, col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; float Y0; mutable ImVec2 P1; mutable ImVec2 UV; }; -template +template struct RendererStairsPostShaded : RendererBase { - RendererStairsPostShaded(const _Getter& getter, ImU32 col) : + RendererStairsPostShaded(const _Getter& getter, const _GetterColor& getter_color) : RendererBase(getter.Count - 1, 6, 4), Getter(getter), - Col(col) + GetterColor(getter_color) { P1 = this->Transformer(Getter[0]); Y0 = this->Transformer(ImPlotPoint(0,0)).y; @@ -1308,12 +1374,13 @@ struct RendererStairsPostShaded : RendererBase { P1 = P2; return false; } - PrimRectFill(draw_list, PMin, PMax, Col, UV); + ImU32 col = GetterColor[prim]; + PrimRectFill(draw_list, PMin, PMax, col, UV); P1 = P2; return true; } const _Getter& Getter; - const ImU32 Col; + const _GetterColor& GetterColor; float Y0; mutable ImVec2 P1; mutable ImVec2 UV; @@ -1321,13 +1388,13 @@ struct RendererStairsPostShaded : RendererBase { -template +template struct RendererShaded : RendererBase { - RendererShaded(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) : + RendererShaded(const _Getter1& getter1, const _Getter2& getter2, const _GetterColor& getter_color) : RendererBase(ImMin(getter1.Count, getter2.Count) - 1, 6, 5), Getter1(getter1), Getter2(getter2), - Col(col) + GetterColor(getter_color) { P11 = this->Transformer(Getter1[0]); P12 = this->Transformer(Getter2[0]); @@ -1344,23 +1411,24 @@ struct RendererShaded : RendererBase { P12 = P22; return false; } + ImU32 col = GetterColor[prim]; const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y); const ImVec2 intersection = intersect == 0 ? ImVec2(0,0) : Intersection(P11,P21,P12,P22); draw_list._VtxWritePtr[0].pos = P11; draw_list._VtxWritePtr[0].uv = UV; - draw_list._VtxWritePtr[0].col = Col; + draw_list._VtxWritePtr[0].col = col; draw_list._VtxWritePtr[1].pos = P21; draw_list._VtxWritePtr[1].uv = UV; - draw_list._VtxWritePtr[1].col = Col; + draw_list._VtxWritePtr[1].col = col; draw_list._VtxWritePtr[2].pos = intersection; draw_list._VtxWritePtr[2].uv = UV; - draw_list._VtxWritePtr[2].col = Col; + draw_list._VtxWritePtr[2].col = col; draw_list._VtxWritePtr[3].pos = P12; draw_list._VtxWritePtr[3].uv = UV; - draw_list._VtxWritePtr[3].col = Col; + draw_list._VtxWritePtr[3].col = col; draw_list._VtxWritePtr[4].pos = P22; draw_list._VtxWritePtr[4].uv = UV; - draw_list._VtxWritePtr[4].col = Col; + draw_list._VtxWritePtr[4].col = col; draw_list._VtxWritePtr += 5; draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect); @@ -1376,7 +1444,7 @@ struct RendererShaded : RendererBase { } const _Getter1& Getter1; const _Getter2& Getter2; - const ImU32 Col; + const _GetterColor& GetterColor; mutable ImVec2 P11; mutable ImVec2 P12; mutable ImVec2 UV; @@ -1468,19 +1536,26 @@ void RenderPrimitives2(const _Getter1& getter1, const _Getter2& getter2, Args... RenderPrimitivesEx(_Renderer<_Getter1,_Getter2>(getter1,getter2,args...), draw_list, cull_rect); } +template