The open source OpenXR runtime
1// MIT License 2 3// Copyright (c) 2023 Evan Pezent 4 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to deal 7// in the Software without restriction, including without limitation the rights 8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9// copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11 12// The above copyright notice and this permission notice shall be included in all 13// copies or substantial portions of the Software. 14 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21// SOFTWARE. 22 23// ImPlot v0.17 24 25#define IMGUI_DEFINE_MATH_OPERATORS 26#include "implot.h" 27#include "implot_internal.h" 28 29//----------------------------------------------------------------------------- 30// [SECTION] Macros and Defines 31//----------------------------------------------------------------------------- 32 33#define SQRT_1_2 0.70710678118f 34#define SQRT_3_2 0.86602540378f 35 36#ifndef IMPLOT_NO_FORCE_INLINE 37 #ifdef _MSC_VER 38 #define IMPLOT_INLINE __forceinline 39 #elif defined(__GNUC__) 40 #define IMPLOT_INLINE inline __attribute__((__always_inline__)) 41 #elif defined(__CLANG__) 42 #if __has_attribute(__always_inline__) 43 #define IMPLOT_INLINE inline __attribute__((__always_inline__)) 44 #else 45 #define IMPLOT_INLINE inline 46 #endif 47 #else 48 #define IMPLOT_INLINE inline 49 #endif 50#else 51 #define IMPLOT_INLINE inline 52#endif 53 54#if defined __SSE__ || defined __x86_64__ || defined _M_X64 55#ifndef IMGUI_ENABLE_SSE 56#include <immintrin.h> 57#endif 58static IMPLOT_INLINE float ImInvSqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); } 59#else 60static IMPLOT_INLINE float ImInvSqrt(float x) { return 1.0f / sqrtf(x); } 61#endif 62 63#define IMPLOT_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImInvSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0) 64 65// Support for pre-1.82 versions. Users on 1.82+ can use 0 (default) flags to mean "all corners" but in order to support older versions we are more explicit. 66#if (IMGUI_VERSION_NUM < 18102) && !defined(ImDrawFlags_RoundCornersAll) 67#define ImDrawFlags_RoundCornersAll ImDrawCornerFlags_All 68#endif 69 70//----------------------------------------------------------------------------- 71// [SECTION] Template instantiation utility 72//----------------------------------------------------------------------------- 73 74// By default, templates are instantiated for `float`, `double`, and for the following integer types, which are defined in imgui.h: 75// signed char ImS8; // 8-bit signed integer 76// unsigned char ImU8; // 8-bit unsigned integer 77// signed short ImS16; // 16-bit signed integer 78// unsigned short ImU16; // 16-bit unsigned integer 79// signed int ImS32; // 32-bit signed integer == int 80// unsigned int ImU32; // 32-bit unsigned integer 81// signed long long ImS64; // 64-bit signed integer 82// unsigned long long ImU64; // 64-bit unsigned integer 83// (note: this list does *not* include `long`, `unsigned long` and `long double`) 84// 85// You can customize the supported types by defining IMPLOT_CUSTOM_NUMERIC_TYPES at compile time to define your own type list. 86// As an example, you could use the compile time define given by the line below in order to support only float and double. 87// -DIMPLOT_CUSTOM_NUMERIC_TYPES="(float)(double)" 88// In order to support all known C++ types, use: 89// -DIMPLOT_CUSTOM_NUMERIC_TYPES="(signed char)(unsigned char)(signed short)(unsigned short)(signed int)(unsigned int)(signed long)(unsigned long)(signed long long)(unsigned long long)(float)(double)(long double)" 90 91#ifdef IMPLOT_CUSTOM_NUMERIC_TYPES 92 #define IMPLOT_NUMERIC_TYPES IMPLOT_CUSTOM_NUMERIC_TYPES 93#else 94 #define IMPLOT_NUMERIC_TYPES (ImS8)(ImU8)(ImS16)(ImU16)(ImS32)(ImU32)(ImS64)(ImU64)(float)(double) 95#endif 96 97// CALL_INSTANTIATE_FOR_NUMERIC_TYPES will duplicate the template instantion code `INSTANTIATE_MACRO(T)` on supported types. 98#define _CAT(x, y) _CAT_(x, y) 99#define _CAT_(x,y) x ## y 100#define _INSTANTIATE_FOR_NUMERIC_TYPES(chain) _CAT(_INSTANTIATE_FOR_NUMERIC_TYPES_1 chain, _END) 101#define _INSTANTIATE_FOR_NUMERIC_TYPES_1(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_2 102#define _INSTANTIATE_FOR_NUMERIC_TYPES_2(T) INSTANTIATE_MACRO(T) _INSTANTIATE_FOR_NUMERIC_TYPES_1 103#define _INSTANTIATE_FOR_NUMERIC_TYPES_1_END 104#define _INSTANTIATE_FOR_NUMERIC_TYPES_2_END 105#define CALL_INSTANTIATE_FOR_NUMERIC_TYPES() _INSTANTIATE_FOR_NUMERIC_TYPES(IMPLOT_NUMERIC_TYPES) 106 107namespace ImPlot { 108 109//----------------------------------------------------------------------------- 110// [SECTION] Utils 111//----------------------------------------------------------------------------- 112 113// Calc maximum index size of ImDrawIdx 114template <typename T> 115struct MaxIdx { static const unsigned int Value; }; 116template <> const unsigned int MaxIdx<unsigned short>::Value = 65535; 117template <> const unsigned int MaxIdx<unsigned int>::Value = 4294967295; 118 119IMPLOT_INLINE void GetLineRenderProps(const ImDrawList& draw_list, float& half_weight, ImVec2& tex_uv0, ImVec2& tex_uv1) { 120 const bool aa = ImHasFlag(draw_list.Flags, ImDrawListFlags_AntiAliasedLines) && 121 ImHasFlag(draw_list.Flags, ImDrawListFlags_AntiAliasedLinesUseTex); 122 if (aa) { 123 ImVec4 tex_uvs = draw_list._Data->TexUvLines[(int)(half_weight*2)]; 124 tex_uv0 = ImVec2(tex_uvs.x, tex_uvs.y); 125 tex_uv1 = ImVec2(tex_uvs.z, tex_uvs.w); 126 half_weight += 1; 127 } 128 else { 129 tex_uv0 = tex_uv1 = draw_list._Data->TexUvWhitePixel; 130 } 131} 132 133IMPLOT_INLINE void PrimLine(ImDrawList& draw_list, const ImVec2& P1, const ImVec2& P2, float half_weight, ImU32 col, const ImVec2& tex_uv0, const ImVec2 tex_uv1) { 134 float dx = P2.x - P1.x; 135 float dy = P2.y - P1.y; 136 IMPLOT_NORMALIZE2F_OVER_ZERO(dx, dy); 137 dx *= half_weight; 138 dy *= half_weight; 139 draw_list._VtxWritePtr[0].pos.x = P1.x + dy; 140 draw_list._VtxWritePtr[0].pos.y = P1.y - dx; 141 draw_list._VtxWritePtr[0].uv = tex_uv0; 142 draw_list._VtxWritePtr[0].col = col; 143 draw_list._VtxWritePtr[1].pos.x = P2.x + dy; 144 draw_list._VtxWritePtr[1].pos.y = P2.y - dx; 145 draw_list._VtxWritePtr[1].uv = tex_uv0; 146 draw_list._VtxWritePtr[1].col = col; 147 draw_list._VtxWritePtr[2].pos.x = P2.x - dy; 148 draw_list._VtxWritePtr[2].pos.y = P2.y + dx; 149 draw_list._VtxWritePtr[2].uv = tex_uv1; 150 draw_list._VtxWritePtr[2].col = col; 151 draw_list._VtxWritePtr[3].pos.x = P1.x - dy; 152 draw_list._VtxWritePtr[3].pos.y = P1.y + dx; 153 draw_list._VtxWritePtr[3].uv = tex_uv1; 154 draw_list._VtxWritePtr[3].col = col; 155 draw_list._VtxWritePtr += 4; 156 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 157 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 158 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 159 draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 160 draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 161 draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 162 draw_list._IdxWritePtr += 6; 163 draw_list._VtxCurrentIdx += 4; 164} 165 166IMPLOT_INLINE void PrimRectFill(ImDrawList& draw_list, const ImVec2& Pmin, const ImVec2& Pmax, ImU32 col, const ImVec2& uv) { 167 draw_list._VtxWritePtr[0].pos = Pmin; 168 draw_list._VtxWritePtr[0].uv = uv; 169 draw_list._VtxWritePtr[0].col = col; 170 draw_list._VtxWritePtr[1].pos = Pmax; 171 draw_list._VtxWritePtr[1].uv = uv; 172 draw_list._VtxWritePtr[1].col = col; 173 draw_list._VtxWritePtr[2].pos.x = Pmin.x; 174 draw_list._VtxWritePtr[2].pos.y = Pmax.y; 175 draw_list._VtxWritePtr[2].uv = uv; 176 draw_list._VtxWritePtr[2].col = col; 177 draw_list._VtxWritePtr[3].pos.x = Pmax.x; 178 draw_list._VtxWritePtr[3].pos.y = Pmin.y; 179 draw_list._VtxWritePtr[3].uv = uv; 180 draw_list._VtxWritePtr[3].col = col; 181 draw_list._VtxWritePtr += 4; 182 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 183 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 184 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 185 draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 186 draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 187 draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 188 draw_list._IdxWritePtr += 6; 189 draw_list._VtxCurrentIdx += 4; 190} 191 192IMPLOT_INLINE void PrimRectLine(ImDrawList& draw_list, const ImVec2& Pmin, const ImVec2& Pmax, float weight, ImU32 col, const ImVec2& uv) { 193 194 draw_list._VtxWritePtr[0].pos.x = Pmin.x; 195 draw_list._VtxWritePtr[0].pos.y = Pmin.y; 196 draw_list._VtxWritePtr[0].uv = uv; 197 draw_list._VtxWritePtr[0].col = col; 198 199 draw_list._VtxWritePtr[1].pos.x = Pmin.x; 200 draw_list._VtxWritePtr[1].pos.y = Pmax.y; 201 draw_list._VtxWritePtr[1].uv = uv; 202 draw_list._VtxWritePtr[1].col = col; 203 204 draw_list._VtxWritePtr[2].pos.x = Pmax.x; 205 draw_list._VtxWritePtr[2].pos.y = Pmax.y; 206 draw_list._VtxWritePtr[2].uv = uv; 207 draw_list._VtxWritePtr[2].col = col; 208 209 draw_list._VtxWritePtr[3].pos.x = Pmax.x; 210 draw_list._VtxWritePtr[3].pos.y = Pmin.y; 211 draw_list._VtxWritePtr[3].uv = uv; 212 draw_list._VtxWritePtr[3].col = col; 213 214 draw_list._VtxWritePtr[4].pos.x = Pmin.x + weight; 215 draw_list._VtxWritePtr[4].pos.y = Pmin.y + weight; 216 draw_list._VtxWritePtr[4].uv = uv; 217 draw_list._VtxWritePtr[4].col = col; 218 219 draw_list._VtxWritePtr[5].pos.x = Pmin.x + weight; 220 draw_list._VtxWritePtr[5].pos.y = Pmax.y - weight; 221 draw_list._VtxWritePtr[5].uv = uv; 222 draw_list._VtxWritePtr[5].col = col; 223 224 draw_list._VtxWritePtr[6].pos.x = Pmax.x - weight; 225 draw_list._VtxWritePtr[6].pos.y = Pmax.y - weight; 226 draw_list._VtxWritePtr[6].uv = uv; 227 draw_list._VtxWritePtr[6].col = col; 228 229 draw_list._VtxWritePtr[7].pos.x = Pmax.x - weight; 230 draw_list._VtxWritePtr[7].pos.y = Pmin.y + weight; 231 draw_list._VtxWritePtr[7].uv = uv; 232 draw_list._VtxWritePtr[7].col = col; 233 234 draw_list._VtxWritePtr += 8; 235 236 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0); 237 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 238 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5); 239 draw_list._IdxWritePtr += 3; 240 241 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0); 242 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5); 243 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4); 244 draw_list._IdxWritePtr += 3; 245 246 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 247 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 248 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6); 249 draw_list._IdxWritePtr += 3; 250 251 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 252 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6); 253 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 5); 254 draw_list._IdxWritePtr += 3; 255 256 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 257 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 258 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7); 259 draw_list._IdxWritePtr += 3; 260 261 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 2); 262 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7); 263 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 6); 264 draw_list._IdxWritePtr += 3; 265 266 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 267 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 0); 268 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4); 269 draw_list._IdxWritePtr += 3; 270 271 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 272 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4); 273 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 7); 274 draw_list._IdxWritePtr += 3; 275 276 draw_list._VtxCurrentIdx += 8; 277} 278 279 280//----------------------------------------------------------------------------- 281// [SECTION] Item Utils 282//----------------------------------------------------------------------------- 283 284ImPlotItem* RegisterOrGetItem(const char* label_id, ImPlotItemFlags flags, bool* just_created) { 285 ImPlotContext& gp = *GImPlot; 286 ImPlotItemGroup& Items = *gp.CurrentItems; 287 ImGuiID id = Items.GetItemID(label_id); 288 if (just_created != nullptr) 289 *just_created = Items.GetItem(id) == nullptr; 290 ImPlotItem* item = Items.GetOrAddItem(id); 291 if (item->SeenThisFrame) 292 return item; 293 item->SeenThisFrame = true; 294 int idx = Items.GetItemIndex(item); 295 item->ID = id; 296 if (!ImHasFlag(flags, ImPlotItemFlags_NoLegend) && ImGui::FindRenderedTextEnd(label_id, nullptr) != label_id) { 297 Items.Legend.Indices.push_back(idx); 298 item->NameOffset = Items.Legend.Labels.size(); 299 Items.Legend.Labels.append(label_id, label_id + strlen(label_id) + 1); 300 } 301 else { 302 item->Show = true; 303 } 304 return item; 305} 306 307ImPlotItem* GetItem(const char* label_id) { 308 ImPlotContext& gp = *GImPlot; 309 return gp.CurrentItems->GetItem(label_id); 310} 311 312bool IsItemHidden(const char* label_id) { 313 ImPlotItem* item = GetItem(label_id); 314 return item != nullptr && !item->Show; 315} 316 317ImPlotItem* GetCurrentItem() { 318 ImPlotContext& gp = *GImPlot; 319 return gp.CurrentItem; 320} 321 322void SetNextLineStyle(const ImVec4& col, float weight) { 323 ImPlotContext& gp = *GImPlot; 324 gp.NextItemData.Colors[ImPlotCol_Line] = col; 325 gp.NextItemData.LineWeight = weight; 326} 327 328void SetNextFillStyle(const ImVec4& col, float alpha) { 329 ImPlotContext& gp = *GImPlot; 330 gp.NextItemData.Colors[ImPlotCol_Fill] = col; 331 gp.NextItemData.FillAlpha = alpha; 332} 333 334void SetNextMarkerStyle(ImPlotMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) { 335 ImPlotContext& gp = *GImPlot; 336 gp.NextItemData.Marker = marker; 337 gp.NextItemData.Colors[ImPlotCol_MarkerFill] = fill; 338 gp.NextItemData.MarkerSize = size; 339 gp.NextItemData.Colors[ImPlotCol_MarkerOutline] = outline; 340 gp.NextItemData.MarkerWeight = weight; 341} 342 343void SetNextErrorBarStyle(const ImVec4& col, float size, float weight) { 344 ImPlotContext& gp = *GImPlot; 345 gp.NextItemData.Colors[ImPlotCol_ErrorBar] = col; 346 gp.NextItemData.ErrorBarSize = size; 347 gp.NextItemData.ErrorBarWeight = weight; 348} 349 350ImVec4 GetLastItemColor() { 351 ImPlotContext& gp = *GImPlot; 352 if (gp.PreviousItem) 353 return ImGui::ColorConvertU32ToFloat4(gp.PreviousItem->Color); 354 return ImVec4(); 355} 356 357void BustItemCache() { 358 ImPlotContext& gp = *GImPlot; 359 for (int p = 0; p < gp.Plots.GetBufSize(); ++p) { 360 ImPlotPlot& plot = *gp.Plots.GetByIndex(p); 361 plot.Items.Reset(); 362 } 363 for (int p = 0; p < gp.Subplots.GetBufSize(); ++p) { 364 ImPlotSubplot& subplot = *gp.Subplots.GetByIndex(p); 365 subplot.Items.Reset(); 366 } 367} 368 369void BustColorCache(const char* plot_title_id) { 370 ImPlotContext& gp = *GImPlot; 371 if (plot_title_id == nullptr) { 372 BustItemCache(); 373 } 374 else { 375 ImGuiID id = ImGui::GetCurrentWindow()->GetID(plot_title_id); 376 ImPlotPlot* plot = gp.Plots.GetByKey(id); 377 if (plot != nullptr) 378 plot->Items.Reset(); 379 else { 380 ImPlotSubplot* subplot = gp.Subplots.GetByKey(id); 381 if (subplot != nullptr) 382 subplot->Items.Reset(); 383 } 384 } 385} 386 387//----------------------------------------------------------------------------- 388// [SECTION] BeginItem / EndItem 389//----------------------------------------------------------------------------- 390 391static const float ITEM_HIGHLIGHT_LINE_SCALE = 2.0f; 392static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f; 393 394// Begins a new item. Returns false if the item should not be plotted. 395bool BeginItem(const char* label_id, ImPlotItemFlags flags, ImPlotCol recolor_from) { 396 ImPlotContext& gp = *GImPlot; 397 IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!"); 398 SetupLock(); 399 bool just_created; 400 ImPlotItem* item = RegisterOrGetItem(label_id, flags, &just_created); 401 // set current item 402 gp.CurrentItem = item; 403 ImPlotNextItemData& s = gp.NextItemData; 404 // set/override item color 405 if (recolor_from != -1) { 406 if (!IsColorAuto(s.Colors[recolor_from])) 407 item->Color = ImGui::ColorConvertFloat4ToU32(s.Colors[recolor_from]); 408 else if (!IsColorAuto(gp.Style.Colors[recolor_from])) 409 item->Color = ImGui::ColorConvertFloat4ToU32(gp.Style.Colors[recolor_from]); 410 else if (just_created) 411 item->Color = NextColormapColorU32(); 412 } 413 else if (just_created) { 414 item->Color = NextColormapColorU32(); 415 } 416 // hide/show item 417 if (gp.NextItemData.HasHidden) { 418 if (just_created || gp.NextItemData.HiddenCond == ImGuiCond_Always) 419 item->Show = !gp.NextItemData.Hidden; 420 } 421 if (!item->Show) { 422 // reset next item data 423 gp.NextItemData.Reset(); 424 gp.PreviousItem = item; 425 gp.CurrentItem = nullptr; 426 return false; 427 } 428 else { 429 ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color); 430 // stage next item colors 431 s.Colors[ImPlotCol_Line] = IsColorAuto(s.Colors[ImPlotCol_Line]) ? ( IsColorAuto(ImPlotCol_Line) ? item_color : gp.Style.Colors[ImPlotCol_Line] ) : s.Colors[ImPlotCol_Line]; 432 s.Colors[ImPlotCol_Fill] = IsColorAuto(s.Colors[ImPlotCol_Fill]) ? ( IsColorAuto(ImPlotCol_Fill) ? item_color : gp.Style.Colors[ImPlotCol_Fill] ) : s.Colors[ImPlotCol_Fill]; 433 s.Colors[ImPlotCol_MarkerOutline] = IsColorAuto(s.Colors[ImPlotCol_MarkerOutline]) ? ( IsColorAuto(ImPlotCol_MarkerOutline) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerOutline] ) : s.Colors[ImPlotCol_MarkerOutline]; 434 s.Colors[ImPlotCol_MarkerFill] = IsColorAuto(s.Colors[ImPlotCol_MarkerFill]) ? ( IsColorAuto(ImPlotCol_MarkerFill) ? s.Colors[ImPlotCol_Line] : gp.Style.Colors[ImPlotCol_MarkerFill] ) : s.Colors[ImPlotCol_MarkerFill]; 435 s.Colors[ImPlotCol_ErrorBar] = IsColorAuto(s.Colors[ImPlotCol_ErrorBar]) ? ( GetStyleColorVec4(ImPlotCol_ErrorBar) ) : s.Colors[ImPlotCol_ErrorBar]; 436 // stage next item style vars 437 s.LineWeight = s.LineWeight < 0 ? gp.Style.LineWeight : s.LineWeight; 438 s.Marker = s.Marker < 0 ? gp.Style.Marker : s.Marker; 439 s.MarkerSize = s.MarkerSize < 0 ? gp.Style.MarkerSize : s.MarkerSize; 440 s.MarkerWeight = s.MarkerWeight < 0 ? gp.Style.MarkerWeight : s.MarkerWeight; 441 s.FillAlpha = s.FillAlpha < 0 ? gp.Style.FillAlpha : s.FillAlpha; 442 s.ErrorBarSize = s.ErrorBarSize < 0 ? gp.Style.ErrorBarSize : s.ErrorBarSize; 443 s.ErrorBarWeight = s.ErrorBarWeight < 0 ? gp.Style.ErrorBarWeight : s.ErrorBarWeight; 444 s.DigitalBitHeight = s.DigitalBitHeight < 0 ? gp.Style.DigitalBitHeight : s.DigitalBitHeight; 445 s.DigitalBitGap = s.DigitalBitGap < 0 ? gp.Style.DigitalBitGap : s.DigitalBitGap; 446 // apply alpha modifier(s) 447 s.Colors[ImPlotCol_Fill].w *= s.FillAlpha; 448 s.Colors[ImPlotCol_MarkerFill].w *= s.FillAlpha; // TODO: this should be separate, if it at all 449 // apply highlight mods 450 if (item->LegendHovered) { 451 if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlotLegendFlags_NoHighlightItem)) { 452 s.LineWeight *= ITEM_HIGHLIGHT_LINE_SCALE; 453 s.MarkerSize *= ITEM_HIGHLIGHT_MARK_SCALE; 454 s.MarkerWeight *= ITEM_HIGHLIGHT_LINE_SCALE; 455 // TODO: how to highlight fills? 456 } 457 if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlotLegendFlags_NoHighlightAxis)) { 458 if (gp.CurrentPlot->EnabledAxesX() > 1) 459 gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentX].ColorHiLi = item->Color; 460 if (gp.CurrentPlot->EnabledAxesY() > 1) 461 gp.CurrentPlot->Axes[gp.CurrentPlot->CurrentY].ColorHiLi = item->Color; 462 } 463 } 464 // set render flags 465 s.RenderLine = s.Colors[ImPlotCol_Line].w > 0 && s.LineWeight > 0; 466 s.RenderFill = s.Colors[ImPlotCol_Fill].w > 0; 467 s.RenderMarkerFill = s.Colors[ImPlotCol_MarkerFill].w > 0; 468 s.RenderMarkerLine = s.Colors[ImPlotCol_MarkerOutline].w > 0 && s.MarkerWeight > 0; 469 // push rendering clip rect 470 PushPlotClipRect(); 471 return true; 472 } 473} 474 475// Ends an item (call only if BeginItem returns true) 476void EndItem() { 477 ImPlotContext& gp = *GImPlot; 478 // pop rendering clip rect 479 PopPlotClipRect(); 480 // reset next item data 481 gp.NextItemData.Reset(); 482 // set current item 483 gp.PreviousItem = gp.CurrentItem; 484 gp.CurrentItem = nullptr; 485} 486 487//----------------------------------------------------------------------------- 488// [SECTION] Indexers 489//----------------------------------------------------------------------------- 490 491template <typename T> 492IMPLOT_INLINE T IndexData(const T* data, int idx, int count, int offset, int stride) { 493 const int s = ((offset == 0) << 0) | ((stride == sizeof(T)) << 1); 494 switch (s) { 495 case 3 : return data[idx]; 496 case 2 : return data[(offset + idx) % count]; 497 case 1 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx) ) * stride); 498 case 0 : return *(const T*)(const void*)((const unsigned char*)data + (size_t)((offset + idx) % count) * stride); 499 default: return T(0); 500 } 501} 502 503template <typename T> 504struct IndexerIdx { 505 IndexerIdx(const T* data, int count, int offset = 0, int stride = sizeof(T)) : 506 Data(data), 507 Count(count), 508 Offset(count ? ImPosMod(offset, count) : 0), 509 Stride(stride) 510 { } 511 template <typename I> IMPLOT_INLINE double operator()(I idx) const { 512 return (double)IndexData(Data, idx, Count, Offset, Stride); 513 } 514 const T* Data; 515 int Count; 516 int Offset; 517 int Stride; 518}; 519 520template <typename _Indexer1, typename _Indexer2> 521struct IndexerAdd { 522 IndexerAdd(const _Indexer1& indexer1, const _Indexer2& indexer2, double scale1 = 1, double scale2 = 1) 523 : Indexer1(indexer1), 524 Indexer2(indexer2), 525 Scale1(scale1), 526 Scale2(scale2), 527 Count(ImMin(Indexer1.Count, Indexer2.Count)) 528 { } 529 template <typename I> IMPLOT_INLINE double operator()(I idx) const { 530 return Scale1 * Indexer1(idx) + Scale2 * Indexer2(idx); 531 } 532 const _Indexer1& Indexer1; 533 const _Indexer2& Indexer2; 534 double Scale1; 535 double Scale2; 536 int Count; 537}; 538 539struct IndexerLin { 540 IndexerLin(double m, double b) : M(m), B(b) { } 541 template <typename I> IMPLOT_INLINE double operator()(I idx) const { 542 return M * idx + B; 543 } 544 const double M; 545 const double B; 546}; 547 548struct IndexerConst { 549 IndexerConst(double ref) : Ref(ref) { } 550 template <typename I> IMPLOT_INLINE double operator()(I) const { return Ref; } 551 const double Ref; 552}; 553 554//----------------------------------------------------------------------------- 555// [SECTION] Getters 556//----------------------------------------------------------------------------- 557 558template <typename _IndexerX, typename _IndexerY> 559struct GetterXY { 560 GetterXY(_IndexerX x, _IndexerY y, int count) : IndxerX(x), IndxerY(y), Count(count) { } 561 template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { 562 return ImPlotPoint(IndxerX(idx),IndxerY(idx)); 563 } 564 const _IndexerX IndxerX; 565 const _IndexerY IndxerY; 566 const int Count; 567}; 568 569/// Interprets a user's function pointer as ImPlotPoints 570struct GetterFuncPtr { 571 GetterFuncPtr(ImPlotGetter getter, void* data, int count) : 572 Getter(getter), 573 Data(data), 574 Count(count) 575 { } 576 template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { 577 return Getter(idx, Data); 578 } 579 ImPlotGetter Getter; 580 void* const Data; 581 const int Count; 582}; 583 584template <typename _Getter> 585struct GetterOverrideX { 586 GetterOverrideX(_Getter getter, double x) : Getter(getter), X(x), Count(getter.Count) { } 587 template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { 588 ImPlotPoint p = Getter(idx); 589 p.x = X; 590 return p; 591 } 592 const _Getter Getter; 593 const double X; 594 const int Count; 595}; 596 597template <typename _Getter> 598struct GetterOverrideY { 599 GetterOverrideY(_Getter getter, double y) : Getter(getter), Y(y), Count(getter.Count) { } 600 template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { 601 ImPlotPoint p = Getter(idx); 602 p.y = Y; 603 return p; 604 } 605 const _Getter Getter; 606 const double Y; 607 const int Count; 608}; 609 610template <typename _Getter> 611struct GetterLoop { 612 GetterLoop(_Getter getter) : Getter(getter), Count(getter.Count + 1) { } 613 template <typename I> IMPLOT_INLINE ImPlotPoint operator()(I idx) const { 614 idx = idx % (Count - 1); 615 return Getter(idx); 616 } 617 const _Getter Getter; 618 const int Count; 619}; 620 621template <typename T> 622struct GetterError { 623 GetterError(const T* xs, const T* ys, const T* neg, const T* pos, int count, int offset, int stride) : 624 Xs(xs), 625 Ys(ys), 626 Neg(neg), 627 Pos(pos), 628 Count(count), 629 Offset(count ? ImPosMod(offset, count) : 0), 630 Stride(stride) 631 { } 632 template <typename I> IMPLOT_INLINE ImPlotPointError operator()(I idx) const { 633 return ImPlotPointError((double)IndexData(Xs, idx, Count, Offset, Stride), 634 (double)IndexData(Ys, idx, Count, Offset, Stride), 635 (double)IndexData(Neg, idx, Count, Offset, Stride), 636 (double)IndexData(Pos, idx, Count, Offset, Stride)); 637 } 638 const T* const Xs; 639 const T* const Ys; 640 const T* const Neg; 641 const T* const Pos; 642 const int Count; 643 const int Offset; 644 const int Stride; 645}; 646 647//----------------------------------------------------------------------------- 648// [SECTION] Fitters 649//----------------------------------------------------------------------------- 650 651template <typename _Getter1> 652struct Fitter1 { 653 Fitter1(const _Getter1& getter) : Getter(getter) { } 654 void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const { 655 for (int i = 0; i < Getter.Count; ++i) { 656 ImPlotPoint p = Getter(i); 657 x_axis.ExtendFitWith(y_axis, p.x, p.y); 658 y_axis.ExtendFitWith(x_axis, p.y, p.x); 659 } 660 } 661 const _Getter1& Getter; 662}; 663 664template <typename _Getter1> 665struct FitterX { 666 FitterX(const _Getter1& getter) : Getter(getter) { } 667 void Fit(ImPlotAxis& x_axis, ImPlotAxis&) const { 668 for (int i = 0; i < Getter.Count; ++i) { 669 ImPlotPoint p = Getter(i); 670 x_axis.ExtendFit(p.x); 671 } 672 } 673 const _Getter1& Getter; 674}; 675 676template <typename _Getter1> 677struct FitterY { 678 FitterY(const _Getter1& getter) : Getter(getter) { } 679 void Fit(ImPlotAxis&, ImPlotAxis& y_axis) const { 680 for (int i = 0; i < Getter.Count; ++i) { 681 ImPlotPoint p = Getter(i); 682 y_axis.ExtendFit(p.y); 683 } 684 } 685 const _Getter1& Getter; 686}; 687 688template <typename _Getter1, typename _Getter2> 689struct Fitter2 { 690 Fitter2(const _Getter1& getter1, const _Getter2& getter2) : Getter1(getter1), Getter2(getter2) { } 691 void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const { 692 for (int i = 0; i < Getter1.Count; ++i) { 693 ImPlotPoint p = Getter1(i); 694 x_axis.ExtendFitWith(y_axis, p.x, p.y); 695 y_axis.ExtendFitWith(x_axis, p.y, p.x); 696 } 697 for (int i = 0; i < Getter2.Count; ++i) { 698 ImPlotPoint p = Getter2(i); 699 x_axis.ExtendFitWith(y_axis, p.x, p.y); 700 y_axis.ExtendFitWith(x_axis, p.y, p.x); 701 } 702 } 703 const _Getter1& Getter1; 704 const _Getter2& Getter2; 705}; 706 707template <typename _Getter1, typename _Getter2> 708struct FitterBarV { 709 FitterBarV(const _Getter1& getter1, const _Getter2& getter2, double width) : 710 Getter1(getter1), 711 Getter2(getter2), 712 HalfWidth(width*0.5) 713 { } 714 void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const { 715 int count = ImMin(Getter1.Count, Getter2.Count); 716 for (int i = 0; i < count; ++i) { 717 ImPlotPoint p1 = Getter1(i); p1.x -= HalfWidth; 718 ImPlotPoint p2 = Getter2(i); p2.x += HalfWidth; 719 x_axis.ExtendFitWith(y_axis, p1.x, p1.y); 720 y_axis.ExtendFitWith(x_axis, p1.y, p1.x); 721 x_axis.ExtendFitWith(y_axis, p2.x, p2.y); 722 y_axis.ExtendFitWith(x_axis, p2.y, p2.x); 723 } 724 } 725 const _Getter1& Getter1; 726 const _Getter2& Getter2; 727 const double HalfWidth; 728}; 729 730template <typename _Getter1, typename _Getter2> 731struct FitterBarH { 732 FitterBarH(const _Getter1& getter1, const _Getter2& getter2, double height) : 733 Getter1(getter1), 734 Getter2(getter2), 735 HalfHeight(height*0.5) 736 { } 737 void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const { 738 int count = ImMin(Getter1.Count, Getter2.Count); 739 for (int i = 0; i < count; ++i) { 740 ImPlotPoint p1 = Getter1(i); p1.y -= HalfHeight; 741 ImPlotPoint p2 = Getter2(i); p2.y += HalfHeight; 742 x_axis.ExtendFitWith(y_axis, p1.x, p1.y); 743 y_axis.ExtendFitWith(x_axis, p1.y, p1.x); 744 x_axis.ExtendFitWith(y_axis, p2.x, p2.y); 745 y_axis.ExtendFitWith(x_axis, p2.y, p2.x); 746 } 747 } 748 const _Getter1& Getter1; 749 const _Getter2& Getter2; 750 const double HalfHeight; 751}; 752 753struct FitterRect { 754 FitterRect(const ImPlotPoint& pmin, const ImPlotPoint& pmax) : 755 Pmin(pmin), 756 Pmax(pmax) 757 { } 758 FitterRect(const ImPlotRect& rect) : 759 FitterRect(rect.Min(), rect.Max()) 760 { } 761 void Fit(ImPlotAxis& x_axis, ImPlotAxis& y_axis) const { 762 x_axis.ExtendFitWith(y_axis, Pmin.x, Pmin.y); 763 y_axis.ExtendFitWith(x_axis, Pmin.y, Pmin.x); 764 x_axis.ExtendFitWith(y_axis, Pmax.x, Pmax.y); 765 y_axis.ExtendFitWith(x_axis, Pmax.y, Pmax.x); 766 } 767 const ImPlotPoint Pmin; 768 const ImPlotPoint Pmax; 769}; 770 771//----------------------------------------------------------------------------- 772// [SECTION] Transformers 773//----------------------------------------------------------------------------- 774 775struct Transformer1 { 776 Transformer1(double pixMin, double pltMin, double pltMax, double m, double scaMin, double scaMax, ImPlotTransform fwd, void* data) : 777 ScaMin(scaMin), 778 ScaMax(scaMax), 779 PltMin(pltMin), 780 PltMax(pltMax), 781 PixMin(pixMin), 782 M(m), 783 TransformFwd(fwd), 784 TransformData(data) 785 { } 786 787 template <typename T> IMPLOT_INLINE float operator()(T p) const { 788 if (TransformFwd != nullptr) { 789 double s = TransformFwd(p, TransformData); 790 double t = (s - ScaMin) / (ScaMax - ScaMin); 791 p = PltMin + (PltMax - PltMin) * t; 792 } 793 return (float)(PixMin + M * (p - PltMin)); 794 } 795 796 double ScaMin, ScaMax, PltMin, PltMax, PixMin, M; 797 ImPlotTransform TransformFwd; 798 void* TransformData; 799}; 800 801struct Transformer2 { 802 Transformer2(const ImPlotAxis& x_axis, const ImPlotAxis& y_axis) : 803 Tx(x_axis.PixelMin, 804 x_axis.Range.Min, 805 x_axis.Range.Max, 806 x_axis.ScaleToPixel, 807 x_axis.ScaleMin, 808 x_axis.ScaleMax, 809 x_axis.TransformForward, 810 x_axis.TransformData), 811 Ty(y_axis.PixelMin, 812 y_axis.Range.Min, 813 y_axis.Range.Max, 814 y_axis.ScaleToPixel, 815 y_axis.ScaleMin, 816 y_axis.ScaleMax, 817 y_axis.TransformForward, 818 y_axis.TransformData) 819 { } 820 821 Transformer2(const ImPlotPlot& plot) : 822 Transformer2(plot.Axes[plot.CurrentX], plot.Axes[plot.CurrentY]) 823 { } 824 825 Transformer2() : 826 Transformer2(*GImPlot->CurrentPlot) 827 { } 828 829 template <typename P> IMPLOT_INLINE ImVec2 operator()(const P& plt) const { 830 ImVec2 out; 831 out.x = Tx(plt.x); 832 out.y = Ty(plt.y); 833 return out; 834 } 835 836 template <typename T> IMPLOT_INLINE ImVec2 operator()(T x, T y) const { 837 ImVec2 out; 838 out.x = Tx(x); 839 out.y = Ty(y); 840 return out; 841 } 842 843 Transformer1 Tx; 844 Transformer1 Ty; 845}; 846 847//----------------------------------------------------------------------------- 848// [SECTION] Renderers 849//----------------------------------------------------------------------------- 850 851struct RendererBase { 852 RendererBase(int prims, int idx_consumed, int vtx_consumed) : 853 Prims(prims), 854 IdxConsumed(idx_consumed), 855 VtxConsumed(vtx_consumed) 856 { } 857 const int Prims; 858 Transformer2 Transformer; 859 const int IdxConsumed; 860 const int VtxConsumed; 861}; 862 863template <class _Getter> 864struct RendererLineStrip : RendererBase { 865 RendererLineStrip(const _Getter& getter, ImU32 col, float weight) : 866 RendererBase(getter.Count - 1, 6, 4), 867 Getter(getter), 868 Col(col), 869 HalfWeight(ImMax(1.0f,weight)*0.5f) 870 { 871 P1 = this->Transformer(Getter(0)); 872 } 873 void Init(ImDrawList& draw_list) const { 874 GetLineRenderProps(draw_list, HalfWeight, UV0, UV1); 875 } 876 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 877 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 878 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { 879 P1 = P2; 880 return false; 881 } 882 PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); 883 P1 = P2; 884 return true; 885 } 886 const _Getter& Getter; 887 const ImU32 Col; 888 mutable float HalfWeight; 889 mutable ImVec2 P1; 890 mutable ImVec2 UV0; 891 mutable ImVec2 UV1; 892}; 893 894template <class _Getter> 895struct RendererLineStripSkip : RendererBase { 896 RendererLineStripSkip(const _Getter& getter, ImU32 col, float weight) : 897 RendererBase(getter.Count - 1, 6, 4), 898 Getter(getter), 899 Col(col), 900 HalfWeight(ImMax(1.0f,weight)*0.5f) 901 { 902 P1 = this->Transformer(Getter(0)); 903 } 904 void Init(ImDrawList& draw_list) const { 905 GetLineRenderProps(draw_list, HalfWeight, UV0, UV1); 906 } 907 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 908 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 909 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { 910 if (!ImNan(P2.x) && !ImNan(P2.y)) 911 P1 = P2; 912 return false; 913 } 914 PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); 915 if (!ImNan(P2.x) && !ImNan(P2.y)) 916 P1 = P2; 917 return true; 918 } 919 const _Getter& Getter; 920 const ImU32 Col; 921 mutable float HalfWeight; 922 mutable ImVec2 P1; 923 mutable ImVec2 UV0; 924 mutable ImVec2 UV1; 925}; 926 927template <class _Getter> 928struct RendererLineSegments1 : RendererBase { 929 RendererLineSegments1(const _Getter& getter, ImU32 col, float weight) : 930 RendererBase(getter.Count / 2, 6, 4), 931 Getter(getter), 932 Col(col), 933 HalfWeight(ImMax(1.0f,weight)*0.5f) 934 { } 935 void Init(ImDrawList& draw_list) const { 936 GetLineRenderProps(draw_list, HalfWeight, UV0, UV1); 937 } 938 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 939 ImVec2 P1 = this->Transformer(Getter(prim*2+0)); 940 ImVec2 P2 = this->Transformer(Getter(prim*2+1)); 941 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) 942 return false; 943 PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); 944 return true; 945 } 946 const _Getter& Getter; 947 const ImU32 Col; 948 mutable float HalfWeight; 949 mutable ImVec2 UV0; 950 mutable ImVec2 UV1; 951}; 952 953template <class _Getter1, class _Getter2> 954struct RendererLineSegments2 : RendererBase { 955 RendererLineSegments2(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, float weight) : 956 RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), 957 Getter1(getter1), 958 Getter2(getter2), 959 Col(col), 960 HalfWeight(ImMax(1.0f,weight)*0.5f) 961 {} 962 void Init(ImDrawList& draw_list) const { 963 GetLineRenderProps(draw_list, HalfWeight, UV0, UV1); 964 } 965 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 966 ImVec2 P1 = this->Transformer(Getter1(prim)); 967 ImVec2 P2 = this->Transformer(Getter2(prim)); 968 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) 969 return false; 970 PrimLine(draw_list,P1,P2,HalfWeight,Col,UV0,UV1); 971 return true; 972 } 973 const _Getter1& Getter1; 974 const _Getter2& Getter2; 975 const ImU32 Col; 976 mutable float HalfWeight; 977 mutable ImVec2 UV0; 978 mutable ImVec2 UV1; 979}; 980 981template <class _Getter1, class _Getter2> 982struct RendererBarsFillV : RendererBase { 983 RendererBarsFillV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width) : 984 RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), 985 Getter1(getter1), 986 Getter2(getter2), 987 Col(col), 988 HalfWidth(width/2) 989 {} 990 void Init(ImDrawList& draw_list) const { 991 UV = draw_list._Data->TexUvWhitePixel; 992 } 993 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 994 ImPlotPoint p1 = Getter1(prim); 995 ImPlotPoint p2 = Getter2(prim); 996 p1.x += HalfWidth; 997 p2.x -= HalfWidth; 998 ImVec2 P1 = this->Transformer(p1); 999 ImVec2 P2 = this->Transformer(p2); 1000 float width_px = ImAbs(P1.x-P2.x); 1001 if (width_px < 1.0f) { 1002 P1.x += P1.x > P2.x ? (1-width_px) / 2 : (width_px-1) / 2; 1003 P2.x += P2.x > P1.x ? (1-width_px) / 2 : (width_px-1) / 2; 1004 } 1005 ImVec2 PMin = ImMin(P1, P2); 1006 ImVec2 PMax = ImMax(P1, P2); 1007 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) 1008 return false; 1009 PrimRectFill(draw_list,PMin,PMax,Col,UV); 1010 return true; 1011 } 1012 const _Getter1& Getter1; 1013 const _Getter2& Getter2; 1014 const ImU32 Col; 1015 const double HalfWidth; 1016 mutable ImVec2 UV; 1017}; 1018 1019template <class _Getter1, class _Getter2> 1020struct RendererBarsFillH : RendererBase { 1021 RendererBarsFillH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height) : 1022 RendererBase(ImMin(getter1.Count, getter1.Count), 6, 4), 1023 Getter1(getter1), 1024 Getter2(getter2), 1025 Col(col), 1026 HalfHeight(height/2) 1027 {} 1028 void Init(ImDrawList& draw_list) const { 1029 UV = draw_list._Data->TexUvWhitePixel; 1030 } 1031 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1032 ImPlotPoint p1 = Getter1(prim); 1033 ImPlotPoint p2 = Getter2(prim); 1034 p1.y += HalfHeight; 1035 p2.y -= HalfHeight; 1036 ImVec2 P1 = this->Transformer(p1); 1037 ImVec2 P2 = this->Transformer(p2); 1038 float height_px = ImAbs(P1.y-P2.y); 1039 if (height_px < 1.0f) { 1040 P1.y += P1.y > P2.y ? (1-height_px) / 2 : (height_px-1) / 2; 1041 P2.y += P2.y > P1.y ? (1-height_px) / 2 : (height_px-1) / 2; 1042 } 1043 ImVec2 PMin = ImMin(P1, P2); 1044 ImVec2 PMax = ImMax(P1, P2); 1045 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) 1046 return false; 1047 PrimRectFill(draw_list,PMin,PMax,Col,UV); 1048 return true; 1049 } 1050 const _Getter1& Getter1; 1051 const _Getter2& Getter2; 1052 const ImU32 Col; 1053 const double HalfHeight; 1054 mutable ImVec2 UV; 1055}; 1056 1057template <class _Getter1, class _Getter2> 1058struct RendererBarsLineV : RendererBase { 1059 RendererBarsLineV(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double width, float weight) : 1060 RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8), 1061 Getter1(getter1), 1062 Getter2(getter2), 1063 Col(col), 1064 HalfWidth(width/2), 1065 Weight(weight) 1066 {} 1067 void Init(ImDrawList& draw_list) const { 1068 UV = draw_list._Data->TexUvWhitePixel; 1069 } 1070 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1071 ImPlotPoint p1 = Getter1(prim); 1072 ImPlotPoint p2 = Getter2(prim); 1073 p1.x += HalfWidth; 1074 p2.x -= HalfWidth; 1075 ImVec2 P1 = this->Transformer(p1); 1076 ImVec2 P2 = this->Transformer(p2); 1077 float width_px = ImAbs(P1.x-P2.x); 1078 if (width_px < 1.0f) { 1079 P1.x += P1.x > P2.x ? (1-width_px) / 2 : (width_px-1) / 2; 1080 P2.x += P2.x > P1.x ? (1-width_px) / 2 : (width_px-1) / 2; 1081 } 1082 ImVec2 PMin = ImMin(P1, P2); 1083 ImVec2 PMax = ImMax(P1, P2); 1084 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) 1085 return false; 1086 PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); 1087 return true; 1088 } 1089 const _Getter1& Getter1; 1090 const _Getter2& Getter2; 1091 const ImU32 Col; 1092 const double HalfWidth; 1093 const float Weight; 1094 mutable ImVec2 UV; 1095}; 1096 1097template <class _Getter1, class _Getter2> 1098struct RendererBarsLineH : RendererBase { 1099 RendererBarsLineH(const _Getter1& getter1, const _Getter2& getter2, ImU32 col, double height, float weight) : 1100 RendererBase(ImMin(getter1.Count, getter1.Count), 24, 8), 1101 Getter1(getter1), 1102 Getter2(getter2), 1103 Col(col), 1104 HalfHeight(height/2), 1105 Weight(weight) 1106 {} 1107 void Init(ImDrawList& draw_list) const { 1108 UV = draw_list._Data->TexUvWhitePixel; 1109 } 1110 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1111 ImPlotPoint p1 = Getter1(prim); 1112 ImPlotPoint p2 = Getter2(prim); 1113 p1.y += HalfHeight; 1114 p2.y -= HalfHeight; 1115 ImVec2 P1 = this->Transformer(p1); 1116 ImVec2 P2 = this->Transformer(p2); 1117 float height_px = ImAbs(P1.y-P2.y); 1118 if (height_px < 1.0f) { 1119 P1.y += P1.y > P2.y ? (1-height_px) / 2 : (height_px-1) / 2; 1120 P2.y += P2.y > P1.y ? (1-height_px) / 2 : (height_px-1) / 2; 1121 } 1122 ImVec2 PMin = ImMin(P1, P2); 1123 ImVec2 PMax = ImMax(P1, P2); 1124 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) 1125 return false; 1126 PrimRectLine(draw_list,PMin,PMax,Weight,Col,UV); 1127 return true; 1128 } 1129 const _Getter1& Getter1; 1130 const _Getter2& Getter2; 1131 const ImU32 Col; 1132 const double HalfHeight; 1133 const float Weight; 1134 mutable ImVec2 UV; 1135}; 1136 1137 1138template <class _Getter> 1139struct RendererStairsPre : RendererBase { 1140 RendererStairsPre(const _Getter& getter, ImU32 col, float weight) : 1141 RendererBase(getter.Count - 1, 12, 8), 1142 Getter(getter), 1143 Col(col), 1144 HalfWeight(ImMax(1.0f,weight)*0.5f) 1145 { 1146 P1 = this->Transformer(Getter(0)); 1147 } 1148 void Init(ImDrawList& draw_list) const { 1149 UV = draw_list._Data->TexUvWhitePixel; 1150 } 1151 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1152 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 1153 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { 1154 P1 = P2; 1155 return false; 1156 } 1157 PrimRectFill(draw_list, ImVec2(P1.x - HalfWeight, P1.y), ImVec2(P1.x + HalfWeight, P2.y), Col, UV); 1158 PrimRectFill(draw_list, ImVec2(P1.x, P2.y + HalfWeight), ImVec2(P2.x, P2.y - HalfWeight), Col, UV); 1159 P1 = P2; 1160 return true; 1161 } 1162 const _Getter& Getter; 1163 const ImU32 Col; 1164 mutable float HalfWeight; 1165 mutable ImVec2 P1; 1166 mutable ImVec2 UV; 1167}; 1168 1169template <class _Getter> 1170struct RendererStairsPost : RendererBase { 1171 RendererStairsPost(const _Getter& getter, ImU32 col, float weight) : 1172 RendererBase(getter.Count - 1, 12, 8), 1173 Getter(getter), 1174 Col(col), 1175 HalfWeight(ImMax(1.0f,weight) * 0.5f) 1176 { 1177 P1 = this->Transformer(Getter(0)); 1178 } 1179 void Init(ImDrawList& draw_list) const { 1180 UV = draw_list._Data->TexUvWhitePixel; 1181 } 1182 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1183 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 1184 if (!cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) { 1185 P1 = P2; 1186 return false; 1187 } 1188 PrimRectFill(draw_list, ImVec2(P1.x, P1.y + HalfWeight), ImVec2(P2.x, P1.y - HalfWeight), Col, UV); 1189 PrimRectFill(draw_list, ImVec2(P2.x - HalfWeight, P2.y), ImVec2(P2.x + HalfWeight, P1.y), Col, UV); 1190 P1 = P2; 1191 return true; 1192 } 1193 const _Getter& Getter; 1194 const ImU32 Col; 1195 mutable float HalfWeight; 1196 mutable ImVec2 P1; 1197 mutable ImVec2 UV; 1198}; 1199 1200template <class _Getter> 1201struct RendererStairsPreShaded : RendererBase { 1202 RendererStairsPreShaded(const _Getter& getter, ImU32 col) : 1203 RendererBase(getter.Count - 1, 6, 4), 1204 Getter(getter), 1205 Col(col) 1206 { 1207 P1 = this->Transformer(Getter(0)); 1208 Y0 = this->Transformer(ImPlotPoint(0,0)).y; 1209 } 1210 void Init(ImDrawList& draw_list) const { 1211 UV = draw_list._Data->TexUvWhitePixel; 1212 } 1213 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1214 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 1215 ImVec2 PMin(ImMin(P1.x, P2.x), ImMin(Y0, P2.y)); 1216 ImVec2 PMax(ImMax(P1.x, P2.x), ImMax(Y0, P2.y)); 1217 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) { 1218 P1 = P2; 1219 return false; 1220 } 1221 PrimRectFill(draw_list, PMin, PMax, Col, UV); 1222 P1 = P2; 1223 return true; 1224 } 1225 const _Getter& Getter; 1226 const ImU32 Col; 1227 float Y0; 1228 mutable ImVec2 P1; 1229 mutable ImVec2 UV; 1230}; 1231 1232template <class _Getter> 1233struct RendererStairsPostShaded : RendererBase { 1234 RendererStairsPostShaded(const _Getter& getter, ImU32 col) : 1235 RendererBase(getter.Count - 1, 6, 4), 1236 Getter(getter), 1237 Col(col) 1238 { 1239 P1 = this->Transformer(Getter(0)); 1240 Y0 = this->Transformer(ImPlotPoint(0,0)).y; 1241 } 1242 void Init(ImDrawList& draw_list) const { 1243 UV = draw_list._Data->TexUvWhitePixel; 1244 } 1245 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1246 ImVec2 P2 = this->Transformer(Getter(prim + 1)); 1247 ImVec2 PMin(ImMin(P1.x, P2.x), ImMin(P1.y, Y0)); 1248 ImVec2 PMax(ImMax(P1.x, P2.x), ImMax(P1.y, Y0)); 1249 if (!cull_rect.Overlaps(ImRect(PMin, PMax))) { 1250 P1 = P2; 1251 return false; 1252 } 1253 PrimRectFill(draw_list, PMin, PMax, Col, UV); 1254 P1 = P2; 1255 return true; 1256 } 1257 const _Getter& Getter; 1258 const ImU32 Col; 1259 float Y0; 1260 mutable ImVec2 P1; 1261 mutable ImVec2 UV; 1262}; 1263 1264 1265 1266template <class _Getter1, class _Getter2> 1267struct RendererShaded : RendererBase { 1268 RendererShaded(const _Getter1& getter1, const _Getter2& getter2, ImU32 col) : 1269 RendererBase(ImMin(getter1.Count, getter2.Count) - 1, 6, 5), 1270 Getter1(getter1), 1271 Getter2(getter2), 1272 Col(col) 1273 { 1274 P11 = this->Transformer(Getter1(0)); 1275 P12 = this->Transformer(Getter2(0)); 1276 } 1277 void Init(ImDrawList& draw_list) const { 1278 UV = draw_list._Data->TexUvWhitePixel; 1279 } 1280 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1281 ImVec2 P21 = this->Transformer(Getter1(prim+1)); 1282 ImVec2 P22 = this->Transformer(Getter2(prim+1)); 1283 ImRect rect(ImMin(ImMin(ImMin(P11,P12),P21),P22), ImMax(ImMax(ImMax(P11,P12),P21),P22)); 1284 if (!cull_rect.Overlaps(rect)) { 1285 P11 = P21; 1286 P12 = P22; 1287 return false; 1288 } 1289 const int intersect = (P11.y > P12.y && P22.y > P21.y) || (P12.y > P11.y && P21.y > P22.y); 1290 const ImVec2 intersection = intersect == 0 ? ImVec2(0,0) : Intersection(P11,P21,P12,P22); 1291 draw_list._VtxWritePtr[0].pos = P11; 1292 draw_list._VtxWritePtr[0].uv = UV; 1293 draw_list._VtxWritePtr[0].col = Col; 1294 draw_list._VtxWritePtr[1].pos = P21; 1295 draw_list._VtxWritePtr[1].uv = UV; 1296 draw_list._VtxWritePtr[1].col = Col; 1297 draw_list._VtxWritePtr[2].pos = intersection; 1298 draw_list._VtxWritePtr[2].uv = UV; 1299 draw_list._VtxWritePtr[2].col = Col; 1300 draw_list._VtxWritePtr[3].pos = P12; 1301 draw_list._VtxWritePtr[3].uv = UV; 1302 draw_list._VtxWritePtr[3].col = Col; 1303 draw_list._VtxWritePtr[4].pos = P22; 1304 draw_list._VtxWritePtr[4].uv = UV; 1305 draw_list._VtxWritePtr[4].col = Col; 1306 draw_list._VtxWritePtr += 5; 1307 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 1308 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1 + intersect); 1309 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3); 1310 draw_list._IdxWritePtr[3] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 1); 1311 draw_list._IdxWritePtr[4] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 4); 1312 draw_list._IdxWritePtr[5] = (ImDrawIdx)(draw_list._VtxCurrentIdx + 3 - intersect); 1313 draw_list._IdxWritePtr += 6; 1314 draw_list._VtxCurrentIdx += 5; 1315 P11 = P21; 1316 P12 = P22; 1317 return true; 1318 } 1319 const _Getter1& Getter1; 1320 const _Getter2& Getter2; 1321 const ImU32 Col; 1322 mutable ImVec2 P11; 1323 mutable ImVec2 P12; 1324 mutable ImVec2 UV; 1325}; 1326 1327struct RectC { 1328 ImPlotPoint Pos; 1329 ImPlotPoint HalfSize; 1330 ImU32 Color; 1331}; 1332 1333template <typename _Getter> 1334struct RendererRectC : RendererBase { 1335 RendererRectC(const _Getter& getter) : 1336 RendererBase(getter.Count, 6, 4), 1337 Getter(getter) 1338 {} 1339 void Init(ImDrawList& draw_list) const { 1340 UV = draw_list._Data->TexUvWhitePixel; 1341 } 1342 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1343 RectC rect = Getter(prim); 1344 ImVec2 P1 = this->Transformer(rect.Pos.x - rect.HalfSize.x , rect.Pos.y - rect.HalfSize.y); 1345 ImVec2 P2 = this->Transformer(rect.Pos.x + rect.HalfSize.x , rect.Pos.y + rect.HalfSize.y); 1346 if ((rect.Color & IM_COL32_A_MASK) == 0 || !cull_rect.Overlaps(ImRect(ImMin(P1, P2), ImMax(P1, P2)))) 1347 return false; 1348 PrimRectFill(draw_list,P1,P2,rect.Color,UV); 1349 return true; 1350 } 1351 const _Getter& Getter; 1352 mutable ImVec2 UV; 1353}; 1354 1355//----------------------------------------------------------------------------- 1356// [SECTION] RenderPrimitives 1357//----------------------------------------------------------------------------- 1358 1359/// Renders primitive shapes in bulk as efficiently as possible. 1360template <class _Renderer> 1361void RenderPrimitivesEx(const _Renderer& renderer, ImDrawList& draw_list, const ImRect& cull_rect) { 1362 unsigned int prims = renderer.Prims; 1363 unsigned int prims_culled = 0; 1364 unsigned int idx = 0; 1365 renderer.Init(draw_list); 1366 while (prims) { 1367 // find how many can be reserved up to end of current draw command's limit 1368 unsigned int cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - draw_list._VtxCurrentIdx) / renderer.VtxConsumed); 1369 // make sure at least this many elements can be rendered to avoid situations where at the end of buffer this slow path is not taken all the time 1370 if (cnt >= ImMin(64u, prims)) { 1371 if (prims_culled >= cnt) 1372 prims_culled -= cnt; // reuse previous reservation 1373 else { 1374 // add more elements to previous reservation 1375 draw_list.PrimReserve((cnt - prims_culled) * renderer.IdxConsumed, (cnt - prims_culled) * renderer.VtxConsumed); 1376 prims_culled = 0; 1377 } 1378 } 1379 else 1380 { 1381 if (prims_culled > 0) { 1382 draw_list.PrimUnreserve(prims_culled * renderer.IdxConsumed, prims_culled * renderer.VtxConsumed); 1383 prims_culled = 0; 1384 } 1385 cnt = ImMin(prims, (MaxIdx<ImDrawIdx>::Value - 0/*draw_list._VtxCurrentIdx*/) / renderer.VtxConsumed); 1386 // reserve new draw command 1387 draw_list.PrimReserve(cnt * renderer.IdxConsumed, cnt * renderer.VtxConsumed); 1388 } 1389 prims -= cnt; 1390 for (unsigned int ie = idx + cnt; idx != ie; ++idx) { 1391 if (!renderer.Render(draw_list, cull_rect, idx)) 1392 prims_culled++; 1393 } 1394 } 1395 if (prims_culled > 0) 1396 draw_list.PrimUnreserve(prims_culled * renderer.IdxConsumed, prims_culled * renderer.VtxConsumed); 1397} 1398 1399template <template <class> class _Renderer, class _Getter, typename ...Args> 1400void RenderPrimitives1(const _Getter& getter, Args... args) { 1401 ImDrawList& draw_list = *GetPlotDrawList(); 1402 const ImRect& cull_rect = GetCurrentPlot()->PlotRect; 1403 RenderPrimitivesEx(_Renderer<_Getter>(getter,args...), draw_list, cull_rect); 1404} 1405 1406template <template <class,class> class _Renderer, class _Getter1, class _Getter2, typename ...Args> 1407void RenderPrimitives2(const _Getter1& getter1, const _Getter2& getter2, Args... args) { 1408 ImDrawList& draw_list = *GetPlotDrawList(); 1409 const ImRect& cull_rect = GetCurrentPlot()->PlotRect; 1410 RenderPrimitivesEx(_Renderer<_Getter1,_Getter2>(getter1,getter2,args...), draw_list, cull_rect); 1411} 1412 1413//----------------------------------------------------------------------------- 1414// [SECTION] Markers 1415//----------------------------------------------------------------------------- 1416 1417template <class _Getter> 1418struct RendererMarkersFill : RendererBase { 1419 RendererMarkersFill(const _Getter& getter, const ImVec2* marker, int count, float size, ImU32 col) : 1420 RendererBase(getter.Count, (count-2)*3, count), 1421 Getter(getter), 1422 Marker(marker), 1423 Count(count), 1424 Size(size), 1425 Col(col) 1426 { } 1427 void Init(ImDrawList& draw_list) const { 1428 UV = draw_list._Data->TexUvWhitePixel; 1429 } 1430 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1431 ImVec2 p = this->Transformer(Getter(prim)); 1432 if (p.x >= cull_rect.Min.x && p.y >= cull_rect.Min.y && p.x <= cull_rect.Max.x && p.y <= cull_rect.Max.y) { 1433 for (int i = 0; i < Count; i++) { 1434 draw_list._VtxWritePtr[0].pos.x = p.x + Marker[i].x * Size; 1435 draw_list._VtxWritePtr[0].pos.y = p.y + Marker[i].y * Size; 1436 draw_list._VtxWritePtr[0].uv = UV; 1437 draw_list._VtxWritePtr[0].col = Col; 1438 draw_list._VtxWritePtr++; 1439 } 1440 for (int i = 2; i < Count; i++) { 1441 draw_list._IdxWritePtr[0] = (ImDrawIdx)(draw_list._VtxCurrentIdx); 1442 draw_list._IdxWritePtr[1] = (ImDrawIdx)(draw_list._VtxCurrentIdx + i - 1); 1443 draw_list._IdxWritePtr[2] = (ImDrawIdx)(draw_list._VtxCurrentIdx + i); 1444 draw_list._IdxWritePtr += 3; 1445 } 1446 draw_list._VtxCurrentIdx += (ImDrawIdx)Count; 1447 return true; 1448 } 1449 return false; 1450 } 1451 const _Getter& Getter; 1452 const ImVec2* Marker; 1453 const int Count; 1454 const float Size; 1455 const ImU32 Col; 1456 mutable ImVec2 UV; 1457}; 1458 1459 1460template <class _Getter> 1461struct RendererMarkersLine : RendererBase { 1462 RendererMarkersLine(const _Getter& getter, const ImVec2* marker, int count, float size, float weight, ImU32 col) : 1463 RendererBase(getter.Count, count/2*6, count/2*4), 1464 Getter(getter), 1465 Marker(marker), 1466 Count(count), 1467 HalfWeight(ImMax(1.0f,weight)*0.5f), 1468 Size(size), 1469 Col(col) 1470 { } 1471 void Init(ImDrawList& draw_list) const { 1472 GetLineRenderProps(draw_list, HalfWeight, UV0, UV1); 1473 } 1474 IMPLOT_INLINE bool Render(ImDrawList& draw_list, const ImRect& cull_rect, int prim) const { 1475 ImVec2 p = this->Transformer(Getter(prim)); 1476 if (p.x >= cull_rect.Min.x && p.y >= cull_rect.Min.y && p.x <= cull_rect.Max.x && p.y <= cull_rect.Max.y) { 1477 for (int i = 0; i < Count; i = i + 2) { 1478 ImVec2 p1(p.x + Marker[i].x * Size, p.y + Marker[i].y * Size); 1479 ImVec2 p2(p.x + Marker[i+1].x * Size, p.y + Marker[i+1].y * Size); 1480 PrimLine(draw_list, p1, p2, HalfWeight, Col, UV0, UV1); 1481 } 1482 return true; 1483 } 1484 return false; 1485 } 1486 const _Getter& Getter; 1487 const ImVec2* Marker; 1488 const int Count; 1489 mutable float HalfWeight; 1490 const float Size; 1491 const ImU32 Col; 1492 mutable ImVec2 UV0; 1493 mutable ImVec2 UV1; 1494}; 1495 1496static const ImVec2 MARKER_FILL_CIRCLE[10] = {ImVec2(1.0f, 0.0f), ImVec2(0.809017f, 0.58778524f),ImVec2(0.30901697f, 0.95105654f),ImVec2(-0.30901703f, 0.9510565f),ImVec2(-0.80901706f, 0.5877852f),ImVec2(-1.0f, 0.0f),ImVec2(-0.80901694f, -0.58778536f),ImVec2(-0.3090171f, -0.9510565f),ImVec2(0.30901712f, -0.9510565f),ImVec2(0.80901694f, -0.5877853f)}; 1497static const ImVec2 MARKER_FILL_SQUARE[4] = {ImVec2(SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2)}; 1498static const ImVec2 MARKER_FILL_DIAMOND[4] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(0, 1)}; 1499static const ImVec2 MARKER_FILL_UP[3] = {ImVec2(SQRT_3_2,0.5f),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f)}; 1500static const ImVec2 MARKER_FILL_DOWN[3] = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f)}; 1501static const ImVec2 MARKER_FILL_LEFT[3] = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2)}; 1502static const ImVec2 MARKER_FILL_RIGHT[3] = {ImVec2(1,0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2)}; 1503 1504static const ImVec2 MARKER_LINE_CIRCLE[20] = { 1505 ImVec2(1.0f, 0.0f), 1506 ImVec2(0.809017f, 0.58778524f), 1507 ImVec2(0.809017f, 0.58778524f), 1508 ImVec2(0.30901697f, 0.95105654f), 1509 ImVec2(0.30901697f, 0.95105654f), 1510 ImVec2(-0.30901703f, 0.9510565f), 1511 ImVec2(-0.30901703f, 0.9510565f), 1512 ImVec2(-0.80901706f, 0.5877852f), 1513 ImVec2(-0.80901706f, 0.5877852f), 1514 ImVec2(-1.0f, 0.0f), 1515 ImVec2(-1.0f, 0.0f), 1516 ImVec2(-0.80901694f, -0.58778536f), 1517 ImVec2(-0.80901694f, -0.58778536f), 1518 ImVec2(-0.3090171f, -0.9510565f), 1519 ImVec2(-0.3090171f, -0.9510565f), 1520 ImVec2(0.30901712f, -0.9510565f), 1521 ImVec2(0.30901712f, -0.9510565f), 1522 ImVec2(0.80901694f, -0.5877853f), 1523 ImVec2(0.80901694f, -0.5877853f), 1524 ImVec2(1.0f, 0.0f) 1525}; 1526static const ImVec2 MARKER_LINE_SQUARE[8] = {ImVec2(SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,-SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2), ImVec2(-SQRT_1_2,SQRT_1_2), ImVec2(SQRT_1_2,SQRT_1_2)}; 1527static const ImVec2 MARKER_LINE_DIAMOND[8] = {ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, -1), ImVec2(-1, 0), ImVec2(-1, 0), ImVec2(0, 1), ImVec2(0, 1), ImVec2(1, 0)}; 1528static const ImVec2 MARKER_LINE_UP[6] = {ImVec2(SQRT_3_2,0.5f), ImVec2(0,-1),ImVec2(0,-1),ImVec2(-SQRT_3_2,0.5f),ImVec2(-SQRT_3_2,0.5f),ImVec2(SQRT_3_2,0.5f)}; 1529static const ImVec2 MARKER_LINE_DOWN[6] = {ImVec2(SQRT_3_2,-0.5f),ImVec2(0,1),ImVec2(0,1),ImVec2(-SQRT_3_2,-0.5f), ImVec2(-SQRT_3_2,-0.5f), ImVec2(SQRT_3_2,-0.5f)}; 1530static const ImVec2 MARKER_LINE_LEFT[6] = {ImVec2(-1,0), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, SQRT_3_2), ImVec2(0.5, -SQRT_3_2) , ImVec2(0.5, -SQRT_3_2) , ImVec2(-1,0) }; 1531static const ImVec2 MARKER_LINE_RIGHT[6] = {ImVec2(1,0), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(-0.5, -SQRT_3_2), ImVec2(1,0) }; 1532static const ImVec2 MARKER_LINE_ASTERISK[6] = {ImVec2(-SQRT_3_2, -0.5f), ImVec2(SQRT_3_2, 0.5f), ImVec2(-SQRT_3_2, 0.5f), ImVec2(SQRT_3_2, -0.5f), ImVec2(0, -1), ImVec2(0, 1)}; 1533static const ImVec2 MARKER_LINE_PLUS[4] = {ImVec2(-1, 0), ImVec2(1, 0), ImVec2(0, -1), ImVec2(0, 1)}; 1534static const ImVec2 MARKER_LINE_CROSS[4] = {ImVec2(-SQRT_1_2,-SQRT_1_2),ImVec2(SQRT_1_2,SQRT_1_2),ImVec2(SQRT_1_2,-SQRT_1_2),ImVec2(-SQRT_1_2,SQRT_1_2)}; 1535 1536template <typename _Getter> 1537void RenderMarkers(const _Getter& getter, ImPlotMarker marker, float size, bool rend_fill, ImU32 col_fill, bool rend_line, ImU32 col_line, float weight) { 1538 if (rend_fill) { 1539 switch (marker) { 1540 case ImPlotMarker_Circle : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_CIRCLE,10,size,col_fill); break; 1541 case ImPlotMarker_Square : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_SQUARE, 4,size,col_fill); break; 1542 case ImPlotMarker_Diamond : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_DIAMOND,4,size,col_fill); break; 1543 case ImPlotMarker_Up : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_UP, 3,size,col_fill); break; 1544 case ImPlotMarker_Down : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_DOWN, 3,size,col_fill); break; 1545 case ImPlotMarker_Left : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_LEFT, 3,size,col_fill); break; 1546 case ImPlotMarker_Right : RenderPrimitives1<RendererMarkersFill>(getter,MARKER_FILL_RIGHT, 3,size,col_fill); break; 1547 } 1548 } 1549 if (rend_line) { 1550 switch (marker) { 1551 case ImPlotMarker_Circle : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_CIRCLE, 20,size,weight,col_line); break; 1552 case ImPlotMarker_Square : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_SQUARE, 8,size,weight,col_line); break; 1553 case ImPlotMarker_Diamond : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_DIAMOND, 8,size,weight,col_line); break; 1554 case ImPlotMarker_Up : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_UP, 6,size,weight,col_line); break; 1555 case ImPlotMarker_Down : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_DOWN, 6,size,weight,col_line); break; 1556 case ImPlotMarker_Left : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_LEFT, 6,size,weight,col_line); break; 1557 case ImPlotMarker_Right : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_RIGHT, 6,size,weight,col_line); break; 1558 case ImPlotMarker_Asterisk : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_ASTERISK,6,size,weight,col_line); break; 1559 case ImPlotMarker_Plus : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_PLUS, 4,size,weight,col_line); break; 1560 case ImPlotMarker_Cross : RenderPrimitives1<RendererMarkersLine>(getter,MARKER_LINE_CROSS, 4,size,weight,col_line); break; 1561 } 1562 } 1563} 1564 1565//----------------------------------------------------------------------------- 1566// [SECTION] PlotLine 1567//----------------------------------------------------------------------------- 1568 1569template <typename _Getter> 1570void PlotLineEx(const char* label_id, const _Getter& getter, ImPlotLineFlags flags) { 1571 if (BeginItemEx(label_id, Fitter1<_Getter>(getter), flags, ImPlotCol_Line)) { 1572 if (getter.Count <= 0) { 1573 EndItem(); 1574 return; 1575 } 1576 const ImPlotNextItemData& s = GetItemData(); 1577 if (getter.Count > 1) { 1578 if (ImHasFlag(flags, ImPlotLineFlags_Shaded) && s.RenderFill) { 1579 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); 1580 GetterOverrideY<_Getter> getter2(getter, 0); 1581 RenderPrimitives2<RendererShaded>(getter,getter2,col_fill); 1582 } 1583 if (s.RenderLine) { 1584 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 1585 if (ImHasFlag(flags,ImPlotLineFlags_Segments)) { 1586 RenderPrimitives1<RendererLineSegments1>(getter,col_line,s.LineWeight); 1587 } 1588 else if (ImHasFlag(flags, ImPlotLineFlags_Loop)) { 1589 if (ImHasFlag(flags, ImPlotLineFlags_SkipNaN)) 1590 RenderPrimitives1<RendererLineStripSkip>(GetterLoop<_Getter>(getter),col_line,s.LineWeight); 1591 else 1592 RenderPrimitives1<RendererLineStrip>(GetterLoop<_Getter>(getter),col_line,s.LineWeight); 1593 } 1594 else { 1595 if (ImHasFlag(flags, ImPlotLineFlags_SkipNaN)) 1596 RenderPrimitives1<RendererLineStripSkip>(getter,col_line,s.LineWeight); 1597 else 1598 RenderPrimitives1<RendererLineStrip>(getter,col_line,s.LineWeight); 1599 } 1600 } 1601 } 1602 // render markers 1603 if (s.Marker != ImPlotMarker_None) { 1604 if (ImHasFlag(flags, ImPlotLineFlags_NoClip)) { 1605 PopPlotClipRect(); 1606 PushPlotClipRect(s.MarkerSize); 1607 } 1608 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]); 1609 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]); 1610 RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight); 1611 } 1612 EndItem(); 1613 } 1614} 1615 1616template <typename T> 1617void PlotLine(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotLineFlags flags, int offset, int stride) { 1618 GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count); 1619 PlotLineEx(label_id, getter, flags); 1620} 1621 1622template <typename T> 1623void PlotLine(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags, int offset, int stride) { 1624 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1625 PlotLineEx(label_id, getter, flags); 1626} 1627 1628#define INSTANTIATE_MACRO(T) \ 1629 template IMPLOT_API void PlotLine<T> (const char* label_id, const T* values, int count, double xscale, double x0, ImPlotLineFlags flags, int offset, int stride); \ 1630 template IMPLOT_API void PlotLine<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotLineFlags flags, int offset, int stride); 1631CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 1632#undef INSTANTIATE_MACRO 1633 1634// custom 1635void PlotLineG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotLineFlags flags) { 1636 GetterFuncPtr getter(getter_func,data, count); 1637 PlotLineEx(label_id, getter, flags); 1638} 1639 1640//----------------------------------------------------------------------------- 1641// [SECTION] PlotScatter 1642//----------------------------------------------------------------------------- 1643 1644template <typename Getter> 1645void PlotScatterEx(const char* label_id, const Getter& getter, ImPlotScatterFlags flags) { 1646 if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_MarkerOutline)) { 1647 if (getter.Count <= 0) { 1648 EndItem(); 1649 return; 1650 } 1651 const ImPlotNextItemData& s = GetItemData(); 1652 ImPlotMarker marker = s.Marker == ImPlotMarker_None ? ImPlotMarker_Circle: s.Marker; 1653 if (marker != ImPlotMarker_None) { 1654 if (ImHasFlag(flags,ImPlotScatterFlags_NoClip)) { 1655 PopPlotClipRect(); 1656 PushPlotClipRect(s.MarkerSize); 1657 } 1658 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]); 1659 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]); 1660 RenderMarkers<Getter>(getter, marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight); 1661 } 1662 EndItem(); 1663 } 1664} 1665 1666template <typename T> 1667void PlotScatter(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotScatterFlags flags, int offset, int stride) { 1668 GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count); 1669 PlotScatterEx(label_id, getter, flags); 1670} 1671 1672template <typename T> 1673void PlotScatter(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags, int offset, int stride) { 1674 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1675 return PlotScatterEx(label_id, getter, flags); 1676} 1677 1678#define INSTANTIATE_MACRO(T) \ 1679 template IMPLOT_API void PlotScatter<T>(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotScatterFlags flags, int offset, int stride); \ 1680 template IMPLOT_API void PlotScatter<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotScatterFlags flags, int offset, int stride); 1681CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 1682#undef INSTANTIATE_MACRO 1683 1684// custom 1685void PlotScatterG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotScatterFlags flags) { 1686 GetterFuncPtr getter(getter_func,data, count); 1687 return PlotScatterEx(label_id, getter, flags); 1688} 1689 1690//----------------------------------------------------------------------------- 1691// [SECTION] PlotStairs 1692//----------------------------------------------------------------------------- 1693 1694template <typename Getter> 1695void PlotStairsEx(const char* label_id, const Getter& getter, ImPlotStairsFlags flags) { 1696 if (BeginItemEx(label_id, Fitter1<Getter>(getter), flags, ImPlotCol_Line)) { 1697 if (getter.Count <= 0) { 1698 EndItem(); 1699 return; 1700 } 1701 const ImPlotNextItemData& s = GetItemData(); 1702 if (getter.Count > 1) { 1703 if (s.RenderFill && ImHasFlag(flags,ImPlotStairsFlags_Shaded)) { 1704 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); 1705 if (ImHasFlag(flags, ImPlotStairsFlags_PreStep)) 1706 RenderPrimitives1<RendererStairsPreShaded>(getter,col_fill); 1707 else 1708 RenderPrimitives1<RendererStairsPostShaded>(getter,col_fill); 1709 } 1710 if (s.RenderLine) { 1711 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 1712 if (ImHasFlag(flags, ImPlotStairsFlags_PreStep)) 1713 RenderPrimitives1<RendererStairsPre>(getter,col_line,s.LineWeight); 1714 else 1715 RenderPrimitives1<RendererStairsPost>(getter,col_line,s.LineWeight); 1716 } 1717 } 1718 // render markers 1719 if (s.Marker != ImPlotMarker_None) { 1720 PopPlotClipRect(); 1721 PushPlotClipRect(s.MarkerSize); 1722 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]); 1723 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]); 1724 RenderMarkers<Getter>(getter, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight); 1725 } 1726 EndItem(); 1727 } 1728} 1729 1730template <typename T> 1731void PlotStairs(const char* label_id, const T* values, int count, double xscale, double x0, ImPlotStairsFlags flags, int offset, int stride) { 1732 GetterXY<IndexerLin,IndexerIdx<T>> getter(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count); 1733 PlotStairsEx(label_id, getter, flags); 1734} 1735 1736template <typename T> 1737void PlotStairs(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags, int offset, int stride) { 1738 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1739 return PlotStairsEx(label_id, getter, flags); 1740} 1741 1742#define INSTANTIATE_MACRO(T) \ 1743 template IMPLOT_API void PlotStairs<T> (const char* label_id, const T* values, int count, double xscale, double x0, ImPlotStairsFlags flags, int offset, int stride); \ 1744 template IMPLOT_API void PlotStairs<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotStairsFlags flags, int offset, int stride); 1745CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 1746#undef INSTANTIATE_MACRO 1747 1748// custom 1749void PlotStairsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotStairsFlags flags) { 1750 GetterFuncPtr getter(getter_func,data, count); 1751 return PlotStairsEx(label_id, getter, flags); 1752} 1753 1754//----------------------------------------------------------------------------- 1755// [SECTION] PlotShaded 1756//----------------------------------------------------------------------------- 1757 1758template <typename Getter1, typename Getter2> 1759void PlotShadedEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, ImPlotShadedFlags flags) { 1760 if (BeginItemEx(label_id, Fitter2<Getter1,Getter2>(getter1,getter2), flags, ImPlotCol_Fill)) { 1761 if (getter1.Count <= 0 || getter2.Count <= 0) { 1762 EndItem(); 1763 return; 1764 } 1765 const ImPlotNextItemData& s = GetItemData(); 1766 if (s.RenderFill) { 1767 const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); 1768 RenderPrimitives2<RendererShaded>(getter1,getter2,col); 1769 } 1770 EndItem(); 1771 } 1772} 1773 1774template <typename T> 1775void PlotShaded(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride) { 1776 if (!(y_ref > -DBL_MAX)) 1777 y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min; 1778 if (!(y_ref < DBL_MAX)) 1779 y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max; 1780 GetterXY<IndexerLin,IndexerIdx<T>> getter1(IndexerLin(xscale,x0),IndexerIdx<T>(values,count,offset,stride),count); 1781 GetterXY<IndexerLin,IndexerConst> getter2(IndexerLin(xscale,x0),IndexerConst(y_ref),count); 1782 PlotShadedEx(label_id, getter1, getter2, flags); 1783} 1784 1785template <typename T> 1786void PlotShaded(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride) { 1787 if (y_ref == -HUGE_VAL) 1788 y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Min; 1789 if (y_ref == HUGE_VAL) 1790 y_ref = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO).Y.Max; 1791 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1792 GetterXY<IndexerIdx<T>,IndexerConst> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(y_ref),count); 1793 PlotShadedEx(label_id, getter1, getter2, flags); 1794} 1795 1796 1797template <typename T> 1798void PlotShaded(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride) { 1799 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys1,count,offset,stride),count); 1800 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys2,count,offset,stride),count); 1801 PlotShadedEx(label_id, getter1, getter2, flags); 1802} 1803 1804#define INSTANTIATE_MACRO(T) \ 1805 template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* values, int count, double y_ref, double xscale, double x0, ImPlotShadedFlags flags, int offset, int stride); \ 1806 template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* xs, const T* ys, int count, double y_ref, ImPlotShadedFlags flags, int offset, int stride); \ 1807 template IMPLOT_API void PlotShaded<T>(const char* label_id, const T* xs, const T* ys1, const T* ys2, int count, ImPlotShadedFlags flags, int offset, int stride); 1808CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 1809#undef INSTANTIATE_MACRO 1810 1811// custom 1812void PlotShadedG(const char* label_id, ImPlotGetter getter_func1, void* data1, ImPlotGetter getter_func2, void* data2, int count, ImPlotShadedFlags flags) { 1813 GetterFuncPtr getter1(getter_func1, data1, count); 1814 GetterFuncPtr getter2(getter_func2, data2, count); 1815 PlotShadedEx(label_id, getter1, getter2, flags); 1816} 1817 1818//----------------------------------------------------------------------------- 1819// [SECTION] PlotBars 1820//----------------------------------------------------------------------------- 1821 1822template <typename Getter1, typename Getter2> 1823void PlotBarsVEx(const char* label_id, const Getter1& getter1, const Getter2 getter2, double width, ImPlotBarsFlags flags) { 1824 if (BeginItemEx(label_id, FitterBarV<Getter1,Getter2>(getter1,getter2,width), flags, ImPlotCol_Fill)) { 1825 if (getter1.Count <= 0 || getter2.Count <= 0) { 1826 EndItem(); 1827 return; 1828 } 1829 const ImPlotNextItemData& s = GetItemData(); 1830 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); 1831 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 1832 bool rend_fill = s.RenderFill; 1833 bool rend_line = s.RenderLine; 1834 if (rend_fill) { 1835 RenderPrimitives2<RendererBarsFillV>(getter1,getter2,col_fill,width); 1836 if (rend_line && col_fill == col_line) 1837 rend_line = false; 1838 } 1839 if (rend_line) { 1840 RenderPrimitives2<RendererBarsLineV>(getter1,getter2,col_line,width,s.LineWeight); 1841 } 1842 EndItem(); 1843 } 1844} 1845 1846template <typename Getter1, typename Getter2> 1847void PlotBarsHEx(const char* label_id, const Getter1& getter1, const Getter2& getter2, double height, ImPlotBarsFlags flags) { 1848 if (BeginItemEx(label_id, FitterBarH<Getter1,Getter2>(getter1,getter2,height), flags, ImPlotCol_Fill)) { 1849 if (getter1.Count <= 0 || getter2.Count <= 0) { 1850 EndItem(); 1851 return; 1852 } 1853 const ImPlotNextItemData& s = GetItemData(); 1854 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_Fill]); 1855 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 1856 bool rend_fill = s.RenderFill; 1857 bool rend_line = s.RenderLine; 1858 if (rend_fill) { 1859 RenderPrimitives2<RendererBarsFillH>(getter1,getter2,col_fill,height); 1860 if (rend_line && col_fill == col_line) 1861 rend_line = false; 1862 } 1863 if (rend_line) { 1864 RenderPrimitives2<RendererBarsLineH>(getter1,getter2,col_line,height,s.LineWeight); 1865 } 1866 EndItem(); 1867 } 1868} 1869 1870template <typename T> 1871void PlotBars(const char* label_id, const T* values, int count, double bar_size, double shift, ImPlotBarsFlags flags, int offset, int stride) { 1872 if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) { 1873 GetterXY<IndexerIdx<T>,IndexerLin> getter1(IndexerIdx<T>(values,count,offset,stride),IndexerLin(1.0,shift),count); 1874 GetterXY<IndexerConst,IndexerLin> getter2(IndexerConst(0),IndexerLin(1.0,shift),count); 1875 PlotBarsHEx(label_id, getter1, getter2, bar_size, flags); 1876 } 1877 else { 1878 GetterXY<IndexerLin,IndexerIdx<T>> getter1(IndexerLin(1.0,shift),IndexerIdx<T>(values,count,offset,stride),count); 1879 GetterXY<IndexerLin,IndexerConst> getter2(IndexerLin(1.0,shift),IndexerConst(0),count); 1880 PlotBarsVEx(label_id, getter1, getter2, bar_size, flags); 1881 } 1882} 1883 1884template <typename T> 1885void PlotBars(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags, int offset, int stride) { 1886 if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) { 1887 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1888 GetterXY<IndexerConst, IndexerIdx<T>> getter2(IndexerConst(0),IndexerIdx<T>(ys,count,offset,stride),count); 1889 PlotBarsHEx(label_id, getter1, getter2, bar_size, flags); 1890 } 1891 else { 1892 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter1(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 1893 GetterXY<IndexerIdx<T>,IndexerConst> getter2(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(0),count); 1894 PlotBarsVEx(label_id, getter1, getter2, bar_size, flags); 1895 } 1896} 1897 1898#define INSTANTIATE_MACRO(T) \ 1899 template IMPLOT_API void PlotBars<T>(const char* label_id, const T* values, int count, double bar_size, double shift, ImPlotBarsFlags flags, int offset, int stride); \ 1900 template IMPLOT_API void PlotBars<T>(const char* label_id, const T* xs, const T* ys, int count, double bar_size, ImPlotBarsFlags flags, int offset, int stride); 1901CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 1902#undef INSTANTIATE_MACRO 1903 1904void PlotBarsG(const char* label_id, ImPlotGetter getter_func, void* data, int count, double bar_size, ImPlotBarsFlags flags) { 1905 if (ImHasFlag(flags, ImPlotBarsFlags_Horizontal)) { 1906 GetterFuncPtr getter1(getter_func, data, count); 1907 GetterOverrideX<GetterFuncPtr> getter2(getter1,0); 1908 PlotBarsHEx(label_id, getter1, getter2, bar_size, flags); 1909 } 1910 else { 1911 GetterFuncPtr getter1(getter_func, data, count); 1912 GetterOverrideY<GetterFuncPtr> getter2(getter1,0); 1913 PlotBarsVEx(label_id, getter1, getter2, bar_size, flags); 1914 } 1915} 1916 1917//----------------------------------------------------------------------------- 1918// [SECTION] PlotBarGroups 1919//----------------------------------------------------------------------------- 1920 1921template <typename T> 1922void PlotBarGroups(const char* const label_ids[], const T* values, int item_count, int group_count, double group_size, double shift, ImPlotBarGroupsFlags flags) { 1923 const bool horz = ImHasFlag(flags, ImPlotBarGroupsFlags_Horizontal); 1924 const bool stack = ImHasFlag(flags, ImPlotBarGroupsFlags_Stacked); 1925 if (stack) { 1926 SetupLock(); 1927 ImPlotContext& gp = *GImPlot; 1928 gp.TempDouble1.resize(4*group_count); 1929 double* temp = gp.TempDouble1.Data; 1930 double* neg = &temp[0]; 1931 double* pos = &temp[group_count]; 1932 double* curr_min = &temp[group_count*2]; 1933 double* curr_max = &temp[group_count*3]; 1934 for (int g = 0; g < group_count*2; ++g) 1935 temp[g] = 0; 1936 if (horz) { 1937 for (int i = 0; i < item_count; ++i) { 1938 if (!IsItemHidden(label_ids[i])) { 1939 for (int g = 0; g < group_count; ++g) { 1940 double v = (double)values[i*group_count+g]; 1941 if (v > 0) { 1942 curr_min[g] = pos[g]; 1943 curr_max[g] = curr_min[g] + v; 1944 pos[g] += v; 1945 } 1946 else { 1947 curr_max[g] = neg[g]; 1948 curr_min[g] = curr_max[g] + v; 1949 neg[g] += v; 1950 } 1951 } 1952 } 1953 GetterXY<IndexerIdx<double>,IndexerLin> getter1(IndexerIdx<double>(curr_min,group_count),IndexerLin(1.0,shift),group_count); 1954 GetterXY<IndexerIdx<double>,IndexerLin> getter2(IndexerIdx<double>(curr_max,group_count),IndexerLin(1.0,shift),group_count); 1955 PlotBarsHEx(label_ids[i],getter1,getter2,group_size,0); 1956 } 1957 } 1958 else { 1959 for (int i = 0; i < item_count; ++i) { 1960 if (!IsItemHidden(label_ids[i])) { 1961 for (int g = 0; g < group_count; ++g) { 1962 double v = (double)values[i*group_count+g]; 1963 if (v > 0) { 1964 curr_min[g] = pos[g]; 1965 curr_max[g] = curr_min[g] + v; 1966 pos[g] += v; 1967 } 1968 else { 1969 curr_max[g] = neg[g]; 1970 curr_min[g] = curr_max[g] + v; 1971 neg[g] += v; 1972 } 1973 } 1974 } 1975 GetterXY<IndexerLin,IndexerIdx<double>> getter1(IndexerLin(1.0,shift),IndexerIdx<double>(curr_min,group_count),group_count); 1976 GetterXY<IndexerLin,IndexerIdx<double>> getter2(IndexerLin(1.0,shift),IndexerIdx<double>(curr_max,group_count),group_count); 1977 PlotBarsVEx(label_ids[i],getter1,getter2,group_size,0); 1978 } 1979 } 1980 } 1981 else { 1982 const double subsize = group_size / item_count; 1983 if (horz) { 1984 for (int i = 0; i < item_count; ++i) { 1985 const double subshift = (i+0.5)*subsize - group_size/2; 1986 PlotBars(label_ids[i],&values[i*group_count],group_count,subsize,subshift+shift,ImPlotBarsFlags_Horizontal); 1987 } 1988 } 1989 else { 1990 for (int i = 0; i < item_count; ++i) { 1991 const double subshift = (i+0.5)*subsize - group_size/2; 1992 PlotBars(label_ids[i],&values[i*group_count],group_count,subsize,subshift+shift); 1993 } 1994 } 1995 } 1996} 1997 1998#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotBarGroups<T>(const char* const label_ids[], const T* values, int items, int groups, double width, double shift, ImPlotBarGroupsFlags flags); 1999CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2000#undef INSTANTIATE_MACRO 2001 2002//----------------------------------------------------------------------------- 2003// [SECTION] PlotErrorBars 2004//----------------------------------------------------------------------------- 2005 2006template <typename _GetterPos, typename _GetterNeg> 2007void PlotErrorBarsVEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) { 2008 if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) { 2009 if (getter_pos.Count <= 0 || getter_neg.Count <= 0) { 2010 EndItem(); 2011 return; 2012 } 2013 const ImPlotNextItemData& s = GetItemData(); 2014 ImDrawList& draw_list = *GetPlotDrawList(); 2015 const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]); 2016 const bool rend_whisker = s.ErrorBarSize > 0; 2017 const float half_whisker = s.ErrorBarSize * 0.5f; 2018 for (int i = 0; i < getter_pos.Count; ++i) { 2019 ImVec2 p1 = PlotToPixels(getter_neg(i),IMPLOT_AUTO,IMPLOT_AUTO); 2020 ImVec2 p2 = PlotToPixels(getter_pos(i),IMPLOT_AUTO,IMPLOT_AUTO); 2021 draw_list.AddLine(p1,p2,col, s.ErrorBarWeight); 2022 if (rend_whisker) { 2023 draw_list.AddLine(p1 - ImVec2(half_whisker, 0), p1 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight); 2024 draw_list.AddLine(p2 - ImVec2(half_whisker, 0), p2 + ImVec2(half_whisker, 0), col, s.ErrorBarWeight); 2025 } 2026 } 2027 EndItem(); 2028 } 2029} 2030 2031template <typename _GetterPos, typename _GetterNeg> 2032void PlotErrorBarsHEx(const char* label_id, const _GetterPos& getter_pos, const _GetterNeg& getter_neg, ImPlotErrorBarsFlags flags) { 2033 if (BeginItemEx(label_id, Fitter2<_GetterPos,_GetterNeg>(getter_pos, getter_neg), flags, IMPLOT_AUTO)) { 2034 if (getter_pos.Count <= 0 || getter_neg.Count <= 0) { 2035 EndItem(); 2036 return; 2037 } 2038 const ImPlotNextItemData& s = GetItemData(); 2039 ImDrawList& draw_list = *GetPlotDrawList(); 2040 const ImU32 col = ImGui::GetColorU32(s.Colors[ImPlotCol_ErrorBar]); 2041 const bool rend_whisker = s.ErrorBarSize > 0; 2042 const float half_whisker = s.ErrorBarSize * 0.5f; 2043 for (int i = 0; i < getter_pos.Count; ++i) { 2044 ImVec2 p1 = PlotToPixels(getter_neg(i),IMPLOT_AUTO,IMPLOT_AUTO); 2045 ImVec2 p2 = PlotToPixels(getter_pos(i),IMPLOT_AUTO,IMPLOT_AUTO); 2046 draw_list.AddLine(p1, p2, col, s.ErrorBarWeight); 2047 if (rend_whisker) { 2048 draw_list.AddLine(p1 - ImVec2(0, half_whisker), p1 + ImVec2(0, half_whisker), col, s.ErrorBarWeight); 2049 draw_list.AddLine(p2 - ImVec2(0, half_whisker), p2 + ImVec2(0, half_whisker), col, s.ErrorBarWeight); 2050 } 2051 } 2052 EndItem(); 2053 } 2054} 2055 2056template <typename T> 2057void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags, int offset, int stride) { 2058 PlotErrorBars(label_id, xs, ys, err, err, count, flags, offset, stride); 2059} 2060 2061template <typename T> 2062void PlotErrorBars(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags, int offset, int stride) { 2063 IndexerIdx<T> indexer_x(xs, count,offset,stride); 2064 IndexerIdx<T> indexer_y(ys, count,offset,stride); 2065 IndexerIdx<T> indexer_n(neg,count,offset,stride); 2066 IndexerIdx<T> indexer_p(pos,count,offset,stride); 2067 GetterError<T> getter(xs, ys, neg, pos, count, offset, stride); 2068 if (ImHasFlag(flags, ImPlotErrorBarsFlags_Horizontal)) { 2069 IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_xp(indexer_x, indexer_p, 1, 1); 2070 IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_xn(indexer_x, indexer_n, 1, -1); 2071 GetterXY<IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>,IndexerIdx<T>> getter_p(indexer_xp, indexer_y, count); 2072 GetterXY<IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>,IndexerIdx<T>> getter_n(indexer_xn, indexer_y, count); 2073 PlotErrorBarsHEx(label_id, getter_p, getter_n, flags); 2074 } 2075 else { 2076 IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_yp(indexer_y, indexer_p, 1, 1); 2077 IndexerAdd<IndexerIdx<T>,IndexerIdx<T>> indexer_yn(indexer_y, indexer_n, 1, -1); 2078 GetterXY<IndexerIdx<T>,IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>> getter_p(indexer_x, indexer_yp, count); 2079 GetterXY<IndexerIdx<T>,IndexerAdd<IndexerIdx<T>,IndexerIdx<T>>> getter_n(indexer_x, indexer_yn, count); 2080 PlotErrorBarsVEx(label_id, getter_p, getter_n, flags); 2081 } 2082} 2083 2084#define INSTANTIATE_MACRO(T) \ 2085 template IMPLOT_API void PlotErrorBars<T>(const char* label_id, const T* xs, const T* ys, const T* err, int count, ImPlotErrorBarsFlags flags, int offset, int stride); \ 2086 template IMPLOT_API void PlotErrorBars<T>(const char* label_id, const T* xs, const T* ys, const T* neg, const T* pos, int count, ImPlotErrorBarsFlags flags, int offset, int stride); 2087CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2088#undef INSTANTIATE_MACRO 2089 2090//----------------------------------------------------------------------------- 2091// [SECTION] PlotStems 2092//----------------------------------------------------------------------------- 2093 2094template <typename _GetterM, typename _GetterB> 2095void PlotStemsEx(const char* label_id, const _GetterM& getter_mark, const _GetterB& getter_base, ImPlotStemsFlags flags) { 2096 if (BeginItemEx(label_id, Fitter2<_GetterM,_GetterB>(getter_mark,getter_base), flags, ImPlotCol_Line)) { 2097 if (getter_mark.Count <= 0 || getter_base.Count <= 0) { 2098 EndItem(); 2099 return; 2100 } 2101 const ImPlotNextItemData& s = GetItemData(); 2102 // render stems 2103 if (s.RenderLine) { 2104 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 2105 RenderPrimitives2<RendererLineSegments2>(getter_mark, getter_base, col_line, s.LineWeight); 2106 } 2107 // render markers 2108 if (s.Marker != ImPlotMarker_None) { 2109 PopPlotClipRect(); 2110 PushPlotClipRect(s.MarkerSize); 2111 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerOutline]); 2112 const ImU32 col_fill = ImGui::GetColorU32(s.Colors[ImPlotCol_MarkerFill]); 2113 RenderMarkers<_GetterM>(getter_mark, s.Marker, s.MarkerSize, s.RenderMarkerFill, col_fill, s.RenderMarkerLine, col_line, s.MarkerWeight); 2114 } 2115 EndItem(); 2116 } 2117} 2118 2119template <typename T> 2120void PlotStems(const char* label_id, const T* values, int count, double ref, double scale, double start, ImPlotStemsFlags flags, int offset, int stride) { 2121 if (ImHasFlag(flags, ImPlotStemsFlags_Horizontal)) { 2122 GetterXY<IndexerIdx<T>,IndexerLin> get_mark(IndexerIdx<T>(values,count,offset,stride),IndexerLin(scale,start),count); 2123 GetterXY<IndexerConst,IndexerLin> get_base(IndexerConst(ref),IndexerLin(scale,start),count); 2124 PlotStemsEx(label_id, get_mark, get_base, flags); 2125 } 2126 else { 2127 GetterXY<IndexerLin,IndexerIdx<T>> get_mark(IndexerLin(scale,start),IndexerIdx<T>(values,count,offset,stride),count); 2128 GetterXY<IndexerLin,IndexerConst> get_base(IndexerLin(scale,start),IndexerConst(ref),count); 2129 PlotStemsEx(label_id, get_mark, get_base, flags); 2130 } 2131} 2132 2133template <typename T> 2134void PlotStems(const char* label_id, const T* xs, const T* ys, int count, double ref, ImPlotStemsFlags flags, int offset, int stride) { 2135 if (ImHasFlag(flags, ImPlotStemsFlags_Horizontal)) { 2136 GetterXY<IndexerIdx<T>,IndexerIdx<T>> get_mark(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 2137 GetterXY<IndexerConst,IndexerIdx<T>> get_base(IndexerConst(ref),IndexerIdx<T>(ys,count,offset,stride),count); 2138 PlotStemsEx(label_id, get_mark, get_base, flags); 2139 } 2140 else { 2141 GetterXY<IndexerIdx<T>,IndexerIdx<T>> get_mark(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 2142 GetterXY<IndexerIdx<T>,IndexerConst> get_base(IndexerIdx<T>(xs,count,offset,stride),IndexerConst(ref),count); 2143 PlotStemsEx(label_id, get_mark, get_base, flags); 2144 } 2145} 2146 2147#define INSTANTIATE_MACRO(T) \ 2148 template IMPLOT_API void PlotStems<T>(const char* label_id, const T* values, int count, double ref, double scale, double start, ImPlotStemsFlags flags, int offset, int stride); \ 2149 template IMPLOT_API void PlotStems<T>(const char* label_id, const T* xs, const T* ys, int count, double ref, ImPlotStemsFlags flags, int offset, int stride); 2150CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2151#undef INSTANTIATE_MACRO 2152 2153 2154//----------------------------------------------------------------------------- 2155// [SECTION] PlotInfLines 2156//----------------------------------------------------------------------------- 2157 2158template <typename T> 2159void PlotInfLines(const char* label_id, const T* values, int count, ImPlotInfLinesFlags flags, int offset, int stride) { 2160 const ImPlotRect lims = GetPlotLimits(IMPLOT_AUTO,IMPLOT_AUTO); 2161 if (ImHasFlag(flags, ImPlotInfLinesFlags_Horizontal)) { 2162 GetterXY<IndexerConst,IndexerIdx<T>> getter_min(IndexerConst(lims.X.Min),IndexerIdx<T>(values,count,offset,stride),count); 2163 GetterXY<IndexerConst,IndexerIdx<T>> getter_max(IndexerConst(lims.X.Max),IndexerIdx<T>(values,count,offset,stride),count); 2164 if (BeginItemEx(label_id, FitterY<GetterXY<IndexerConst,IndexerIdx<T>>>(getter_min), flags, ImPlotCol_Line)) { 2165 if (count <= 0) { 2166 EndItem(); 2167 return; 2168 } 2169 const ImPlotNextItemData& s = GetItemData(); 2170 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 2171 if (s.RenderLine) 2172 RenderPrimitives2<RendererLineSegments2>(getter_min, getter_max, col_line, s.LineWeight); 2173 EndItem(); 2174 } 2175 } 2176 else { 2177 GetterXY<IndexerIdx<T>,IndexerConst> get_min(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Min),count); 2178 GetterXY<IndexerIdx<T>,IndexerConst> get_max(IndexerIdx<T>(values,count,offset,stride),IndexerConst(lims.Y.Max),count); 2179 if (BeginItemEx(label_id, FitterX<GetterXY<IndexerIdx<T>,IndexerConst>>(get_min), flags, ImPlotCol_Line)) { 2180 if (count <= 0) { 2181 EndItem(); 2182 return; 2183 } 2184 const ImPlotNextItemData& s = GetItemData(); 2185 const ImU32 col_line = ImGui::GetColorU32(s.Colors[ImPlotCol_Line]); 2186 if (s.RenderLine) 2187 RenderPrimitives2<RendererLineSegments2>(get_min, get_max, col_line, s.LineWeight); 2188 EndItem(); 2189 } 2190 } 2191} 2192#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotInfLines<T>(const char* label_id, const T* xs, int count, ImPlotInfLinesFlags flags, int offset, int stride); 2193CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2194#undef INSTANTIATE_MACRO 2195 2196//----------------------------------------------------------------------------- 2197// [SECTION] PlotPieChart 2198//----------------------------------------------------------------------------- 2199 2200IMPLOT_INLINE void RenderPieSlice(ImDrawList& draw_list, const ImPlotPoint& center, double radius, double a0, double a1, ImU32 col) { 2201 const float resolution = 50 / (2 * IM_PI); 2202 ImVec2 buffer[52]; 2203 buffer[0] = PlotToPixels(center,IMPLOT_AUTO,IMPLOT_AUTO); 2204 int n = ImMax(3, (int)((a1 - a0) * resolution)); 2205 double da = (a1 - a0) / (n - 1); 2206 int i = 0; 2207 for (; i < n; ++i) { 2208 double a = a0 + i * da; 2209 buffer[i + 1] = PlotToPixels(center.x + radius * cos(a), center.y + radius * sin(a),IMPLOT_AUTO,IMPLOT_AUTO); 2210 } 2211 buffer[i+1] = buffer[0]; 2212 // fill 2213 draw_list.AddConvexPolyFilled(buffer, n + 1, col); 2214 // border (for AA) 2215 draw_list.AddPolyline(buffer, n + 2, col, 0, 2.0f); 2216} 2217 2218template <typename T> 2219double PieChartSum(const T* values, int count, bool ignore_hidden) { 2220 double sum = 0; 2221 if (ignore_hidden) { 2222 ImPlotContext& gp = *GImPlot; 2223 ImPlotItemGroup& Items = *gp.CurrentItems; 2224 for (int i = 0; i < count; ++i) { 2225 if (i >= Items.GetItemCount()) 2226 break; 2227 2228 ImPlotItem* item = Items.GetItemByIndex(i); 2229 IM_ASSERT(item != nullptr); 2230 if (item->Show) { 2231 sum += (double)values[i]; 2232 } 2233 } 2234 } 2235 else { 2236 for (int i = 0; i < count; ++i) { 2237 sum += (double)values[i]; 2238 } 2239 } 2240 return sum; 2241} 2242 2243template <typename T> 2244void PlotPieChartEx(const char* const label_ids[], const T* values, int count, ImPlotPoint center, double radius, double angle0, ImPlotPieChartFlags flags) { 2245 ImDrawList& draw_list = *GetPlotDrawList(); 2246 2247 const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden); 2248 const double sum = PieChartSum(values, count, ignore_hidden); 2249 const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0; 2250 2251 double a0 = angle0 * 2 * IM_PI / 360.0; 2252 double a1 = angle0 * 2 * IM_PI / 360.0; 2253 ImPlotPoint Pmin = ImPlotPoint(center.x - radius, center.y - radius); 2254 ImPlotPoint Pmax = ImPlotPoint(center.x + radius, center.y + radius); 2255 for (int i = 0; i < count; ++i) { 2256 ImPlotItem* item = GetItem(label_ids[i]); 2257 2258 const double percent = normalize ? (double)values[i] / sum : (double)values[i]; 2259 const bool skip = sum <= 0.0 || (ignore_hidden && item != nullptr && !item->Show); 2260 if (!skip) 2261 a1 = a0 + 2 * IM_PI * percent; 2262 2263 if (BeginItemEx(label_ids[i], FitterRect(Pmin, Pmax))) { 2264 if (sum > 0.0) { 2265 ImU32 col = GetCurrentItem()->Color; 2266 if (percent < 0.5) { 2267 RenderPieSlice(draw_list, center, radius, a0, a1, col); 2268 } 2269 else { 2270 RenderPieSlice(draw_list, center, radius, a0, a0 + (a1 - a0) * 0.5, col); 2271 RenderPieSlice(draw_list, center, radius, a0 + (a1 - a0) * 0.5, a1, col); 2272 } 2273 } 2274 EndItem(); 2275 } 2276 if (!skip) 2277 a0 = a1; 2278 } 2279} 2280 2281int PieChartFormatter(double value, char* buff, int size, void* data) { 2282 const char* fmt = (const char*)data; 2283 return snprintf(buff, size, fmt, value); 2284}; 2285 2286template <typename T> 2287void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags) { 2288 PlotPieChart<T>(label_ids, values, count, x, y, radius, PieChartFormatter, (void*)fmt, angle0, flags); 2289} 2290#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart<T>(const char* const label_ids[], const T* values, int count, double x, double y, double radius, const char* fmt, double angle0, ImPlotPieChartFlags flags); 2291CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2292#undef INSTANTIATE_MACRO 2293 2294template <typename T> 2295void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags) { 2296 IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotPieChart() needs to be called between BeginPlot() and EndPlot()!"); 2297 ImDrawList& draw_list = *GetPlotDrawList(); 2298 2299 const bool ignore_hidden = ImHasFlag(flags, ImPlotPieChartFlags_IgnoreHidden); 2300 const double sum = PieChartSum(values, count, ignore_hidden); 2301 const bool normalize = ImHasFlag(flags, ImPlotPieChartFlags_Normalize) || sum > 1.0; 2302 ImPlotPoint center(x, y); 2303 2304 PushPlotClipRect(); 2305 PlotPieChartEx(label_ids, values, count, center, radius, angle0, flags); 2306 if (fmt != nullptr) { 2307 double a0 = angle0 * 2 * IM_PI / 360.0; 2308 double a1 = angle0 * 2 * IM_PI / 360.0; 2309 char buffer[32]; 2310 for (int i = 0; i < count; ++i) { 2311 ImPlotItem* item = GetItem(label_ids[i]); 2312 IM_ASSERT(item != nullptr); 2313 2314 const double percent = normalize ? (double)values[i] / sum : (double)values[i]; 2315 const bool skip = ignore_hidden && item != nullptr && !item->Show; 2316 2317 if (!skip) { 2318 a1 = a0 + 2 * IM_PI * percent; 2319 if (item->Show) { 2320 fmt((double)values[i], buffer, 32, fmt_data); 2321 ImVec2 size = ImGui::CalcTextSize(buffer); 2322 double angle = a0 + (a1 - a0) * 0.5; 2323 ImVec2 pos = PlotToPixels(center.x + 0.5 * radius * cos(angle), center.y + 0.5 * radius * sin(angle), IMPLOT_AUTO, IMPLOT_AUTO); 2324 ImU32 col = CalcTextColor(ImGui::ColorConvertU32ToFloat4(item->Color)); 2325 draw_list.AddText(pos - size * 0.5f, col, buffer); 2326 } 2327 a0 = a1; 2328 } 2329 } 2330 } 2331 PopPlotClipRect(); 2332} 2333#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotPieChart(const char* const label_ids[], const T* values, int count, double x, double y, double radius, ImPlotFormatter fmt, void* fmt_data, double angle0, ImPlotPieChartFlags flags); 2334CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2335#undef INSTANTIATE_MACRO 2336 2337//----------------------------------------------------------------------------- 2338// [SECTION] PlotHeatmap 2339//----------------------------------------------------------------------------- 2340 2341template <typename T> 2342struct GetterHeatmapRowMaj { 2343 GetterHeatmapRowMaj(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) : 2344 Values(values), 2345 Count(rows*cols), 2346 Rows(rows), 2347 Cols(cols), 2348 ScaleMin(scale_min), 2349 ScaleMax(scale_max), 2350 Width(width), 2351 Height(height), 2352 XRef(xref), 2353 YRef(yref), 2354 YDir(ydir), 2355 HalfSize(Width*0.5, Height*0.5) 2356 { } 2357 template <typename I> IMPLOT_INLINE RectC operator()(I idx) const { 2358 double val = (double)Values[idx]; 2359 const int r = idx / Cols; 2360 const int c = idx % Cols; 2361 const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height)); 2362 RectC rect; 2363 rect.Pos = p; 2364 rect.HalfSize = HalfSize; 2365 const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); 2366 ImPlotContext& gp = *GImPlot; 2367 rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t); 2368 return rect; 2369 } 2370 const T* const Values; 2371 const int Count, Rows, Cols; 2372 const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir; 2373 const ImPlotPoint HalfSize; 2374}; 2375 2376template <typename T> 2377struct GetterHeatmapColMaj { 2378 GetterHeatmapColMaj(const T* values, int rows, int cols, double scale_min, double scale_max, double width, double height, double xref, double yref, double ydir) : 2379 Values(values), 2380 Count(rows*cols), 2381 Rows(rows), 2382 Cols(cols), 2383 ScaleMin(scale_min), 2384 ScaleMax(scale_max), 2385 Width(width), 2386 Height(height), 2387 XRef(xref), 2388 YRef(yref), 2389 YDir(ydir), 2390 HalfSize(Width*0.5, Height*0.5) 2391 { } 2392 template <typename I> IMPLOT_INLINE RectC operator()(I idx) const { 2393 double val = (double)Values[idx]; 2394 const int r = idx % Rows; 2395 const int c = idx / Rows; 2396 const ImPlotPoint p(XRef + HalfSize.x + c*Width, YRef + YDir * (HalfSize.y + r*Height)); 2397 RectC rect; 2398 rect.Pos = p; 2399 rect.HalfSize = HalfSize; 2400 const float t = ImClamp((float)ImRemap01(val, ScaleMin, ScaleMax),0.0f,1.0f); 2401 ImPlotContext& gp = *GImPlot; 2402 rect.Color = gp.ColormapData.LerpTable(gp.Style.Colormap, t); 2403 return rect; 2404 } 2405 const T* const Values; 2406 const int Count, Rows, Cols; 2407 const double ScaleMin, ScaleMax, Width, Height, XRef, YRef, YDir; 2408 const ImPlotPoint HalfSize; 2409}; 2410 2411template <typename T> 2412void RenderHeatmap(ImDrawList& draw_list, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, bool reverse_y, bool col_maj) { 2413 ImPlotContext& gp = *GImPlot; 2414 Transformer2 transformer; 2415 if (scale_min == 0 && scale_max == 0) { 2416 T temp_min, temp_max; 2417 ImMinMaxArray(values,rows*cols,&temp_min,&temp_max); 2418 scale_min = (double)temp_min; 2419 scale_max = (double)temp_max; 2420 } 2421 if (scale_min == scale_max) { 2422 ImVec2 a = transformer(bounds_min); 2423 ImVec2 b = transformer(bounds_max); 2424 ImU32 col = GetColormapColorU32(0,gp.Style.Colormap); 2425 draw_list.AddRectFilled(a, b, col); 2426 return; 2427 } 2428 const double yref = reverse_y ? bounds_max.y : bounds_min.y; 2429 const double ydir = reverse_y ? -1 : 1; 2430 if (col_maj) { 2431 GetterHeatmapColMaj<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir); 2432 RenderPrimitives1<RendererRectC>(getter); 2433 } 2434 else { 2435 GetterHeatmapRowMaj<T> getter(values, rows, cols, scale_min, scale_max, (bounds_max.x - bounds_min.x) / cols, (bounds_max.y - bounds_min.y) / rows, bounds_min.x, yref, ydir); 2436 RenderPrimitives1<RendererRectC>(getter); 2437 } 2438 // labels 2439 if (fmt != nullptr) { 2440 const double w = (bounds_max.x - bounds_min.x) / cols; 2441 const double h = (bounds_max.y - bounds_min.y) / rows; 2442 const ImPlotPoint half_size(w*0.5,h*0.5); 2443 int i = 0; 2444 if (col_maj) { 2445 for (int c = 0; c < cols; ++c) { 2446 for (int r = 0; r < rows; ++r) { 2447 ImPlotPoint p; 2448 p.x = bounds_min.x + 0.5*w + c*w; 2449 p.y = yref + ydir * (0.5*h + r*h); 2450 ImVec2 px = transformer(p); 2451 char buff[32]; 2452 ImFormatString(buff, 32, fmt, values[i]); 2453 ImVec2 size = ImGui::CalcTextSize(buff); 2454 double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0); 2455 ImVec4 color = SampleColormap((float)t); 2456 ImU32 col = CalcTextColor(color); 2457 draw_list.AddText(px - size * 0.5f, col, buff); 2458 i++; 2459 } 2460 } 2461 } 2462 else { 2463 for (int r = 0; r < rows; ++r) { 2464 for (int c = 0; c < cols; ++c) { 2465 ImPlotPoint p; 2466 p.x = bounds_min.x + 0.5*w + c*w; 2467 p.y = yref + ydir * (0.5*h + r*h); 2468 ImVec2 px = transformer(p); 2469 char buff[32]; 2470 ImFormatString(buff, 32, fmt, values[i]); 2471 ImVec2 size = ImGui::CalcTextSize(buff); 2472 double t = ImClamp(ImRemap01((double)values[i], scale_min, scale_max),0.0,1.0); 2473 ImVec4 color = SampleColormap((float)t); 2474 ImU32 col = CalcTextColor(color); 2475 draw_list.AddText(px - size * 0.5f, col, buff); 2476 i++; 2477 } 2478 } 2479 } 2480 } 2481} 2482 2483template <typename T> 2484void PlotHeatmap(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags) { 2485 if (BeginItemEx(label_id, FitterRect(bounds_min, bounds_max))) { 2486 if (rows <= 0 || cols <= 0) { 2487 EndItem(); 2488 return; 2489 } 2490 ImDrawList& draw_list = *GetPlotDrawList(); 2491 const bool col_maj = ImHasFlag(flags, ImPlotHeatmapFlags_ColMajor); 2492 RenderHeatmap(draw_list, values, rows, cols, scale_min, scale_max, fmt, bounds_min, bounds_max, true, col_maj); 2493 EndItem(); 2494 } 2495} 2496#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotHeatmap<T>(const char* label_id, const T* values, int rows, int cols, double scale_min, double scale_max, const char* fmt, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max, ImPlotHeatmapFlags flags); 2497CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2498#undef INSTANTIATE_MACRO 2499 2500//----------------------------------------------------------------------------- 2501// [SECTION] PlotHistogram 2502//----------------------------------------------------------------------------- 2503 2504template <typename T> 2505double PlotHistogram(const char* label_id, const T* values, int count, int bins, double bar_scale, ImPlotRange range, ImPlotHistogramFlags flags) { 2506 2507 const bool cumulative = ImHasFlag(flags, ImPlotHistogramFlags_Cumulative); 2508 const bool density = ImHasFlag(flags, ImPlotHistogramFlags_Density); 2509 const bool outliers = !ImHasFlag(flags, ImPlotHistogramFlags_NoOutliers); 2510 2511 if (count <= 0 || bins == 0) 2512 return 0; 2513 2514 if (range.Min == 0 && range.Max == 0) { 2515 T Min, Max; 2516 ImMinMaxArray(values, count, &Min, &Max); 2517 range.Min = (double)Min; 2518 range.Max = (double)Max; 2519 } 2520 2521 double width; 2522 if (bins < 0) 2523 CalculateBins(values, count, bins, range, bins, width); 2524 else 2525 width = range.Size() / bins; 2526 2527 ImPlotContext& gp = *GImPlot; 2528 ImVector<double>& bin_centers = gp.TempDouble1; 2529 ImVector<double>& bin_counts = gp.TempDouble2; 2530 bin_centers.resize(bins); 2531 bin_counts.resize(bins); 2532 int below = 0; 2533 2534 for (int b = 0; b < bins; ++b) { 2535 bin_centers[b] = range.Min + b * width + width * 0.5; 2536 bin_counts[b] = 0; 2537 } 2538 int counted = 0; 2539 double max_count = 0; 2540 for (int i = 0; i < count; ++i) { 2541 double val = (double)values[i]; 2542 if (range.Contains(val)) { 2543 const int b = ImClamp((int)((val - range.Min) / width), 0, bins - 1); 2544 bin_counts[b] += 1.0; 2545 if (bin_counts[b] > max_count) 2546 max_count = bin_counts[b]; 2547 counted++; 2548 } 2549 else if (val < range.Min) { 2550 below++; 2551 } 2552 } 2553 if (cumulative && density) { 2554 if (outliers) 2555 bin_counts[0] += below; 2556 for (int b = 1; b < bins; ++b) 2557 bin_counts[b] += bin_counts[b-1]; 2558 double scale = 1.0 / (outliers ? count : counted); 2559 for (int b = 0; b < bins; ++b) 2560 bin_counts[b] *= scale; 2561 max_count = bin_counts[bins-1]; 2562 } 2563 else if (cumulative) { 2564 if (outliers) 2565 bin_counts[0] += below; 2566 for (int b = 1; b < bins; ++b) 2567 bin_counts[b] += bin_counts[b-1]; 2568 max_count = bin_counts[bins-1]; 2569 } 2570 else if (density) { 2571 double scale = 1.0 / ((outliers ? count : counted) * width); 2572 for (int b = 0; b < bins; ++b) 2573 bin_counts[b] *= scale; 2574 max_count *= scale; 2575 } 2576 if (ImHasFlag(flags, ImPlotHistogramFlags_Horizontal)) 2577 PlotBars(label_id, &bin_counts.Data[0], &bin_centers.Data[0], bins, bar_scale*width, ImPlotBarsFlags_Horizontal); 2578 else 2579 PlotBars(label_id, &bin_centers.Data[0], &bin_counts.Data[0], bins, bar_scale*width); 2580 return max_count; 2581} 2582#define INSTANTIATE_MACRO(T) template IMPLOT_API double PlotHistogram<T>(const char* label_id, const T* values, int count, int bins, double bar_scale, ImPlotRange range, ImPlotHistogramFlags flags); 2583CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2584#undef INSTANTIATE_MACRO 2585 2586//----------------------------------------------------------------------------- 2587// [SECTION] PlotHistogram2D 2588//----------------------------------------------------------------------------- 2589 2590template <typename T> 2591double PlotHistogram2D(const char* label_id, const T* xs, const T* ys, int count, int x_bins, int y_bins, ImPlotRect range, ImPlotHistogramFlags flags) { 2592 2593 // const bool cumulative = ImHasFlag(flags, ImPlotHistogramFlags_Cumulative); NOT SUPPORTED 2594 const bool density = ImHasFlag(flags, ImPlotHistogramFlags_Density); 2595 const bool outliers = !ImHasFlag(flags, ImPlotHistogramFlags_NoOutliers); 2596 const bool col_maj = ImHasFlag(flags, ImPlotHistogramFlags_ColMajor); 2597 2598 if (count <= 0 || x_bins == 0 || y_bins == 0) 2599 return 0; 2600 2601 if (range.X.Min == 0 && range.X.Max == 0) { 2602 T Min, Max; 2603 ImMinMaxArray(xs, count, &Min, &Max); 2604 range.X.Min = (double)Min; 2605 range.X.Max = (double)Max; 2606 } 2607 if (range.Y.Min == 0 && range.Y.Max == 0) { 2608 T Min, Max; 2609 ImMinMaxArray(ys, count, &Min, &Max); 2610 range.Y.Min = (double)Min; 2611 range.Y.Max = (double)Max; 2612 } 2613 2614 double width, height; 2615 if (x_bins < 0) 2616 CalculateBins(xs, count, x_bins, range.X, x_bins, width); 2617 else 2618 width = range.X.Size() / x_bins; 2619 if (y_bins < 0) 2620 CalculateBins(ys, count, y_bins, range.Y, y_bins, height); 2621 else 2622 height = range.Y.Size() / y_bins; 2623 2624 const int bins = x_bins * y_bins; 2625 2626 ImPlotContext& gp = *GImPlot; 2627 ImVector<double>& bin_counts = gp.TempDouble1; 2628 bin_counts.resize(bins); 2629 2630 for (int b = 0; b < bins; ++b) 2631 bin_counts[b] = 0; 2632 2633 int counted = 0; 2634 double max_count = 0; 2635 for (int i = 0; i < count; ++i) { 2636 if (range.Contains((double)xs[i], (double)ys[i])) { 2637 const int xb = ImClamp( (int)((double)(xs[i] - range.X.Min) / width) , 0, x_bins - 1); 2638 const int yb = ImClamp( (int)((double)(ys[i] - range.Y.Min) / height) , 0, y_bins - 1); 2639 const int b = yb * x_bins + xb; 2640 bin_counts[b] += 1.0; 2641 if (bin_counts[b] > max_count) 2642 max_count = bin_counts[b]; 2643 counted++; 2644 } 2645 } 2646 if (density) { 2647 double scale = 1.0 / ((outliers ? count : counted) * width * height); 2648 for (int b = 0; b < bins; ++b) 2649 bin_counts[b] *= scale; 2650 max_count *= scale; 2651 } 2652 2653 if (BeginItemEx(label_id, FitterRect(range))) { 2654 if (y_bins <= 0 || x_bins <= 0) { 2655 EndItem(); 2656 return max_count; 2657 } 2658 ImDrawList& draw_list = *GetPlotDrawList(); 2659 RenderHeatmap(draw_list, &bin_counts.Data[0], y_bins, x_bins, 0, max_count, nullptr, range.Min(), range.Max(), false, col_maj); 2660 EndItem(); 2661 } 2662 return max_count; 2663} 2664#define INSTANTIATE_MACRO(T) template IMPLOT_API double PlotHistogram2D<T>(const char* label_id, const T* xs, const T* ys, int count, int x_bins, int y_bins, ImPlotRect range, ImPlotHistogramFlags flags); 2665CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2666#undef INSTANTIATE_MACRO 2667 2668//----------------------------------------------------------------------------- 2669// [SECTION] PlotDigital 2670//----------------------------------------------------------------------------- 2671 2672// TODO: Make this behave like all the other plot types (.e. not fixed in y axis) 2673 2674template <typename Getter> 2675void PlotDigitalEx(const char* label_id, Getter getter, ImPlotDigitalFlags flags) { 2676 if (BeginItem(label_id, flags, ImPlotCol_Fill)) { 2677 ImPlotContext& gp = *GImPlot; 2678 ImDrawList& draw_list = *GetPlotDrawList(); 2679 const ImPlotNextItemData& s = GetItemData(); 2680 if (getter.Count > 1 && s.RenderFill) { 2681 ImPlotPlot& plot = *gp.CurrentPlot; 2682 ImPlotAxis& x_axis = plot.Axes[plot.CurrentX]; 2683 ImPlotAxis& y_axis = plot.Axes[plot.CurrentY]; 2684 2685 int pixYMax = 0; 2686 ImPlotPoint itemData1 = getter(0); 2687 for (int i = 0; i < getter.Count; ++i) { 2688 ImPlotPoint itemData2 = getter(i); 2689 if (ImNanOrInf(itemData1.y)) { 2690 itemData1 = itemData2; 2691 continue; 2692 } 2693 if (ImNanOrInf(itemData2.y)) itemData2.y = ImConstrainNan(ImConstrainInf(itemData2.y)); 2694 int pixY_0 = (int)(s.LineWeight); 2695 itemData1.y = ImMax(0.0, itemData1.y); 2696 float pixY_1_float = s.DigitalBitHeight * (float)itemData1.y; 2697 int pixY_1 = (int)(pixY_1_float); //allow only positive values 2698 int pixY_chPosOffset = (int)(ImMax(s.DigitalBitHeight, pixY_1_float) + s.DigitalBitGap); 2699 pixYMax = ImMax(pixYMax, pixY_chPosOffset); 2700 ImVec2 pMin = PlotToPixels(itemData1,IMPLOT_AUTO,IMPLOT_AUTO); 2701 ImVec2 pMax = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO); 2702 int pixY_Offset = 0; //20 pixel from bottom due to mouse cursor label 2703 pMin.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset) - pixY_Offset); 2704 pMax.y = (y_axis.PixelMin) + ((-gp.DigitalPlotOffset) - pixY_0 - pixY_1 - pixY_Offset); 2705 //plot only one rectangle for same digital state 2706 while (((i+2) < getter.Count) && (itemData1.y == itemData2.y)) { 2707 const int in = (i + 1); 2708 itemData2 = getter(in); 2709 if (ImNanOrInf(itemData2.y)) break; 2710 pMax.x = PlotToPixels(itemData2,IMPLOT_AUTO,IMPLOT_AUTO).x; 2711 i++; 2712 } 2713 //do not extend plot outside plot range 2714 if (pMin.x < x_axis.PixelMin) pMin.x = x_axis.PixelMin; 2715 if (pMax.x < x_axis.PixelMin) pMax.x = x_axis.PixelMin; 2716 if (pMin.x > x_axis.PixelMax) pMin.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 2717 if (pMax.x > x_axis.PixelMax) pMax.x = x_axis.PixelMax - 1; //fix issue related to https://github.com/ocornut/imgui/issues/3976 2718 //plot a rectangle that extends up to x2 with y1 height 2719 if ((pMax.x > pMin.x) && (gp.CurrentPlot->PlotRect.Contains(pMin) || gp.CurrentPlot->PlotRect.Contains(pMax))) { 2720 // ImVec4 colAlpha = item->Color; 2721 // colAlpha.w = item->Highlight ? 1.0f : 0.9f; 2722 draw_list.AddRectFilled(pMin, pMax, ImGui::GetColorU32(s.Colors[ImPlotCol_Fill])); 2723 } 2724 itemData1 = itemData2; 2725 } 2726 gp.DigitalPlotItemCnt++; 2727 gp.DigitalPlotOffset += pixYMax; 2728 } 2729 EndItem(); 2730 } 2731} 2732 2733 2734template <typename T> 2735void PlotDigital(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags, int offset, int stride) { 2736 GetterXY<IndexerIdx<T>,IndexerIdx<T>> getter(IndexerIdx<T>(xs,count,offset,stride),IndexerIdx<T>(ys,count,offset,stride),count); 2737 return PlotDigitalEx(label_id, getter, flags); 2738} 2739#define INSTANTIATE_MACRO(T) template IMPLOT_API void PlotDigital<T>(const char* label_id, const T* xs, const T* ys, int count, ImPlotDigitalFlags flags, int offset, int stride); 2740CALL_INSTANTIATE_FOR_NUMERIC_TYPES() 2741#undef INSTANTIATE_MACRO 2742 2743// custom 2744void PlotDigitalG(const char* label_id, ImPlotGetter getter_func, void* data, int count, ImPlotDigitalFlags flags) { 2745 GetterFuncPtr getter(getter_func,data,count); 2746 return PlotDigitalEx(label_id, getter, flags); 2747} 2748 2749//----------------------------------------------------------------------------- 2750// [SECTION] PlotImage 2751//----------------------------------------------------------------------------- 2752 2753void PlotImage(const char* label_id, ImTextureID user_texture_id, const ImPlotPoint& bmin, const ImPlotPoint& bmax, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlotImageFlags) { 2754 if (BeginItemEx(label_id, FitterRect(bmin,bmax))) { 2755 ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col); 2756 GetCurrentItem()->Color = tint_col32; 2757 ImDrawList& draw_list = *GetPlotDrawList(); 2758 ImVec2 p1 = PlotToPixels(bmin.x, bmax.y,IMPLOT_AUTO,IMPLOT_AUTO); 2759 ImVec2 p2 = PlotToPixels(bmax.x, bmin.y,IMPLOT_AUTO,IMPLOT_AUTO); 2760 PushPlotClipRect(); 2761 draw_list.AddImage(user_texture_id, p1, p2, uv0, uv1, tint_col32); 2762 PopPlotClipRect(); 2763 EndItem(); 2764 } 2765} 2766 2767//----------------------------------------------------------------------------- 2768// [SECTION] PlotText 2769//----------------------------------------------------------------------------- 2770 2771void PlotText(const char* text, double x, double y, const ImVec2& pixel_offset, ImPlotTextFlags flags) { 2772 IM_ASSERT_USER_ERROR(GImPlot->CurrentPlot != nullptr, "PlotText() needs to be called between BeginPlot() and EndPlot()!"); 2773 SetupLock(); 2774 ImDrawList & draw_list = *GetPlotDrawList(); 2775 PushPlotClipRect(); 2776 ImU32 colTxt = GetStyleColorU32(ImPlotCol_InlayText); 2777 if (ImHasFlag(flags,ImPlotTextFlags_Vertical)) { 2778 ImVec2 siz = CalcTextSizeVertical(text) * 0.5f; 2779 ImVec2 ctr = siz * 0.5f; 2780 ImVec2 pos = PlotToPixels(ImPlotPoint(x,y),IMPLOT_AUTO,IMPLOT_AUTO) + ImVec2(-ctr.x, ctr.y) + pixel_offset; 2781 if (FitThisFrame() && !ImHasFlag(flags, ImPlotItemFlags_NoFit)) { 2782 FitPoint(PixelsToPlot(pos)); 2783 FitPoint(PixelsToPlot(pos.x + siz.x, pos.y - siz.y)); 2784 } 2785 AddTextVertical(&draw_list, pos, colTxt, text); 2786 } 2787 else { 2788 ImVec2 siz = ImGui::CalcTextSize(text); 2789 ImVec2 pos = PlotToPixels(ImPlotPoint(x,y),IMPLOT_AUTO,IMPLOT_AUTO) - siz * 0.5f + pixel_offset; 2790 if (FitThisFrame() && !ImHasFlag(flags, ImPlotItemFlags_NoFit)) { 2791 FitPoint(PixelsToPlot(pos)); 2792 FitPoint(PixelsToPlot(pos+siz)); 2793 } 2794 draw_list.AddText(pos, colTxt, text); 2795 } 2796 PopPlotClipRect(); 2797} 2798 2799//----------------------------------------------------------------------------- 2800// [SECTION] PlotDummy 2801//----------------------------------------------------------------------------- 2802 2803void PlotDummy(const char* label_id, ImPlotDummyFlags flags) { 2804 if (BeginItem(label_id, flags, ImPlotCol_Line)) 2805 EndItem(); 2806} 2807 2808} // namespace ImPlot