implot_items.cpp 122 KB

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