├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── examples ├── LinePlots.nim ├── LogScale.nim └── demo │ ├── ImPlotDemo.nim │ ├── LICENSE_implot.txt │ ├── Makefile │ ├── README.md │ ├── axes │ ├── AutoFittingData.nim │ ├── AxisConstraints.nim │ ├── CustomScale.nim │ ├── EqualAxes.nim │ ├── LinkedAxes.nim │ ├── LogScale.nim │ ├── MultipleAxes.nim │ ├── SymmetricLogScale.nim │ ├── TickLabels.nim │ └── TimeScale.nim │ ├── config.nims │ ├── config │ └── Config.nim │ ├── custom │ ├── CustomDataAndGetters.nim │ ├── CustomPlottersAndTooltips.nim │ ├── CustomRendering.nim │ └── CustomStyles.nim │ ├── help │ └── Help.nim │ ├── indexDemo.nim │ ├── plots │ ├── BarGroups.nim │ ├── BarPlots.nim │ ├── BarStacks.nim │ ├── DigitalPlots.nim │ ├── ErrorBars.nim │ ├── FilledLinePlots.nim │ ├── HeatMaps.nim │ ├── Histogram.nim │ ├── Images.nim │ ├── InfiniteLines.nim │ ├── LinePlots.nim │ ├── MarkersAndText.nim │ ├── NaNValues.nim │ ├── PieCharts.nim │ ├── RealtimePlots.nim │ ├── ScatterPlots.nim │ ├── ShadedPlots.nim │ ├── SimpleImGui.nim │ ├── SimplePlots.nim │ ├── StairstepPlots.nim │ └── StemPlots.nim │ ├── subplots │ ├── AxisLinking.nim │ ├── ItemSharing.nim │ ├── Sizing.nim │ └── Tables.nim │ ├── tools │ ├── Annotations.nim │ ├── ColormapWidgets.nim │ ├── DragAndDrop.nim │ ├── DragLines.nim │ ├── DragPoints.nim │ ├── DragRects.nim │ ├── LegendOptions.nim │ ├── LegendPopups.nim │ ├── OffsetAndStride.nim │ ├── Querying.nim │ └── Tags.nim │ └── utils.nim ├── img ├── BarGroups.png ├── BarPlots.png ├── BarStacks.png ├── CustomDataAndGetters.png ├── DigitalPlots.png ├── DragAndDrop.png ├── DragRects.png ├── ErrorBars.png ├── FilledLinePlots.png ├── HeatMaps.png ├── Histogram.png ├── Images.png ├── InfiniteLines.png ├── ItemSharing.png ├── LinePlots.png ├── LogScale.png ├── MarkersAndText.png ├── MultipleAxes.png ├── NaNValues.png ├── OffsetAndStride.png ├── PieCharts.png ├── RealTimePlots.png ├── ScatterPlots.png ├── ShadedPlots.png ├── SimplePlots.png ├── StairstepPlots.png ├── StemPlots.png ├── Tables.png └── nim_implot-demo.png ├── imgui.ini ├── implot.nimble ├── src ├── implot.nim └── implot │ └── private │ └── ncimplot.h ├── tests ├── Makefile ├── config.nims └── imPlotTest.nim └── tools ├── LICENSE ├── generator.nim ├── test.nim └── utils.nim /.gitignore: -------------------------------------------------------------------------------- 1 | ### C ### 2 | # Prerequisites 3 | *.d 4 | 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Linker output 12 | *.ilk 13 | *.map 14 | *.exp 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Executables 21 | *.exe 22 | *.out 23 | *.app 24 | *.i*86 25 | *.x86_64 26 | *.hex 27 | 28 | # Debug files 29 | *.dSYM/ 30 | *.su 31 | *.idb 32 | *.pdb 33 | 34 | # Kernel Module Compile Results 35 | *.mod* 36 | *.cmd 37 | .tmp_versions/ 38 | modules.order 39 | Module.symvers 40 | Mkfile.old 41 | dkms.conf 42 | 43 | ### C++ ### 44 | # Prerequisites 45 | 46 | # Compiled Object files 47 | *.slo 48 | 49 | # Precompiled Headers 50 | 51 | # Compiled Dynamic libraries 52 | 53 | # Fortran module files 54 | *.mod 55 | *.smod 56 | 57 | # Compiled Static libraries 58 | *.lai 59 | 60 | # Executables 61 | 62 | ### Linux ### 63 | *~ 64 | 65 | # temporary files which can be created if a process still has a handle open of a deleted file 66 | .fuse_hidden* 67 | 68 | # KDE directory preferences 69 | .directory 70 | 71 | # Linux trash folder which might appear on any partition or disk 72 | .Trash-* 73 | 74 | # .nfs files are created when an open file is removed but is still being accessed 75 | .nfs* 76 | 77 | ### macOS ### 78 | *.DS_Store 79 | .AppleDouble 80 | .LSOverride 81 | 82 | # Icon must end with two \r 83 | Icon 84 | 85 | # Thumbnails 86 | ._* 87 | 88 | # Files that might appear in the root of a volume 89 | .DocumentRevisions-V100 90 | .fseventsd 91 | .Spotlight-V100 92 | .TemporaryItems 93 | .Trashes 94 | .VolumeIcon.icns 95 | .com.apple.timemachine.donotpresent 96 | 97 | # Directories potentially created on remote AFP share 98 | .AppleDB 99 | .AppleDesktop 100 | Network Trash Folder 101 | Temporary Items 102 | .apdisk 103 | 104 | ### Nim ### 105 | nimcache/ 106 | 107 | ### OSX ### 108 | 109 | # Icon must end with two \r 110 | 111 | # Thumbnails 112 | 113 | # Files that might appear in the root of a volume 114 | 115 | # Directories potentially created on remote AFP share 116 | 117 | ### VisualStudioCode ### 118 | .vscode/* 119 | !.vscode/settings.json 120 | !.vscode/tasks.json 121 | !.vscode/launch.json 122 | !.vscode/extensions.json 123 | .history 124 | 125 | ### Windows ### 126 | # Windows thumbnail cache files 127 | Thumbs.db 128 | ehthumbs.db 129 | ehthumbs_vista.db 130 | 131 | # Folder config file 132 | Desktop.ini 133 | 134 | # Recycle Bin used on file shares 135 | $RECYCLE.BIN/ 136 | 137 | # Binaries 138 | [Bb]in/ 139 | 140 | # Windows Installer files 141 | *.cab 142 | *.msi 143 | *.msm 144 | *.msp 145 | 146 | # Windows shortcuts 147 | *.lnk 148 | 149 | # Dynamic Libraries 150 | *.dll 151 | *.so 152 | *.dylib 153 | 154 | ### NimGL ### 155 | 156 | # Tests 157 | tests/general 158 | tests/tgeneral 159 | tests/tglfw 160 | tests/tmath 161 | tests/topengl 162 | tools/generator 163 | tests/test 164 | tests/tnull 165 | imgui.ini 166 | docs/ 167 | 168 | .nimcache/ 169 | setenv.common.bat 170 | .hg/ 171 | img/org-image 172 | org.html 173 | GPATH 174 | GRTAGS 175 | GTAGS 176 | .hgignore 177 | README.html 178 | examples/*.cpp 179 | examples/*.c 180 | # End of https://www.gitignore.io/api/c,osx,nim,c++,linux,macos,windows,visualstudiocode 181 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/implot/private/cimplot"] 2 | path = src/implot/private/cimplot 3 | url = https://github.com/cimgui/cimplot 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 dinau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [Nim ImPlot binding](#nim-implot-binding) 5 | - [Direct nimble install from Web](#direct-nimble-install-from-web) 6 | - [Runing all demo programs](#runing-all-demo-programs) 7 | - [Compiling application](#compiling-application) 8 | - [Notice: Compilation options](#notice-compilation-options) 9 | - [Generating ImPlot bindings for development](#generating-implot-bindings-for-development) 10 | - [Development](#development) 11 | - [Tools info](#tools-info) 12 | - [Example gallery written in Nim language](#example-gallery-written-in-nim-language) 13 | - [Plots](#plots) 14 | - [LinePlots.nim](#lineplotsnim) 15 | - [FilledLinePlots.nim](#filledlineplotsnim) 16 | - [ShadedPlots.nim](#shadedplotsnim) 17 | - [ScatterPlots.nim](#scatterplotsnim) 18 | - [RealTimePlots.nim](#realtimeplotsnim) 19 | - [StairstepPlots.nim](#stairstepplotsnim) 20 | - [BarGroups.nim](#bargroupsnim) 21 | - [BarPlots.nim](#barplotsnim) 22 | - [BarStacks.nim](#barstacksnim) 23 | - [ErrorBars.nim](#errorbarsnim) 24 | - [StemPlots.nim](#stemplotsnim) 25 | - [InfiniteLines.nim](#infinitelinesnim) 26 | - [PieCharts.nim](#piechartsnim) 27 | - [HeatMaps.nim](#heatmapsnim) 28 | - [Histogram.nim](#histogramnim) 29 | - [DigitalPlots.nim](#digitalplotsnim) 30 | - [Images.nim](#imagesnim) 31 | - [MarkersAndText.nim](#markersandtextnim) 32 | - [NaNValues.nim](#nanvaluesnim) 33 | - [Subplots](#subplots) 34 | - [Tables.nim](#tablesnim) 35 | - [ItemSharing.nim](#itemsharingnim) 36 | - [Axes](#axes) 37 | - [LogScale.nim](#logscalenim) 38 | - [MultipleAxes.nim](#multipleaxesnim) 39 | - [Tools](#tools) 40 | - [OffsetAndStride.nim](#offsetandstridenim) 41 | - [DragRects.nim](#dragrectsnim) 42 | - [DragAndDrop.nim](#draganddropnim) 43 | - [Custom](#custom) 44 | - [CustomDataAndGetters.nim](#customdataandgettersnim) 45 | 46 | 47 | 48 | 49 | ### Nim ImPlot binding 50 | 51 | --- 52 | 53 | [ImPlot ](https://github.com/epezent/implot) is an immediate mode, GPU accelerated plotting library for [Dear ImGui](https://github.com/ocornut/imgui). 54 | 55 | 1. This project uses the modified generator that derived from the achievement of [Nimgl/imgui](https://github.com/nimgl/imgui) and [nimgl-imgui](https://github.com/daniel-j/nimgl-imgui)(forked). 56 | 1. This project also uses ImGui library ([nim-imgui (ImGui v1.89.9 latest)](https://github.com/dinau/nimgl-imgui)) derived from [Nimgl/imgui](https://github.com/nimgl/imgui) and [nimgl-imgui](https://github.com/daniel-j/nimgl-imgui)(forked). 57 | 1. Also have used [CImGui library](https://github.com/cimgui/cimgui) 58 | 59 | ### Direct nimble install from Web 60 | 61 | --- 62 | 63 | ```sh 64 | nimble install https://github.com/dinau/nim_implot 65 | ``` 66 | 67 | ### Runing all demo programs 68 | 69 | --- 70 | 71 | ```bash 72 | git clone --recursive https://github.com/dinau/nim_implot 73 | cd nim_implot 74 | nimble test 75 | ``` 76 | 77 | Test source: [examples/demo](examples/demo) 78 | 79 | ### Compiling application 80 | 81 | --- 82 | 83 | It has to be used **cpp** backend at compilation for example, 84 | 85 | ```sh 86 | pwd 87 | nim_implot 88 | cd examples/demo 89 | nim cpp -r ImPlotDemo.nim 90 | ``` 91 | 92 | **Note**: **C** backend is not supported. 93 | 94 | ### Notice: Compilation options 95 | 96 | --- 97 | 98 | If demo programs crash, please try to specify compilation option 99 | `--mm:refc` instead of `--mm:arc` or `--mm:orc`, 100 | especially if you use Nim-2.00, try to specify `--mm:refc`. 101 | These are TODO at this moment. 102 | 103 | ### Generating ImPlot bindings for development 104 | 105 | --- 106 | 107 | ```bash 108 | pwd 109 | nim_implot 110 | nimble gen 111 | ``` 112 | 113 | Genarated file: [src/implot.nim](src/implot.nim) 114 | 115 | 116 | ### Development 117 | 118 | --- 119 | 120 | It is currently being developed and tested on 121 | 122 | * Windows 10 123 | * (Debian 12 Bookworm) 124 | 125 | ```sh 126 | $ sudo apt install xorg-dev libopengl-dev libgl1-mesa-dev 127 | ``` 128 | 129 | ### Tools info 130 | 131 | --- 132 | 133 | - Windows10 134 | - Nim Compiler Version 1.6.14 135 | - gcc.exe (Rev2, Built by MSYS2 project) 13.2.0 136 | - Debian 12 Bookworm 137 | - Nim Compiler Version 1.6.14 138 | - gcc (Debian 12.2.0-14) 12.2.0 139 | 140 | ### Example gallery written in Nim language 141 | 142 | --- 143 | 144 | **Now all demo (over 50) programs have been implemented in Nim language** (2023/10), 145 | (Orignal demo program is here [implot_demo.cpp](https://github.com/epezent/implot/blob/master/implot_demo.cpp), (C++)) 146 | below images are part of them. 147 | 148 | #### Plots 149 | 150 | --- 151 | 152 | ##### [LinePlots.nim](examples/demo/plots/LinePlots.nim) 153 | 154 | ![alt](img/LinePlots.png) 155 | 156 | ##### [FilledLinePlots.nim](examples/demo/plots/FilledLinePlots.nim) 157 | 158 | ![alt](img/FilledLinePlots.png) 159 | 160 | ##### [ShadedPlots.nim](examples/demo/plots/ShadedPlots.nim) 161 | 162 | ![alt](img/ShadedPlots.png) 163 | 164 | ##### [ScatterPlots.nim](examples/demo/plots/ScatterPlots.nim) 165 | 166 | ![alt](img/ScatterPlots.png) 167 | 168 | ##### [RealTimePlots.nim](examples/demo/plots/RealTimePlots.nim) 169 | 170 | ![alt](img/RealTimePlots.png) 171 | 172 | ##### [StairstepPlots.nim](examples/demo/plots/StairstepPlots.nim) 173 | 174 | ![alt](img/StairstepPlots.png) 175 | 176 | ##### [BarGroups.nim](examples/demo/plots/BarGroups.nim) 177 | 178 | ![alt](img/BarGroups.png) 179 | 180 | ##### [BarPlots.nim](examples/demo/plots/BarPlots.nim) 181 | 182 | ![alt](img/BarPlots.png) 183 | 184 | ##### [BarStacks.nim](examples/demo/plots/BarStacks.nim) 185 | 186 | ![alt](img/BarStacks.png) 187 | 188 | ##### [ErrorBars.nim](examples/demo/plots/ErrorBars.nim) 189 | 190 | ![alt](img/ErrorBars.png) 191 | 192 | ##### [StemPlots.nim](examples/demo/plots/StemPlots.nim) 193 | 194 | ![alt](img/StemPlots.png) 195 | 196 | ##### [InfiniteLines.nim](examples/demo/plots/InfiniteLines.nim) 197 | 198 | ![alt](img/InfiniteLines.png) 199 | 200 | ##### [PieCharts.nim](examples/demo/plots/PieCharts.nim) 201 | 202 | ![alt](img/PieCharts.png) 203 | 204 | ##### [HeatMaps.nim](examples/demo/plots/HeatMaps.nim) 205 | 206 | ![alt](img/HeatMaps.png) 207 | 208 | ##### [Histogram.nim](examples/demo/plots/Histogram.nim) 209 | 210 | ![alt](img/Histogram.png) 211 | 212 | ##### [DigitalPlots.nim](examples/demo/plots/DigitalPlots.nim) 213 | 214 | ![alt](img/DigitalPlots.png) 215 | 216 | ##### [Images.nim](examples/demo/plots/Images.nim) 217 | 218 | ![alt](img/Images.png) 219 | 220 | ##### [MarkersAndText.nim](examples/demo/plots/MarkersAndText.nim) 221 | 222 | ![alt](img/MarkersAndText.png) 223 | 224 | ##### [NaNValues.nim](examples/demo/plots/NaNValues.nim) 225 | 226 | ![alt](img/NaNValues.png) 227 | 228 | #### Subplots 229 | 230 | --- 231 | 232 | ##### [Tables.nim](examples/demo/subplots/Tables.nim) 233 | 234 | ![alt](img/Tables.png) 235 | 236 | ##### [ItemSharing.nim](examples/demo/subplots/ItemSharing.nim) 237 | 238 | ![alt](img/ItemSharing.png) 239 | 240 | #### Axes 241 | 242 | --- 243 | 244 | ##### [LogScale.nim](examples/demo/axes/LogScale.nim) 245 | 246 | ![alt](img/LogScale.png) 247 | 248 | ##### [MultipleAxes.nim](examples/demo/axes/MultipleAxes.nim) 249 | 250 | ![alt](img/MultipleAxes.png) 251 | 252 | #### Tools 253 | 254 | --- 255 | 256 | ##### [OffsetAndStride.nim](examples/demo/tools/OffsetAndStride.nim) 257 | 258 | ![alt](img/OffsetAndStride.png) 259 | 260 | ##### [DragRects.nim](examples/demo/tools/DragRects.nim) 261 | 262 | ![alt](img/DragRects.png) 263 | 264 | ##### [DragAndDrop.nim](examples/demo/tools/DragAndDrop.nim) 265 | 266 | ![alt](img/DragAndDrop.png) 267 | 268 | #### Custom 269 | 270 | --- 271 | 272 | ##### [CustomDataAndGetters.nim](examples/demo/custom/CustomDataAndGetters.nim) 273 | 274 | ![alt](img/CustomDataAndGetters.png) 275 | -------------------------------------------------------------------------------- /examples/LinePlots.nim: -------------------------------------------------------------------------------- 1 | This file has been moved to 2 | 3 | https://github.com/dinau/nim_implot/blob/main/examples/demo/plots/LinePlots.nim 4 | 5 | -------------------------------------------------------------------------------- /examples/LogScale.nim: -------------------------------------------------------------------------------- 1 | This file has been moved to 2 | 3 | https://github.com/dinau/nim_implot/blob/main/examples/demo/axes/LogScale.nim 4 | -------------------------------------------------------------------------------- /examples/demo/ImPlotDemo.nim: -------------------------------------------------------------------------------- 1 | # Modified: for ImPlot by dinau 2023/09 2 | # Copyright 2019, NimGL contributors. 3 | 4 | import imgui, imgui/[impl_opengl, impl_glfw] 5 | import nimgl/[opengl, glfw] 6 | import implot 7 | 8 | import indexDemo 9 | 10 | #--------------------- 11 | # Forward definitions 12 | #--------------------- 13 | 14 | #---------- 15 | # main() 16 | #---------- 17 | proc main() = 18 | doAssert glfwInit() 19 | defer: glfwTerminate() 20 | 21 | glfwWindowHint(GLFWContextVersionMajor, 3) 22 | glfwWindowHint(GLFWContextVersionMinor, 3) 23 | glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE) 24 | glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE) 25 | glfwWindowHint(GLFWResizable, GLFW_TRUE) 26 | 27 | var glfwWindow: GLFWWindow = glfwCreateWindow(1080, 800) 28 | if glfwWindow == nil: 29 | quit(-1) 30 | glfwWindow.makeContextCurrent() 31 | defer: glfwWindow.destroyWindow() 32 | 33 | glfwSwapInterval(1) # Enable vsync 34 | 35 | doAssert glInit() 36 | 37 | var context = igCreateContext() 38 | defer: context.igDestroyContext() 39 | 40 | # setup ImPlot 41 | var imPlotContext = ipCreateContext() 42 | defer: imPlotContext.ipDestroyContext() 43 | 44 | doAssert igGlfwInitForOpenGL(glfwWindow, true) 45 | defer: igGlfwShutdown() 46 | # 47 | doAssert igOpenGL3Init() 48 | defer: igOpenGL3Shutdown() 49 | 50 | #imgui.igStyleColorsCherry() 51 | 52 | var 53 | showDemoImplot: bool = true 54 | showDemoImgui: bool = false 55 | 56 | #----------- 57 | # Main loop 58 | #----------- 59 | while not glfwWindow.windowShouldClose: 60 | glfwPollEvents() 61 | 62 | igOpenGL3NewFrame() 63 | igGlfwNewFrame() 64 | igNewFrame() 65 | 66 | if showDemoImplot: 67 | ipShowDemoWindow(showDemoImplot.addr) 68 | if showDemoImgui: 69 | igShowDemoWindow(showDemoImgui.addr) 70 | 71 | #------------- 72 | # Demo Window 73 | #------------- 74 | igSetNextWindowPos(ImVec2(x: 25, y: 25), FirstUseEver) 75 | igSetNextWindowSize(ImVec2(x: 580, y: 400), FirstUseEver) 76 | block: 77 | igBegin("All Demos have been written in Nim language." & " [ Nim-" & Nimversion & " ]") 78 | defer: igEnd() 79 | igText("Application average %.3f ms/frame (%.1f FPS)", 80 | 1000.0f / igGetIO().framerate, igGetIO().framerate) 81 | igCheckbox("ImPlot Demo", showDemoImPlot.addr) 82 | igSameLine() 83 | igCheckbox("ImGui Demo", showDemoImgui.addr) 84 | 85 | # ImPlot test window 86 | imPlotDemoTabs() 87 | # 88 | igRender() 89 | glClearColor(0.45f, 0.55f, 0.60f, 1.00f) 90 | glClear(GL_COLOR_BUFFER_BIT) 91 | igOpenGL3RenderDrawData(igGetDrawData()) 92 | glfwWindow.swapBuffers() 93 | 94 | #-------- 95 | # main() 96 | #-------- 97 | main() 98 | -------------------------------------------------------------------------------- /examples/demo/LICENSE_implot.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Evan Pezent 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/demo/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ImPlotDemo 2 | OPT += -d:release 3 | OPT += -d:strip 4 | #OPT += --cc:vcc 5 | all: 6 | nim cpp $(OPT) --nimcache:.nimcache $(TARGET).nim 7 | 8 | run: all 9 | #rm imgui.ini 10 | ./$(TARGET) 11 | 12 | gen: 13 | (cd ../..;nimble gen) 14 | 15 | clean: 16 | -rm -fr .nimcache 17 | -rm $(TARGET) 18 | -------------------------------------------------------------------------------- /examples/demo/README.md: -------------------------------------------------------------------------------- 1 | ### Aboue Demo programs 2 | 3 | - Demo programs have been converted to Nim language from ImPlot C++ language (implot\_demo.cpp). 4 | by dinau 2023/09 (https://github.com/dinau) 5 | -------------------------------------------------------------------------------- /examples/demo/axes/AutoFittingData.nim: -------------------------------------------------------------------------------- 1 | import std/[math,random] 2 | import imgui 3 | import implot 4 | 5 | #----------------------------- 6 | # demo_Axes_AutoFittingData() 7 | #----------------------------- 8 | proc demo_Axes_AutoFittingData*() = 9 | igBulletText("The Y-axis has been configured to auto-fit to only the data visible in X-axis range.") 10 | igBulletText("Zoom and pan the X-axis. Disable Stems to see a difference in fit.") 11 | igBulletText("If ImPlotAxisFlags_RangeFit is disabled, the axis will fit ALL data.") 12 | var 13 | xflags{.global.} = ImPlotAxisFlags.None 14 | yflags{.global.} = ImPlotAxisFlags.AutoFit or ImPlotAxisFlags.RangeFit 15 | 16 | igTextUnformatted("X: ");igSameLine() 17 | igCheckboxFlags("ImPlotAxisFlags_AutoFit##X", xflags.pu32, ImPlotAxisFlags.AutoFit.uint32);igSameLine() 18 | igCheckboxFlags("ImPlotAxisFlags_RangeFit##X", xflags.pu32, ImPlotAxisFlags.RangeFit.uint32) 19 | 20 | igTextUnformatted("Y: "); igSameLine() 21 | igCheckboxFlags("ImPlotAxisFlags_AutoFit##Y", yflags.pu32, ImPlotAxisFlags.AutoFit.uint32);igSameLine() 22 | igCheckboxFlags("ImPlotAxisFlags_RangeFit##Y", yflags.pu32, ImPlotAxisFlags.RangeFit.uint32) 23 | 24 | var data{.global.}:array[101,cdouble] 25 | randomize(0) # srand(0) : C++ 26 | for i in 0..<101: 27 | data[i] = 1.cfloat + sin(i.cfloat/10.0f) 28 | 29 | if ipBeginPlot("##DataFitting"): 30 | defer: ipEndPlot() 31 | ipSetupAxes("X","Y",xflags,yflags) 32 | ipPlotLine("Line",data.ptz,101) 33 | ipPlotStems("Stems",data.ptz,101) 34 | -------------------------------------------------------------------------------- /examples/demo/axes/AxisConstraints.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #---------------------------- 6 | # demo_Axes_AxisConstraints() 7 | #---------------------------- 8 | proc demo_Axes_AxisConstraints*() = 9 | var 10 | constraintsA{.global.} = [-10.cfloat, 10] 11 | constraintsB{.global.} = [1.cfloat, 20] 12 | flags{.global.}: ImPlotAxisFlags 13 | 14 | igDragFloat2("Limits Constraints", constraintsA, 0.01f) 15 | igDragFloat2("Zoom Constraints" , constraintsB, 0.01f) 16 | CHECKBOX_FLAG(flags, ImPlotAxisFlags.PanStretch) 17 | if ipBeginPlot("##AxisConstraints", ImVec2(x: -1, y: 0)): 18 | defer: ipEndPlot() 19 | ipSetupAxes("X", "Y", flags, flags) 20 | ipSetupAxesLimits(-1, 1, -1, 1) 21 | ipSetupAxisLimitsConstraints(ImAxis.X1, constraintsA[0], constraintsA[1]) 22 | ipSetupAxisZoomConstraints( ImAxis.X1, constraintsB[0], constraintsB[1]) 23 | ipSetupAxisLimitsConstraints(ImAxis.Y1, constraintsA[0], constraintsA[1]) 24 | ipSetupAxisZoomConstraints( ImAxis.Y1, constraintsB[0], constraintsB[1]) 25 | -------------------------------------------------------------------------------- /examples/demo/axes/CustomScale.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import implot 3 | 4 | proc TransformForward_Sqrt( v:cdouble, data: pointer): cdouble {.cdecl.} = 5 | return sqrt(v) 6 | 7 | proc TransformInverse_Sqrt(v:cdouble, data:pointer): cdouble {.cdecl.} = 8 | return v * v 9 | 10 | #------------------------ 11 | # demo_Axes_CustomScale() 12 | #------------------------ 13 | proc demo_Axes_CustomScale*() = 14 | var v:array[100,cfloat] 15 | for i in 0..<100: 16 | v[i] = i.cfloat * 0.01f 17 | if ipBeginPlot("Sqrt"): 18 | defer: ipEndPlot() 19 | ipSetupAxis(ImAxis.X1, "Linear") 20 | ipSetupAxis(ImAxis.Y1, "Sqrt") 21 | ipSetupAxisScale(ImAxis.Y1, TransformForward_Sqrt, TransformInverse_Sqrt) 22 | ipSetupAxisLimitsConstraints(ImAxis.Y1, 0, Inf) 23 | ipPlotLine("##data",v.ptz,v.ptz,100) 24 | -------------------------------------------------------------------------------- /examples/demo/axes/EqualAxes.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #---------------------- 6 | # demo_Axes_EqualAxes() 7 | #---------------------- 8 | proc demo_Axes_EqualAxes*() = 9 | igBulletText("Equal constraint applies to axis pairs (e.g ImAxis_X1/Y1, ImAxis_X2/Y2)") 10 | var 11 | xs1{.global.}:array[360,cdouble] 12 | ys1{.global.}:array[360,cdouble] 13 | once: 14 | for i in 0..<360: 15 | let angle = i.cfloat * 2 * PI / 359.0 16 | xs1[i] = cos(angle) 17 | ys1[i] = sin(angle) 18 | var 19 | xs2 = [-1.cfloat,0,1,0,-1] 20 | ys2 = [0.cfloat,1,0,-1,0] 21 | if ipBeginPlot("##EqualAxes",ImVec2(x: -1,y: 0),ImPlotFlags.Equal): 22 | defer: ipEndPlot() 23 | ipSetupAxis(ImAxis.X2, nullptr, ImPlotAxisFlags.AuxDefault) 24 | ipSetupAxis(ImAxis.Y2, nullptr, ImPlotAxisFlags.AuxDefault) 25 | ipPlotLine("Circle",xs1.ptz,ys1.ptz,360) 26 | ipSetAxes(ImAxis.X2, ImAxis.Y2) 27 | ipPlotLine("Diamond",xs2.ptz,ys2.ptz,5) 28 | -------------------------------------------------------------------------------- /examples/demo/axes/LinkedAxes.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------------ 5 | # demo_Axes_LinkedAxes() 6 | #------------------------ 7 | proc demo_Axes_LinkedAxes*() = 8 | var 9 | rx = ImPlotRange(min: 0,max: 1) 10 | ry = ImPlotRange(min: 0,max: 1) 11 | lims {.global.} : ImPlotRect 12 | linkx{.global.} = true 13 | linky{.global.} = true 14 | data = [0.int32,1] 15 | once: 16 | lims = ImPlotRect(x: rx,y: ry ) 17 | 18 | igCheckbox("Link X", linkx.addr) 19 | igSameLine() 20 | igCheckbox("Link Y", linky.addr) 21 | 22 | igDragScalarN("Limits",ImGuiDataType.Double,lims.x.min.addr,4,0.01f) 23 | 24 | if ipBeginAlignedPlots("AlignedGroup"): 25 | defer: ipEndAlignedPlots() 26 | if ipBeginPlot("Plot A"): 27 | defer: ipEndPlot() 28 | ipSetupAxisLinks(ImAxis.X1, if linkx : lims.x.min.addr else: nullptr 29 | , if linkx : lims.x.max.addr else: nullptr) 30 | ipSetupAxisLinks(ImAxis.Y1, if linky : lims.y.min.addr else: nullptr 31 | , if linky : lims.y.max.addr else: nullptr) 32 | ipPlotLine("Line",data.ptz,2) 33 | if ipBeginPlot("Plot B"): 34 | defer: ipEndPlot() 35 | ipSetupAxisLinks(ImAxis.X1, if linkx : lims.x.min.addr else: nullptr 36 | , if linkx : lims.x.max.addr else: nullptr) 37 | ipSetupAxisLinks(ImAxis.Y1, if linky : lims.y.min.addr else: nullptr 38 | , if linky : lims.y.max.addr else: nullptr) 39 | ipPlotLine("Line",data.ptz,2) 40 | -------------------------------------------------------------------------------- /examples/demo/axes/LogScale.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #-------------------- 6 | # demo_Axes_LogScale() 7 | #-------------------- 8 | proc demo_Axes_LogScale*() = 9 | var 10 | xs {.global.} : array[1001,cdouble] 11 | ys1{.global.} : array[1001,cdouble] 12 | ys2{.global.} : array[1001,cdouble] 13 | ys3{.global.} : array[1001,cdouble] 14 | 15 | once: 16 | for i in 0..<1001: 17 | xs[i] = i.float32 * 0.1f 18 | ys1[i] = sin(xs[i]) + 1 19 | ys2[i] = log(xs[i],10) 20 | ys3[i] = pow(10.0, xs[i]) 21 | 22 | if ipBeginPlot("Log Plot", ImVec2(x: -1,y: 0)): 23 | defer: ipEndPlot() 24 | ipSetupAxisScale(ImAxis.X1, ImPlotScale.Log10) 25 | ipSetupAxesLimits(0.1, 100, 0, 10) 26 | ipPlotLine("f(x) = x", xs.ptz, xs.ptz, 1001) 27 | ipPlotLine("f(x) = sin(x)+1", xs.ptz, ys1.ptz, 1001) 28 | ipPlotLine("f(x) = log(x)", xs.ptz, ys2.ptz, 1001) 29 | ipPlotLine("f(x) = 10^x", xs.ptz, ys3.ptz, 21) 30 | -------------------------------------------------------------------------------- /examples/demo/axes/MultipleAxes.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #-------------------------- 6 | # demo_Axes_MultipleAxes() 7 | #-------------------------- 8 | proc demo_Axes_MultipleAxes*() = 9 | var 10 | xs {.global.}:array[1001,cfloat] 11 | xs2{.global.}:array[1001,cfloat] 12 | ys1{.global.}:array[1001,cfloat] 13 | ys2{.global.}:array[1001,cfloat] 14 | ys3{.global.}:array[1001,cfloat] 15 | once: 16 | for i in 0..<1001: 17 | xs[i] = (i.cfloat * 0.1f) 18 | xs2[i] = xs[i] + 10.0f 19 | ys1[i] = sin(xs[i]) * 3 + 1 20 | ys2[i] = cos(xs[i]) * 0.2f + 0.5f 21 | ys3[i] = sin(xs[i]+0.5f) * 100 + 200 22 | var 23 | x2_axis{.global.} = true 24 | y2_axis{.global.} = true 25 | y3_axis{.global.} = true 26 | 27 | igCheckbox("X-Axis 2", x2_axis.addr) 28 | igSameLine() 29 | igCheckbox("Y-Axis 2", y2_axis.addr) 30 | igSameLine() 31 | igCheckbox("Y-Axis 3", y3_axis.addr) 32 | 33 | igBulletText("You can drag axes to the opposite side of the plot.") 34 | igBulletText("Hover over legend items to see which axis they are plotted on.") 35 | 36 | if ipBeginPlot("Multi-Axis Plot", ImVec2(x: -1,y: 0)): 37 | defer: ipEndPlot() 38 | ipSetupAxes("X-Axis 1", "Y-Axis 1") 39 | ipSetupAxesLimits(0, 100, 0, 10) 40 | if x2_axis: 41 | ipSetupAxis(ImAxis.X2, "X-Axis 2",ImPlotAxisFlags.AuxDefault) 42 | ipSetupAxisLimits(ImAxis.X2, 0, 100) 43 | if y2_axis: 44 | ipSetupAxis(ImAxis.Y2, "Y-Axis 2",ImPlotAxisFlags.AuxDefault) 45 | ipSetupAxisLimits(ImAxis.Y2, 0, 1) 46 | if y3_axis: 47 | ipSetupAxis(ImAxis.Y3, "Y-Axis 3",ImPlotAxisFlags.AuxDefault) 48 | ipSetupAxisLimits(ImAxis.Y3, 0, 300) 49 | 50 | ipPlotLine("f(x) = x", xs.ptz, xs.ptz, 1001) 51 | if x2_axis: 52 | ipSetAxes(ImAxis.X2, ImAxis.Y1) 53 | ipPlotLine("f(x) = sin(x)*3+1", xs2.ptz, ys1.ptz, 1001) 54 | if y2_axis: 55 | ipSetAxes(ImAxis.X1, ImAxis.Y2) 56 | ipPlotLine("f(x) = cos(x)*.2+.5", xs.ptz, ys2.ptz, 1001) 57 | if y3_axis: 58 | ipSetAxes(ImAxis.X2, ImAxis.Y3) 59 | ipPlotLine("f(x) = sin(x+.5)*100+200 ", xs2.ptz, ys3.ptz, 1001) 60 | -------------------------------------------------------------------------------- /examples/demo/axes/SymmetricLogScale.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #------------------------------ 6 | # demo_Axis_SymmetricLogScale() 7 | #------------------------------ 8 | proc demo_Axes_SymmetricLogScale*() = 9 | var 10 | xs {.global.}:array[1001,cdouble] 11 | ys1{.global.}:array[1001,cdouble] 12 | ys2{.global.}:array[1001,cdouble] 13 | 14 | for i in 0..<1001: 15 | xs[i] = i.cfloat * 0.1f - 50.cfloat 16 | ys1[i] = sin(xs[i]) 17 | ys2[i] = i.cfloat * 0.002 - 1.cfloat 18 | if ipBeginPlot("SymLog Plot", ImVec2(x: -1,y: 0)): 19 | ipSetupAxisScale(ImAxis.X1, ImPlotScale.SymLog) 20 | ipPlotLine("f(x) = a*x+b",xs.ptz,ys2.ptz,1001) 21 | ipPlotLine("f(x) = sin(x)",xs.ptz,ys1.ptz,1001) 22 | ipEndPlot() 23 | -------------------------------------------------------------------------------- /examples/demo/axes/TickLabels.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | 6 | #------------------------ 7 | # demo_Axes_TickLabels() 8 | #------------------------ 9 | proc demo_Axes_TickLabels*() = 10 | var 11 | custom_fmt {.global} = true 12 | custom_ticks {.global} = false 13 | custom_labels{.global} = true 14 | igCheckbox("Show Custom Format", custom_fmt.addr) 15 | igSameLine() 16 | igCheckbox("Show Custom Ticks", custom_ticks.addr) 17 | if custom_ticks: 18 | igSameLine() 19 | igCheckbox("Show Custom Labels", custom_labels.addr) 20 | var pi = 3.14.cdouble 21 | var 22 | pi_str = "PI".cstring 23 | yticks{.global} = [100.cdouble,300,700,900] 24 | var ylabels = ["One".cstring,"Three","Seven","Nine"] 25 | var yticks_aux = [0.cdouble,2,0.4,0.6] 26 | var ylabels_aux = ["A".cstring,"B","C","D","E","F"] 27 | if ipBeginPlot("##Ticks"): 28 | defer: ipEndPlot() 29 | ipSetupAxesLimits(2.5,5,0,1000) 30 | ipSetupAxis(ImAxis.Y2, nullptr, ImPlotAxisFlags.AuxDefault) 31 | ipSetupAxis(ImAxis.Y3, nullptr, ImPlotAxisFlags.AuxDefault) 32 | if custom_fmt: 33 | ipSetupAxisFormat(ImAxis.X1, "%g ms") 34 | ipSetupAxisFormat(ImAxis.Y1, MetricFormatter, "Hz".cstring) 35 | ipSetupAxisFormat(ImAxis.Y2, "%g dB") 36 | ipSetupAxisFormat(ImAxis.Y3, MetricFormatter, "m".cstring) 37 | if custom_ticks: 38 | ipSetupAxisTicks(ImAxis.X1, pi.addr,1,if custom_labels : pi_str.addr else: nullptr, true) 39 | ipSetupAxisTicks(ImAxis.Y1, yticks.ptz, 4, if custom_labels : ylabels.ptz else: nullptr, false) 40 | ipSetupAxisTicks(ImAxis.Y2, yticks_aux.ptz, 3, if custom_labels : ylabels_aux.ptz else: nullptr, false) 41 | ipSetupAxisTicks(ImAxis.Y3, 0, 1, 6, if custom_labels : ylabels_aux.ptz else: nullptr, false) 42 | -------------------------------------------------------------------------------- /examples/demo/axes/TimeScale.nim: -------------------------------------------------------------------------------- 1 | import std/[math,times] 2 | import imgui 3 | import implot 4 | 5 | #[// Huge data used by Time Formatting example (~500 MB allocation!) 6 | struct HugeTimeData { 7 | HugeTimeData(double min) { 8 | Ts = new double[Size]; 9 | Ys = new double[Size]; 10 | for (int i = 0; i < Size; ++i) { 11 | Ts[i] = min + i; 12 | Ys[i] = GetY(Ts[i]); 13 | } 14 | } 15 | ~HugeTimeData() { delete[] Ts; delete[] Ys; } 16 | static double GetY(double t) { 17 | return 0.5 + 0.25 * sin(t/86400/12) + 0.005 * sin(t/3600); 18 | } 19 | double* Ts; 20 | double* Ys; 21 | static const int Size = 60*60*24*366; 22 | }; ]# 23 | 24 | const Size = 60*60*24*366; 25 | type 26 | HugeTimeData = ref object 27 | Ts*: array[Size,cdouble] 28 | Ys*: array[Size,cdouble] 29 | 30 | proc GetY(t:cdouble) : cdouble = 31 | 0.5 + 0.25 * sin(t/86400/12) + 0.005 * sin(t/3600); 32 | proc newHugeTimeData(minf:cdouble): HugeTimeData = 33 | result.new 34 | for i in 0.. Size - 1 : Size - 1 else: start) 75 | var endi = ((rect.x.max - t_min) + 1000).int32 76 | endi = if endi < 0 : 0 else: (if endi > Size - 1 : Size - 1 else: endi) 77 | var size = (endi - start) div downsample 78 | #// plot it 79 | ipPlotLine("Time Series", data.Ts[start].addr 80 | , data.Ys[start].addr 81 | , size, 0.ImPlotLineFlags, 0, sizeof(cdouble) * downsample) 82 | #// plot time now 83 | var t_now = epochtime().cdouble 84 | var y_now = GetY(t_now) 85 | ipPlotScatter("Now",t_now.addr,y_now.addr,1) 86 | var vec4:ImVec4 87 | ipGetLastItemColorNonUdT(vec4.addr) 88 | ipAnnotation(t_now,y_now,vec4,ImVec2(x: 10,y: 10),false,"Now") 89 | ipEndPlot() 90 | -------------------------------------------------------------------------------- /examples/demo/config.nims: -------------------------------------------------------------------------------- 1 | # for development local path 2 | #switch "path","../../../nimgl-imgui/src" # for imgui 3 | switch "path","../../src" # for implot 4 | 5 | # 6 | switch "path","." 7 | switch "path","plots" 8 | switch "path","axes" 9 | switch "path","subplots" 10 | switch "path","tools" 11 | switch "path","custom" 12 | switch "path","config" 13 | switch "path","help" 14 | 15 | when (NimMajor, NimMinor, NimPatch) < (1, 6, 2): 16 | switch "gc","refc" 17 | else: 18 | switch "mm","refc" 19 | # Notice: Very important option at this time for Nim-2.0.0. TODO 20 | # ,effects axes/TimeScale.nim 21 | 22 | switch "warning","HoleEnumConv:off" # nim-1.6.0 or later 23 | 24 | # Compilation options 25 | switch "define","release" 26 | switch "nimcache",".nimcache" 27 | -------------------------------------------------------------------------------- /examples/demo/config/Config.nim: -------------------------------------------------------------------------------- 1 | import std/[times] 2 | import imgui 3 | import implot 4 | 5 | #---------------------- 6 | # Demo_Config_Config() 7 | #---------------------- 8 | proc demo_Config_Config*() = 9 | igShowFontSelector("Font") 10 | igShowStyleSelector("ImGui Style") 11 | ipShowStyleSelector("ImPlot Style") 12 | ipShowColormapSelector("ImPlot Colormap") 13 | ipShowInputMapSelector("Input Map") 14 | igSeparator() 15 | igCheckbox("Use Local Time", ipGetStyle().useLocalTime.addr) 16 | igCheckbox("Use ISO 8601", ipGetStyle().useISO8601.addr) 17 | igCheckbox("Use 24 Hour Clock", ipGetStyle().use24HourClock.addr) 18 | igSeparator() 19 | if ipBeginPlot("Preview"): 20 | defer: ipEndPlot() 21 | var nowd {.global.}:cdouble 22 | once: 23 | nowd = epochTime().cdouble 24 | ipSetupAxisScale(ImAxis.X1, ImPlotScale.Time) 25 | ipSetupAxisLimits(ImAxis.X1, nowd, nowd + 24 * 3600) 26 | for i in 0..<10: 27 | var 28 | x = [nowd, nowd + 24*3600] 29 | y = [0.cdouble,i.cdouble/9.0] 30 | igPushID(i.int32) 31 | ipPlotLine("##Line",x.ptz,y.ptz,2) 32 | igPopID() 33 | -------------------------------------------------------------------------------- /examples/demo/custom/CustomDataAndGetters.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #// Example for Custom Data and Getters section. 7 | type 8 | Vector2f = object 9 | x, y:cfloat 10 | 11 | proc Spiral(data: pointer, idx: cint , point: ptr ImPlotPoint) : pointer {.cdecl.} = 12 | var 13 | r = 0.9f #// outer radius 14 | a = 0f #// inner radius 15 | b = 0.05f #// increment per rev 16 | n = (r - a) / b #// number of revolutions 17 | let th = (2 * n * 3.14).cdouble; #// angle 18 | let Th = (th * idx.cdouble / (1000 - 1)).cfloat 19 | point.x = (0.5f + (a + b*Th / (2.0f * 3.14))*cos(Th)).cfloat 20 | point.y = (0.5f + (a + b*Th / (2.0f * 3.14))*sin(Th)).cfloat 21 | 22 | #----------------------------------- 23 | # demo_Custom_CustomDataAndGetters() 24 | #----------------------------------- 25 | proc demo_Custom_CustomDataAndGetters*() = 26 | igBulletText("You can plot custom structs using the stride feature.") 27 | igBulletText("Most plotters can also be passed a function pointer for getting data.") 28 | igIndent() 29 | igBulletText("You can optionally pass user data to be given to your getter function.") 30 | igBulletText("C++ lambdas can be passed as function pointers as well!") 31 | igUnindent() 32 | 33 | var vec2_data = [ Vector2f(x: 0,y: 0), Vector2f(x:1,y: 1) ] 34 | 35 | if ipBeginPlot("##Custom Data"): 36 | defer: ipEndPlot() 37 | #// custom structs using stride example: 38 | ipPlotLine("Vector2f", vec2_data[0].x.addr, vec2_data[0].y.addr 39 | , 2 40 | , 0.ImPlotLineFlags, 0, #[sizeof(Vector2f).int32]# (sizeof(cfloat) * 2).int32 ) 41 | 42 | #// custom getter example 1: 43 | ipPlotLineG("Spiral", Spiral, nullptr, 1000) 44 | 45 | #// custom getter example 2: 46 | var 47 | data1 = WaveData(X: 0.001, Amp: 0.2, Freq: 2, Offset: 0.75) 48 | data2 = WaveData(X: 0.001, Amp: 0.2, Freq: 4, Offset: 0.25) 49 | ipPlotLineG("Waves", SineWave2, data1.addr, 1000) 50 | ipPlotLineG("Waves", SawWave, data2.addr, 1000) 51 | ipPushStyleVar(ImPlotStyleVar.FillAlpha, 0.25f) 52 | ipPlotShadedG("Waves", SineWave2, data1.addr, SawWave, data2.addr, 1000) 53 | ipPopStyleVar() 54 | 55 | #// you can also pass C++ lambdas: 56 | #// auto lamda = [](void* data, int idx) { ... return ImPlotPoint(x,y); } 57 | #// ipPlotLine("My Lambda", lambda, data, 1000) 58 | -------------------------------------------------------------------------------- /examples/demo/custom/CustomPlottersAndTooltips.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #---------------------------------------- 6 | # demo_Custom_CustomPlottersAndTooltips() 7 | #---------------------------------------- 8 | proc demo_Custom_CustomPlottersAndTooltips*() = 9 | var 10 | dates = [1546300800.cdouble,1546387200,1546473600,1546560000,1546819200,1546905600,1546992000,1547078400,1547164800,1547424000,1547510400,1547596800,1547683200,1547769600,1547942400,1548028800,1548115200,1548201600,1548288000,1548374400,1548633600,1548720000,1548806400,1548892800,1548979200,1549238400,1549324800,1549411200,1549497600,1549584000,1549843200,1549929600,1550016000,1550102400,1550188800,1550361600,1550448000,1550534400,1550620800,1550707200,1550793600,1551052800,1551139200,1551225600,1551312000,1551398400,1551657600,1551744000,1551830400,1551916800,1552003200,1552262400,1552348800,1552435200,1552521600,1552608000,1552867200,1552953600,1553040000,1553126400,1553212800,1553472000,1553558400,1553644800,1553731200,1553817600,1554076800,1554163200,1554249600,1554336000,1554422400,1554681600,1554768000,1554854400,1554940800,1555027200,1555286400,1555372800,1555459200,1555545600,1555632000,1555891200,1555977600,1556064000,1556150400,1556236800,1556496000,1556582400,1556668800,1556755200,1556841600,1557100800,1557187200,1557273600,1557360000,1557446400,1557705600,1557792000,1557878400,1557964800,1558051200,1558310400,1558396800,1558483200,1558569600,1558656000,1558828800,1558915200,1559001600,1559088000,1559174400,1559260800,1559520000,1559606400,1559692800,1559779200,1559865600,1560124800,1560211200,1560297600,1560384000,1560470400,1560729600,1560816000,1560902400,1560988800,1561075200,1561334400,1561420800,1561507200,1561593600,1561680000,1561939200,1562025600,1562112000,1562198400,1562284800,1562544000,1562630400,1562716800,1562803200,1562889600,1563148800,1563235200,1563321600,1563408000,1563494400,1563753600,1563840000,1563926400,1564012800,1564099200,1564358400,1564444800,1564531200,1564617600,1564704000,1564963200,1565049600,1565136000,1565222400,1565308800,1565568000,1565654400,1565740800,1565827200,1565913600,1566172800,1566259200,1566345600,1566432000,1566518400,1566777600,1566864000,1566950400,1567036800,1567123200,1567296000,1567382400,1567468800,1567555200,1567641600,1567728000,1567987200,1568073600,1568160000,1568246400,1568332800,1568592000,1568678400,1568764800,1568851200,1568937600,1569196800,1569283200,1569369600,1569456000,1569542400,1569801600,1569888000,1569974400,1570060800,1570147200,1570406400,1570492800,1570579200,1570665600,1570752000,1571011200,1571097600,1571184000,1571270400,1571356800,1571616000,1571702400,1571788800,1571875200,1571961600] 11 | opens = [1284.7.cdouble,1319.9,1318.7,1328,1317.6,1321.6,1314.3,1325,1319.3,1323.1,1324.7,1321.3,1323.5,1322,1281.3,1281.95,1311.1,1315,1314,1313.1,1331.9,1334.2,1341.3,1350.6,1349.8,1346.4,1343.4,1344.9,1335.6,1337.9,1342.5,1337,1338.6,1337,1340.4,1324.65,1324.35,1349.5,1371.3,1367.9,1351.3,1357.8,1356.1,1356,1347.6,1339.1,1320.6,1311.8,1314,1312.4,1312.3,1323.5,1319.1,1327.2,1332.1,1320.3,1323.1,1328,1330.9,1338,1333,1335.3,1345.2,1341.1,1332.5,1314,1314.4,1310.7,1314,1313.1,1315,1313.7,1320,1326.5,1329.2,1314.2,1312.3,1309.5,1297.4,1293.7,1277.9,1295.8,1295.2,1290.3,1294.2,1298,1306.4,1299.8,1302.3,1297,1289.6,1302,1300.7,1303.5,1300.5,1303.2,1306,1318.7,1315,1314.5,1304.1,1294.7,1293.7,1291.2,1290.2,1300.4,1284.2,1284.25,1301.8,1295.9,1296.2,1304.4,1323.1,1340.9,1341,1348,1351.4,1351.4,1343.5,1342.3,1349,1357.6,1357.1,1354.7,1361.4,1375.2,1403.5,1414.7,1433.2,1438,1423.6,1424.4,1418,1399.5,1435.5,1421.25,1434.1,1412.4,1409.8,1412.2,1433.4,1418.4,1429,1428.8,1420.6,1441,1460.4,1441.7,1438.4,1431,1439.3,1427.4,1431.9,1439.5,1443.7,1425.6,1457.5,1451.2,1481.1,1486.7,1512.1,1515.9,1509.2,1522.3,1513,1526.6,1533.9,1523,1506.3,1518.4,1512.4,1508.8,1545.4,1537.3,1551.8,1549.4,1536.9,1535.25,1537.95,1535.2,1556,1561.4,1525.6,1516.4,1507,1493.9,1504.9,1506.5,1513.1,1506.5,1509.7,1502,1506.8,1521.5,1529.8,1539.8,1510.9,1511.8,1501.7,1478,1485.4,1505.6,1511.6,1518.6,1498.7,1510.9,1510.8,1498.3,1492,1497.7,1484.8,1494.2,1495.6,1495.6,1487.5,1491.1,1495.1,1506.4] 12 | highs = [1284.75.cdouble,1320.6,1327,1330.8,1326.8,1321.6,1326,1328,1325.8,1327.1,1326,1326,1323.5,1322.1,1282.7,1282.95,1315.8,1316.3,1314,1333.2,1334.7,1341.7,1353.2,1354.6,1352.2,1346.4,1345.7,1344.9,1340.7,1344.2,1342.7,1342.1,1345.2,1342,1350,1324.95,1330.75,1369.6,1374.3,1368.4,1359.8,1359,1357,1356,1353.4,1340.6,1322.3,1314.1,1316.1,1312.9,1325.7,1323.5,1326.3,1336,1332.1,1330.1,1330.4,1334.7,1341.1,1344.2,1338.8,1348.4,1345.6,1342.8,1334.7,1322.3,1319.3,1314.7,1316.6,1316.4,1315,1325.4,1328.3,1332.2,1329.2,1316.9,1312.3,1309.5,1299.6,1296.9,1277.9,1299.5,1296.2,1298.4,1302.5,1308.7,1306.4,1305.9,1307,1297.2,1301.7,1305,1305.3,1310.2,1307,1308,1319.8,1321.7,1318.7,1316.2,1305.9,1295.8,1293.8,1293.7,1304.2,1302,1285.15,1286.85,1304,1302,1305.2,1323,1344.1,1345.2,1360.1,1355.3,1363.8,1353,1344.7,1353.6,1358,1373.6,1358.2,1369.6,1377.6,1408.9,1425.5,1435.9,1453.7,1438,1426,1439.1,1418,1435,1452.6,1426.65,1437.5,1421.5,1414.1,1433.3,1441.3,1431.4,1433.9,1432.4,1440.8,1462.3,1467,1443.5,1444,1442.9,1447,1437.6,1440.8,1445.7,1447.8,1458.2,1461.9,1481.8,1486.8,1522.7,1521.3,1521.1,1531.5,1546.1,1534.9,1537.7,1538.6,1523.6,1518.8,1518.4,1514.6,1540.3,1565,1554.5,1556.6,1559.8,1541.9,1542.9,1540.05,1558.9,1566.2,1561.9,1536.2,1523.8,1509.1,1506.2,1532.2,1516.6,1519.7,1515,1519.5,1512.1,1524.5,1534.4,1543.3,1543.3,1542.8,1519.5,1507.2,1493.5,1511.4,1525.8,1522.2,1518.8,1515.3,1518,1522.3,1508,1501.5,1503,1495.5,1501.1,1497.9,1498.7,1492.1,1499.4,1506.9,1520.9] 13 | lows = [1282.85.cdouble,1315,1318.7,1309.6,1317.6,1312.9,1312.4,1319.1,1319,1321,1318.1,1321.3,1319.9,1312,1280.5,1276.15,1308,1309.9,1308.5,1312.3,1329.3,1333.1,1340.2,1347,1345.9,1338,1340.8,1335,1332,1337.9,1333,1336.8,1333.2,1329.9,1340.4,1323.85,1324.05,1349,1366.3,1351.2,1349.1,1352.4,1350.7,1344.3,1338.9,1316.3,1308.4,1306.9,1309.6,1306.7,1312.3,1315.4,1319,1327.2,1317.2,1320,1323,1328,1323,1327.8,1331.7,1335.3,1336.6,1331.8,1311.4,1310,1309.5,1308,1310.6,1302.8,1306.6,1313.7,1320,1322.8,1311,1312.1,1303.6,1293.9,1293.5,1291,1277.9,1294.1,1286,1289.1,1293.5,1296.9,1298,1299.6,1292.9,1285.1,1288.5,1296.3,1297.2,1298.4,1298.6,1302,1300.3,1312,1310.8,1301.9,1292,1291.1,1286.3,1289.2,1289.9,1297.4,1283.65,1283.25,1292.9,1295.9,1290.8,1304.2,1322.7,1336.1,1341,1343.5,1345.8,1340.3,1335.1,1341.5,1347.6,1352.8,1348.2,1353.7,1356.5,1373.3,1398,1414.7,1427,1416.4,1412.7,1420.1,1396.4,1398.8,1426.6,1412.85,1400.7,1406,1399.8,1404.4,1415.5,1417.2,1421.9,1415,1413.7,1428.1,1434,1435.7,1427.5,1429.4,1423.9,1425.6,1427.5,1434.8,1422.3,1412.1,1442.5,1448.8,1468.2,1484.3,1501.6,1506.2,1498.6,1488.9,1504.5,1518.3,1513.9,1503.3,1503,1506.5,1502.1,1503,1534.8,1535.3,1541.4,1528.6,1525.6,1535.25,1528.15,1528,1542.6,1514.3,1510.7,1505.5,1492.1,1492.9,1496.8,1493.1,1503.4,1500.9,1490.7,1496.3,1505.3,1505.3,1517.9,1507.4,1507.1,1493.3,1470.5,1465,1480.5,1501.7,1501.4,1493.3,1492.1,1505.1,1495.7,1478,1487.1,1480.8,1480.6,1487,1488.3,1484.8,1484,1490.7,1490.4,1503.1] 14 | closes = [1283.35.cdouble,1315.3,1326.1,1317.4,1321.5,1317.4,1323.5,1319.2,1321.3,1323.3,1319.7,1325.1,1323.6,1313.8,1282.05,1279.05,1314.2,1315.2,1310.8,1329.1,1334.5,1340.2,1340.5,1350,1347.1,1344.3,1344.6,1339.7,1339.4,1343.7,1337,1338.9,1340.1,1338.7,1346.8,1324.25,1329.55,1369.6,1372.5,1352.4,1357.6,1354.2,1353.4,1346,1341,1323.8,1311.9,1309.1,1312.2,1310.7,1324.3,1315.7,1322.4,1333.8,1319.4,1327.1,1325.8,1330.9,1325.8,1331.6,1336.5,1346.7,1339.2,1334.7,1313.3,1316.5,1312.4,1313.4,1313.3,1312.2,1313.7,1319.9,1326.3,1331.9,1311.3,1313.4,1309.4,1295.2,1294.7,1294.1,1277.9,1295.8,1291.2,1297.4,1297.7,1306.8,1299.4,1303.6,1302.2,1289.9,1299.2,1301.8,1303.6,1299.5,1303.2,1305.3,1319.5,1313.6,1315.1,1303.5,1293,1294.6,1290.4,1291.4,1302.7,1301,1284.15,1284.95,1294.3,1297.9,1304.1,1322.6,1339.3,1340.1,1344.9,1354,1357.4,1340.7,1342.7,1348.2,1355.1,1355.9,1354.2,1362.1,1360.1,1408.3,1411.2,1429.5,1430.1,1426.8,1423.4,1425.1,1400.8,1419.8,1432.9,1423.55,1412.1,1412.2,1412.8,1424.9,1419.3,1424.8,1426.1,1423.6,1435.9,1440.8,1439.4,1439.7,1434.5,1436.5,1427.5,1432.2,1433.3,1441.8,1437.8,1432.4,1457.5,1476.5,1484.2,1519.6,1509.5,1508.5,1517.2,1514.1,1527.8,1531.2,1523.6,1511.6,1515.7,1515.7,1508.5,1537.6,1537.2,1551.8,1549.1,1536.9,1529.4,1538.05,1535.15,1555.9,1560.4,1525.5,1515.5,1511.1,1499.2,1503.2,1507.4,1499.5,1511.5,1513.4,1515.8,1506.2,1515.1,1531.5,1540.2,1512.3,1515.2,1506.4,1472.9,1489,1507.9,1513.8,1512.9,1504.4,1503.9,1512.8,1500.9,1488.7,1497.6,1483.5,1494,1498.3,1494.1,1488.1,1487.5,1495.7,1504.7,1505.3] 15 | var tooltip{.global.} = true 16 | igCheckbox("Show Tooltip", tooltip.addr) 17 | igSameLine() 18 | var 19 | bullCol{.global.} = [0.000.cfloat, 1.000, 0.441, 1.000] 20 | bearCol{.global.} = [0.853.cfloat, 0.050, 0.310, 1.000] 21 | igSameLine(); igColorEdit4("##Bull", bullCol, ImGuiColorEditFlags.NoInputs) 22 | igSameLine(); igColorEdit4("##Bear", bearCol, ImGuiColorEditFlags.NoInputs) 23 | ipGetStyle().useLocalTime = false 24 | 25 | if ipBeginPlot("Candlestick Chart",ImVec2(x: -1,y: 0)): 26 | defer: ipEndPlot() 27 | ipSetupAxes(nullptr,nullptr,0.ImPlotAxisFlags,ImPlotAxisFlags.AutoFit or ImPlotAxisFlags.RangeFit) 28 | ipSetupAxesLimits(1546300800, 1571961600, 1250, 1600) 29 | ipSetupAxisScale(ImAxis.X1, ImPlotScale.Time) 30 | ipSetupAxisLimitsConstraints(ImAxis.X1, 1546300800, 1571961600) 31 | ipSetupAxisZoomConstraints(ImAxis.X1, 60*60*24*14, 1571961600-1546300800) 32 | ipSetupAxisFormat(ImAxis.Y1, "$%.0f") 33 | var bull = ImVec4(x: bullCol[0], y: bullCol[1], z: bullCol[2],w: bullCol[3]) 34 | var bear = ImVec4(x: bearCol[0], y: bearCol[1], z: bearCol[2],w: bearCol[3]) 35 | PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f , bull, bear) 36 | -------------------------------------------------------------------------------- /examples/demo/custom/CustomRendering.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #------------------------ 6 | # demo_CustomRendering() 7 | #------------------------ 8 | proc demo_Custom_CustomRendering*() = 9 | if ipBeginPlot("##CustomRend"): 10 | var vec2:ImVec2 11 | ipPlotToPixelsNonUDT(vec2.addr,ImPlotPoint(x: 0.5f, y: 0.5f)) 12 | var cntr = vec2 13 | ipPlotToPixelsNonUDT(vec2.addr,ImPlotPoint(x: 0.25f, y: 0.75f)) 14 | var rmin = vec2 15 | ipPlotToPixelsNonUDT(vec2.addr,ImPlotPoint(x: 0.75f, y: 0.25f)) 16 | var rmax = vec2 17 | ipPushPlotClipRect() 18 | ipGetPlotDrawList().addCircleFilled(cntr,20,IM_COL32(255,255,0,255),20) 19 | ipGetPlotDrawList().addRect(rmin, rmax, IM_COL32(128,0,255,255)) 20 | ipPopPlotClipRect() 21 | ipEndPlot() 22 | -------------------------------------------------------------------------------- /examples/demo/custom/CustomStyles.nim: -------------------------------------------------------------------------------- 1 | import implot 2 | import utils 3 | 4 | #----------------------------- 5 | # demo_Custom_CustomStyles*() 6 | #----------------------------- 7 | proc demo_Custom_CustomStyles*() = 8 | ipPushColormap(ImPlotColormap.Deep) 9 | #// normally you wouldn't change the entire style each frame 10 | var backup = ipGetStyle()[] 11 | StyleSeaborn() 12 | if ipBeginPlot("seaborn style"): 13 | defer: ipEndPlot() 14 | ipSetupAxes( "x-axis", "y-axis") 15 | ipSetupAxesLimits(-0.5f, 9.5f, 0, 10) 16 | var 17 | lin = [8.uint32,8,9,7,8,8,8,9,7,8] 18 | bar = [1.uint32,2,5,3,4,1,2,5,3,4] 19 | dot = [7.uint32,6,6,7,8,5,6,5,8,7] 20 | ipPlotBars("Bars", bar.ptz, 10, 0.5f) 21 | ipPlotLine("Line", lin.ptz, 10) 22 | ipNextColormapColorU32() #// skip green 23 | ipPlotScatter("Scatter", dot.ptz, 10) 24 | ipGetStyle()[] = backup 25 | ipPopColormap() 26 | -------------------------------------------------------------------------------- /examples/demo/help/Help.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------------ 5 | # demo_Help_Help() { 6 | #------------------------ 7 | proc demo_Help_Help*() = 8 | igText("ABOUT THIS DEMO:") 9 | igBulletText("Sections below are demonstrating many aspects of the library.") 10 | igBulletText("""The \"Tools\" menu above gives access to: Style Editors (ImPlot/ImGui)\n" 11 | "and Metrics (general purpose Dear ImGui debugging tool).""") 12 | igSeparator() 13 | igText("PROGRAMMER GUIDE:") 14 | igBulletText("See the ShowDemoWindow() code in implot_demo.cpp. <- you are here!") 15 | igBulletText("If you see visual artifacts, do one of the following:") 16 | igIndent() 17 | igBulletText("Handle ImGuiBackendFlags_RendererHasVtxOffset for 16-bit indices in your backend.") 18 | igBulletText("Or, enable 32-bit indices in imconfig.h.") 19 | igBulletText("Your current configuration is:") 20 | igIndent() 21 | igBulletText("ImDrawIdx: %d-bit", (int)(sizeof(ImDrawIdx) * 8)) 22 | igBulletText("ImGuiBackendFlags_RendererHasVtxOffset: %s" 23 | , if 0 != (igGetIO().backendFlags.uint32 and ImGuiBackendFlags.RendererHasVtxOffset.uint32) : "True".cstring else: "False".cstring) 24 | igUnindent() 25 | igUnindent() 26 | igSeparator() 27 | igText("USER GUIDE:") 28 | ipShowUserGuide() 29 | -------------------------------------------------------------------------------- /examples/demo/indexDemo.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | 3 | # Plots 4 | import LinePlots 5 | import FilledLinePlots 6 | import ShadedPlots 7 | import ScatterPlots 8 | import RealtimePlots 9 | import StairstepPlots 10 | import BarStacks 11 | import BarPlots 12 | import BarGroups 13 | import ErrorBars 14 | import StemPlots 15 | import InfiniteLines 16 | #import PieCharts 17 | import HeatMaps 18 | #import Histogram 19 | import DigitalPlots 20 | #import Images 21 | import MarkersAndText 22 | import NaNValues 23 | # 24 | import SimplePlots 25 | import SimpleImGui 26 | 27 | # SubPlots 28 | import Sizing 29 | import ItemSharing 30 | import AxisLinking 31 | import Tables 32 | # Axes 33 | import LogScale 34 | import SymmetricLogScale 35 | import CustomScale 36 | import MultipleAxes 37 | import EqualAxes 38 | import AutoFittingData 39 | import LinkedAxes 40 | #import AxisConstraints 41 | import TimeScale 42 | import TickLabels 43 | # Tools 44 | import DragPoints 45 | import DragLines 46 | import DragRects 47 | import Tags 48 | #import ColormapWidgets 49 | #import LegendPopups 50 | #import LegendOptions 51 | import Annotations 52 | import OffsetAndStride 53 | import Querying 54 | import DragAndDrop 55 | # Custom 56 | import CustomStyles 57 | import CustomDataAndGetters 58 | #import CustomPlottersAndTooltips 59 | import CustomRendering 60 | # Config 61 | import Config 62 | # Help 63 | import Help 64 | 65 | #--------------- 66 | # demoHeaeder() 67 | #--------------- 68 | proc demoHeader(label: string, demo: proc()) = 69 | if igTreeNodeEx(label.cstring): 70 | demo() 71 | igTreePop() 72 | 73 | #------------------ 74 | # imPlotDemoTabs() 75 | #------------------ 76 | proc imPlotDemoTabs*() = 77 | if igBeginTabBar("ImPlotDemoTabs"): 78 | defer: igEndTabBar() 79 | 80 | if (igBeginTabItem("Plots")): 81 | defer: igEndTabItem() 82 | demoHeader("Line Plots", demo_LinePlots) 83 | demoHeader("Filled Line Plots", demo_FilledLinePlots) 84 | demoHeader("Shaded Plots", demo_ShadedPlots) 85 | demoHeader("Scatter Plots", demo_ScatterPlots) 86 | demoHeader("RealTime Plots",demo_RealtimePlots) 87 | demoHeader("Stairstep Plots",demo_StairstepPlots) 88 | demoHeader("Bar Plots", demo_BarPlots) 89 | demoHeader("Bar Groups", demo_BarGroups) 90 | demoHeader("Bar Stacks",demo_BarStacks) 91 | demoHeader("Error Bars", demo_ErrorBars) 92 | demoHeader("Stem Plots##", demo_StemPlots) 93 | demoHeader("Infinite Lines" , demo_InfiniteLines) 94 | #demoHeader("Pie Charts", demo_PieCharts) 95 | demoHeader("HeatMaps", demo_Heatmaps) 96 | #demoHeader("Histogram", demo_Histogram) 97 | #demoHeader("Histogram2D", demo_Histogram2D) 98 | demoHeader("Digital Plots", demo_DigitalPlots) 99 | #demoHeader("Images" , demo_Images) 100 | demoHeader("Markers and Text" , demo_MarkersAndText) 101 | demoHeader("Nan Values" , demo_NaNValues) 102 | # 103 | demoHeader("Simple Plots", demo_SimplePlot) 104 | 105 | if igBeginTabItem("Subplots"): 106 | defer: igEndTabItem() 107 | demoHeader("Sizing", demo_Subplots_Sizing) 108 | demoHeader("Item Sharing", demo_Subplots_ItemSharing) 109 | demoHeader("Axis Linking", demo_Subplots_AxisLinking) 110 | demoHeader("Tables", demo_Subplots_Tables) 111 | 112 | if igBeginTabItem("Axes"): 113 | defer: igEndTabItem() 114 | demoHeader("Log Scale", demo_Axes_LogScale) 115 | demoHeader("Symmetric Log Scale", demo_Axes_SymmetricLogScale) 116 | demoHeader("Time Scale", demo_Axes_TimeScale) 117 | demoHeader("Custom Scale", demo_Axes_CustomScale) 118 | demoHeader("Multiple Axes", demo_Axes_MultipleAxes) 119 | demoHeader("Tick Labels", demo_Axes_TickLabels) 120 | demoHeader("Linked Axes", demo_Axes_LinkedAxes) 121 | #demoHeader("Axis Constraints", demo_Axes_AxisConstraints) 122 | demoHeader("Equal Axes", demo_Axes_EqualAxes) 123 | demoHeader("Auto-Fitting Data", demo_Axes_AutoFittingData) 124 | 125 | if igBeginTabItem("Tools"): 126 | defer: igEndTabItem() 127 | demoHeader("Offset and Stride", demo_Tools_OffsetAndStride) 128 | demoHeader("Drag Points", demo_Tools_DragPoints) 129 | demoHeader("Drag Lines", demo_Tools_DragLines) 130 | demoHeader("Drag Rects", demo_Tools_DragRects) 131 | demoHeader("Querying", demo_Tools_Querying) 132 | demoHeader("Annotations", demo_Tools_Annotations) 133 | demoHeader("Tags", demo_Tools_Tags) 134 | demoHeader("Drag and Drop", demo_Tools_DragAndDrop) 135 | #demoHeader("Legend Options", demo_Tools_LegendOptions) 136 | #demoHeader("Legend Popups", demo_Tools_LegendPopups) 137 | #demoHeader("Colormap Widgets", demo_Tools_ColormapWidgets) 138 | 139 | if igBeginTabItem("Custom"): 140 | defer: igEndTabItem() 141 | demoHeader("Custom Styles", demo_Custom_CustomStyles) 142 | demoHeader("Custom Data and Getters", demo_Custom_CustomDataAndGetters) 143 | demoHeader("Custom Rendering", demo_Custom_CustomRendering) 144 | #demoHeader("Custom Plotters and Tooltips", demo_Custom_CustomPlottersAndTooltips) 145 | 146 | if igBeginTabItem("Config"): 147 | defer: igEndTabItem() 148 | demo_Config_Config() 149 | 150 | if igBeginTabItem("Help"): 151 | defer: igEndTabItem() 152 | demo_Help_Help() 153 | 154 | if igBeginTabItem("ImGui"): 155 | defer: igEndTabItem() 156 | demoHeader("Simple demo", demo_SimpleImGui) 157 | -------------------------------------------------------------------------------- /examples/demo/plots/BarGroups.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------- 5 | # demo_BarGroups() 6 | #------------------- 7 | proc demo_BarGroups*() = 8 | var 9 | data{.global.} = [83'i8, 67, 23, 89, 83, 78, 91, 82, 85, 90, #// midterm 10 | 80, 62, 56, 99, 55, 78, 88, 78, 90, 100, #// final 11 | 80, 69, 52, 92, 72, 78, 75, 76, 89, 95] #// course 12 | ilabels = ["Midterm Exam".cstring,"Final Exam","Course Grade"] 13 | glabels = ["S1".cstring,"S2","S3","S4","S5","S6","S7","S8","S9","S10"] 14 | positions = [0.cdouble,1,2,3,4,5,6,7,8,9] 15 | Items{.global.} = 3.int32 16 | groups{.global.} = 10 17 | size{.global.} = 0.67f 18 | flags{.global.} = 0'i32 # ImPlotBarGroupsFlags 19 | horz{.global.} = false 20 | 21 | igCheckboxFlags("Stacked", addr flags, ImPlotBarGroupsFlags.Stacked.int32) 22 | igSameLine() 23 | igCheckbox("Horizontal",addr horz) 24 | 25 | igSliderInt("items",addr Items,1,3) 26 | igSliderFloat("Size",addr size,0,1) 27 | 28 | if ipBeginPlot("Bar Group"): 29 | ipSetupLegend(ImPlotLocation.East, ImPlotLegendFlags.Outside) 30 | if horz: 31 | ipSetupAxes("Score","Student",ImPlotAxisFlags.AutoFit,ImPlotAxisFlags.AutoFit) 32 | ipSetupAxisTicks(ImAxis.Y1,positions.ptz, groups, glabels.ptz) 33 | ipPlotBarGroups(ilabels.ptz, data.ptz, Items,groups,size,0 34 | ,flags or ImPlotBarGroupsFlags.Horizontal) 35 | else: 36 | ipSetupAxes("Student","Score",ImPlotAxisFlags.AutoFit,ImPlotAxisFlags.AutoFit) 37 | ipSetupAxisTicks(ImAxis.X1,positions.ptz, groups, glabels.ptz) 38 | ipPlotBarGroups(ilabels.ptz, data.ptz,Items,groups,size,0,flags.ImPlotBarGroupsFlags) 39 | ipEndPlot() 40 | -------------------------------------------------------------------------------- /examples/demo/plots/BarPlots.nim: -------------------------------------------------------------------------------- 1 | import implot 2 | 3 | 4 | #----------------- 5 | # demo_BarPlots() 6 | #----------------- 7 | proc demo_BarPlots*() = 8 | var data{.global.} = [1'i8,2,3,4,5,6,7,8,9,10] 9 | if ipBeginPlot("Bar Plot"): 10 | ipPlotBars("Vertical" , data.ptz,10,0.7,1) 11 | ipPlotBars("Horizontal", data.ptz,10,0.4,1,ImPlotBarsFlags.Horizontal) 12 | ipEndPlot() 13 | -------------------------------------------------------------------------------- /examples/demo/plots/BarStacks.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------ 5 | # demo_BarStacks() 6 | #------------------ 7 | proc demo_BarStacks*() = 8 | var Liars{.global.} = -1 9 | if Liars == -1: 10 | var Liars_Data{.global.} = [ 4282515870'u32, 4282609140'u32, 4287357182'u32, 4294630301'u32, 4294945280'u32, 4294921472'u32 ] 11 | Liars = ipAddColormap("LiarsNim", Liars_Data.ptz, 6).int32 12 | 13 | var diverging{.global.} = true 14 | igCheckbox("Diverging", addr diverging) 15 | 16 | var 17 | politicians{.global.} = ["Trump".cstring,"Bachman","Cruz","Gingrich","Palin","Santorum","Walker","Perry","Ryan","McCain","Rubio","Romney","Rand Paul","Christie","Biden","Kasich","Sanders","J Bush","H Clinton","Obama"] 18 | data_reg{.global.} = [18.int8,26,7,14,10,8,6,11,4,4,3,8,6,8,6,5,0,3,1,2, #// Pants on Fire 19 | 43,36,30,21,30,27,25,17,11,22,15,16,16,17,12,12,14,6,13,12, #// False 20 | 16,13,28,22,15,21,15,18,30,17,24,18,13,10,14,15,17,22,14,12, #// Mostly False 21 | 17,10,13,25,12,22,19,26,23,17,22,27,20,26,29,17,18,22,21,27, #// Half True 22 | 5,7,16,10,10,12,23,13,17,20,22,16,23,19,20,26,36,29,27,26, #// Mostly True 23 | 1,8,6,8,23,10,12,15,15,20,14,15,22,20,19,25,15,18,24,21] #// True 24 | labels_reg{.global.} = ["Pants on Fire".cstring,"False","Mostly False","Half True","Mostly True","True"] 25 | data_div{.global} = [0.int8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, #// Pants on Fire (dummy, to order legend logically) 26 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, #// False (dummy, to order legend logically) 27 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, #// Mostly False (dummy, to order legend logically) 28 | -16,-13,-28,-22,-15,-21,-15,-18,-30,-17,-24,-18,-13,-10,-14,-15,-17,-22,-14,-12, #// Mostly False 29 | -43,-36,-30,-21,-30,-27,-25,-17,-11,-22,-15,-16,-16,-17,-12,-12,-14,-6,-13,-12, #// False 30 | -18,-26,-7,-14,-10,-8,-6,-11,-4,-4,-3,-8,-6,-8,-6,-5,0,-3,-1,-2, #// Pants on Fire 31 | 17,10,13,25,12,22,19,26,23,17,22,27,20,26,29,17,18,22,21,27, #// Half True 32 | 5,7,16,10,10,12,23,13,17,20,22,16,23,19,20,26,36,29,27,26, #// Mostly True 33 | 1,8,6,8,23,10,12,15,15,20,14,15,22,20,19,25,15,18,24,21] #// True 34 | labels_div{.global.} = ["Pants on Fire".cstring,"False","Mostly False","Mostly False","False","Pants on Fire","Half True","Mostly True","True"] 35 | 36 | #ipPushColormap(Liars.ImPlotColormap) # Error: "PushID/PopID or TreeNode/TreePop Mismatch!", 37 | ipPushColormap("LiarsNim") 38 | if ipBeginPlot("PolitiFact: Who Lies More?",ImVec2(x: -1,y: 400),ImPlotFlags.NoMouseText): 39 | ipSetupLegend(ImPlotLocation.South, ImPlotLegendFlags.Outside or ImPlotLegendFlags.Horizontal) 40 | ipSetupAxes(nullptr,nullptr 41 | ,ImPlotAxisFlags.AutoFit or ImPlotAxisFlags.NoDecorations 42 | ,ImPlotAxisFlags.AutoFit or ImPlotAxisFlags.Invert) 43 | ipSetupAxisTicks(ImAxis.Y1,0,19,20, politicians.ptz,false) 44 | if diverging: 45 | ipPlotBarGroups(labels_div.ptz, data_div.ptz 46 | ,9 # item_count : int 47 | ,20 # group_count: int 48 | ,0.75 # group_size: cdouble 49 | ,0 # shift: cdouble 50 | ,ImPlotBarGroupsFlags.Stacked or ImPlotBarGroupsFlags.Horizontal) 51 | else: 52 | ipPlotBarGroups(labels_reg.ptz, data_reg.ptz 53 | ,6 54 | ,20 55 | ,0.75 56 | ,0 57 | ,ImPlotBarGroupsFlags.Stacked or ImPlotBarGroupsFlags.Horizontal) 58 | ipEndPlot() 59 | ipPopColormap() 60 | -------------------------------------------------------------------------------- /examples/demo/plots/DigitalPlots.nim: -------------------------------------------------------------------------------- 1 | import std/[strutils, math] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #--------------------- 7 | # demo_DigitalPlots*() 8 | #--------------------- 9 | proc demo_DigitalPlots*() = 10 | var 11 | paused{.global.} = false 12 | dataDigital{.global.} : array[2,ScrollingBuffer] 13 | dataAnalog {.global.} : array[2,ScrollingBuffer] 14 | showDigital{.global.} = [true, false] 15 | showAnalog{.global.} = [true, false] 16 | once: 17 | dataDigital = [newScrollingBuffer(), newScrollingBuffer()] 18 | dataAnalog = [newScrollingBuffer(), newScrollingBuffer()] 19 | 20 | igBulletText("Digital plots do not respond to Y drag and zoom, so that") 21 | igIndent() 22 | igText("you can drag analog plots over the rising/falling digital edge.") 23 | igUnindent() 24 | 25 | var label: string # char[32] 26 | igCheckbox("digital_0", showDigital[0].addr) 27 | igSameLine() 28 | igCheckbox("digital_1", showDigital[1].addr) 29 | igSameLine() 30 | igCheckbox("analog_0", showAnalog[0].addr) 31 | igSameLine() 32 | igCheckbox("analog_1", showAnalog[1].addr) 33 | var t{.global.} = 0.float32 34 | if not paused: 35 | t += igGetIO().deltaTime 36 | #//digital signal values 37 | if showDigital[0]: 38 | dataDigital[0].AddPoint(t, (sin(2*t) > 0.45).int.tofloat) 39 | if showDigital[1]: 40 | dataDigital[1].AddPoint(t, (sin(2*t) < 0.45).int.tofloat) 41 | # //Analog signal values 42 | if showAnalog[0]: 43 | dataAnalog[0].AddPoint(t, sin(2*t)) 44 | if showAnalog[1]: 45 | dataAnalog[1].AddPoint(t, cos(2*t)) 46 | 47 | if ipBeginPlot("##Digital"): 48 | defer: ipEndPlot() 49 | ipSetupAxisLimits(ImAxis.X1, (t - 10.0).cdouble, t.cdouble 50 | , (if paused: ImPlotCond.Once else: ImPlotCond.Always)) 51 | ipSetupAxisLimits(ImAxis.Y1, -1.cdouble, 1.cdouble) 52 | for i in 0..<2: 53 | if showDigital[i] and (dataDigital[i].Data.len() > 0): 54 | label = "digital_$#" % [$i] 55 | ipPlotDigital(label.cstring 56 | , addr dataDigital[i].Data[0].x 57 | , addr dataDigital[i].Data[0].y 58 | , dataDigital[i].Data.len() 59 | , 0.ImPlotDigitalFlags 60 | , dataDigital[i].Offset 61 | , 2 * sizeof(float32)) 62 | for i in 0..<2: 63 | if showAnalog[i]: 64 | label = "analog_$#" % [$i] 65 | if dataAnalog[i].Data.len() > 0: 66 | ipPlotLine(label.cstring 67 | , addr dataAnalog[i].Data[0].x 68 | , addr dataAnalog[i].Data[0].y 69 | , dataAnalog[i].Data.len() 70 | , 0.ImPlotLineFlags 71 | , dataAnalog[i].Offset 72 | , 2 * sizeof(float32)) 73 | -------------------------------------------------------------------------------- /examples/demo/plots/ErrorBars.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #---------------- 5 | # Demo_ErrorBars() 6 | #---------------- 7 | proc demo_ErrorBars*() = 8 | var 9 | xs = [1'f32,2,3,4,5] 10 | bar = [1'f32,2,5,3,4] 11 | lin1 = [8'f32,8,9,7,8] 12 | lin2 = [6'f32,7,6,9,6] 13 | err1 = [0.2f, 0.4f, 0.2f, 0.6f, 0.4f] 14 | err2 = [0.4f, 0.2f, 0.4f, 0.8f, 0.6f] 15 | err3 = [0.09f, 0.14f, 0.09f, 0.12f, 0.16f] 16 | err4 = [0.02f, 0.08f, 0.15f, 0.05f, 0.2f] 17 | 18 | if ipBeginPlot("##ErrorBars"): 19 | ipSetupAxesLimits(0, 6, 0, 10) 20 | ipPlotBars("Bar", xs.ptz, bar.ptz, 5, 0.5f) 21 | ipPlotErrorBars("Bar", xs.ptz, bar.ptz, err1.ptz, 5) 22 | var vec4:ImVec4 23 | ipGetColormapColorNonUDT(addr vec4,1) 24 | ipSetNextErrorBarStyle(vec4, 0) 25 | ipPlotErrorBars("Line", xs.ptz, lin1.ptz, err1.ptz, err2.ptz, 5) 26 | ipSetNextMarkerStyle(ImPlotMarker.Square) 27 | ipPlotLine("Line", xs.ptz, lin1.ptz, 5) 28 | 29 | ipGetColormapColorNonUDT( addr vec4,2) 30 | ipPushStyleColor(ImPlotCol.ErrorBar, vec4) 31 | ipPlotErrorBars("Scatter", xs.ptz, lin2.ptz, err2.ptz, 5) 32 | ipPlotErrorBars("Scatter", xs.ptz, lin2.ptz, err3.ptz, err4.ptz, 5, ImPlotErrorBarsFlags.Horizontal) 33 | ipPopStyleColor() 34 | ipPlotScatter("Scatter", xs.ptz, lin2.ptz, 5) 35 | 36 | ipEndPlot() 37 | -------------------------------------------------------------------------------- /examples/demo/plots/FilledLinePlots.nim: -------------------------------------------------------------------------------- 1 | import std/[random] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #------------------------ 7 | # demo_FilledLinePlots() 8 | #------------------------ 9 | proc demo_FilledLinePlots*() = 10 | var 11 | xs1{.global.}: array[101, double] 12 | ys1{.global.}: array[101, double] 13 | ys2{.global.}: array[101, double] 14 | ys3{.global.}: array[101, double] 15 | 16 | randomize(0) # srand(0) : C++ 17 | for i in 0..<101: 18 | xs1[i] = (float)i 19 | ys1[i] = RandomRange(400.0, 450.0) 20 | ys2[i] = RandomRange(275.0, 350.0) 21 | ys3[i] = RandomRange(150.0, 225.0) 22 | var 23 | show_lines{.global.} = true 24 | show_fills{.global.} = true 25 | fill_ref{.global.} = 0.float32 26 | shade_mode{.global.} = 0 27 | flags{.global.} = 0.ImPlotShadedFlags 28 | 29 | igCheckbox("Lines", addr show_lines) 30 | igSameLine() 31 | igCheckbox("Fills", addr show_fills) 32 | if show_fills: 33 | igSameLine() 34 | if igRadioButton("To -INF", shade_mode == 0): shade_mode = 0 35 | igSameLine() 36 | if igRadioButton("To +INF", shade_mode == 1): shade_mode = 1 37 | igSameLine() 38 | if igRadioButton("To Ref", shade_mode == 2): shade_mode = 2 39 | if shade_mode == 2: 40 | igSameLine() 41 | igSetNextItemWidth(100) 42 | igDragFloat("##Ref", addr fill_ref, 1, -100, 500) 43 | 44 | if ipBeginPlot("Stock Prices"): 45 | ipSetupAxes("Days", "Price") 46 | ipSetupAxesLimits(0, 100, 0, 500) 47 | if show_fills: 48 | ipPushStyleVar(ImPlotStyleVar.FillAlpha, 0.25f) 49 | ipPlotShaded("Stock 1", xs1.ptz, ys1.ptz, 101 50 | , if shade_mode == 0: -Inf 51 | else: 52 | if shade_mode == 1: Inf 53 | else: fill_ref 54 | , flags) 55 | ipPlotShaded("Stock 2", xs1.ptz, ys2.ptz, 101 56 | , if shade_mode == 0: -Inf 57 | else: 58 | if shade_mode == 1: Inf 59 | else: fill_ref 60 | , flags) 61 | ipPlotShaded("Stock 3", xs1.ptz, ys3.ptz, 101 62 | , if shade_mode == 0: -Inf 63 | else: 64 | if shade_mode == 1: Inf 65 | else: fill_ref 66 | , flags) 67 | ipPopStyleVar() 68 | 69 | if show_lines: 70 | ipPlotLine("Stock 1", xs1.ptz, ys1.ptz, 101) 71 | ipPlotLine("Stock 2", xs1.ptz, ys2.ptz, 101) 72 | ipPlotLine("Stock 3", xs1.ptz, ys3.ptz, 101) 73 | 74 | ipEndPlot() 75 | -------------------------------------------------------------------------------- /examples/demo/plots/HeatMaps.nim: -------------------------------------------------------------------------------- 1 | import std/[random] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | 7 | #----------------- 8 | # demo_Heatmaps() 9 | #----------------- 10 | proc demo_Heatmaps*() = 11 | var 12 | values1{.global.} = [ [0.8f, 2.4f, 2.5f, 3.9f, 0.0f, 4.0f, 0.0f], 13 | [2.4f, 0.0f, 4.0f, 1.0f, 2.7f, 0.0f, 0.0f], 14 | [1.1f, 2.4f, 0.8f, 4.3f, 1.9f, 4.4f, 0.0f], 15 | [0.6f, 0.0f, 0.3f, 0.0f, 3.1f, 0.0f, 0.0f], 16 | [0.7f, 1.7f, 0.6f, 2.6f, 2.2f, 6.2f, 0.0f], 17 | [1.3f, 1.2f, 0.0f, 0.0f, 0.0f, 3.2f, 5.1f], 18 | [0.1f, 2.0f, 0.0f, 1.4f, 0.0f, 1.9f, 6.3f]] 19 | scale_min{.global.} = 0.float32 20 | scale_max{.global.} = 6.3.float32 21 | xlabels{.global.} = ["C1".cstring, "C2", "C3", "C4", "C5", "C6", "C7"] 22 | ylabels{.global.} = ["R1".cstring, "R2", "R3", "R4", "R5", "R6", "R7"] 23 | 24 | map{.global.} = ImPlotColormap.Viridis 25 | 26 | if ipColormapButton(ipGetColormapName(map), ImVec2(x: 225, y: 0), map): 27 | map = ((map.int + 1) mod ipGetColormapCount()).ImPlotColormap 28 | #// We bust the color cache of our plots so that item colors will 29 | #// resample the new colormap in the event that they have already 30 | #// been created. See documentation in implot.h. 31 | ipBustColorCache("##Heatmap1".cstring) 32 | ipBustColorCache("##Heatmap2".cstring) 33 | 34 | igSameLine() 35 | igLabelText("##Colormap Index", "%s", "Change Colormap") 36 | igSetNextItemWidth(225) 37 | igDragFloatRange2("Min / Max", addr scale_min, addr scale_max, 0.01f, -20, 20) 38 | 39 | var hm_flags{.global.} = 0.ImPlotHeatmapFlags.int32 40 | 41 | igCheckboxFlags("Column Major", addr hm_flags, ImPlotHeatmapFlags.ColMajor.int32) 42 | 43 | var axes_flags{.global.} = cast[ImPlotAxisFlags](ImPlotAxisFlags.Lock.int32 or 44 | ImPlotAxisFlags.NoGridLines.int32 or 45 | ImPlotAxisFlags.NoTickMarks.int32) 46 | 47 | ipPushColormap(map) 48 | 49 | if ipBeginPlot("##Heatmap1", ImVec2(x: 225, y: 225) , ImPlotFlags.NoLegend or ImPlotFlags.NoMouseText): 50 | ipSetupAxes(nullptr, nullptr, axes_flags, axes_flags) 51 | ipSetupAxisTicks(ImAxis.X1, 0 + 1.0/14.0, 1 - 1.0/14.0, 7, xlabels.ptz) 52 | ipSetupAxisTicks(ImAxis.Y1, 1 - 1.0/14.0, 0 + 1.0/14.0, 7, ylabels.ptz) 53 | ipPlotHeatmap("heat", values1[0].ptz, 7, 7, scale_min, scale_max 54 | , "%g", ImPlotPoint(x: 0, y: 0), ImPlotPoint(x: 1, y: 1), hm_flags.ImPlotHeatmapFlags) 55 | ipEndPlot() 56 | 57 | igSameLine() 58 | ipColormapScale("##HeatScale", scale_min, scale_max, ImVec2(x: 60, y: 225)) 59 | 60 | igSameLine() 61 | 62 | const size = 80 63 | var values2{.global.}: array[size*size, cdouble] 64 | randomize((igGetTime()*1000000).int64) 65 | for i in 0..<(size * size): 66 | values2[i] = RandomRange(0.0, 1.0) 67 | if ipBeginPlot("##Heatmap2", ImVec2(x: 225, y: 225)): 68 | ipSetupAxes(nullptr, nullptr, ImPlotAxisFlags.NoDecorations, ImPlotAxisFlags.NoDecorations) 69 | ipSetupAxesLimits(-1, 1, -1, 1) 70 | ipPlotHeatmap("heat1", values2.ptz, size, size, 0, 1, nullptr) 71 | ipPlotHeatmap("heat2", values2.ptz, size, size, 0, 1, nullptr 72 | , ImPlotPoint(x: -1, y: -1) 73 | , ImPlotPoint(x: 0, y: 0)) 74 | ipEndPlot() 75 | 76 | ipPopColormap() 77 | -------------------------------------------------------------------------------- /examples/demo/plots/Histogram.nim: -------------------------------------------------------------------------------- 1 | import std/[math, random, sugar] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #------------------ 7 | # demo_Histogram() 8 | #------------------ 9 | proc demo_Histogram*() = 10 | const 11 | mu: double = 5 12 | sigma: double = 2 13 | var 14 | dist {.global.}: seq[cdouble] 15 | hist_flags{.global.} = Density.int32 16 | bins {.global.}: ImPlotBin = cast[ImPlotBin](50) 17 | once: 18 | discard initRand() 19 | dist = collect(for i in 0..<10000: gauss(mu, sigma).cdouble) 20 | 21 | igSetNextItemWidth(200) 22 | if igRadioButton("Sqrt", bins == Sqrt): bins = Sqrt 23 | igSameLine() 24 | if igRadioButton("Sturges", bins == Sturges): bins = Sturges 25 | igSameLine() 26 | if igRadioButton("Rice", bins == Rice): bins = Rice 27 | igSameLine() 28 | if igRadioButton("Scott", bins == Scott): bins = Scott 29 | #igSameLine() 30 | if igRadioButton("N Bins", bins.int32 >= 0): bins = cast[ImPlotBin](50) 31 | if bins.int32 >= 0: 32 | igSameLine() 33 | igSetNextItemWidth(200) 34 | igSliderInt("##Bins", cast[ptr int32](addr bins), 1, 100) 35 | 36 | igCheckboxFlags("Horizontal", addr hist_flags, ImPlotHistogramFlags.Horizontal.int32) 37 | igSameLine() 38 | igCheckboxFlags("Density", addr hist_flags, Density.int32) 39 | igSameLine() 40 | igCheckboxFlags("Cumulative", addr hist_flags, Cumulative.int32) 41 | 42 | var frange{.global.} = false 43 | igCheckbox("Range", addr frange) 44 | var 45 | rmin{.global.}: cfloat = -3 46 | rmax{.global.}: cfloat = 13 47 | range1{.global.} = [rmin, rmax] 48 | if frange: 49 | igSameLine() 50 | igSetNextItemWidth(200) 51 | igDragFloat2("##Range", range1, 0.1f, -3, 13) 52 | rmin = range1[0] 53 | rmax = range1[1] 54 | igSameLine() 55 | igCheckboxFlags("Exclude Outliers", addr hist_flags, NoOutliers.int32) 56 | 57 | #static NormalDistribution<10000> dist(mu, sigma) 58 | var 59 | x{.global.}: array[100, double] 60 | y{.global.}: array[100, double] 61 | if 0 != (hist_flags and Density.int32): 62 | for i in 0..<100: 63 | x[i] = -3 + 16 * i.double / 99.0 64 | y[i] = exp( - (x[i] - mu) * (x[i] - mu) / (2 * sigma * sigma)) / (sigma * sqrt(2 * 3.141592653589793238)) 65 | if 0 != (hist_flags and Cumulative.int32): 66 | for i in 1..<100: 67 | y[i] += y[i-1] 68 | for i in 0..<100: 69 | y[i] /= y[99] 70 | 71 | if ipBeginPlot("##Histograms"): 72 | defer: ipEndPlot() 73 | ipSetupAxes(nil, nil, AutoFit, AutoFit) 74 | ipSetNextFillStyle(IMPLOT_AUTO_COL,0.5f) 75 | #ipSetNextFillStyle(ImVec4(x: 0, y: 0, z: 0, w: -1), 0.5f) 76 | ipPlotHistogram("Empirical", dist.ptz, 10000.int, bins.int, 77 | 1.0.cdouble, (if frange: ImPlotRange(min: rmin, max: rmax) else: ImPlotRange()), 78 | hist_flags.ImPlotHistogramFlags) 79 | if (0 != (hist_flags and Density.int32)) and not (0 != (hist_flags and NoOutliers.int32)): 80 | if 0 != (hist_flags and ImPlotHistogramFlags.Horizontal.int32): 81 | ipPlotLine("Theoretical", y.ptz, x.ptz, 100) 82 | else: 83 | ipPlotLine("Theoretical", x.ptz, y.ptz, 100) 84 | 85 | #------------------ 86 | # demo_Histogram2D() 87 | #------------------ 88 | proc demo_Histogram2D*() = 89 | var 90 | count{.global.} = 50000.int32 91 | xybins{.global.} = [100.int32,100] 92 | hist_flags{.global.} = 0.int32 93 | dist1 {.global.}: seq[cdouble] 94 | dist2 {.global.}: seq[cdouble] 95 | once: 96 | discard initRand() 97 | dist1 = collect(for i in 0..<100000: gauss(1, 2).cdouble) 98 | dist2 = collect(for i in 0..<100000: gauss(1, 1).cdouble) 99 | 100 | igSliderInt("Count",addr count,100,100000) 101 | igSliderInt2("Bins", xybins,1,500) 102 | igSameLine() 103 | igCheckboxFlags("Density", addr hist_flags, Density.int32) 104 | #static NormalDistribution<100000> dist1(1, 2) 105 | #static NormalDistribution<100000> dist2(1, 1) 106 | var max_count = 0.cdouble 107 | var flags = AutoFit or ImPlotAxisFlags.Foreground 108 | ipPushColormap("Hot") 109 | var regn = ImVec2() 110 | igGetContentRegionAvailNonUDT(addr regn) 111 | if ipBeginPlot("##Hist2D",ImVec2(x: regn.x - 100 - igGetStyle().itemSpacing.x,y: 0)): 112 | ipSetupAxes(nullptr, nullptr, flags.ImPlotAxisFlags , flags.ImPlotAxisFlags ) 113 | ipSetupAxesLimits(-6,6,-6,6) 114 | max_count = ipPlotHistogram2D("Hist2D" 115 | ,dist1.ptz 116 | ,dist2.ptz 117 | ,count.int 118 | ,xybins[0].int 119 | ,xybins[1].int 120 | ,ImPlotRect(x: ImPlotRange(min: -6,max: 6) ,y: ImPlotRange(min: -6,max: 6)) 121 | ,hist_flags.ImPlotHistogramFlags) 122 | ipEndPlot() 123 | igSameLine() 124 | ipColormapScale((if 0 != (hist_flags and Density.int32) : "Density" else: "Count").cstring 125 | ,0,max_count,ImVec2(x: 100,y: 0)) 126 | ipPopColormap() 127 | -------------------------------------------------------------------------------- /examples/demo/plots/Images.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #--------------- 5 | # demo_Images() 6 | #--------------- 7 | proc demo_Images*() = 8 | igBulletText("Below we are displaying the font texture, which is the only texture we have\naccess to in this demo.") 9 | igBulletText("Use the 'ImTextureID' type as storage to pass pointers or identifiers to your\nown texture data.") 10 | igBulletText("See ImGui Wiki page 'Image Loading and Displaying Examples'.") 11 | var 12 | bmin{.global.} = [0.cfloat, 0] 13 | bmax{.global.} = [1.cfloat, 1] 14 | uv0 {.global.} = [0.cfloat, 0] 15 | uv1 {.global.} = [1.cfloat, 1] 16 | tint{.global.} = [1.cfloat, 1, 1, 1] 17 | 18 | igSliderFloat2("Min", bmin, -2, 2, "%.1f") 19 | igSliderFloat2("Max", bmax, -2, 2, "%.1f") 20 | igSliderFloat2("UV0", uv0, -2, 2, "%.1f") 21 | igSliderFloat2("UV1", uv1, -2, 2, "%.1f") 22 | igColorEdit4("Tint",tint) 23 | 24 | if ipBeginPlot("##image"): 25 | var 26 | bminPoint = ImPlotPoint(x: bmin[0], y: bmin[1]) 27 | bmaxPoint = ImPlotPoint(x: bmax[0], y: bmax[1]) 28 | uv0Vec2 = ImVec2(x: uv0[0], y: uv0[1]) 29 | uv1Vec2 = ImVec2(x: uv1[0], y: uv1[1]) 30 | tintVec4 = ImVec4( x: tint[0], y: tint[1], z: tint[2], w: tint[3]) 31 | ipPlotImage("my image",igGetIO().fonts.texID 32 | , bminPoint, bmaxPoint 33 | , uv0Vec2 , uv1Vec2 34 | , tintVec4) 35 | ipEndPlot() 36 | -------------------------------------------------------------------------------- /examples/demo/plots/InfiniteLines.nim: -------------------------------------------------------------------------------- 1 | import implot 2 | 3 | #---------------------- 4 | # demo_InfiniteLines() 5 | #---------------------- 6 | proc demo_InfiniteLines*() = 7 | var 8 | vals{.global.} = [0.25, 0.5, 0.75] 9 | if ipBeginPlot("##Infinite"): 10 | ipSetupAxes(nullptr,nullptr,ImPlotAxisFlags.NoInitialFit,ImPlotAxisFlags.NoInitialFit) 11 | ipPlotInfLines("Vertical",vals.ptz,3) 12 | ipPlotInfLines("Horizontal",vals.ptz,3,ImPlotInfLinesFlags.Horizontal) 13 | ipEndPlot() 14 | -------------------------------------------------------------------------------- /examples/demo/plots/LinePlots.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #------------------ 6 | # demo_LinePlots() 7 | #------------------ 8 | proc demo_LinePlots*() = 9 | var 10 | xs1{.global.}: array[1001, float] 11 | ys1{.global.}: array[1001, float] 12 | for i in 0..<1001: 13 | xs1[i] = i.float * 0.001f 14 | ys1[i] = 0.5f + 0.5f * sin(50 * (xs1[i] + igGetTime().float / 10)) 15 | var 16 | xs2{.global.}: array[20, float64] 17 | ys2{.global.}: array[20, float64] 18 | for i in 0..<20: 19 | xs2[i] = i.float * 1/19.0f 20 | ys2[i] = xs2[i] * xs2[i] 21 | if ipBeginPlot("Line Plots"): 22 | defer: ipEndPlot() 23 | ipSetupAxes("x", "y") 24 | ipPlotLine("f(x)", xs1.ptz, ys1.ptz, 1001) 25 | ipSetNextMarkerStyle(Circle) 26 | ipPlotLine("g(x)", xs2.ptz, ys2.ptz, 20, Segments) 27 | -------------------------------------------------------------------------------- /examples/demo/plots/MarkersAndText.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #---------------------- 6 | # demo_MarkersAndText() 7 | #---------------------- 8 | proc demo_MarkersAndText*() = 9 | var 10 | mk_size {.global.}:cfloat 11 | mk_weight{.global.}:cfloat 12 | once: 13 | mk_size = ipGetStyle().markerSize 14 | mk_weight = ipGetStyle().markerWeight 15 | 16 | igDragFloat("Marker Size", addr mk_size ,0.1f,2.0f,10.0f,"%.2f px") 17 | igDragFloat("Marker Weight", addr mk_weight,0.05f,0.5f,3.0f,"%.2f px") 18 | 19 | if ipBeginPlot("##MarkerStyles", ImVec2(x: -1,y: 0), ImPlotFlags.CanvasOnly): 20 | ipSetupAxes(nullptr, nullptr, ImPlotAxisFlags.NoDecorations, ImPlotAxisFlags.NoDecorations) 21 | ipSetupAxesLimits(0, 10, 0, 12) 22 | var 23 | xs = [1'i8 ,4] 24 | ys = [10'i8,11] 25 | 26 | #// filled markers 27 | for m in 0.. 1: 35 | var vec4: ImVec4 36 | ipSampleColormapNonUDT(vec4.addr, i.cfloat / (rows * cols - 1).cfloat, ImPlotColormap.Jet) 37 | ipSetNextLineStyle(vec4) 38 | ipPlotLineG("data", Sinewave, fi.addr, 1000) # fi must be cfloat type 39 | -------------------------------------------------------------------------------- /examples/demo/subplots/Tables.nim: -------------------------------------------------------------------------------- 1 | import std/[random] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #----------------------- 7 | # demo_Subplots_Tables() 8 | #----------------------- 9 | proc demo_Subplots_Tables*() = 10 | var 11 | flags{.global.} = ImGuiTableFlags.BordersOuter or ImGuiTableFlags.BordersV or 12 | ImGuiTableFlags.RowBg or ImGuiTableFlags.Resizable or 13 | ImGuiTableFlags.Reorderable 14 | anim{.global.} = true 15 | offset{.global.} = 0 16 | 17 | igBulletText("Plots can be used inside of ImGui tables as another means of creating subplots.") 18 | igCheckbox("Animate",addr anim) 19 | if anim: 20 | offset = (offset + 1) mod 100 21 | if igBeginTable("##table", 3, flags, ImVec2(x: -1,y: 0)): 22 | igTableSetupColumn("Electrode", ImGuiTableColumnFlags.WidthFixed, 75.0f) 23 | igTableSetupColumn("Voltage", ImGuiTableColumnFlags.WidthFixed, 75.0f) 24 | igTableSetupColumn("EMG Signal") 25 | igTableHeadersRow() 26 | ipPushColormap(ImPlotColormap.Cool) 27 | for row in 0..<10.int32: 28 | igTableNextRow() 29 | var data{.global.}: array[100,cfloat] 30 | randomize(row) # srand() : C++ 31 | for i in 0..<100: 32 | data[i] = RandomRange(0.0f,10.0f) 33 | igTableSetColumnIndex(0) 34 | igText("EMG %d", row) 35 | igTableSetColumnIndex(1) 36 | igText("%.3f V", data[offset]) 37 | igTableSetColumnIndex(2) 38 | igPushID(row) 39 | var map:ImVec4 40 | ipGetColormapColorNonUDT(addr map,row) 41 | sparkline("##spark",data.ptz,100,0,11.0f,offset.int32,map,ImVec2(x: -1, y: 35)) 42 | igPopID() 43 | 44 | ipPopColormap() 45 | igEndTable() 46 | -------------------------------------------------------------------------------- /examples/demo/tools/Annotations.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #-------------------- 5 | # Demo_Annotations() 6 | #-------------------- 7 | proc demo_Tools_Annotations*() = 8 | var clamp{.global.} = false 9 | igCheckbox("Clamp", clamp.addr) 10 | if ipBeginPlot("##Annotations"): 11 | defer: ipEndPlot() 12 | ipSetupAxesLimits(0, 2, 0, 1) 13 | var p{.global.} = [0.25f, 0.25f, 0.75f, 0.75f, 0.25f] 14 | ipPlotScatter("##Points", p.ptz, p.ptz, 4) 15 | var col: ImVec4 16 | ipGetLastItemColorNonUDT(col.addr) 17 | ipAnnotation(0.25, 0.25, col, ImVec2(x: -15, y: 15), clamp, "BL") 18 | ipAnnotation(0.75, 0.25, col, ImVec2(x: 15, y: 15), clamp, "BR") 19 | ipAnnotation(0.75, 0.75, col, ImVec2(x: 15, y: -15), clamp, "TR") 20 | ipAnnotation(0.25, 0.75, col, ImVec2(x: -15, y: -15), clamp, "TL") 21 | ipAnnotation(0.5, 0.5, col, ImVec2(), clamp, "Center") 22 | 23 | ipAnnotation(1.25, 0.75, ImVec4(x: 0, y: 1, z: 0, w: 1), ImVec2(), clamp) 24 | var 25 | bx = [1.2f, 1.5f, 1.8f] 26 | by = [0.25f, 0.5f, 0.75f] 27 | ipPlotBars("##Bars", bx.ptz, by.ptz, 3, 0.2) 28 | for i in 0..<3: 29 | ipAnnotation(bx[i], by[i], ImVec4(), ImVec2(x: 0, y: -5), clamp, "B[%d]=%.2f", i, by[i]) 30 | -------------------------------------------------------------------------------- /examples/demo/tools/ColormapWidgets.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #----------------------------- 6 | # demo_Tools_ColormapWidgets() { 7 | #----------------------------- 8 | proc demo_Tools_ColormapWidgets*() = 9 | var cmap{.global.} = ImPlotColormap.Viridis 10 | 11 | if ipColormapButton("Button",ImVec2(x: 0,y: 0),cmap): 12 | cmap = cast[ImPlotColormap]( (cmap.uint32 + 1) mod ipGetColormapCount().uint32 ) 13 | var 14 | t {.global.} = 0.5f 15 | col{.global.} = ImVec4() 16 | igColorButton("##Display",col,ImGuiColorEditFlags.NoInputs) 17 | igSameLine() 18 | ipColormapSlider("Slider", t.addr, col.addr, "%.3f", cmap) 19 | 20 | ipColormapIcon(cmap);igSameLine();igText("Icon") 21 | var 22 | flags{.global.} = 0.ImPlotColormapScaleFlags 23 | scale{.global.} = [0.cfloat, 100] 24 | ipColormapScale("Scale",scale[0].cdouble,scale[1].cdouble,ImVec2(x: 0,y: 0),"%g dB",flags,cmap) 25 | igInputFloat2("Scale",scale) 26 | CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags.NoLabel) 27 | CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags.Opposite) 28 | CHECKBOX_FLAG(flags, ImPlotColormapScaleFlags.Invert) 29 | -------------------------------------------------------------------------------- /examples/demo/tools/DragAndDrop.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | # // convenience struct to manage DND items; do this however you like 7 | # struct MyDndItem { 8 | # int Idx 9 | # int Plt 10 | # ImAxis Yax 11 | # char Label[16] 12 | # ImVector Data 13 | # ImVec4 Color 14 | # MyDndItem() { 15 | # static int i = 0 16 | # Idx = i++ 17 | # Plt = 0 18 | # Yax = ImAxis_Y1 19 | # snprintf(Label, sizeof(Label), "%02d Hz", Idx+1) 20 | # Color = RandomColor() 21 | # Data.reserve(1001) 22 | # for (int k = 0; k < 1001; ++k) { 23 | # float t = k * 1.0f / 999 24 | # Data.push_back(ImVec2(t, 0.5f + 0.5f * sinf(2*3.14f*t*(Idx+1)))) 25 | # } 26 | # } 27 | # void Reset() { Plt = 0; Yax = ImAxis_Y1; } 28 | # } 29 | 30 | type 31 | MyDndItem = ref object 32 | Idx*: int32 33 | Plt*: int32 34 | Yax*: ImAxis 35 | Label*: array[16, cchar] 36 | Data*: seq[ImVec2] 37 | Color*: ImVec4 38 | 39 | proc newMyDndItem(): MyDndItem = 40 | result = new MyDndItem 41 | var i{.global.} = 0'i32 42 | result.Idx = i 43 | result.Plt = 0 44 | result.Yax = ImAxis.Y1 45 | i.inc 46 | discard snprintf(result.Label.ptz.cstringCast, result.Label.len.cint, "%02d Hz".cstring 47 | , (result.Idx + 1.int32).cint) 48 | result.Color = RandomColor() 49 | result.Data = newSeqOfCap[ImVec2](1001) 50 | for k in 0..<1001: 51 | let t = k.float * 1.0f / 999.float 52 | result.Data.add(ImVec2(x: t, y: 0.5f + 0.5f * sin(2 * 3.14f * t * (result.Idx + 1).float))) 53 | 54 | proc Reset(this: var MyDndItem) = 55 | this.Plt = 0 56 | this.Yax = ImAxis.Y1 57 | 58 | #------------------------- 59 | # demo_Tools_DragAndDrop() 60 | #-------------------------- 61 | proc demo_Tools_DragAndDrop*() = 62 | igBulletText("Drag/drop items from the left column.") 63 | igBulletText("Drag/drop items between plots.") 64 | igIndent() 65 | igBulletText("Plot 1 Targets: Plot, Y-Axes, Legend") 66 | igBulletText("Plot 1 Sources: Legend Item Labels") 67 | igBulletText("Plot 2 Targets: Plot, X-Axis, Y-Axis") 68 | igBulletText("Plot 2 Sources: Plot, X-Axis, Y-Axis (hold Ctrl)") 69 | igUnindent() 70 | 71 | const k_dnd = 20 72 | var 73 | dnd {.global.}: array[k_dnd, MyDndItem] 74 | dndx{.global.}: MyDndItem = nullptr #// for plot 2 75 | dndy{.global.}: MyDndItem = nullptr #// for plot 2 76 | once: 77 | for i in 0.. 0: 90 | continue 91 | ipItemIcon(dnd[k].Color); igSameLine() 92 | igSelectable(dnd[k].Label.ptz.cstringCast, false, 0.ImGuiSelectableFlags, ImVec2(x: 100, y: 0)) 93 | if igBeginDragDropSource(ImGuiDragDropFlags.None): 94 | igSetDragDropPayload("MY_DND", kk.addr, sizeof(int).uint) 95 | ipItemIcon(dnd[k].Color); igSameLine() 96 | igTextUnformatted(dnd[k].Label.ptz.cstringCast) 97 | igEndDragDropSource() 98 | igEndChild() 99 | if igBeginDragDropTarget(): 100 | let payload = igAcceptDragDropPayload("MY_DND") 101 | if not payload.isNil: 102 | let i = cast[ptr int](payload.data)[] 103 | dnd[i].Reset() 104 | igEndDragDropTarget() 105 | igSameLine() 106 | igBeginChild("DND_RIGHT", ImVec2(x: -1, y: 400)) 107 | #// plot 1 (time series) 108 | var flags = ImPlotAxisFlags.NoTickLabels or ImPlotAxisFlags.NoGridLines or ImPlotAxisFlags.NoHighlight 109 | if ipBeginPlot("##DND1", ImVec2(x: -1, y: 195)): 110 | ipSetupAxis(ImAxis.X1, nullptr, flags or ImPlotAxisFlags.Lock) 111 | ipSetupAxis(ImAxis.Y1, "[drop here]", flags) 112 | ipSetupAxis(ImAxis.Y2, "[drop here]", flags or ImPlotAxisFlags.Opposite) 113 | ipSetupAxis(ImAxis.Y3, "[drop here]", flags or ImPlotAxisFlags.Opposite) 114 | 115 | for k in 0.. 0: 118 | ipSetAxis(dnd[k].Yax) 119 | ipSetNextLineStyle(dnd[k].Color) 120 | ipPlotLine(dnd[k].Label.ptz.cstringCast 121 | , dnd[k].Data[0].x.addr 122 | , dnd[k].Data[0].y.addr 123 | , dnd[k].Data.len, 0.ImPlotLineFlags, 0, 2 * sizeof(cfloat)) # Being sizeof(cfloat) is very important. 124 | #// allow legend item labels to be DND sources 125 | if ipBeginDragDropSourceItem(dnd[k].Label.ptz.cstringCast): 126 | igSetDragDropPayload("MY_DND", kk.addr, sizeof(int).uint) 127 | ipItemIcon(dnd[k].Color); igSameLine() 128 | igTextUnformatted(dnd[k].Label.ptz.cstringCast) 129 | ipEndDragDropSource() 130 | #// allow the main plot area to be a DND target 131 | if ipBeginDragDropTargetPlot(): 132 | let payload = igAcceptDragDropPayload("MY_DND") 133 | if not payload.isNil: 134 | var i = cast[ptr int](payload.data)[]; dnd[i].Plt = 1; dnd[i].Yax = ImAxis.Y1 135 | ipEndDragDropTarget() 136 | #// allow each y-axis to be a DND target 137 | for y in ImAxis.Y1..ImAxis.Y3: 138 | if ipBeginDragDropTargetAxis(y): 139 | let payload = igAcceptDragDropPayload("MY_DND") 140 | if not payload.isNil: 141 | var i = cast[ptr int](payload.data)[]; dnd[i].Plt = 1; dnd[i].Yax = y 142 | ipEndDragDropTarget() 143 | #// allow the legend to be a DND target 144 | if ipBeginDragDropTargetLegend(): 145 | let payload = igAcceptDragDropPayload("MY_DND") 146 | if not payload.isNil: 147 | var i = cast[ptr int](payload.data)[]; dnd[i].Plt = 1; dnd[i].Yax = ImAxis.Y1 148 | ipEndDragDropTarget() 149 | ipEndPlot() 150 | 151 | #// plot 2 (Lissajous) 152 | if ipBeginPlot("##DND2", ImVec2(x: -1, y: 195)): 153 | defer: ipEndPlot() 154 | ipPushStyleColor(ImPlotCol.AxisBg, if dndx != nullptr: dndx.Color else: ipGetStyle().colors[ImPlotCol.AxisBg.int]) 155 | ipSetupAxis(ImAxis.X1, if dndx == nullptr: "[drop here]".cstring else: dndx.Label.ptz.cstringCast, flags) 156 | ipPushStyleColor(ImPlotCol.AxisBg, if dndy != nullptr: dndy.Color else: ipGetStyle().colors[ImPlotCol.AxisBg.int]) 157 | ipSetupAxis(ImAxis.Y1, if dndy == nullptr: "[drop here]".cstring else: dndy.Label.ptz.cstringCast, flags) 158 | ipPopStyleColor(2) 159 | if dndx != nullptr and dndy != nullptr: 160 | var mixed = ImVec4(x: (dndx.Color.x + dndy.Color.x)/2 161 | , y: (dndx.Color.y + dndy.Color.y)/2 162 | , z: (dndx.Color.z + dndy.Color.z)/2 163 | , w: (dndx.Color.w + dndy.Color.w)/2) 164 | ipSetNextLineStyle(mixed) 165 | ipPlotLine("##dndxy", dndx.Data[0].y.addr 166 | , dndy.Data[0].y.addr 167 | , dndx.Data.len, 0.ImPlotLineFlags, 0, 2 * sizeof(float)) 168 | #// allow the x-axis to be a DND target 169 | if ipBeginDragDropTargetAxis(ImAxis.X1): 170 | let payload = igAcceptDragDropPayload("MY_DND") 171 | if not payload.isNil: 172 | var i = cast[ptr int](payload.data)[]; dndx = dnd[i] 173 | ipEndDragDropTarget() 174 | 175 | #// allow the x-axis to be a DND source 176 | if dndx != nullptr and ipBeginDragDropSourceAxis(ImAxis.X1): 177 | igSetDragDropPayload("MY_DND", dndx.Idx.addr, sizeof(int).uint) 178 | ipItemIcon(dndx.Color); igSameLine() 179 | igTextUnformatted(dndx.Label.ptz.cstringCast) 180 | ipEndDragDropSource() 181 | #// allow the y-axis to be a DND target 182 | if ipBeginDragDropTargetAxis(ImAxis.Y1): 183 | let payload = igAcceptDragDropPayload("MY_DND") 184 | if not payload.isNil: 185 | var i = cast[ptr int](payload.data)[]; dndy = dnd[i] 186 | ipEndDragDropTarget() 187 | 188 | #// allow the y-axis to be a DND source 189 | if dndy != nullptr and ipBeginDragDropSourceAxis(ImAxis.Y1): 190 | igSetDragDropPayload("MY_DND", dndy.Idx.addr, sizeof(int).uint) 191 | ipItemIcon(dndy.Color); igSameLine() 192 | igTextUnformatted(dndy.Label.ptz.cstringCast) 193 | ipEndDragDropSource() 194 | 195 | #// allow the plot area to be a DND target 196 | if ipBeginDragDropTargetPlot(): 197 | let payload = igAcceptDragDropPayload("MY_DND") 198 | if not payload.isNil: 199 | var i = cast[ptr int](payload.data)[] 200 | dndx = dnd[i] 201 | dndy = dnd[i] 202 | 203 | #// allow the plot area to be a DND source 204 | if ipBeginDragDropSourcePlot(): 205 | igTextUnformatted("Yes, you can\ndrag this!") 206 | ipEndDragDropSource() 207 | 208 | igEndChild() 209 | -------------------------------------------------------------------------------- /examples/demo/tools/DragLines.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #----------------------------- 6 | # demo_Tools_DragLines() 7 | #----------------------------- 8 | proc demo_Tools_DragLines*() = 9 | igBulletText("Click and drag the horizontal and vertical lines.") 10 | var 11 | x1 {.global.} = 0.2.cdouble 12 | x2 {.global.} = 0.8.cdouble 13 | y1 {.global.} = 0.25.cdouble 14 | y2 {.global.} = 0.75.cdouble 15 | f {.global.} = 0.1.cdouble 16 | flags{.global.} = ImPlotDragToolFlags.None 17 | igCheckboxFlags("NoCursors", flags.pu32, ImPlotDragToolFlags.NoCursors.uint32); igSameLine() 18 | igCheckboxFlags("NoFit", flags.pu32, ImPlotDragToolFlags.NoFit.uint32); igSameLine() 19 | igCheckboxFlags("NoInput", flags.pu32, ImPlotDragToolFlags.NoInputs.uint32) 20 | if ipBeginPlot("##lines", ImVec2(x: -1, y: 0)): 21 | defer: ipEndPlot() 22 | ipSetupAxesLimits(0, 1, 0, 1) 23 | ipDragLineX(0, x1.addr, ImVec4(x: 1, y: 1, z: 1, w: 1), 1, flags) 24 | ipDragLineX(1, x2.addr, ImVec4(x: 1, y: 1, z: 1, w: 1), 1, flags) 25 | ipDragLineY(2, y1.addr, ImVec4(x: 1, y: 1, z: 1, w: 1), 1, flags) 26 | ipDragLineY(3, y2.addr, ImVec4(x: 1, y: 1, z: 1, w: 1), 1, flags) 27 | var 28 | xs: array[1000, cdouble] 29 | ys: array[1000, cdouble] 30 | for i in 0..<1000: 31 | xs[i] = (x2+x1)/2+abs(x2-x1)*(i.cfloat/1000.0f - 0.5f) 32 | ys[i] = (y1+y2)/2+abs(y2-y1)/2*sin(f*i.cfloat/10) 33 | ipPlotLine("Interactive Data", xs.ptz, ys.ptz, 1000) 34 | ipDragLineY(120482, f.addr, ImVec4(x: 1, y: 0.5f, z: 1, w: 1), 1, flags) 35 | -------------------------------------------------------------------------------- /examples/demo/tools/DragPoints.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------------ 5 | # demo_Tools_DragPoints() 6 | #------------------------ 7 | proc demo_Tools_DragPoints*() = 8 | igBulletText("Click and drag each point.") 9 | var flags{.global.} = ImPlotDragToolFlags.None 10 | igCheckboxFlags("NoCursors", flags.pu32, ImPlotDragToolFlags.NoCursors.uint32); igSameLine() 11 | igCheckboxFlags("NoFit", flags.pu32, ImPlotDragToolFlags.NoFit.uint32); igSameLine() 12 | igCheckboxFlags("NoInput", flags.pu32, ImPlotDragToolFlags.NoInputs.uint32) 13 | var ax_flags = ImPlotAxisFlags.NoTickLabels or ImPlotAxisFlags.NoTickMarks 14 | if ipBeginPlot("##Bezier",ImVec2(x: -1,y: 0),ImPlotFlags.CanvasOnly): 15 | defer: ipEndPlot() 16 | ipSetupAxes(nullptr,nullptr,ax_flags,ax_flags) 17 | ipSetupAxesLimits(0,1,0,1) 18 | var P{.global.} = [ImPlotPoint(x: 0.05f,y: 0.05f), ImPlotPoint(x: 0.2,y: 0.4), ImPlotPoint(x: 0.8,y: 0.6), ImPlotPoint(x: 0.95f,y: 0.95f)] 19 | ipDragPoint(0,P[0].x.addr,P[0].y.addr, ImVec4(x: 0,y: 0.9f,z: 0,w: 1),4,flags) 20 | ipDragPoint(1,P[1].x.addr,P[1].y.addr, ImVec4(x: 1,y: 0.5f,z: 1,w: 1),4,flags) 21 | ipDragPoint(2,P[2].x.addr,P[2].y.addr, ImVec4(x: 0,y: 0.5f,z: 1,w: 1),4,flags) 22 | ipDragPoint(3,P[3].x.addr,P[3].y.addr, ImVec4(x: 0,y: 0.9f,z: 0,w: 1),4,flags) 23 | 24 | var B{.global.}: array[100,ImPlotPoint] 25 | for i in 0..<100: 26 | var t :cdouble = i.float / 99.0 27 | var u :cdouble = 1 - t 28 | var w1:cdouble = u * u * u 29 | var w2:cdouble = 3 * u * u * t 30 | var w3:cdouble = 3 * u * t * t 31 | var w4:cdouble = t * t * t 32 | B[i] = ImPlotPoint(x: w1*P[0].x + w2*P[1].x + w3*P[2].x + w4*P[3].x, y: w1*P[0].y + w2*P[1].y + w3*P[2].y + w4*P[3].y) 33 | 34 | ipSetNextLineStyle(ImVec4(x: 1,y: 0.5f,z: 1,w: 1)) 35 | ipPlotLine("##h1",P[0].x.addr, P[0].y.addr, 2, 0.ImPlotLineFlags, 0, sizeof(ImPlotPoint)) 36 | ipSetNextLineStyle(ImVec4(x: 0,y: 0.5f,z: 1,w: 1)) 37 | ipPlotLine("##h2",P[2].x.addr, P[2].y.addr, 2, 0.ImPlotLineFlags, 0, sizeof(ImPlotPoint)) 38 | ipSetNextLineStyle(ImVec4(x: 0,y: 0.9f,z: 0,w: 1), 2) 39 | ipPlotLine("##bez",B[0].x.addr, B[0].y.addr,100,0.ImPlotLineFlags, 0, sizeof(ImPlotPoint)) 40 | -------------------------------------------------------------------------------- /examples/demo/tools/DragRects.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #----------------------- 6 | # demo_Tools_DragRects() 7 | #----------------------- 8 | proc demo_Tools_DragRects*() = 9 | var 10 | x_data {.global.}: array[512, cfloat] 11 | y_data1{.global.}: array[512, cfloat] 12 | y_data2{.global.}: array[512, cfloat] 13 | y_data3{.global.}: array[512, cfloat] 14 | sampling_freq{.global.} = 44100.cfloat 15 | freq {.global.} = 500.cfloat 16 | 17 | for i in 0..<512: 18 | let t = i.cfloat / sampling_freq 19 | x_data[i] = t 20 | let arg = 2 * 3.14f * freq * t 21 | y_data1[i] = sin(arg) 22 | y_data2[i] = y_data1[i] * -0.6f + sin(2 * arg) * 0.4f 23 | y_data3[i] = y_data2[i] * -0.6f + sin(3 * arg) * 0.4f 24 | igBulletText("Click and drag the edges, corners, and center of the rect.") 25 | var 26 | rx = ImPlotRange(min: 0.0025, max: 0.0045) 27 | ry = ImPlotRange(min: 0, max: 0.5) 28 | rect{.global.} : ImPlotRect 29 | flags{.global.} = ImPlotDragToolFlags.None 30 | once: 31 | rect = ImPlotRect(x: rx , y: ry) 32 | 33 | igCheckboxFlags("NoCursors", flags.pu32, ImPlotDragToolFlags.NoCursors.uint32); igSameLine() 34 | igCheckboxFlags("NoFit", flags.pu32, ImPlotDragToolFlags.NoFit.uint32); igSameLine() 35 | igCheckboxFlags("NoInput", flags.pu32, ImPlotDragToolFlags.NoInputs.uint32) 36 | 37 | if ipBeginPlot("##Main", ImVec2(x: -1, y: 150)): 38 | defer: ipEndPlot() 39 | ipSetupAxes(nullptr, nullptr, ImPlotAxisFlags.NoTickLabels, ImPlotAxisFlags.NoTickLabels) 40 | ipSetupAxesLimits(0, 0.01, -1, 1) 41 | ipPlotLine("Signal 1", x_data.ptz, y_data1.ptz, 512) 42 | ipPlotLine("Signal 2", x_data.ptz, y_data2.ptz, 512) 43 | ipPlotLine("Signal 3", x_data.ptz, y_data3.ptz, 512) 44 | ipDragRect(0, rect.x.min.addr, rect.y.min.addr, rect.x.max.addr, rect.y.max.addr, ImVec4(x: 1, y: 0, z: 1, w: 1), flags) 45 | if ipBeginPlot("##rect", ImVec2(x: -1, y: 150), ImPlotFlags.CanvasOnly): 46 | defer: ipEndPlot() 47 | ipSetupAxes(nullptr, nullptr, ImPlotAxisFlags.NoDecorations, ImPlotAxisFlags.NoDecorations) 48 | ipSetupAxesLimits(rect.x.min, rect.x.max, rect.y.min, rect.y.max, ImPlotCond.Always) 49 | ipPlotLine("Signal 1", x_data.ptz, y_data1.ptz, 512) 50 | ipPlotLine("Signal 2", x_data.ptz, y_data2.ptz, 512) 51 | ipPlotLine("Signal 3", x_data.ptz, y_data3.ptz, 512) 52 | -------------------------------------------------------------------------------- /examples/demo/tools/LegendOptions.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | import utils 4 | 5 | #--------------------------- 6 | # demo_Tools_LegendOptions() 7 | #--------------------------- 8 | proc demo_Tools_LegendOptions*() = 9 | var loc{.global.} = ImPlotLocation.East 10 | igCheckboxFlags("North", loc.pu32, ImPlotLocation.North.uint32); igSameLine() 11 | igCheckboxFlags("South", loc.pu32, ImPlotLocation.South.uint32); igSameLine() 12 | igCheckboxFlags("West", loc.pu32, ImPlotLocation.West.uint32); igSameLine() 13 | igCheckboxFlags("East", loc.pu32, ImPlotLocation.East.uint32) 14 | 15 | var flags{.global.} = 0.ImPlotLegendFlags 16 | 17 | CHECKBOX_FLAG(flags, ImPlotLegendFlags.Horizontal) 18 | CHECKBOX_FLAG(flags, ImPlotLegendFlags.Outside) 19 | CHECKBOX_FLAG(flags, ImPlotLegendFlags.Sort) 20 | var pad:array[2,cfloat] 21 | let v = ipGetStyle().legendPadding 22 | pad[0] = v.x 23 | pad[1] = v.y 24 | igSliderFloat2("LegendPadding", pad, 0.0f, 20.0f, "%.0f") 25 | igSliderFloat2("LegendInnerPadding", pad, 0.0f, 10.0f, "%.0f") 26 | igSliderFloat2("LegendSpacing", pad, 0.0f, 5.0f, "%.0f") 27 | 28 | if ipBeginPlot("##Legend",ImVec2(x: -1,y: 0)): 29 | defer: ipEndPlot() 30 | ipSetupLegend(loc, flags) 31 | var 32 | data1{.global.} = WaveData(X: 0.001, Amp:0.2, Freq: 4, Offset: 0.2) 33 | data2{.global.} = WaveData(X: 0.001, Amp:0.2, Freq: 4, Offset: 0.4) 34 | data3{.global.} = WaveData(X: 0.001, Amp:0.2, Freq: 4, Offset: 0.6) 35 | data4{.global.} = WaveData(X: 0.001, Amp:0.2, Freq: 4, Offset: 0.8) 36 | data5{.global.} = WaveData(X: 0.001, Amp:0.2, Freq: 4, Offset: 1.0) 37 | 38 | ipPlotLineG("Item B", utils.SawWave, data1.addr, 1000) #// "Item B" added to legend 39 | ipPlotLineG("Item A##IDText", utils.SawWave, data2.addr, 1000) #// "Item A" added to legend, text after ## used for ID only 40 | ipPlotLineG("##NotListed", utils.SawWave, data3.addr, 1000) #// plotted, but not added to legend 41 | ipPlotLineG("Item C", utils.SawWave, data4.addr, 1000) #// "Item C" added to legend 42 | ipPlotLineG("Item C", utils.SawWave, data5.addr, 1000) #// combined with previous "Item C" 43 | -------------------------------------------------------------------------------- /examples/demo/tools/LegendPopups.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | 5 | #-------------------------- 6 | # demo_ToolsLegendPopups() 7 | #-------------------------- 8 | proc demo_Tools_LegendPopups*() = 9 | igBulletText("You can implement legend context menus to inject per-item controls and widgets.") 10 | igBulletText("Right click the legend label/icon to edit custom item attributes.") 11 | var 12 | frequency{.global.} = 0.1f 13 | amplitude{.global.} = 0.5f 14 | color {.global.} = ImVec4(x: 1,y: 1,z: 0,w: 1) 15 | alpha {.global.} = 1.0f 16 | line {.global.} = false 17 | thickness{.global.} = 1.cfloat 18 | markers {.global.} = false 19 | shaded {.global.} = false 20 | 21 | var vals{.global.} :array[101,cfloat] 22 | for i in 0..<101: 23 | vals[i] = amplitude * sin(frequency * i.cfloat) 24 | 25 | if ipBeginPlot("Right Click the Legend"): 26 | defer: ipEndPlot() 27 | ipSetupAxesLimits(0,100,-1,1) 28 | #// rendering logic 29 | ipPushStyleVar(ImPlotStyleVar.FillAlpha, alpha) 30 | if not line: 31 | ipSetNextFillStyle(color) 32 | ipPlotBars("Right Click Me", vals.ptz, 101) 33 | else: 34 | if markers: ipSetNextMarkerStyle(ImPlotMarker.Square) 35 | ipSetNextLineStyle(color, thickness) 36 | ipPlotLine("Right Click Me", vals.ptz, 101) 37 | if shaded: ipPlotShaded("Right Click Me",vals.ptz,101) 38 | ipPopStyleVar() 39 | #// custom legend context menu 40 | if ipBeginLegendPopup("Right Click Me") : 41 | defer: ipEndLegendPopup() 42 | igSliderFloat("Frequency",frequency.addr,0,1,"%0.2f") 43 | igSliderFloat("Amplitude",amplitude.addr,0,1,"%0.2f") 44 | igSeparator() 45 | var col = [color.x,color.y,color.z] 46 | igColorEdit3("Color",col) 47 | color.x = col[0]; color.y = col[1]; color.z = col[2] 48 | igSliderFloat("Transparency",alpha.addr,0,1,"%.2f") 49 | igCheckbox("Line Plot", line.addr) 50 | if line: 51 | igSliderFloat("Thickness", thickness.addr, 0, 5) 52 | igCheckbox("Markers", markers.addr) 53 | igCheckbox("Shaded",shaded.addr) 54 | -------------------------------------------------------------------------------- /examples/demo/tools/OffsetAndStride.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | import utils 5 | 6 | #----------------------------- 7 | # demo_Tools_OffsetAndStride() 8 | #----------------------------- 9 | proc demo_Tools_OffsetAndStride*() = 10 | const 11 | k_circles = 11 12 | k_points_per = 50 13 | k_size = 2 * k_points_per * k_circles 14 | var interleaved_data{.global.}:array[k_size,cdouble] 15 | for p in 0.. 0: 42 | ipSetNextMarkerStyle(ImPlotMarker.Square, 6) 43 | ipPlotScatter("Centroid", centroid.x.addr, centroid.y.addr, 1) 44 | if igIsMouseClicked(ipGetInputMap().selectCancel): 45 | ipCancelPlotSelection() 46 | rects.add(select) 47 | for i in 0.. 0: 51 | ipSetNextMarkerStyle(ImPlotMarker.Square, 6) 52 | ipPlotScatter("Centroid", centroid.x.addr, centroid.y.addr, 1) 53 | ipDragRect(i, rects[i].x.min.addr, rects[i].y.min.addr 54 | , rects[i].x.max.addr, rects[i].y.max.addr 55 | , ImVec4(x: 1, y: 0, z: 1, w: 1)) 56 | ipGetPlotLimitsNonUDT(limits.addr) 57 | -------------------------------------------------------------------------------- /examples/demo/tools/Tags.nim: -------------------------------------------------------------------------------- 1 | import imgui 2 | import implot 3 | 4 | #------------------ 5 | # Demo_Tools_Tags() 6 | #------------------ 7 | proc demo_Tools_Tags*() = 8 | var 9 | show{.global.} = true 10 | igCheckbox("Show Tags",show.addr) 11 | if ipBeginPlot("##Tags"): 12 | defer: ipEndPlot() 13 | ipSetupAxis(ImAxis.X2) 14 | ipSetupAxis(ImAxis.Y2) 15 | if show: 16 | ipTagX(0.25, ImVec4(x: 1,y: 1,z: 0,w: 1)) 17 | ipTagY(0.75, ImVec4(x: 1,y: 1,z: 0,w: 1)) 18 | var drag_tag{.global.} = 0.25.cdouble 19 | ipDragLineY(0,drag_tag.addr,ImVec4(x: 1,y: 0,z: 0,w: 1),1,ImPlotDragToolFlags.NoFit) 20 | ipTagY(drag_tag, ImVec4(x: 1,y: 0,z: 0,w: 1), "Drag") 21 | ipSetAxes(ImAxis.X2, ImAxis.Y2) 22 | ipTagX(0.5, ImVec4(x: 0,y: 1,z: 1,w: 1), "%s", "MyTag") 23 | ipTagY(0.5, ImVec4(x: 0,y: 1,z: 1,w: 1), "Tag: %d", 42) 24 | -------------------------------------------------------------------------------- /examples/demo/utils.nim: -------------------------------------------------------------------------------- 1 | import std/[math] 2 | import imgui 3 | import implot 4 | import std/random 5 | export random.rand 6 | 7 | #---------- 8 | # snprintf 9 | #---------- 10 | #proc snprintf*(s: cstring, n: cint, fmt: cstring, count: cint): cint {.importc, 11 | proc snprintf*(s: cstring): cint {.importc, 12 | header: "", varargs.} 13 | 14 | const IMPLOT_AUTO_COL* = ImVec4(x: 0, y: 0, z: 0, w: -1) 15 | 16 | #define CHECKBOX_FLAG(flags, flag) ImGui::CheckboxFlags(#flag, (unsigned int*)&flags, flag) 17 | template CHECKBOX_FLAG*(flags,flag:untyped) = 18 | igCheckboxFlags(($flag).cstring,flags.pu32,flag.uint32) 19 | 20 | const RAND_MAX* = 0x7FFF.int 21 | template RandomRange*[T](vmin, vmax: T): T = 22 | let scale: T = T(rand(RAND_MAX)) / T(RAND_MAX) 23 | vmin + scale * (vmax - vmin) 24 | 25 | proc RandomColor*(): ImVec4 = 26 | result.x = RandomRange(0.0f,1.0f) 27 | result.y = RandomRange(0.0f,1.0f) 28 | result.z = RandomRange(0.0f,1.0f) 29 | result.w = 1.0f 30 | 31 | #// utility structure for realtime plot 32 | #----------------- 33 | # ScrollingBuffer TODO: Memory managemant 34 | #----------------- 35 | type 36 | ScrollingBuffer* {.bycopy.} = object 37 | MaxSize*: int32 38 | Offset*: int32 39 | Data*: seq[ImVec2] 40 | 41 | proc newScrollingBuffer*(max_size: int32 = 2000): ScrollingBuffer = 42 | #result.new 43 | result.MaxSize = max_size 44 | result.Offset = 0 45 | result.Data = newSeqOfCap[ImVec2](max_size) 46 | 47 | proc AddPoint*(self: var ScrollingBuffer, x, y: cfloat) = 48 | if self.Data.len < self.MaxSize: 49 | self.Data.add ImVec2(x: x, y: y) 50 | else: 51 | self.Data[self.Offset] = ImVec2(x: x, y: y) 52 | self.Offset = (self.Offset + 1) mod self.MaxSize 53 | 54 | proc Erase*(self: var ScrollingBuffer) = 55 | if self.Data.len > 0: 56 | self.Data = @[] #self.Data.shrink(0); TODO 57 | self.Offset = 0 58 | 59 | #// utility structure for realtime plot 60 | #--------------- 61 | # RollingBuffer TODO: Memory mangagement 62 | #--------------- 63 | type 64 | RollingBuffer* {.bycopy.} = object 65 | Span*: cfloat 66 | Data*: seq[ImVec2] 67 | 68 | proc newRollingBuffer*(): RollingBuffer = 69 | #result.new 70 | result.Span = 10.0f 71 | result.Data = newSeqOfCap[ImVec2](2000) 72 | 73 | proc AddPoint*(self: var RollingBuffer, x, y: cfloat) = 74 | var xmod = x mod self.Span 75 | if (self.Data.len > 0) and (xmod < self.Data[self.Data.len - 1].x): 76 | self.Data = @[] #self.Data.shrink(0); TODO 77 | self.Data.add ImVec2(x: xmod, y: y) 78 | 79 | #----------- 80 | # sparkline 81 | #----------- 82 | proc sparkline*(id: cstring, values: ptr cfloat, count: int32, min_v: cfloat, 83 | max_v: cfloat, offset: int32, col: ImVec4, size: ImVec2) = 84 | ipPushStyleVar(ImPlotStyleVar.PlotPadding, ImVec2(x: 0, y: 0)) 85 | if ipBeginPlot(id, size, ImPlotFlags.CanvasOnly or ImPlotFlags.NoChild): 86 | defer: ipEndPlot() 87 | ipSetupAxes(nullptr, nullptr, ImPlotAxisFlags.NoDecorations, 88 | ImPlotAxisFlags.NoDecorations) 89 | ipSetupAxesLimits(0, (count - 1).cdouble, min_v, max_v, ImPlotCond.Always) 90 | ipSetNextLineStyle(col) 91 | ipSetNextFillStyle(col, 0.25) 92 | ipPlotLine(id, values, count, 1, 0, ImPlotLineFlags.Shaded, offset) 93 | ipPopStyleVar() 94 | 95 | #[ from cimplot.h 96 | //ImPlotPoint getters manually wrapped use this 97 | typedef void *(*ImPlotPoint_getter)(void* data, int idx, ImPlotPoint *point) 98 | ]# 99 | 100 | type 101 | WaveData* {.bycopy.} = object 102 | X*, Amp*, Freq*, Offset*: cdouble 103 | 104 | #---------- 105 | # Sinewave 106 | #---------- 107 | proc Sinewave*(data: pointer, idx: cint, point: ptr ImPlotPoint): pointer {.cdecl.} = 108 | let f = cast[ptr cfloat](data)[] 109 | point.x = idx.cfloat 110 | point.y = sin(f * idx.cfloat) 111 | 112 | #----------- 113 | # Sinewave2 114 | #----------- 115 | proc Sinewave2*(data: pointer, idx: cint, point: ptr ImPlotPoint): pointer {.cdecl.} = 116 | let wd = cast[ptr WaveData](data)[] 117 | let x = idx.cdouble * wd.X 118 | point.x = x 119 | point.y = wd.Offset + wd.Amp * sin(2 * 3.14 * wd.Freq * x) 120 | 121 | #----------- 122 | # SawWave() 123 | #----------- 124 | proc SawWave*(data: pointer, idx: cint, point: ptr ImPlotPoint): pointer {.cdecl.} = 125 | let wd = cast[ptr WaveData](data)[] 126 | let x = idx.cdouble * wd.X 127 | point.x = x 128 | point.y = wd.Offset + wd.Amp * (-2 / 3.14 * arctan(cos(3.14 * wd.Freq * x) / sin(3.14 * wd.Freq * x))) 129 | 130 | #-------------- 131 | # FindCentroid 132 | #-------------- 133 | proc FindCentroid*(data: seq[ImPlotPoint], bounds:ImPlotRect , cnt: var int): ImPlotPoint = 134 | var 135 | avg: ImPlotPoint 136 | bounds_fixed: ImPlotRect 137 | cnt = 0 138 | bounds_fixed.x.min = if bounds.x.min < bounds.x.max : bounds.x.min else: bounds.x.max 139 | bounds_fixed.x.max = if bounds.x.min < bounds.x.max : bounds.x.max else: bounds.x.min 140 | bounds_fixed.y.min = if bounds.y.min < bounds.y.max : bounds.y.min else: bounds.y.max 141 | bounds_fixed.y.max = if bounds.y.min < bounds.y.max : bounds.y.max else: bounds.y.min 142 | for i in 0.. 0: 148 | avg.x = avg.x / cnt.cdouble 149 | avg.y = avg.y / cnt.cdouble 150 | return avg 151 | 152 | #---------------- 153 | # StyleSeaborn 154 | #---------------- 155 | proc StyleSeaborn*() = 156 | const ImVec4 = proc(x: float32, y: float32, z: float32, w: float32): ImVec4 = ImVec4(x: x, y: y, z: z, w: w) 157 | const ImVec2 = proc(x: float32, y: float32): ImVec2 = ImVec2(x: x, y: y) 158 | var style = ipGetStyle() 159 | 160 | style.colors[Line.uint32] = IMPLOT_AUTO_COL 161 | style.colors[Fill.uint32] = IMPLOT_AUTO_COL 162 | style.colors[MarkerOutline.uint32] = IMPLOT_AUTO_COL 163 | style.colors[MarkerFill.uint32] = IMPLOT_AUTO_COL 164 | style.colors[ErrorBar.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f) 165 | style.colors[ImPlotCol.FrameBg.uint32] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f) 166 | style.colors[PlotBg.uint32] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f) 167 | style.colors[PlotBorder.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f) 168 | style.colors[LegendBg.uint32] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f) 169 | style.colors[LegendBorder.uint32] = ImVec4(0.80f, 0.81f, 0.85f, 1.00f) 170 | style.colors[LegendText.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f) 171 | style.colors[TitleText.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f) 172 | style.colors[InlayText.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f) 173 | style.colors[AxisText.uint32] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f) 174 | style.colors[AxisGrid.uint32] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f) 175 | style.colors[AxisBgHovered.uint32] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f) 176 | style.colors[AxisBgActive.uint32] = ImVec4(0.92f, 0.92f, 0.95f, 0.75f) 177 | style.colors[Selection.uint32] = ImVec4(1.00f, 0.65f, 0.00f, 1.00f) 178 | style.colors[ImPlotCol.Crosshairs.uint32] = ImVec4(0.23f, 0.10f, 0.64f, 0.50f) 179 | 180 | style.lineWeight = 1.5 181 | style.marker = ImPlotMarker.None.int 182 | style.markerSize = 4 183 | style.markerWeight = 1 184 | style.fillAlpha = 1.0f 185 | style.errorBarSize = 5 186 | style.errorBarWeight = 1.5f 187 | style.digitalBitHeight = 8 188 | style.digitalBitGap = 4 189 | style.plotBorderSize = 0 190 | style.minorAlpha = 1.0f 191 | style.majorTickLen = ImVec2(0, 0) 192 | style.minorTickLen = ImVec2(0, 0) 193 | style.majorTickSize = ImVec2(0, 0) 194 | style.minorTickSize = ImVec2(0, 0) 195 | style.majorGridSize = ImVec2(1.2f, 1.2f) 196 | style.minorGridSize = ImVec2(1.2f, 1.2f) 197 | style.plotPadding = ImVec2(12, 12) 198 | style.labelPadding = ImVec2(5, 5) 199 | style.legendPadding = ImVec2(5, 5) 200 | style.mousePosPadding = ImVec2(5, 5) 201 | style.plotMinSize = ImVec2(300, 225) 202 | 203 | #-------------- 204 | # BinarySearch 205 | #-------------- 206 | proc BinarySearch*[T](arr:openArray[T], l:int, r:int, x:T):int = 207 | if r >= l: 208 | var mid = l + (r - l) div 2 209 | if arr[mid] == x: 210 | return mid 211 | if arr[mid] > x: 212 | return BinarySearch(arr, l, mid - 1, x); 213 | return BinarySearch(arr, mid + 1, r, x); 214 | return -1 215 | 216 | type ImU32 = cuint 217 | # convert RR,GG,BB,AA -> AA,BB,GG,RR 218 | template ImCol32*(r, g, b, a: untyped): ImU32 = 219 | (a.uint32 shl 24) or (b.uint32 shl 16) or (g.uint32 shl 8) or r.uint32 220 | # convert RR,GG,BB -> AA,BB,GG,RR 221 | template ImCol32*(r, g, b: untyped): ImU32{.used.} = 222 | (0xff.uint32 shl 24) or (b.uint32 shl 16) or (g.uint32 shl 8) or r.uint32 223 | 224 | #----------------- 225 | # PlotCandlestick 226 | #----------------- 227 | proc PlotCandlestick*(label_id:cstring, xs: openArray[cdouble], opens: openArray[cdouble], closes: openArray[cdouble], lows: openArray[cdouble], highs: openArray[cdouble], count:int, tooltip: bool, width_percent: cfloat, bullCol: ImVec4, bearCol: ImVec4) = #// get ImGui window DrawList 228 | var draw_list = ipGetPlotDrawList() 229 | #// calc real value width 230 | var half_width:cdouble = if count > 1 : (xs[1] - xs[0]) * width_percent.cdouble 231 | else: width_percent.cdouble 232 | #// custom tool 233 | if ipIsPlotHovered() and tooltip: 234 | var mouse:ImPlotPoint 235 | ipGetPlotMousePosNonUDT(mouse.addr) 236 | var tm,tm2:ImPlotTime 237 | fromDoubleNonUDT(tm2.addr,mouse.x) 238 | ipRoundTimeNonUDT(tm.addr,tm2, ImPlotTimeUnit.Day) 239 | mouse.x = tm.addr.toDouble() 240 | var pt:ImVec2 241 | ipPlotToPixelsNonUDT2(pt.addr,mouse.x - half_width * 1.5, mouse.y) 242 | var tool_l = pt.x 243 | ipPlotToPixelsNonUDT2(pt.addr,mouse.x + half_width * 1.5, mouse.y) 244 | var tool_r = pt.x 245 | ipGetPlotPosNonUDT(pt.addr) 246 | var tool_t = pt.y 247 | ipGetPlotSizeNonUDT(pt.addr) 248 | var tool_b = tool_t + pt.y 249 | ipPushPlotClipRect() 250 | draw_list.addRectFilled(ImVec2(x: tool_l, y: tool_t), ImVec2(x: tool_r, y: tool_b), IM_COL32(128,128,128,64)) 251 | ipPopPlotClipRect() 252 | #// find mouse location index 253 | var idx = BinarySearch(xs, 0, count - 1, mouse.x) 254 | #// render tool tip (won't be affected by plot clip rect) 255 | if idx != -1: 256 | igBeginTooltip() 257 | var buff:array[32,cchar] 258 | var tm:ImPlotTime 259 | fromDoubleNonUDT(tm.addr,xs[idx]) 260 | ipFormatDate(tm,buff.ptz.cstringCast,32,ImPlotDateFmt.DayMoYr,ipGetStyle().useISO8601) 261 | igText("Day: %s", buff) 262 | igText("Open: $%.2f", opens[idx]) 263 | igText("Close: $%.2f", closes[idx]) 264 | igText("Low: $%.2f", lows[idx]) 265 | igText("High: $%.2f", highs[idx]) 266 | igEndTooltip() 267 | 268 | #// begin plot item 269 | if ipBeginItem(label_id): 270 | defer: ipEndItem() 271 | #// override legend icon color 272 | ipGetCurrentItem().color = IM_COL32(64,64,64,255) 273 | #// fit data if requested 274 | if ipFitThisFrame(): 275 | for i in 0.. closes[i] : bearCol else: bullCol) 289 | draw_list.addLine(low_pos, high_pos, color) 290 | draw_list.addRectFilled(open_pos, close_pos, color) 291 | 292 | #----------------- 293 | # MetricFormatter 294 | #----------------- 295 | var MetricFormatter* = proc(value:cdouble, buff:cstring, size:int, data:pointer): int {.cdecl.} = 296 | var unit = cast[ptr cchar](data) 297 | var v = [1000000000.cdouble,1000000,1000,1,0.001,0.000001,0.000000001] 298 | const p = ["G".cstring,"M","k","","m","u","n"] 299 | if value == 0: 300 | return snprintf(buff,size.cint,"0 %s", unit); 301 | for i in 0..<7: 302 | if abs(value) >= v[i]: 303 | return snprintf(buff,size,"%g %s%s",value/v[i],p[i],unit); 304 | return snprintf(buff,size,"%g %s%s",value/v[6],p[6],unit); 305 | -------------------------------------------------------------------------------- /img/BarGroups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/BarGroups.png -------------------------------------------------------------------------------- /img/BarPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/BarPlots.png -------------------------------------------------------------------------------- /img/BarStacks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/BarStacks.png -------------------------------------------------------------------------------- /img/CustomDataAndGetters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/CustomDataAndGetters.png -------------------------------------------------------------------------------- /img/DigitalPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/DigitalPlots.png -------------------------------------------------------------------------------- /img/DragAndDrop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/DragAndDrop.png -------------------------------------------------------------------------------- /img/DragRects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/DragRects.png -------------------------------------------------------------------------------- /img/ErrorBars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/ErrorBars.png -------------------------------------------------------------------------------- /img/FilledLinePlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/FilledLinePlots.png -------------------------------------------------------------------------------- /img/HeatMaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/HeatMaps.png -------------------------------------------------------------------------------- /img/Histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/Histogram.png -------------------------------------------------------------------------------- /img/Images.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/Images.png -------------------------------------------------------------------------------- /img/InfiniteLines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/InfiniteLines.png -------------------------------------------------------------------------------- /img/ItemSharing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/ItemSharing.png -------------------------------------------------------------------------------- /img/LinePlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/LinePlots.png -------------------------------------------------------------------------------- /img/LogScale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/LogScale.png -------------------------------------------------------------------------------- /img/MarkersAndText.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/MarkersAndText.png -------------------------------------------------------------------------------- /img/MultipleAxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/MultipleAxes.png -------------------------------------------------------------------------------- /img/NaNValues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/NaNValues.png -------------------------------------------------------------------------------- /img/OffsetAndStride.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/OffsetAndStride.png -------------------------------------------------------------------------------- /img/PieCharts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/PieCharts.png -------------------------------------------------------------------------------- /img/RealTimePlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/RealTimePlots.png -------------------------------------------------------------------------------- /img/ScatterPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/ScatterPlots.png -------------------------------------------------------------------------------- /img/ShadedPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/ShadedPlots.png -------------------------------------------------------------------------------- /img/SimplePlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/SimplePlots.png -------------------------------------------------------------------------------- /img/StairstepPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/StairstepPlots.png -------------------------------------------------------------------------------- /img/StemPlots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/StemPlots.png -------------------------------------------------------------------------------- /img/Tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/Tables.png -------------------------------------------------------------------------------- /img/nim_implot-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dinau/nim_implot/c390af886c97c537b49753087385a8a41a787388/img/nim_implot-demo.png -------------------------------------------------------------------------------- /imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][ImPlot Demo] 7 | Pos=594,6 8 | Size=600,750 9 | Collapsed=0 10 | 11 | [Window][All Demos have been written in Nim language.] 12 | Pos=15,10 13 | Size=580,760 14 | Collapsed=0 15 | 16 | [Window][All Demos have been written in Nim language. [ Nim-1.6.14 ]] 17 | Pos=19,3 18 | Size=580,487 19 | Collapsed=0 20 | 21 | [Window][Dear ImGui Demo] 22 | Pos=650,20 23 | Size=550,680 24 | Collapsed=0 25 | 26 | [Window][All Demos have been written in Nim language. [ Nim-1.6.18 ]] 27 | Pos=11,9 28 | Size=580,603 29 | Collapsed=0 30 | 31 | [Window][All Demos have been written in Nim language. [ Nim-2.0.2 ]] 32 | Pos=21,15 33 | Size=580,509 34 | Collapsed=0 35 | 36 | [Window][All Demos have been written in Nim language. [ Nim-2.0.8 ]] 37 | Pos=7,7 38 | Size=580,400 39 | Collapsed=0 40 | 41 | [Table][0xDB58FA2F,3] 42 | RefScale=13 43 | Column 0 Width=75 44 | Column 1 Width=75 45 | Column 2 Weight=1.0000 46 | 47 | -------------------------------------------------------------------------------- /implot.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.16.7" 4 | author = "dinau" 5 | description = "ImPlot bindings for Nim" 6 | license = "MIT" 7 | srcDir = "src" 8 | skipDirs = @["tests","examples","img"] 9 | 10 | # Dependencies 11 | 12 | requires "nim >= 1.6.0" # Depends on [HoleEnumConv] warning 13 | requires "nimgl >= 1.3.2" 14 | requires "https://github.com/dinau/nimgl-imgui == 1.89.9.4" 15 | 16 | 17 | import std/[strutils] 18 | task gen, "Generate bindings from source": 19 | exec("nim c -r tools/generator.nim") 20 | 21 | let opt = "-d:strip" 22 | task test, "Create window with implot demo": 23 | exec("nim cpp -r $# examples/demo/imPlotDemo.nim" % [opt]) 24 | -------------------------------------------------------------------------------- /src/implot/private/ncimplot.h: -------------------------------------------------------------------------------- 1 | #ifndef NCIMGUI_H 2 | #define NCIMGUI_H 3 | 4 | #include "implot.h" 5 | #include "implot_internal.h" 6 | #include "cimplot.h" 7 | 8 | // Should open an issue in cimplot about this... 9 | // This isn't best practice in c++ so bear with me. 10 | #endif /* NCIMGUI_H */ 11 | 12 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = imPlotTest 2 | OPT += --passC:-static --passL:-static 3 | all: 4 | nim cpp -d:release -d:strip $(OPT) --nimcache:.nimcache $(TARGET).nim 5 | 6 | run: all 7 | #rm imgui.ini 8 | ./$(TARGET) 9 | 10 | gen: 11 | (cd ..;nimble gen) 12 | 13 | clean: 14 | -rm -fr .nimcache 15 | -rm $(TARGET).exe 16 | -------------------------------------------------------------------------------- /tests/config.nims: -------------------------------------------------------------------------------- 1 | switch("path", "$projectDir/../src") 2 | 3 | switch "warning","HoleEnumConv:off" 4 | 5 | # Compilation options 6 | switch "define","release" 7 | switch "nimcache",".nimcache" 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/imPlotTest.nim: -------------------------------------------------------------------------------- 1 | # Modified: for ImPlot by dinau 2023/09 2 | # Copyright 2019, NimGL contributors. 3 | 4 | import std/[math, random, sugar, sequtils] 5 | import imgui, imgui/[impl_opengl, impl_glfw] 6 | import nimgl/[opengl, glfw] 7 | import implot 8 | 9 | #--------------------- 10 | # Forward definitions 11 | #--------------------- 12 | proc imPlotDemoTabs() 13 | proc demo_LinePlots() 14 | proc demo_SimplePlot() 15 | proc demo_Histogram() 16 | proc demo_simpleImGui() 17 | 18 | var 19 | showDemoImplot: bool = true 20 | showDemoImgui: bool = false 21 | 22 | #---------- 23 | # main() 24 | #---------- 25 | proc main() = 26 | doAssert glfwInit() 27 | defer: glfwTerminate() 28 | 29 | glfwWindowHint(GLFWContextVersionMajor, 3) 30 | glfwWindowHint(GLFWContextVersionMinor, 3) 31 | glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE) 32 | glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE) 33 | glfwWindowHint(GLFWResizable, GLFW_TRUE) 34 | 35 | var glfwWindow: GLFWWindow = glfwCreateWindow(1080, 800) 36 | if glfwWindow == nil: 37 | quit(-1) 38 | glfwWindow.makeContextCurrent() 39 | defer: glfwWindow.destroyWindow() 40 | 41 | glfwSwapInterval(1) # Enable vsync 42 | 43 | doAssert glInit() 44 | 45 | let context = igCreateContext() 46 | defer: context.igDestroyContext() 47 | 48 | # setup ImPlot 49 | var imPlotContext = ipCreateContext() 50 | defer: imPlotContext.ipDestroyContext() 51 | 52 | doAssert igGlfwInitForOpenGL(glfwWindow, true) 53 | defer: igGlfwShutdown() 54 | # 55 | doAssert igOpenGL3Init() 56 | defer: igOpenGL3Shutdown() 57 | 58 | #implot.igStyleColorsCherry() 59 | #imgui.igStyleColorsCherry() 60 | 61 | #----------- 62 | # Main loop 63 | #----------- 64 | while not glfwWindow.windowShouldClose: 65 | glfwPollEvents() 66 | 67 | igOpenGL3NewFrame() 68 | igGlfwNewFrame() 69 | igNewFrame() 70 | 71 | if showDemoImgui: 72 | igShowDemoWindow(showDemoImgui.addr) 73 | if showDemoImplot: 74 | ipShowDemoWindow(showDemoImplot.addr) 75 | 76 | #------------- 77 | # Demo Window 78 | #------------- 79 | block: 80 | igSetNextWindowPos(ImVec2(x: 25, y: 25), FirstUseEver) 81 | igSetNextWindowSize(ImVec2(x: 400, y: 400), FirstUseEver) 82 | igBegin("This Demos have been written in Nim language.") 83 | defer: igEnd() 84 | igText("Application average %.3f ms/frame (%.1f FPS)", 85 | 1000.0f / igGetIO().framerate, igGetIO().framerate) 86 | # ImPlot test window 87 | imPlotDemoTabs() 88 | 89 | igRender() 90 | glClearColor(0.45f, 0.55f, 0.60f, 1.00f) 91 | glClear(GL_COLOR_BUFFER_BIT) 92 | igOpenGL3RenderDrawData(igGetDrawData()) 93 | glfwWindow.swapBuffers() 94 | 95 | #--------------- 96 | # demoHeaeder() 97 | #--------------- 98 | proc demoHeader(label: string, demo: proc()) = 99 | if igTreeNodeEx(label.cstring): 100 | demo() 101 | igTreePop() 102 | 103 | #------------------ 104 | # imPlotDemoTabs() 105 | #------------------ 106 | proc imPlotDemoTabs() = 107 | if igBeginTabBar("ImPlotDemoTabs"): 108 | defer: igEndTabBar() 109 | if (igBeginTabItem("ImPlot")): 110 | defer: igEndTabItem() 111 | demoHeader("Simple Plots", demo_SimplePlot) 112 | demoHeader("Line Plots", demo_LinePlots) 113 | demoHeader("Histogram", demo_Histogram) 114 | if (igBeginTabItem("ImGui")): 115 | defer: igEndTabItem() 116 | demoHeader("Simple demo", demo_simpleImGui) 117 | 118 | #------------------ 119 | # demo_LinePlots() 120 | #------------------ 121 | proc demo_LinePlots() = 122 | var 123 | xs1{.global.}: array[1001, float] 124 | ys1{.global.}: array[1001, float] 125 | for i in 0..<1001: 126 | xs1[i] = i.float * 0.001f 127 | ys1[i] = 0.5f + 0.5f * sin(50 * (xs1[i] + igGetTime().float / 10)) 128 | var 129 | xs2{.global.}: array[20, float64] 130 | ys2{.global.}: array[20, float64] 131 | for i in 0..<20: 132 | xs2[i] = i.float * 1/19.0f 133 | ys2[i] = xs2[i] * xs2[i] 134 | if ipBeginPlot("Line Plots"): 135 | defer: ipEndPlot() 136 | ipSetupAxes("x", "y") 137 | ipPlotLine("f(x)", addr xs1[0], addr ys1[0], 1001) 138 | ipSetNextMarkerStyle(Circle) 139 | ipPlotLine("g(x)", addr xs2[0], addr ys2[0], 20, Segments) 140 | 141 | #------------------ 142 | # demo_Histogram() 143 | #------------------ 144 | proc demo_Histogram() = 145 | const 146 | mu: double = 5 147 | sigma: double = 2 148 | var 149 | dist {.global.}: seq[cfloat64] 150 | hist_flags{.global.} = Density.int32 151 | bins {.global.}: ImPlotBin = cast[ImPlotBin](50) 152 | once: 153 | discard initRand() 154 | dist = collect(for i in 0..<10000: gauss(mu, sigma).cfloat64) 155 | 156 | igSetNextItemWidth(200) 157 | if igRadioButton("Sqrt", bins == Sqrt): bins = Sqrt 158 | igSameLine() 159 | if igRadioButton("Sturges", bins == Sturges): bins = Sturges 160 | igSameLine() 161 | if igRadioButton("Rice", bins == Rice): bins = Rice 162 | igSameLine() 163 | if igRadioButton("Scott", bins == Scott): bins = Scott 164 | #igSameLine() 165 | if igRadioButton("N Bins", bins.int32 >= 0): bins = cast[ImPlotBin](50) 166 | if bins.int32 >= 0: 167 | igSameLine() 168 | igSetNextItemWidth(200) 169 | igSliderInt("##Bins", cast[ptr int32](addr bins), 1, 100) 170 | 171 | igCheckboxFlags("Horizontal", addr hist_flags, ImPlotHistogramFlags.Horizontal.int32) 172 | igSameLine() 173 | igCheckboxFlags("Density", addr hist_flags, Density.int32) 174 | igSameLine() 175 | igCheckboxFlags("Cumulative", addr hist_flags, Cumulative.int32) 176 | 177 | var frange{.global.} = false 178 | igCheckbox("Range", addr frange) 179 | var 180 | rmin{.global.}: cfloat = -3 181 | rmax{.global.}: cfloat = 13 182 | range1{.global.} = [rmin, rmax] 183 | if frange: 184 | igSameLine() 185 | igSetNextItemWidth(200) 186 | igDragFloat2("##Range", range1, 0.1f, -3, 13) 187 | rmin = range1[0] 188 | rmax = range1[1] 189 | igSameLine() 190 | igCheckboxFlags("Exclude Outliers", addr hist_flags, NoOutliers.int32) 191 | 192 | #static NormalDistribution<10000> dist(mu, sigma) 193 | var 194 | x{.global.}: array[100, double] 195 | y{.global.}: array[100, double] 196 | if 0 != (hist_flags and Density.int32): 197 | for i in 0..<100: 198 | x[i] = -3 + 16 * i.double / 99.0 199 | y[i] = exp( - (x[i] - mu) * (x[i] - mu) / (2 * sigma * sigma)) / (sigma * sqrt(2 * 3.141592653589793238)) 200 | if 0 != (hist_flags and Cumulative.int32): 201 | for i in 1..<100: 202 | y[i] += y[i-1] 203 | for i in 0..<100: 204 | y[i] /= y[99] 205 | 206 | if ipBeginPlot("##Histograms"): 207 | defer: ipEndPlot() 208 | ipSetupAxes(nil, nil, AutoFit, AutoFit) 209 | const IMPLOT_AUTO_COL = ImVec4(x: 0,y: 0,z: 0,w: -1) 210 | ipSetNextFillStyle(IMPLOT_AUTO_COL,0.5f) 211 | #ipSetNextFillStyle(ImVec4(x: 0, y: 0, z: 0, w: -1), 0.5f) 212 | ipPlotHistogram("Empirical", addr dist[0], 10000.int, bins.int, 213 | 1.0.cfloat64, (if frange: ImPlotRange(min: rmin, max: rmax) else: ImPlotRange()), 214 | hist_flags.ImPlotHistogramFlags) 215 | if (0 != (hist_flags and Density.int32)) and not (0 != (hist_flags and NoOutliers.int32)): 216 | if 0 != (hist_flags and ImPlotHistogramFlags.Horizontal.int32): 217 | ipPlotLine("Theoretical", addr y[0], addr x[0], 100) 218 | else: 219 | ipPlotLine("Theoretical", addr x[0], addr y[0], 100) 220 | 221 | #------------------- 222 | # demo_SimplePlot() 223 | #------------------- 224 | proc demo_SimplePlot() = 225 | var 226 | bar_data{.global.}:seq[cint] 227 | x_data{.global.}:seq[cint] 228 | y_data{.global.}:seq[cint] 229 | once: 230 | discard initRand() 231 | bar_data = collect(for i in 0..10: rand(100).cint) 232 | x_data = collect(for i in 0..10: i.cint) 233 | y_data = x_data.mapIt((it * it).cint) # y = x^2 234 | 235 | if ipBeginPlot("My Plot"): 236 | defer: ipEndPlot() 237 | ipPlotBars("My Bar Plot", addr bar_data[0], bar_data.len) 238 | ipPlotLine("My Line Plot", addr x_data[0], addr y_data[0], xdata.len) 239 | 240 | #-------------------- 241 | # demo_simpleImGui() 242 | #-------------------- 243 | proc demo_simpleImGui() = 244 | var 245 | somefloat{.global.} = 0.0f 246 | counter{.global.} = 0 247 | 248 | igText("This is some useful text.") 249 | igCheckbox("ImPlot Demo Window", showDemoImPlot.addr) 250 | igCheckbox("ImGui Demo Window", showDemoImgui.addr) 251 | igSliderFloat("float", somefloat.addr, 0.0f, 1.0f) 252 | if igButton("Button", ImVec2(x: 0, y: 0)): 253 | counter.inc 254 | igSameLine() 255 | igText("counter = %d", counter) 256 | 257 | #-------- 258 | # main() 259 | #-------- 260 | main() 261 | -------------------------------------------------------------------------------- /tools/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | 2023/09: Modified for ImPlot from 4 | https://github.com/nimgl/imgui, 5 | https://github.com/daniel-j/nimgl-imgui (forked), 6 | by dinau 7 | 8 | Copyright (c) 2019 Leonardo Mariscal 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | -------------------------------------------------------------------------------- /tools/generator.nim: -------------------------------------------------------------------------------- 1 | # Modified for ImPlot by dinau 2023/09 2 | # Written by Leonardo Mariscal , 2019 3 | 4 | import strutils, json, strformat, tables, 5 | algorithm, sets, re, ./utils 6 | import pegs 7 | 8 | var enums: HashSet[string] 9 | var enumsCount: Table[string, int] 10 | 11 | proc decho(str:string){.used.} = 12 | echo str 13 | 14 | proc translateType(name: string): string # translateProc needs this 15 | 16 | proc uncapitalize(str: string): string = 17 | if str.len < 1: 18 | result = "" 19 | else: 20 | result = toLowerAscii(str[0]) & str[1 ..< str.len] 21 | 22 | proc isUpper(str: string): bool = 23 | for c in str: 24 | if not c.isUpperAscii(): 25 | return false 26 | return true 27 | 28 | proc translateProc(name: string): string = 29 | var nameSplit = name.replace(";", "").split("(*)", 1) 30 | let procType = nameSplit[0].translateType() 31 | 32 | nameSplit[1] = nameSplit[1][1 ..< nameSplit[1].len - 1] 33 | var isVarArgs = false 34 | var argsSplit = nameSplit[1].split(',') 35 | var argSeq: seq[tuple[name: string, kind: string]] 36 | var unnamedArgCounter = 0 37 | for arg in argsSplit: 38 | let argPieces = arg.replace(" const", "").rsplit(' ', 1) 39 | if argPieces[0] == "...": 40 | isVarArgs = true 41 | continue 42 | var argName = if argPieces.len == 1: 43 | inc(unnamedArgCounter) 44 | "unamed_arg_{unnamedArgCounter}".fmt 45 | else: 46 | argPieces[1] 47 | var argType = argPieces[0] 48 | if argName.contains('*'): 49 | argType.add('*') 50 | argName = argName.replace("*", "") 51 | if reservedWordsDictionary.contains(argName): 52 | argName = "`{argName}`".fmt 53 | argType = argType.translateType() 54 | argSeq.add((name: argName, kind: argType)) 55 | 56 | result = "proc(" 57 | for arg in argSeq: 58 | result.add("{arg.name}: {arg.kind}, ".fmt) 59 | if argSeq.len > 0: 60 | result = result[0 ..< result.len - 2] 61 | if isVarArgs: 62 | result.add("): {procType} {{.cdecl.}}".fmt) 63 | else: 64 | result.add("): {procType} {{.cdecl, varargs.}}".fmt) 65 | 66 | proc translateArray(name: string): tuple[size: string, name: string] = 67 | let nameSplit = name.rsplit('[', 1) 68 | var arraySize = nameSplit[1] 69 | arraySize = arraySize[0 ..< arraySize.len - 1] 70 | if arraySize.contains("COUNT"): 71 | arraySize = $enumsCount[arraySize] 72 | if arraySize == "(0xFFFF+1)/4096/8": # If more continue to appear automate it 73 | arraySize = "2" 74 | result.size = arraySize 75 | result.name = nameSplit[0] 76 | 77 | proc translateType(name: string): string = 78 | if name.contains("(") and name.contains(")"): 79 | return name.translateProc() 80 | if name == "const char* const[]": 81 | return "ptr cstring" 82 | result = name.replace("const ", "") 83 | result = result.replace("unsigned ", "u") 84 | result = result.replace("signed ", "") 85 | 86 | var depth = result.count('*') 87 | result = result.replace(" ", "") 88 | result = result.replace("*", "") 89 | result = result.replace("&", "") 90 | 91 | result = result.replace("time_t", "int32") 92 | result = result.replace("double", "cdouble") # TODO 93 | result = result.replace("structtm", "tm") 94 | result = result.replace("cfloat64", "cdouble") # TODO 95 | result = result.replace(" int", " int32") 96 | result = result.replace("size_t", "uint") # uint matches pointer size just like size_t 97 | result = result.replace("int3264_t", "int64") 98 | result = result.replace("float", "float32") 99 | result = result.replace("double", "float64") # TODO 100 | result = result.replace("short", "int16") 101 | result = result.replace("_Simple", "") 102 | if result.contains("char") and not result.contains("Wchar"): 103 | if result.contains("uchar"): 104 | result = "uint8" 105 | elif depth > 0: 106 | result = result.replace("char", "cstring") 107 | depth.dec 108 | if result.startsWith("u"): 109 | result = result[1 ..< result.len] 110 | else: 111 | result = result.replace("char", "int8") 112 | if depth > 0 and result.contains("void"): 113 | result = result.replace("void", "pointer") 114 | depth.dec 115 | 116 | result = result.replace("ImBitArrayForNamedKeys", "ImU32") 117 | result = result.replace("ImBitArray", "ImU32") 118 | result = result.replace("ImGuiWindowPtr", "ptr ImGuiWindow") 119 | result = result.replace("ImS8", "int8") # Doing it a little verbose to avoid issues in the future. 120 | result = result.replace("ImS16", "int16") 121 | result = result.replace("ImS32", "int32") 122 | result = result.replace("ImS64", "int64") 123 | result = result.replace("ImU8", "uint8") 124 | result = result.replace("ImU16", "uint16") 125 | result = result.replace("ImU32", "uint32") 126 | result = result.replace("ImU64", "uint64") 127 | result = result.replace("Pair", "ImPair") 128 | result = result.replace("ImFontPtr", "ptr ImFont") 129 | 130 | if result.startsWith("ImVector_"): 131 | result = result["ImVector_".len ..< result.len] 132 | result = "ImVector[{result}]".fmt 133 | 134 | result = result.replace("ImChunkStream_T", "ImChunkStream") 135 | 136 | result = result.replace("ImGuiStorageImPair", "ImGuiStoragePair") 137 | 138 | for d in 0 ..< depth: 139 | result = "ptr " & result 140 | if result == "ptr ptr ImDrawList": 141 | result = "UncheckedArray[ptr ImDrawList]" 142 | 143 | if result == "": 144 | result = "void" 145 | 146 | 147 | proc genEnums(output: var string) = 148 | let file = readFile("src/implot/private/cimplot/generator/output/structs_and_enums.json") 149 | let data = file.parseJson() 150 | 151 | output.add("\n# Enums\ntype\n") 152 | 153 | var tableNamedKeys: Table[string, int] 154 | for name, obj in data["enums"].pairs: 155 | var enumName = name 156 | if enumName.endsWith("_"): 157 | enumName = name[0 ..< name.len - 1] # 末尾のアンダースコアをカット 158 | 159 | output.add(" {enumName}* {{.pure, size: int32.sizeof.}} = enum\n".fmt) 160 | enums.incl(enumName) 161 | var table: Table[int, string] 162 | for data in obj: 163 | var dataName = data["name"].getStr() # ImAxis_X1 164 | let dataValue = data["calc_value"].getInt() # 値は0 165 | dataName = dataName.replace("__", "_") 166 | dataName = dataName.split("_", 1)[1] # dataName = X1 とする 167 | if dataName.endsWith("_"): # X1の末尾にアンダースコアがあれば排除 168 | dataName = dataName[0 ..< dataName.len - 1] 169 | if dataName.match(re"^[0-9]"): # X1の先頭文字が 非数字 なら 170 | dataName = "`\"" & dataName & "\"`" # `"X1"` とする 171 | if dataName.match(re".*COUNT$"): # "COUNT"を含むなら 172 | # enumsCount[ "ImPlotXXX_COUNT" ] = enumの値 とする 173 | enumsCount[data["name"].getStr()] = data["calc_value"].getInt() 174 | #echo data 175 | #continue 176 | if table.hasKey(dataValue): # enum値(=0)が既に存在するなら 177 | echo "Notice: Enum {enumName}.{dataName} already exists as {enumName}.{table[dataValue]} with value {dataValue}, use constant {enumName}_{dataName} to access it".fmt 178 | tableNamedKeys[enumName & "_" & dataName] = dataValue 179 | #tableNamedKeys[ "ImAxis" & "_" & "X1"] = 0 180 | continue 181 | table[dataValue] = dataName # 0に `"X1"` を対応させる 182 | 183 | var tableOrder: OrderedTable[int, string] # Weird error where data is erased if used directly 184 | for k, v in table.pairs: # Sort開始 185 | tableOrder[k] = v 186 | tableOrder.sort(system.cmp) 187 | 188 | for k, v in tableOrder.pairs: # Sort結果を出力 189 | output.add(" {v} = {k}\n".fmt) # X1 = 0 190 | 191 | if tableNamedKeys.len > 0: # 値が重複ものはconst に置き換える 192 | output.add("\n# Duplicate enums as consts\n") 193 | for k, v in tableNamedKeys.pairs: 194 | output.add("const {k}* = {v}\n".fmt) 195 | 196 | proc genTypeDefs(output: var string) = 197 | # Must be run after genEnums 198 | let file = readFile("src/implot/private/cimplot/generator/output/typedefs_dict.json") 199 | let data = file.parseJson() 200 | 201 | output.add("\n# TypeDefs\ntype\n") 202 | 203 | for name, obj in data.pairs: 204 | let ignorable = ["const_iterator", "iterator", "value_type", "ImS8", 205 | "ImS16", "ImS32", "ImS64", "ImU8", "ImU16", "ImU32", 206 | "ImU64", "ImBitArrayForNamedKeys"] 207 | if obj.getStr().startsWith("struct") or enums.contains(name) or ignorable.contains(name): 208 | continue 209 | output.add(" {name}* = {obj.getStr().translateType()}\n".fmt) 210 | 211 | 212 | proc genTypes(output: var string) = 213 | # Does not add a `type` keyword 214 | # Must be run after genEnums 215 | let file = readFile("src/implot/private/cimplot/generator/output/structs_and_enums.json") 216 | let data = file.parseJson() 217 | 218 | output.add("\n") 219 | #output.add(notDefinedStructs) 220 | 221 | for name, obj in data["structs"].pairs: 222 | if name == "Pair" or name == "ImGuiStoragePair" or name == "ImGuiStyleMod" or name == "ImGuiInputEvent": 223 | continue 224 | 225 | if name == "ImDrawChannel": 226 | output.add(" ImDrawChannel* {.importc: \"ImDrawChannel\", implot_header.} = ptr object\n") 227 | continue 228 | 229 | output.add(" {name}* {{.importc: \"{name}\", implot_header.}} = object\n".fmt) 230 | for member in obj: 231 | var memberName = member["name"].getStr() 232 | if memberName == "Ptr": 233 | memberName = "`ptr`" 234 | if memberName == "Type": 235 | memberName = "`type`" 236 | var memberImGuiName = "{{.importc: \"{memberName}\".}}".fmt 237 | if memberName.startsWith("_"): 238 | memberName = memberName[1 ..< memberName.len] 239 | if memberName.isUpper(): 240 | memberName = memberName.normalize() 241 | memberName = memberName.uncapitalize() 242 | 243 | if memberImGuiName.contains('['): 244 | memberImGuiName = memberImGuiName[0 ..< memberImGuiName.find('[')] & "\".}" 245 | 246 | if not memberName.contains("["): 247 | if not member.contains("template_type"): 248 | output.add(" {memberName}* {memberImGuiName}: {member[\"type\"].getStr().translateType()}\n".fmt) 249 | else: 250 | # Assuming all template_type containers are ImVectors 251 | var templateType = member["template_type"].getStr() 252 | if templateType == "ImGui*OrIndex": 253 | templateType = "ImGuiPtrOrIndex" 254 | templateType = templateType.translateType() 255 | 256 | if templateType == "ImGuiTabBar": # Hope I don't regret this hardocoded if 257 | output.add(" {memberName}* {memberImGuiName}: ptr ImPool\n".fmt) 258 | elif templateType == "ImGuiColumns": 259 | output.add(" {memberName}* {memberImGuiName}: ImVectorImGuiColumns\n".fmt) 260 | else: 261 | output.add(" {memberName}* {memberImGuiName}: ImVector[{templateType}]\n".fmt) 262 | continue 263 | 264 | let arrayData = memberName.translateArray() 265 | output.add(" {arrayData[1]}* {memberImGuiName}: array[{arrayData[0]}, {member[\"type\"].getStr().translateType()}]\n".fmt) 266 | 267 | proc genProcs(output: var string) = 268 | let file = readFile("src/implot/private/cimplot/generator/output/definitions.json") 269 | let data = file.parseJson() 270 | 271 | output.add("\n{preProcs}\n".fmt) 272 | 273 | for name, obj in data.pairs: 274 | var isNonUDT = false 275 | var nonUDTNumber = 0 276 | for variation in obj: 277 | if variation.contains("nonUDT"): 278 | nonUDTNumber.inc 279 | isNonUDT = true 280 | if blackListProc.contains(variation["cimguiname"].getStr()): 281 | continue 282 | 283 | # Name 284 | var funcname = "" 285 | if variation.contains("stname") and variation["stname"].getStr() != "": 286 | if variation.contains("destructor"): 287 | funcname = "destroy" 288 | else: 289 | funcname = variation["funcname"].getStr() 290 | else: 291 | funcname = variation["cimguiname"].getStr() 292 | #funcname = funcname.rsplit("_", 1)[1] 293 | 294 | if isNonUDT: 295 | funcname = funcname & "NonUDT" 296 | if nonUDTNumber != 1: 297 | funcname = funcname & $nonUDTNumber 298 | 299 | if variation.contains("constructor"): 300 | if funcname.startsWith("ImVector"): 301 | continue 302 | funcname = "new" & funcname.capitalizeAscii() 303 | 304 | if funcname.isUpper(): 305 | funcname = funcname.normalize() 306 | funcname = funcname.uncapitalize() 307 | 308 | if funcname.startsWith("_"): 309 | funcname = funcname[1 ..< funcname.len] 310 | 311 | if reservedWordsDictionary.contains(funcname): 312 | funcname = "`{funcname}`".fmt 313 | 314 | output.add("proc {funcname}*".fmt) 315 | 316 | var isGeneric = false 317 | var isVarArgs = variation.contains("isvararg") and variation["isvararg"].getBool() 318 | 319 | var argsOutput = "" 320 | # Args 321 | for arg in variation["argsT"]: 322 | var argName = arg["name"].getStr() 323 | var argType = arg["type"].getStr().translateType() 324 | if arg.contains("custom_type"): 325 | let ctype = arg["custom_type"].getStr().split('_') # custom_type = "ImPlotPoint_getter" 326 | argType = ctype[0] & ctype[1][0].toUpperAscii() & ctype[1][1 ..< ctype[1].len] 327 | # argType == "ImPlotPointGetter" 328 | 329 | var argDefault = "" 330 | if variation.contains("defaults") and variation["defaults"].kind == JObject and 331 | variation["defaults"].contains(argName): 332 | argDefault = variation["defaults"][argName].getStr() 333 | argDefault = argDefault.replace("4294967295", "high(uint32)") 334 | argDefault = argDefault.replace("(((ImU32)(255)<<24)|((ImU32)(255)<<16)|((ImU32)(255)<<8)|((ImU32)(255)<<0))", "high(uint32)") 335 | argDefault = argDefault.replace("(((ImU32)(255)<<24)|((ImU32)(0)<<16)|((ImU32)(0)<<8)|((ImU32)(255)<<0))", "4278190335") 336 | argDefault = argDefault.replace("4278190335", "4278190335'u32") 337 | argDefault = argDefault.replace("FLT_MAX", "high(float32)") 338 | argDefault = argDefault.replace("((void*)0)", "nil") 339 | argDefault = argDefault.replace("NULL", "nil") 340 | argDefault = argDefault.replace("-FLT_MIN", "0") 341 | argDefault = argDefault.replace("~0", "-1") 342 | argDefault = argDefault.replace("sizeof(float)", "sizeof(float32).int32") 343 | 344 | argDefault = argDefault.replace("ImS8)" , "int8).int32") # Doing it a little verbose to avoid issues in the future. 345 | argDefault = argDefault.replace("ImS16)", "int16).int32") 346 | argDefault = argDefault.replace("ImS32)", "int32).int32") 347 | argDefault = argDefault.replace("ImS64)", "int64).int32") 348 | argDefault = argDefault.replace("ImU8)" , "uint8).int32") 349 | argDefault = argDefault.replace("ImU16)", "uint16).int32") 350 | argDefault = argDefault.replace("ImU32)", "uint32).int32") 351 | argDefault = argDefault.replace("ImU64)", "uint64).int32") 352 | 353 | if argDefault.startsWith("ImVec"): 354 | let letters = ['x', 'y', 'z', 'w'] 355 | var argPices = argDefault[7 ..< argDefault.len - 1].split(',') 356 | argDefault = argDefault[0 ..< 7] 357 | for p in 0 ..< argPices.len: 358 | argDefault.add("{letters[p]}: {argPices[p]}, ".fmt) 359 | argDefault = argDefault[0 ..< argDefault.len - 2] & ")" 360 | 361 | if (argType.startsWith("ImPlot") or argType.startsWith("Im")) and not argType.contains("Callback") and not argType.contains("ImVec"): # Ugly hack, should fix later 362 | argDefault.add(".{argType}".fmt) 363 | 364 | if argName.startsWith("_"): 365 | argName = argName[1 ..< argName.len] 366 | if argName.isUpper(): 367 | argName = argName.normalize() 368 | argName = argName.uncapitalize() 369 | 370 | if reservedWordsDictionary.contains(argName): 371 | argName = "`{argName}`".fmt 372 | 373 | if argType.contains('[') and not argType.contains("ImVector[") and not argType.contains("UncheckedArray["): 374 | let arrayData = argType.translateArray() 375 | if arrayData[1].contains("cstringconst"): 376 | echo "{name}\n{obj.pretty}".fmt 377 | argType = "var array[{arrayData[0]}, {arrayData[1]}]".fmt 378 | argType = argType.replace(" {.cdecl.}", "") 379 | 380 | if argName == "..." or argType == "..." or argType == "va_list": 381 | isVarArgs = true 382 | continue 383 | if argType == "T" or argType == "ptr T": 384 | isGeneric = true 385 | 386 | if argDefault == "": 387 | argsOutput.add("{argName}: {argType}, ".fmt) 388 | else: 389 | argsOutput.add("{argName}: {argType} = {argDefault}, ".fmt) 390 | if variation["argsT"].len > 0: 391 | argsOutput = argsOutput[0 ..< argsOutput.len - 2] 392 | 393 | # Ret 394 | var argRet = "void" 395 | if variation.contains("ret"): 396 | argRet = variation["ret"].getStr().translateType() 397 | if argRet == "T" or argRet == "ptr T": 398 | isGeneric = true 399 | if argRet == "explicit": 400 | argRet = "ptr ImVec2ih" # Ugly solution for a temporal problem 401 | 402 | output.add(if isGeneric: "[T](" else: "(") 403 | output.add(argsOutput) 404 | output.add("): ") 405 | output.add(argRet) 406 | 407 | # Pragmas 408 | var pragmaName = variation["cimguiname"].getStr() 409 | if variation.contains("ov_cimguiname"): 410 | pragmaName = variation["ov_cimguiname"].getStr() 411 | output.add(" {" & ".importc: \"{pragmaName}\"".fmt) 412 | if isVarArgs: 413 | output.add(", varargs") 414 | output.add(".}") 415 | 416 | output.add("\n") 417 | 418 | # Checking if it doesn't exist already 419 | let outSplit = output.rsplit("\n", 3) 420 | if outSplit[1] == outSplit[2] or outSplit[1].split('{')[0] == outSplit[2].split('{')[0]: 421 | output = "{outSplit[0]}\n{outSplit[1]}\n".fmt 422 | 423 | output.add("\n{postProcs}\n".fmt) 424 | 425 | proc fixAfter(fname:string) = 426 | var s:seq[string] 427 | for line in fname.lines: 428 | var st = line 429 | # ignore line 430 | if st.toLowerAscii.contains(peg" '#' \s* 'noreplace' "): 431 | s.add st 432 | continue 433 | # cast issue 434 | st = st.replace(peg"'-1.ImPlotColormap'","cast[ImPlotcolormap](-1)") 435 | st = st.replace(peg"'-1.ImPlotCol'","cast[ImPlotcol](-1)") 436 | st = st.replace(peg"'-1.ImAxis'","cast[ImAxis](-1)") 437 | # 438 | st = st.replace(peg"'ImPlotRange().ImPlotRange'","ImPlotRange()") 439 | st = st.replace(peg"'ImPlotRect().ImPlotRect'","ImPlotRect()") 440 | # 441 | st = st.replace(peg"'ImPlotCond_Once.ImPlotCond'","ImPlotCond.Once") 442 | st = st.replace(peg"'sizeof(double)'","sizeof(cdouble).int32") 443 | st = st.replacef(peg"'ImPlotPoint32'","ImPlotPoint") 444 | while st.contains(peg"'ImPlotPoint(' \d+ "): 445 | st = st.replacef(peg"{@}'ImPlotPoint(' {\d+} ',' {\d+} ').ImPlotPoint' {@}$","$1ImPlotPoint(x:$2,y:$3)$4") 446 | while st.contains(peg"'ImPlotBin_Sturges'"): 447 | st = st.replacef(peg"{@}'ImPlotBin_Sturges'{@}$","$1ImPlotBin.Sturges.int$2") 448 | # rename `proc implot_` to `proc ip` 449 | st = st.replace(peg"^'proc imPlot_'","proc ip") 450 | # replace `range` to `Range` 451 | st = st.replace(peg"'range:'","Range:") 452 | st = st.replace(peg"' range* '"," Range* ") 453 | # replace cfloat64 to cdouble 454 | while st.contains(peg"'cfloat64'"): 455 | st = st.replacef(peg"{@}'cfloat64'{@}$","$1cdouble$2") 456 | 457 | s.add st 458 | 459 | writeFile(fname,s.join("\n")) 460 | 461 | proc igGenerate*() = 462 | var output = srcHeader 463 | 464 | output.genEnums() 465 | output.genTypeDefs() 466 | output.genTypes() 467 | output.genProcs() 468 | #output.add("\n" & cherryTheme) 469 | 470 | writeFile("src/implot.nim", output) 471 | fixAfter("src/implot.nim") 472 | 473 | when isMainModule: 474 | igGenerate() 475 | -------------------------------------------------------------------------------- /tools/test.nim: -------------------------------------------------------------------------------- 1 | type 2 | test {.pure, size:int32.sizeof.} = enum 3 | a,b,c 4 | 5 | var res = cast[test](-1) 6 | inc res 7 | echo res 8 | 9 | -------------------------------------------------------------------------------- /tools/utils.nim: -------------------------------------------------------------------------------- 1 | # Written by Leonardo Mariscal , 2019 2 | 3 | const srcHeader* = """ 4 | # Modified for ImPlot by dinau,2023 5 | # Written by Leonardo Mariscal , 2019 6 | 7 | ## ImGUI Bindings 8 | ## ==== 9 | ## WARNING: This is a generated file. Do not edit 10 | ## Any edits will be overwritten by the generator. 11 | ## 12 | ## The aim is to achieve as much compatibility with C as possible. 13 | ## Optional helper functions have been created as a submodule 14 | ## ``imgui/imgui_helpers`` to better bind this library to Nim. 15 | ## 16 | ## You can check the original documentation `here `_. 17 | ## 18 | ## Source language of ImGui is C++, since Nim is able to compile both to C 19 | ## and C++ you can select which compile target you wish to use. Note that to use 20 | ## the C backend you must supply a `cimgui `_ 21 | ## dynamic library file. 22 | ## 23 | ## HACK: If you are targeting Windows, be sure to compile the cimgui dll with 24 | ## visual studio and not with mingw. 25 | 26 | import strutils 27 | import imgui 28 | 29 | ## Tentative workaround [start] 30 | type 31 | Imguidockrequest* = distinct object 32 | ImGuiDockNodeSettings* = distinct object 33 | const_cstringPtr* {.pure, inheritable, bycopy.} = object 34 | Size*: cint 35 | Capacity*: cint 36 | Data*: ptr ptr cschar 37 | tm {.pure, inheritable, bycopy.} = object 38 | tmsec*: cint 39 | tmmin*: cint 40 | tmhour*: cint 41 | tmmday*: cint 42 | tmmon*: cint 43 | tmyear*: cint 44 | tmwday*: cint 45 | tmyday*: cint 46 | tmisdst*: cint 47 | cfloat64* = cdouble # NoReplace 48 | double* = cdouble 49 | Ims32* = cint 50 | const 51 | nullptr* = nil 52 | IMPLOT_AUTO* = -1 # from 53 | 54 | #-------------------------------------- 55 | # Enum: logical calculation definitions 56 | #-------------------------------------- 57 | # Assumed enum size is 32bit. 58 | # or 59 | template `or`*[E:enum](a,b:E):E = 60 | cast[E](a.uint32 or b.uint32) 61 | template `or`*[E:enum,I:SomeInteger](a:E,b:I):E = 62 | cast[E](a.uint32 or b.uint32) 63 | template `or`*[E:enum,I:SomeInteger](a:I,b:E):E = 64 | cast[E](a.uint32 or b.uint32 ) 65 | 66 | # xor 67 | template `xor`*[E:enum](a,b:E):E = 68 | cast[E](a.uint32 xor b.uint32) 69 | template `xor`*[E:enum,I:SomeInteger](a:E,b:I):E = 70 | cast[E](a.uint32 xor b) 71 | template `xor`*[E:enum,I:SomeInteger](a:I,b:E):E = 72 | cast[E](a.uint32 xor b.uint32 ) 73 | 74 | # and 75 | template `and`*[E:enum](a,b:E):E = 76 | cast[E](a.uint32 and b.uint32) 77 | template `and`*[E:enum,I:SomeInteger](a:E,b:I):E = 78 | cast[E](a.uint32 and b.uint32 ) 79 | template `and`*[E:enum,I:SomeInteger](a:I,b:E):E = 80 | cast[E](cast[uint32](a) and cast[uint32](b) ) 81 | 82 | #----------- 83 | # templates 84 | #----------- 85 | template ptz*(val:untyped): untyped = 86 | val[0].addr 87 | template pu32*(v: untyped) : untyped = cast[ptr uint32](v.addr) 88 | template pi32*(v: untyped) : untyped = cast[ptr int32](v.addr) 89 | template cstringCast*(v: untyped) : untyped = cast[cstring](v) 90 | 91 | ## Tentative workaround [end] 92 | 93 | proc currentSourceDir(): string {.compileTime.} = 94 | result = currentSourcePath().replace("\\", "/") 95 | result = result[0 ..< result.rfind("/")] 96 | 97 | {.passC:"-DImDrawIdx=\"unsigned int\"".} 98 | 99 | {.compile: "implot/private/cimplot/cimplot.cpp", 100 | compile: "implot/private/cimplot/implot/implot.cpp", 101 | compile: "implot/private/cimplot/implot/implot_demo.cpp", 102 | compile: "implot/private/cimplot/implot/implot_items.cpp".} 103 | {.passC:"-I" & currentSourceDir() & "/implot/private/cimplot".} 104 | {.passC:"-I" & currentSourceDir() & "/implot/private/cimplot/implot".} 105 | {.pragma: implot_header, header: currentSourceDir() & "/implot/private/ncimplot.h".} 106 | 107 | when defined(windows): 108 | {.passC:"-static".} 109 | {.passL:"-static".} 110 | 111 | """ 112 | 113 | const preProcs* = """ 114 | # Procs 115 | 116 | when not defined(cpp) or defined(cimguiDLL): 117 | {.push dynlib: imgui_dll, cdecl, discardable, header: currentSourceDir() & "/implot/private/ncimplot.h".} 118 | else: 119 | {.push nodecl, discardable, header: currentSourceDir() & "/implot/private/ncimplot.h".} 120 | 121 | type 122 | ImPlotPointGetter* = proc (data: pointer; idx: cint; point: ptr ImPlotPoint): pointer {.cdecl.} 123 | """ 124 | 125 | const postProcs* = """ 126 | 127 | {.pop.} # push dynlib / nodecl, etc... 128 | 129 | """ 130 | 131 | let reservedWordsDictionary* = [ 132 | "end", "type", "out", "in", "ptr", "ref" 133 | ] 134 | 135 | let blackListProc* = [ "" ] 136 | --------------------------------------------------------------------------------