implot.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. package imgui
  2. // #cgo CXXFLAGS: -std=c++11
  3. // #include "implotWrapper.h"
  4. import "C"
  5. import "unsafe"
  6. // The following functions MUST be called BEFORE BeginPlot!
  7. // Set the axes range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the axes limits will be locked.
  8. func ImPlotSetNextPlotLimits(xmin, xmax, ymin, ymax float64, cond Condition) {
  9. C.iggImPlotSetNextPlotLimits(C.double(xmin), C.double(xmax), C.double(ymin), C.double(ymax), C.int(cond))
  10. }
  11. func ImPlotSetNextPlotTicksX(values []float64, labels []string, showDefault bool) {
  12. if len(values) == 0 || len(labels) == 0 {
  13. return
  14. }
  15. labelsArg := make([]*C.char, len(labels))
  16. for i, l := range labels {
  17. la, lf := wrapString(l)
  18. defer lf()
  19. labelsArg[i] = la
  20. }
  21. C.iggImPlotSetNextPlotTicksX(
  22. (*C.double)(unsafe.Pointer(&values[0])),
  23. C.int(len(values)),
  24. &labelsArg[0],
  25. castBool(showDefault),
  26. )
  27. }
  28. func ImPlotSetNextPlotTicksY(values []float64, labels []string, showDefault bool, yAxis int) {
  29. if len(values) == 0 || len(labels) == 0 {
  30. return
  31. }
  32. labelsArg := make([]*C.char, len(labels))
  33. for i, l := range labels {
  34. la, lf := wrapString(l)
  35. defer lf()
  36. labelsArg[i] = la
  37. }
  38. C.iggImPlotSetNextPlotTicksY(
  39. (*C.double)(unsafe.Pointer(&values[0])),
  40. C.int(len(values)),
  41. &labelsArg[0],
  42. castBool(showDefault),
  43. C.int(yAxis),
  44. )
  45. }
  46. func ImPlotFitNextPlotAxis(x, y, y2, y3 bool) {
  47. C.iggImPlotFitNextPlotAxes(
  48. castBool(x),
  49. castBool(y),
  50. castBool(y2),
  51. castBool(y3),
  52. )
  53. }
  54. type ImPlotContext struct {
  55. handle C.IggImPlotContext
  56. }
  57. // Creates a new ImPlot context. Call this after ImGui::CreateContext.
  58. func ImPlotCreateContext() *ImPlotContext {
  59. return &ImPlotContext{handle: C.iggImPlotCreateContext()}
  60. }
  61. // Destroys an ImPlot context. Call this before ImGui::DestroyContext. NULL = destroy current context
  62. func ImPlotDestroyContext() {
  63. C.iggImPlotDestroyContext()
  64. }
  65. type ImPlotFlags int
  66. const (
  67. ImPlotFlags_None ImPlotFlags = 0 // default
  68. ImPlotFlags_NoTitle ImPlotFlags = 1 << 0 // the plot title will not be displayed (titles are also hidden if preceeded by double hashes, e.g. "##MyPlot")
  69. ImPlotFlags_NoLegend ImPlotFlags = 1 << 1 // the legend will not be displayed
  70. ImPlotFlags_NoMenus ImPlotFlags = 1 << 2 // the user will not be able to open context menus with right-click
  71. ImPlotFlags_NoBoxSelect ImPlotFlags = 1 << 3 // the user will not be able to box-select with right-click drag
  72. ImPlotFlags_NoMousePos ImPlotFlags = 1 << 4 // the mouse position, in plot coordinates, will not be displayed inside of the plot
  73. ImPlotFlags_NoHighlight ImPlotFlags = 1 << 5 // plot items will not be highlighted when their legend entry is hovered
  74. ImPlotFlags_NoChild ImPlotFlags = 1 << 6 // a child window region will not be used to capture mouse scroll (can boost performance for single ImGui window applications)
  75. ImPlotFlags_Equal ImPlotFlags = 1 << 7 // primary x and y axes will be constrained to have the same units/pixel (does not apply to auxiliary y-axes)
  76. ImPlotFlags_YAxis2 ImPlotFlags = 1 << 8 // enable a 2nd y-axis on the right side
  77. ImPlotFlags_YAxis3 ImPlotFlags = 1 << 9 // enable a 3rd y-axis on the right side
  78. ImPlotFlags_Query ImPlotFlags = 1 << 10 // the user will be able to draw query rects with middle-mouse or CTRL + right-click drag
  79. ImPlotFlags_Crosshairs ImPlotFlags = 1 << 11 // the default mouse cursor will be replaced with a crosshair when hovered
  80. ImPlotFlags_AntiAliased ImPlotFlags = 1 << 12 // plot lines will be software anti-aliased (not recommended for high density plots, prefer MSAA)
  81. ImPlotFlags_CanvasOnly ImPlotFlags = ImPlotFlags_NoTitle | ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMousePos
  82. )
  83. type ImPlotAxisFlags int
  84. const (
  85. ImPlotAxisFlags_None ImPlotAxisFlags = 0 // default
  86. ImPlotAxisFlags_NoLabel ImPlotAxisFlags = 1 << 0 // the axis label will not be displayed (axis labels also hidden if the supplied string name is NULL)
  87. ImPlotAxisFlags_NoGridLines ImPlotAxisFlags = 1 << 1 // no grid lines will be displayed
  88. ImPlotAxisFlags_NoTickMarks ImPlotAxisFlags = 1 << 2 // no tick marks will be displayed
  89. ImPlotAxisFlags_NoTickLabels ImPlotAxisFlags = 1 << 3 // no text labels will be displayed
  90. ImPlotAxisFlags_Foreground ImPlotAxisFlags = 1 << 4 // grid lines will be displayed in the foreground (i.e. on top of data) in stead of the background
  91. ImPlotAxisFlags_LogScale ImPlotAxisFlags = 1 << 5 // a logartithmic (base 10) axis scale will be used (mutually exclusive with ImPlotAxisFlags_Time)
  92. ImPlotAxisFlags_Time ImPlotAxisFlags = 1 << 6 // axis will display date/time formatted labels (mutually exclusive with ImPlotAxisFlags_LogScale)
  93. ImPlotAxisFlags_Invert ImPlotAxisFlags = 1 << 7 // the axis will be inverted
  94. ImPlotAxisFlags_NoInitialFit ImPlotAxisFlags = 1 << 8 // axis will not be initially fit to data extents on the first rendered frame (also the case if SetNextPlotLimits explicitly called)
  95. ImPlotAxisFlags_AutoFit ImPlotAxisFlags = 1 << 9 // axis will be auto-fitting to data extents
  96. ImPlotAxisFlags_RangeFit ImPlotAxisFlags = 1 << 10 // axis will only fit points if the point is in the visible range of the **orthoganol** axis
  97. ImPlotAxisFlags_LockMin ImPlotAxisFlags = 1 << 11 // the axis minimum value will be locked when panning/zooming
  98. ImPlotAxisFlags_LockMax ImPlotAxisFlags = 1 << 12 // the axis maximum value will be locked when panning/zooming
  99. ImPlotAxisFlags_Lock ImPlotAxisFlags = ImPlotAxisFlags_LockMin | ImPlotAxisFlags_LockMax
  100. ImPlotAxisFlags_NoDecorations ImPlotAxisFlags = ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines | ImPlotAxisFlags_NoTickMarks | ImPlotAxisFlags_NoTickLabels
  101. )
  102. type ImPlotYAxis int
  103. const (
  104. ImPlotYAxis_1 ImPlotYAxis = 0
  105. ImPlotYAxis_2 ImPlotYAxis = 1
  106. ImPlotYAxis_3 ImPlotYAxis = 2
  107. )
  108. //-----------------------------------------------------------------------------
  109. // Begin/End Plot
  110. //-----------------------------------------------------------------------------
  111. // Starts a 2D plotting context. If this function returns true, EndPlot() must
  112. // be called, e.g. "if (BeginPlot(...)) { ... EndPlot(); }". #title_id must
  113. // be unique. If you need to avoid ID collisions or don't want to display a
  114. // title in the plot, use double hashes (e.g. "MyPlot##Hidden" or "##NoTitle").
  115. // If #x_label and/or #y_label are provided, axes labels will be displayed.
  116. func ImPlotBegin(title string, xLabel, yLabel string, size Vec2, flags ImPlotFlags, xFlags, yFlags, y2Flags, y3Flags ImPlotAxisFlags, y2Label, y3Label string) bool {
  117. titleArg, titleFin := wrapString(title)
  118. defer titleFin()
  119. xLabelArg, xLabelFin := wrapString(xLabel)
  120. defer xLabelFin()
  121. yLabelArg, yLabelFin := wrapString(yLabel)
  122. defer yLabelFin()
  123. sizeArg, _ := size.wrapped()
  124. y2LabelArg, y2LabelFin := wrapString(y2Label)
  125. defer y2LabelFin()
  126. y3LabelArg, y3LabelFin := wrapString(y3Label)
  127. defer y3LabelFin()
  128. return C.iggImPlotBeginPlot(
  129. titleArg,
  130. xLabelArg,
  131. yLabelArg,
  132. sizeArg,
  133. C.int(flags),
  134. C.int(xFlags),
  135. C.int(yFlags),
  136. C.int(y2Flags),
  137. C.int(y3Flags),
  138. y2LabelArg,
  139. y3LabelArg) != 0
  140. }
  141. // Only call EndPlot() if BeginPlot() returns true! Typically called at the end
  142. // of an if statement conditioned on BeginPlot().
  143. func ImPlotEnd() {
  144. C.iggImPlotEndPlot()
  145. }
  146. // Plots a vertical bar graph. #width and #shift are in X units.
  147. func ImPlotBars(label string, values []float64, width, shift float64, offset int) {
  148. if len(values) == 0 {
  149. return
  150. }
  151. labelArg, labelFin := wrapString(label)
  152. defer labelFin()
  153. C.iggImPlotBars(labelArg, (*C.double)(unsafe.Pointer(&values[0])), C.int(len(values)), C.double(width), C.double(shift), C.int(offset))
  154. }
  155. // Plots a vertical bar graph. #width and #shift are in X units.
  156. func ImPlotBarsXY(label string, xs, ys []float64, width float64, offset int) {
  157. if len(xs) == 0 || len(ys) == 0 {
  158. return
  159. }
  160. labelArg, labelDeleter := wrapString(label)
  161. defer labelDeleter()
  162. C.iggImPlotBarsXY(
  163. labelArg,
  164. (*C.double)(unsafe.Pointer(&xs[0])),
  165. (*C.double)(unsafe.Pointer(&ys[0])),
  166. C.int(len(xs)),
  167. C.double(width),
  168. C.int(offset))
  169. }
  170. // Plots a horizontal bar graph. #height and #shift are in Y units.
  171. func ImPlotBarsH(label string, values []float64, height, shift float64, offset int) {
  172. if len(values) == 0 {
  173. return
  174. }
  175. labelArg, labelFin := wrapString(label)
  176. defer labelFin()
  177. C.iggImPlotBarsH(labelArg, (*C.double)(unsafe.Pointer(&values[0])), C.int(len(values)), C.double(height), C.double(shift), C.int(offset))
  178. }
  179. // Plots a horizontal bar graph. #height and #shift are in Y units.
  180. func ImPlotBarsHXY(label string, xs, ys []float64, height float64, offset int) {
  181. if len(xs) == 0 || len(ys) == 0 {
  182. return
  183. }
  184. labelArg, labelDeleter := wrapString(label)
  185. defer labelDeleter()
  186. C.iggImPlotBarsHXY(
  187. labelArg,
  188. (*C.double)(unsafe.Pointer(&xs[0])),
  189. (*C.double)(unsafe.Pointer(&ys[0])),
  190. C.int(len(xs)),
  191. C.double(height),
  192. C.int(offset),
  193. )
  194. }
  195. // Plots a standard 2D line plot.
  196. func ImPlotLine(label string, values []float64, xscale, x0 float64, offset int) {
  197. if len(values) == 0 {
  198. return
  199. }
  200. labelArg, labelFin := wrapString(label)
  201. defer labelFin()
  202. C.iggImPlotLine(
  203. labelArg,
  204. (*C.double)(unsafe.Pointer(&values[0])),
  205. C.int(len(values)),
  206. C.double(xscale),
  207. C.double(x0),
  208. C.int(offset),
  209. )
  210. }
  211. // Plots a standard 2D line plot.
  212. func ImPlotLineXY(label string, xs, ys []float64, offset int) {
  213. if len(xs) == 0 || len(ys) == 0 || (len(xs) != len(ys)) {
  214. return
  215. }
  216. labelArg, labelFin := wrapString(label)
  217. defer labelFin()
  218. C.iggImPlotLineXY(
  219. labelArg,
  220. (*C.double)(unsafe.Pointer(&xs[0])),
  221. (*C.double)(unsafe.Pointer(&ys[0])),
  222. C.int(len(xs)),
  223. C.int(offset),
  224. )
  225. }
  226. // Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.
  227. func ImPlotScatter(label string, values []float64, xscale, x0 float64, offset int) {
  228. if len(values) == 0 {
  229. return
  230. }
  231. labelArg, labelDeleter := wrapString(label)
  232. defer labelDeleter()
  233. C.iggImPlotScatter(
  234. labelArg,
  235. (*C.double)(unsafe.Pointer(&values[0])),
  236. C.int(len(values)),
  237. C.double(xscale),
  238. C.double(x0),
  239. C.int(offset),
  240. )
  241. }
  242. // Plots a standard 2D scatter plot. Default marker is ImPlotMarker_Circle.
  243. func ImPlotScatterXY(label string, xs, ys []float64, offset int) {
  244. if len(xs) == 0 || len(ys) == 0 {
  245. return
  246. }
  247. labelArg, labelDeleter := wrapString(label)
  248. defer labelDeleter()
  249. C.iggImPlotScatterXY(
  250. labelArg,
  251. (*C.double)(unsafe.Pointer(&xs[0])),
  252. (*C.double)(unsafe.Pointer(&ys[0])),
  253. C.int(len(xs)),
  254. C.int(offset),
  255. )
  256. }
  257. // Plots a a stairstep graph. The y value is continued constantly from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i].
  258. func ImPlotStairs(label string, values []float64, xscale, x0 float64, offset int) {
  259. if len(values) == 0 {
  260. return
  261. }
  262. labelArg, labelDeleter := wrapString(label)
  263. defer labelDeleter()
  264. C.iggImPlotStairs(
  265. labelArg,
  266. (*C.double)(unsafe.Pointer(&values[0])),
  267. C.int(len(values)),
  268. C.double(xscale),
  269. C.double(x0),
  270. C.int(offset),
  271. )
  272. }
  273. // Plots a a stairstep graph. The y value is continued constantly from every x position, i.e. the interval [x[i], x[i+1]) has the value y[i].
  274. func ImPlotStairsXY(label string, xs, ys []float64, offset int) {
  275. if len(xs) == 0 || len(ys) == 0 {
  276. return
  277. }
  278. labelArg, labelDeleter := wrapString(label)
  279. defer labelDeleter()
  280. C.iggImPlotStairsXY(
  281. labelArg,
  282. (*C.double)(unsafe.Pointer(&xs[0])),
  283. (*C.double)(unsafe.Pointer(&ys[0])),
  284. C.int(len(xs)),
  285. C.int(offset),
  286. )
  287. }
  288. // Plots vertical error bar. The label_id should be the same as the label_id of the associated line or bar plot.
  289. func ImPlotErrorBars(label string, xs, ys, err []float64, offset int) {
  290. if len(xs) == 0 || len(ys) == 0 || len(err) == 0 {
  291. return
  292. }
  293. labelArg, labelDeleter := wrapString(label)
  294. defer labelDeleter()
  295. C.iggImPlotErrorBars(
  296. labelArg,
  297. (*C.double)(unsafe.Pointer(&xs)),
  298. (*C.double)(unsafe.Pointer(&ys)),
  299. (*C.double)(unsafe.Pointer(&err)),
  300. C.int(len(xs)),
  301. C.int(offset),
  302. )
  303. }
  304. // Plots horizontal error bars. The label_id should be the same as the label_id of the associated line or bar plot.
  305. func ImPlotErrorBarsH(label string, xs, ys, err []float64, offset int) {
  306. if len(xs) == 0 || len(ys) == 0 || len(err) == 0 {
  307. return
  308. }
  309. labelArg, labelDeleter := wrapString(label)
  310. defer labelDeleter()
  311. C.iggImPlotErrorBarsH(
  312. labelArg,
  313. (*C.double)(unsafe.Pointer(&xs)),
  314. (*C.double)(unsafe.Pointer(&ys)),
  315. (*C.double)(unsafe.Pointer(&err)),
  316. C.int(len(xs)),
  317. C.int(offset),
  318. )
  319. }
  320. /// Plots vertical stems.
  321. func ImPlotStems(label string, values []float64, yRef, xscale, x0 float64, offset int) {
  322. if len(values) == 0 {
  323. return
  324. }
  325. labelArg, labelDeleter := wrapString(label)
  326. defer labelDeleter()
  327. C.iggImPlotStems(
  328. labelArg,
  329. (*C.double)(unsafe.Pointer(&values[0])),
  330. C.int(len(values)),
  331. C.double(yRef),
  332. C.double(xscale),
  333. C.double(x0),
  334. C.int(offset),
  335. )
  336. }
  337. /// Plots vertical stems.
  338. func ImPlotStemsXY(label string, xs, ys []float64, yRef float64, offset int) {
  339. if len(xs) == 0 || len(ys) == 0 {
  340. return
  341. }
  342. labelArg, labelDeleter := wrapString(label)
  343. defer labelDeleter()
  344. C.iggImPlotStemsXY(
  345. labelArg,
  346. (*C.double)(unsafe.Pointer(&xs[0])),
  347. (*C.double)(unsafe.Pointer(&ys[0])),
  348. C.int(len(xs)),
  349. C.double(yRef),
  350. C.int(offset),
  351. )
  352. }
  353. /// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
  354. func ImPlotVLines(label string, xs []float64, offset int) {
  355. if len(xs) == 0 {
  356. return
  357. }
  358. labelArg, labelDeleter := wrapString(label)
  359. defer labelDeleter()
  360. C.iggImPlotVLines(
  361. labelArg,
  362. (*C.double)(unsafe.Pointer(&xs[0])),
  363. C.int(len(xs)),
  364. C.int(offset),
  365. )
  366. }
  367. /// Plots infinite vertical or horizontal lines (e.g. for references or asymptotes).
  368. func ImPlotHLines(label string, ys []float64, offset int) {
  369. if len(ys) == 0 {
  370. return
  371. }
  372. labelArg, labelDeleter := wrapString(label)
  373. defer labelDeleter()
  374. C.iggImPlotHLines(
  375. labelArg,
  376. (*C.double)(unsafe.Pointer(&ys[0])),
  377. C.int(len(ys)),
  378. C.int(offset),
  379. )
  380. }
  381. // Plots a pie chart. If the sum of values > 1 or normalize is true, each value will be normalized. Center and radius are in plot units. #label_fmt can be set to NULL for no labels.
  382. func ImPlotPieChart(labelIds []string, values []float64, x, y, radius float64, normalize bool, labelFmt string, angle0 float64) {
  383. if len(labelIds) == 0 || len(values) == 0 {
  384. return
  385. }
  386. labelIdsArg := make([]*C.char, len(labelIds))
  387. for i, l := range labelIds {
  388. la, lf := wrapString(l)
  389. defer lf()
  390. labelIdsArg[i] = la
  391. }
  392. labelFmtArg, labelFmtDeleter := wrapString(labelFmt)
  393. defer labelFmtDeleter()
  394. C.iggImPlotPieChart(
  395. &labelIdsArg[0],
  396. (*C.double)(unsafe.Pointer(&values[0])),
  397. C.int(len(values)),
  398. C.double(x),
  399. C.double(y),
  400. C.double(radius),
  401. castBool(normalize),
  402. labelFmtArg,
  403. C.double(angle0),
  404. )
  405. }
  406. func ImPlotGetPlotPos() Vec2 {
  407. var pos Vec2
  408. posArg, _ := pos.wrapped()
  409. C.iggImPlotGetPlotPos(posArg)
  410. return pos
  411. }
  412. func ImPlotGetPlotSize() Vec2 {
  413. var size Vec2
  414. sizeArg, _ := size.wrapped()
  415. C.iggImPlotGetPlotSize(sizeArg)
  416. return size
  417. }
  418. func ImPlotIsPlotHovered() bool {
  419. return C.iggImPlotIsPlotHovered() != 0
  420. }
  421. func ImPlotIsPlotXAxisHovered() bool {
  422. return C.iggImPlotIsPlotXAxisHovered() != 0
  423. }
  424. func ImPlotIsPlotYAxisHovered(yAxis int) bool {
  425. return C.iggImPlotIsPlotYAxisHovered(C.int(yAxis)) != -0
  426. }
  427. func ImPlotUseLocalTime(localtime bool) {
  428. C.iggImPlotUseLocalTime(castBool(localtime))
  429. }
  430. func ImPlotUseISO8601(iso8601 bool) {
  431. C.iggImPlotUseISO8601(castBool(iso8601))
  432. }
  433. func ImPlotUse24HourClock(clock24h bool) {
  434. C.iggImPlotUse24HourClock(castBool(clock24h))
  435. }
  436. func ImPlotSetPlotYAxis(yAxis ImPlotYAxis) {
  437. C.iggImPlotSetPlotYAxis(C.int(yAxis))
  438. }